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