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