xref: /freebsd/contrib/llvm-project/clang/lib/AST/TemplateBase.cpp (revision 62cfcf62f627e5093fb37026a6d8c98e4d2ef04c)
1 //===- TemplateBase.cpp - Common template AST class implementation --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements common classes used throughout C++ template
10 // representations.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/TemplateBase.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/PrettyPrinter.h"
22 #include "clang/AST/TemplateName.h"
23 #include "clang/AST/Type.h"
24 #include "clang/AST/TypeLoc.h"
25 #include "clang/Basic/Diagnostic.h"
26 #include "clang/Basic/LLVM.h"
27 #include "clang/Basic/LangOptions.h"
28 #include "clang/Basic/SourceLocation.h"
29 #include "llvm/ADT/APSInt.h"
30 #include "llvm/ADT/FoldingSet.h"
31 #include "llvm/ADT/None.h"
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/ADT/StringRef.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/Compiler.h"
36 #include "llvm/Support/ErrorHandling.h"
37 #include "llvm/Support/raw_ostream.h"
38 #include <cassert>
39 #include <cstddef>
40 #include <cstdint>
41 #include <cstring>
42 
43 using namespace clang;
44 
45 /// Print a template integral argument value.
46 ///
47 /// \param TemplArg the TemplateArgument instance to print.
48 ///
49 /// \param Out the raw_ostream instance to use for printing.
50 ///
51 /// \param Policy the printing policy for EnumConstantDecl printing.
52 static void printIntegral(const TemplateArgument &TemplArg,
53                           raw_ostream &Out, const PrintingPolicy& Policy) {
54   const Type *T = TemplArg.getIntegralType().getTypePtr();
55   const llvm::APSInt &Val = TemplArg.getAsIntegral();
56 
57   if (const EnumType *ET = T->getAs<EnumType>()) {
58     for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
59       // In Sema::CheckTemplateArugment, enum template arguments value are
60       // extended to the size of the integer underlying the enum type.  This
61       // may create a size difference between the enum value and template
62       // argument value, requiring isSameValue here instead of operator==.
63       if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
64         ECD->printQualifiedName(Out, Policy);
65         return;
66       }
67     }
68   }
69 
70   if (T->isBooleanType() && !Policy.MSVCFormatting) {
71     Out << (Val.getBoolValue() ? "true" : "false");
72   } else if (T->isCharType()) {
73     const char Ch = Val.getZExtValue();
74     Out << ((Ch == '\'') ? "'\\" : "'");
75     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
76     Out << "'";
77   } else {
78     Out << Val;
79   }
80 }
81 
82 //===----------------------------------------------------------------------===//
83 // TemplateArgument Implementation
84 //===----------------------------------------------------------------------===//
85 
86 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
87                                    QualType Type) {
88   Integer.Kind = Integral;
89   // Copy the APSInt value into our decomposed form.
90   Integer.BitWidth = Value.getBitWidth();
91   Integer.IsUnsigned = Value.isUnsigned();
92   // If the value is large, we have to get additional memory from the ASTContext
93   unsigned NumWords = Value.getNumWords();
94   if (NumWords > 1) {
95     void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
96     std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
97     Integer.pVal = static_cast<uint64_t *>(Mem);
98   } else {
99     Integer.VAL = Value.getZExtValue();
100   }
101 
102   Integer.Type = Type.getAsOpaquePtr();
103 }
104 
105 TemplateArgument
106 TemplateArgument::CreatePackCopy(ASTContext &Context,
107                                  ArrayRef<TemplateArgument> Args) {
108   if (Args.empty())
109     return getEmptyPack();
110 
111   return TemplateArgument(Args.copy(Context));
112 }
113 
114 bool TemplateArgument::isDependent() const {
115   switch (getKind()) {
116   case Null:
117     llvm_unreachable("Should not have a NULL template argument");
118 
119   case Type:
120     return getAsType()->isDependentType() ||
121            isa<PackExpansionType>(getAsType());
122 
123   case Template:
124     return getAsTemplate().isDependent();
125 
126   case TemplateExpansion:
127     return true;
128 
129   case Declaration:
130     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
131       return DC->isDependentContext();
132     return getAsDecl()->getDeclContext()->isDependentContext();
133 
134   case NullPtr:
135     return false;
136 
137   case Integral:
138     // Never dependent
139     return false;
140 
141   case Expression:
142     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
143             isa<PackExpansionExpr>(getAsExpr()));
144 
145   case Pack:
146     for (const auto &P : pack_elements())
147       if (P.isDependent())
148         return true;
149     return false;
150   }
151 
152   llvm_unreachable("Invalid TemplateArgument Kind!");
153 }
154 
155 bool TemplateArgument::isInstantiationDependent() const {
156   switch (getKind()) {
157   case Null:
158     llvm_unreachable("Should not have a NULL template argument");
159 
160   case Type:
161     return getAsType()->isInstantiationDependentType();
162 
163   case Template:
164     return getAsTemplate().isInstantiationDependent();
165 
166   case TemplateExpansion:
167     return true;
168 
169   case Declaration:
170     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
171       return DC->isDependentContext();
172     return getAsDecl()->getDeclContext()->isDependentContext();
173 
174   case NullPtr:
175     return false;
176 
177   case Integral:
178     // Never dependent
179     return false;
180 
181   case Expression:
182     return getAsExpr()->isInstantiationDependent();
183 
184   case Pack:
185     for (const auto &P : pack_elements())
186       if (P.isInstantiationDependent())
187         return true;
188     return false;
189   }
190 
191   llvm_unreachable("Invalid TemplateArgument Kind!");
192 }
193 
194 bool TemplateArgument::isPackExpansion() const {
195   switch (getKind()) {
196   case Null:
197   case Declaration:
198   case Integral:
199   case Pack:
200   case Template:
201   case NullPtr:
202     return false;
203 
204   case TemplateExpansion:
205     return true;
206 
207   case Type:
208     return isa<PackExpansionType>(getAsType());
209 
210   case Expression:
211     return isa<PackExpansionExpr>(getAsExpr());
212   }
213 
214   llvm_unreachable("Invalid TemplateArgument Kind!");
215 }
216 
217 bool TemplateArgument::containsUnexpandedParameterPack() const {
218   switch (getKind()) {
219   case Null:
220   case Declaration:
221   case Integral:
222   case TemplateExpansion:
223   case NullPtr:
224     break;
225 
226   case Type:
227     if (getAsType()->containsUnexpandedParameterPack())
228       return true;
229     break;
230 
231   case Template:
232     if (getAsTemplate().containsUnexpandedParameterPack())
233       return true;
234     break;
235 
236   case Expression:
237     if (getAsExpr()->containsUnexpandedParameterPack())
238       return true;
239     break;
240 
241   case Pack:
242     for (const auto &P : pack_elements())
243       if (P.containsUnexpandedParameterPack())
244         return true;
245 
246     break;
247   }
248 
249   return false;
250 }
251 
252 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
253   assert(getKind() == TemplateExpansion);
254   if (TemplateArg.NumExpansions)
255     return TemplateArg.NumExpansions - 1;
256 
257   return None;
258 }
259 
260 QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
261   switch (getKind()) {
262   case TemplateArgument::Null:
263   case TemplateArgument::Type:
264   case TemplateArgument::Template:
265   case TemplateArgument::TemplateExpansion:
266   case TemplateArgument::Pack:
267     return QualType();
268 
269   case TemplateArgument::Integral:
270     return getIntegralType();
271 
272   case TemplateArgument::Expression:
273     return getAsExpr()->getType();
274 
275   case TemplateArgument::Declaration:
276     return getParamTypeForDecl();
277 
278   case TemplateArgument::NullPtr:
279     return getNullPtrType();
280   }
281 
282   llvm_unreachable("Invalid TemplateArgument Kind!");
283 }
284 
285 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
286                                const ASTContext &Context) const {
287   ID.AddInteger(getKind());
288   switch (getKind()) {
289   case Null:
290     break;
291 
292   case Type:
293     getAsType().Profile(ID);
294     break;
295 
296   case NullPtr:
297     getNullPtrType().Profile(ID);
298     break;
299 
300   case Declaration:
301     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
302     break;
303 
304   case Template:
305   case TemplateExpansion: {
306     TemplateName Template = getAsTemplateOrTemplatePattern();
307     if (TemplateTemplateParmDecl *TTP
308           = dyn_cast_or_null<TemplateTemplateParmDecl>(
309                                                 Template.getAsTemplateDecl())) {
310       ID.AddBoolean(true);
311       ID.AddInteger(TTP->getDepth());
312       ID.AddInteger(TTP->getPosition());
313       ID.AddBoolean(TTP->isParameterPack());
314     } else {
315       ID.AddBoolean(false);
316       ID.AddPointer(Context.getCanonicalTemplateName(Template)
317                                                           .getAsVoidPointer());
318     }
319     break;
320   }
321 
322   case Integral:
323     getAsIntegral().Profile(ID);
324     getIntegralType().Profile(ID);
325     break;
326 
327   case Expression:
328     getAsExpr()->Profile(ID, Context, true);
329     break;
330 
331   case Pack:
332     ID.AddInteger(Args.NumArgs);
333     for (unsigned I = 0; I != Args.NumArgs; ++I)
334       Args.Args[I].Profile(ID, Context);
335   }
336 }
337 
338 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
339   if (getKind() != Other.getKind()) return false;
340 
341   switch (getKind()) {
342   case Null:
343   case Type:
344   case Expression:
345   case Template:
346   case TemplateExpansion:
347   case NullPtr:
348     return TypeOrValue.V == Other.TypeOrValue.V;
349 
350   case Declaration:
351     return getAsDecl() == Other.getAsDecl();
352 
353   case Integral:
354     return getIntegralType() == Other.getIntegralType() &&
355            getAsIntegral() == Other.getAsIntegral();
356 
357   case Pack:
358     if (Args.NumArgs != Other.Args.NumArgs) return false;
359     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
360       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
361         return false;
362     return true;
363   }
364 
365   llvm_unreachable("Invalid TemplateArgument Kind!");
366 }
367 
368 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
369   assert(isPackExpansion());
370 
371   switch (getKind()) {
372   case Type:
373     return getAsType()->castAs<PackExpansionType>()->getPattern();
374 
375   case Expression:
376     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
377 
378   case TemplateExpansion:
379     return TemplateArgument(getAsTemplateOrTemplatePattern());
380 
381   case Declaration:
382   case Integral:
383   case Pack:
384   case Null:
385   case Template:
386   case NullPtr:
387     return TemplateArgument();
388   }
389 
390   llvm_unreachable("Invalid TemplateArgument Kind!");
391 }
392 
393 void TemplateArgument::print(const PrintingPolicy &Policy,
394                              raw_ostream &Out) const {
395   switch (getKind()) {
396   case Null:
397     Out << "(no value)";
398     break;
399 
400   case Type: {
401     PrintingPolicy SubPolicy(Policy);
402     SubPolicy.SuppressStrongLifetime = true;
403     getAsType().print(Out, SubPolicy);
404     break;
405   }
406 
407   case Declaration: {
408     NamedDecl *ND = getAsDecl();
409     Out << '&';
410     if (ND->getDeclName()) {
411       // FIXME: distinguish between pointer and reference args?
412       ND->printQualifiedName(Out);
413     } else {
414       Out << "(anonymous)";
415     }
416     break;
417   }
418 
419   case NullPtr:
420     Out << "nullptr";
421     break;
422 
423   case Template:
424     getAsTemplate().print(Out, Policy);
425     break;
426 
427   case TemplateExpansion:
428     getAsTemplateOrTemplatePattern().print(Out, Policy);
429     Out << "...";
430     break;
431 
432   case Integral:
433     printIntegral(*this, Out, Policy);
434     break;
435 
436   case Expression:
437     getAsExpr()->printPretty(Out, nullptr, Policy);
438     break;
439 
440   case Pack:
441     Out << "<";
442     bool First = true;
443     for (const auto &P : pack_elements()) {
444       if (First)
445         First = false;
446       else
447         Out << ", ";
448 
449       P.print(Policy, Out);
450     }
451     Out << ">";
452     break;
453   }
454 }
455 
456 void TemplateArgument::dump(raw_ostream &Out) const {
457   LangOptions LO; // FIXME! see also TemplateName::dump().
458   LO.CPlusPlus = true;
459   LO.Bool = true;
460   print(PrintingPolicy(LO), Out);
461 }
462 
463 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
464 
465 //===----------------------------------------------------------------------===//
466 // TemplateArgumentLoc Implementation
467 //===----------------------------------------------------------------------===//
468 
469 SourceRange TemplateArgumentLoc::getSourceRange() const {
470   switch (Argument.getKind()) {
471   case TemplateArgument::Expression:
472     return getSourceExpression()->getSourceRange();
473 
474   case TemplateArgument::Declaration:
475     return getSourceDeclExpression()->getSourceRange();
476 
477   case TemplateArgument::NullPtr:
478     return getSourceNullPtrExpression()->getSourceRange();
479 
480   case TemplateArgument::Type:
481     if (TypeSourceInfo *TSI = getTypeSourceInfo())
482       return TSI->getTypeLoc().getSourceRange();
483     else
484       return SourceRange();
485 
486   case TemplateArgument::Template:
487     if (getTemplateQualifierLoc())
488       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
489                          getTemplateNameLoc());
490     return SourceRange(getTemplateNameLoc());
491 
492   case TemplateArgument::TemplateExpansion:
493     if (getTemplateQualifierLoc())
494       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
495                          getTemplateEllipsisLoc());
496     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
497 
498   case TemplateArgument::Integral:
499     return getSourceIntegralExpression()->getSourceRange();
500 
501   case TemplateArgument::Pack:
502   case TemplateArgument::Null:
503     return SourceRange();
504   }
505 
506   llvm_unreachable("Invalid TemplateArgument Kind!");
507 }
508 
509 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
510                                            const TemplateArgument &Arg) {
511   switch (Arg.getKind()) {
512   case TemplateArgument::Null:
513     // This is bad, but not as bad as crashing because of argument
514     // count mismatches.
515     return DB << "(null template argument)";
516 
517   case TemplateArgument::Type:
518     return DB << Arg.getAsType();
519 
520   case TemplateArgument::Declaration:
521     return DB << Arg.getAsDecl();
522 
523   case TemplateArgument::NullPtr:
524     return DB << "nullptr";
525 
526   case TemplateArgument::Integral:
527     return DB << Arg.getAsIntegral().toString(10);
528 
529   case TemplateArgument::Template:
530     return DB << Arg.getAsTemplate();
531 
532   case TemplateArgument::TemplateExpansion:
533     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
534 
535   case TemplateArgument::Expression: {
536     // This shouldn't actually ever happen, so it's okay that we're
537     // regurgitating an expression here.
538     // FIXME: We're guessing at LangOptions!
539     SmallString<32> Str;
540     llvm::raw_svector_ostream OS(Str);
541     LangOptions LangOpts;
542     LangOpts.CPlusPlus = true;
543     PrintingPolicy Policy(LangOpts);
544     Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
545     return DB << OS.str();
546   }
547 
548   case TemplateArgument::Pack: {
549     // FIXME: We're guessing at LangOptions!
550     SmallString<32> Str;
551     llvm::raw_svector_ostream OS(Str);
552     LangOptions LangOpts;
553     LangOpts.CPlusPlus = true;
554     PrintingPolicy Policy(LangOpts);
555     Arg.print(Policy, OS);
556     return DB << OS.str();
557   }
558   }
559 
560   llvm_unreachable("Invalid TemplateArgument Kind!");
561 }
562 
563 const ASTTemplateArgumentListInfo *
564 ASTTemplateArgumentListInfo::Create(const ASTContext &C,
565                                     const TemplateArgumentListInfo &List) {
566   std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
567   void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
568   return new (Mem) ASTTemplateArgumentListInfo(List);
569 }
570 
571 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
572     const TemplateArgumentListInfo &Info) {
573   LAngleLoc = Info.getLAngleLoc();
574   RAngleLoc = Info.getRAngleLoc();
575   NumTemplateArgs = Info.size();
576 
577   TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
578   for (unsigned i = 0; i != NumTemplateArgs; ++i)
579     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
580 }
581 
582 void ASTTemplateKWAndArgsInfo::initializeFrom(
583     SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
584     TemplateArgumentLoc *OutArgArray) {
585   this->TemplateKWLoc = TemplateKWLoc;
586   LAngleLoc = Info.getLAngleLoc();
587   RAngleLoc = Info.getRAngleLoc();
588   NumTemplateArgs = Info.size();
589 
590   for (unsigned i = 0; i != NumTemplateArgs; ++i)
591     new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
592 }
593 
594 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
595   assert(TemplateKWLoc.isValid());
596   LAngleLoc = SourceLocation();
597   RAngleLoc = SourceLocation();
598   this->TemplateKWLoc = TemplateKWLoc;
599   NumTemplateArgs = 0;
600 }
601 
602 void ASTTemplateKWAndArgsInfo::initializeFrom(
603     SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
604     TemplateArgumentLoc *OutArgArray, bool &Dependent,
605     bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) {
606   this->TemplateKWLoc = TemplateKWLoc;
607   LAngleLoc = Info.getLAngleLoc();
608   RAngleLoc = Info.getRAngleLoc();
609   NumTemplateArgs = Info.size();
610 
611   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
612     Dependent = Dependent || Info[i].getArgument().isDependent();
613     InstantiationDependent = InstantiationDependent ||
614                              Info[i].getArgument().isInstantiationDependent();
615     ContainsUnexpandedParameterPack =
616         ContainsUnexpandedParameterPack ||
617         Info[i].getArgument().containsUnexpandedParameterPack();
618 
619     new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
620   }
621 }
622 
623 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
624                                         TemplateArgumentListInfo &Info) const {
625   Info.setLAngleLoc(LAngleLoc);
626   Info.setRAngleLoc(RAngleLoc);
627   for (unsigned I = 0; I != NumTemplateArgs; ++I)
628     Info.addArgument(ArgArray[I]);
629 }
630