• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
27 #include <cctype>
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.
printIntegral(const TemplateArgument & TemplArg,raw_ostream & Out)36 static void printIntegral(const TemplateArgument &TemplArg,
37                           raw_ostream &Out) {
38   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
39   const llvm::APSInt *Val = TemplArg.getAsIntegral();
40 
41   if (T->isBooleanType()) {
42     Out << (Val->getBoolValue() ? "true" : "false");
43   } else if (T->isCharType()) {
44     const char Ch = Val->getZExtValue();
45     Out << ((Ch == '\'') ? "'\\" : "'");
46     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
47     Out << "'";
48   } else {
49     Out << Val->toString(10);
50   }
51 }
52 
53 //===----------------------------------------------------------------------===//
54 // TemplateArgument Implementation
55 //===----------------------------------------------------------------------===//
56 
CreatePackCopy(ASTContext & Context,const TemplateArgument * Args,unsigned NumArgs)57 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
58                                                   const TemplateArgument *Args,
59                                                   unsigned NumArgs) {
60   if (NumArgs == 0)
61     return TemplateArgument(0, 0);
62 
63   TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
64   std::copy(Args, Args + NumArgs, Storage);
65   return TemplateArgument(Storage, NumArgs);
66 }
67 
isDependent() const68 bool TemplateArgument::isDependent() const {
69   switch (getKind()) {
70   case Null:
71     llvm_unreachable("Should not have a NULL template argument");
72 
73   case Type:
74     return getAsType()->isDependentType();
75 
76   case Template:
77     return getAsTemplate().isDependent();
78 
79   case TemplateExpansion:
80     return true;
81 
82   case Declaration:
83     if (Decl *D = getAsDecl()) {
84       if (DeclContext *DC = dyn_cast<DeclContext>(D))
85         return DC->isDependentContext();
86       return D->getDeclContext()->isDependentContext();
87     }
88 
89     return false;
90 
91   case Integral:
92     // Never dependent
93     return false;
94 
95   case Expression:
96     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
97 
98   case Pack:
99     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
100       if (P->isDependent())
101         return true;
102     }
103 
104     return false;
105   }
106 
107   llvm_unreachable("Invalid TemplateArgument Kind!");
108 }
109 
isInstantiationDependent() const110 bool TemplateArgument::isInstantiationDependent() const {
111   switch (getKind()) {
112   case Null:
113     llvm_unreachable("Should not have a NULL template argument");
114 
115   case Type:
116     return getAsType()->isInstantiationDependentType();
117 
118   case Template:
119     return getAsTemplate().isInstantiationDependent();
120 
121   case TemplateExpansion:
122     return true;
123 
124   case Declaration:
125     if (Decl *D = getAsDecl()) {
126       if (DeclContext *DC = dyn_cast<DeclContext>(D))
127         return DC->isDependentContext();
128       return D->getDeclContext()->isDependentContext();
129     }
130     return false;
131 
132   case Integral:
133     // Never dependent
134     return false;
135 
136   case Expression:
137     return getAsExpr()->isInstantiationDependent();
138 
139   case Pack:
140     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
141       if (P->isInstantiationDependent())
142         return true;
143     }
144 
145     return false;
146   }
147 
148   llvm_unreachable("Invalid TemplateArgument Kind!");
149 }
150 
isPackExpansion() const151 bool TemplateArgument::isPackExpansion() const {
152   switch (getKind()) {
153   case Null:
154   case Declaration:
155   case Integral:
156   case Pack:
157   case Template:
158     return false;
159 
160   case TemplateExpansion:
161     return true;
162 
163   case Type:
164     return isa<PackExpansionType>(getAsType());
165 
166   case Expression:
167     return isa<PackExpansionExpr>(getAsExpr());
168   }
169 
170   llvm_unreachable("Invalid TemplateArgument Kind!");
171 }
172 
containsUnexpandedParameterPack() const173 bool TemplateArgument::containsUnexpandedParameterPack() const {
174   switch (getKind()) {
175   case Null:
176   case Declaration:
177   case Integral:
178   case TemplateExpansion:
179     break;
180 
181   case Type:
182     if (getAsType()->containsUnexpandedParameterPack())
183       return true;
184     break;
185 
186   case Template:
187     if (getAsTemplate().containsUnexpandedParameterPack())
188       return true;
189     break;
190 
191   case Expression:
192     if (getAsExpr()->containsUnexpandedParameterPack())
193       return true;
194     break;
195 
196   case Pack:
197     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
198       if (P->containsUnexpandedParameterPack())
199         return true;
200 
201     break;
202   }
203 
204   return false;
205 }
206 
getNumTemplateExpansions() const207 llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
208   assert(Kind == TemplateExpansion);
209   if (TemplateArg.NumExpansions)
210     return TemplateArg.NumExpansions - 1;
211 
212   return llvm::Optional<unsigned>();
213 }
214 
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context) const215 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
216                                const ASTContext &Context) const {
217   ID.AddInteger(Kind);
218   switch (Kind) {
219   case Null:
220     break;
221 
222   case Type:
223     getAsType().Profile(ID);
224     break;
225 
226   case Declaration:
227     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
228     break;
229 
230   case Template:
231   case TemplateExpansion: {
232     TemplateName Template = getAsTemplateOrTemplatePattern();
233     if (TemplateTemplateParmDecl *TTP
234           = dyn_cast_or_null<TemplateTemplateParmDecl>(
235                                                 Template.getAsTemplateDecl())) {
236       ID.AddBoolean(true);
237       ID.AddInteger(TTP->getDepth());
238       ID.AddInteger(TTP->getPosition());
239       ID.AddBoolean(TTP->isParameterPack());
240     } else {
241       ID.AddBoolean(false);
242       ID.AddPointer(Context.getCanonicalTemplateName(Template)
243                                                           .getAsVoidPointer());
244     }
245     break;
246   }
247 
248   case Integral:
249     getAsIntegral()->Profile(ID);
250     getIntegralType().Profile(ID);
251     break;
252 
253   case Expression:
254     getAsExpr()->Profile(ID, Context, true);
255     break;
256 
257   case Pack:
258     ID.AddInteger(Args.NumArgs);
259     for (unsigned I = 0; I != Args.NumArgs; ++I)
260       Args.Args[I].Profile(ID, Context);
261   }
262 }
263 
structurallyEquals(const TemplateArgument & Other) const264 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
265   if (getKind() != Other.getKind()) return false;
266 
267   switch (getKind()) {
268   case Null:
269   case Type:
270   case Declaration:
271   case Expression:
272   case Template:
273   case TemplateExpansion:
274     return TypeOrValue == Other.TypeOrValue;
275 
276   case Integral:
277     return getIntegralType() == Other.getIntegralType() &&
278            *getAsIntegral() == *Other.getAsIntegral();
279 
280   case Pack:
281     if (Args.NumArgs != Other.Args.NumArgs) return false;
282     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
283       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
284         return false;
285     return true;
286   }
287 
288   llvm_unreachable("Invalid TemplateArgument Kind!");
289 }
290 
getPackExpansionPattern() const291 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
292   assert(isPackExpansion());
293 
294   switch (getKind()) {
295   case Type:
296     return getAsType()->getAs<PackExpansionType>()->getPattern();
297 
298   case Expression:
299     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
300 
301   case TemplateExpansion:
302     return TemplateArgument(getAsTemplateOrTemplatePattern());
303 
304   case Declaration:
305   case Integral:
306   case Pack:
307   case Null:
308   case Template:
309     return TemplateArgument();
310   }
311 
312   llvm_unreachable("Invalid TemplateArgument Kind!");
313 }
314 
print(const PrintingPolicy & Policy,raw_ostream & Out) const315 void TemplateArgument::print(const PrintingPolicy &Policy,
316                              raw_ostream &Out) const {
317   switch (getKind()) {
318   case Null:
319     Out << "<no value>";
320     break;
321 
322   case Type: {
323     PrintingPolicy SubPolicy(Policy);
324     SubPolicy.SuppressStrongLifetime = true;
325     std::string TypeStr;
326     getAsType().getAsStringInternal(TypeStr, SubPolicy);
327     Out << TypeStr;
328     break;
329   }
330 
331   case Declaration: {
332     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
333       if (ND->getDeclName()) {
334         Out << *ND;
335       } else {
336         Out << "<anonymous>";
337       }
338     } else {
339       Out << "nullptr";
340     }
341     break;
342   }
343 
344   case Template:
345     getAsTemplate().print(Out, Policy);
346     break;
347 
348   case TemplateExpansion:
349     getAsTemplateOrTemplatePattern().print(Out, Policy);
350     Out << "...";
351     break;
352 
353   case Integral: {
354     printIntegral(*this, Out);
355     break;
356   }
357 
358   case Expression:
359     getAsExpr()->printPretty(Out, 0, Policy);
360     break;
361 
362   case Pack:
363     Out << "<";
364     bool First = true;
365     for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
366          P != PEnd; ++P) {
367       if (First)
368         First = false;
369       else
370         Out << ", ";
371 
372       P->print(Policy, Out);
373     }
374     Out << ">";
375     break;
376   }
377 }
378 
379 //===----------------------------------------------------------------------===//
380 // TemplateArgumentLoc Implementation
381 //===----------------------------------------------------------------------===//
382 
TemplateArgumentLocInfo()383 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
384   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
385 }
386 
getSourceRange() const387 SourceRange TemplateArgumentLoc::getSourceRange() const {
388   switch (Argument.getKind()) {
389   case TemplateArgument::Expression:
390     return getSourceExpression()->getSourceRange();
391 
392   case TemplateArgument::Declaration:
393     return getSourceDeclExpression()->getSourceRange();
394 
395   case TemplateArgument::Type:
396     if (TypeSourceInfo *TSI = getTypeSourceInfo())
397       return TSI->getTypeLoc().getSourceRange();
398     else
399       return SourceRange();
400 
401   case TemplateArgument::Template:
402     if (getTemplateQualifierLoc())
403       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
404                          getTemplateNameLoc());
405     return SourceRange(getTemplateNameLoc());
406 
407   case TemplateArgument::TemplateExpansion:
408     if (getTemplateQualifierLoc())
409       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
410                          getTemplateEllipsisLoc());
411     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
412 
413   case TemplateArgument::Integral:
414   case TemplateArgument::Pack:
415   case TemplateArgument::Null:
416     return SourceRange();
417   }
418 
419   llvm_unreachable("Invalid TemplateArgument Kind!");
420 }
421 
422 TemplateArgumentLoc
getPackExpansionPattern(SourceLocation & Ellipsis,llvm::Optional<unsigned> & NumExpansions,ASTContext & Context) const423 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
424                                        llvm::Optional<unsigned> &NumExpansions,
425                                              ASTContext &Context) const {
426   assert(Argument.isPackExpansion());
427 
428   switch (Argument.getKind()) {
429   case TemplateArgument::Type: {
430     // FIXME: We shouldn't ever have to worry about missing
431     // type-source info!
432     TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
433     if (!ExpansionTSInfo)
434       ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
435                                                      getArgument().getAsType(),
436                                                          Ellipsis);
437     PackExpansionTypeLoc Expansion
438       = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
439     Ellipsis = Expansion.getEllipsisLoc();
440 
441     TypeLoc Pattern = Expansion.getPatternLoc();
442     NumExpansions = Expansion.getTypePtr()->getNumExpansions();
443 
444     // FIXME: This is horrible. We know where the source location data is for
445     // the pattern, and we have the pattern's type, but we are forced to copy
446     // them into an ASTContext because TypeSourceInfo bundles them together
447     // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
448     TypeSourceInfo *PatternTSInfo
449       = Context.CreateTypeSourceInfo(Pattern.getType(),
450                                      Pattern.getFullDataSize());
451     memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
452            Pattern.getOpaqueData(), Pattern.getFullDataSize());
453     return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
454                                PatternTSInfo);
455   }
456 
457   case TemplateArgument::Expression: {
458     PackExpansionExpr *Expansion
459       = cast<PackExpansionExpr>(Argument.getAsExpr());
460     Expr *Pattern = Expansion->getPattern();
461     Ellipsis = Expansion->getEllipsisLoc();
462     NumExpansions = Expansion->getNumExpansions();
463     return TemplateArgumentLoc(Pattern, Pattern);
464   }
465 
466   case TemplateArgument::TemplateExpansion:
467     Ellipsis = getTemplateEllipsisLoc();
468     NumExpansions = Argument.getNumTemplateExpansions();
469     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
470                                getTemplateQualifierLoc(),
471                                getTemplateNameLoc());
472 
473   case TemplateArgument::Declaration:
474   case TemplateArgument::Template:
475   case TemplateArgument::Integral:
476   case TemplateArgument::Pack:
477   case TemplateArgument::Null:
478     return TemplateArgumentLoc();
479   }
480 
481   llvm_unreachable("Invalid TemplateArgument Kind!");
482 }
483 
operator <<(const DiagnosticBuilder & DB,const TemplateArgument & Arg)484 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
485                                            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     if (Decl *D = Arg.getAsDecl())
497       return DB << D;
498     return DB << "nullptr";
499 
500   case TemplateArgument::Integral:
501     return DB << Arg.getAsIntegral()->toString(10);
502 
503   case TemplateArgument::Template:
504     return DB << Arg.getAsTemplate();
505 
506   case TemplateArgument::TemplateExpansion:
507     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
508 
509   case TemplateArgument::Expression: {
510     // This shouldn't actually ever happen, so it's okay that we're
511     // regurgitating an expression here.
512     // FIXME: We're guessing at LangOptions!
513     SmallString<32> Str;
514     llvm::raw_svector_ostream OS(Str);
515     LangOptions LangOpts;
516     LangOpts.CPlusPlus = true;
517     PrintingPolicy Policy(LangOpts);
518     Arg.getAsExpr()->printPretty(OS, 0, Policy);
519     return DB << OS.str();
520   }
521 
522   case TemplateArgument::Pack: {
523     // FIXME: We're guessing at LangOptions!
524     SmallString<32> Str;
525     llvm::raw_svector_ostream OS(Str);
526     LangOptions LangOpts;
527     LangOpts.CPlusPlus = true;
528     PrintingPolicy Policy(LangOpts);
529     Arg.print(Policy, OS);
530     return DB << OS.str();
531   }
532   }
533 
534   llvm_unreachable("Invalid TemplateArgument Kind!");
535 }
536 
537 const ASTTemplateArgumentListInfo *
Create(ASTContext & C,const TemplateArgumentListInfo & List)538 ASTTemplateArgumentListInfo::Create(ASTContext &C,
539                                     const TemplateArgumentListInfo &List) {
540   std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
541                      ASTTemplateArgumentListInfo::sizeFor(List.size());
542   void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
543   ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
544   TAI->initializeFrom(List);
545   return TAI;
546 }
547 
initializeFrom(const TemplateArgumentListInfo & Info)548 void ASTTemplateArgumentListInfo::initializeFrom(
549                                       const TemplateArgumentListInfo &Info) {
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     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
557 }
558 
initializeFrom(const TemplateArgumentListInfo & Info,bool & Dependent,bool & InstantiationDependent,bool & ContainsUnexpandedParameterPack)559 void ASTTemplateArgumentListInfo::initializeFrom(
560                                           const TemplateArgumentListInfo &Info,
561                                                   bool &Dependent,
562                                                   bool &InstantiationDependent,
563                                        bool &ContainsUnexpandedParameterPack) {
564   LAngleLoc = Info.getLAngleLoc();
565   RAngleLoc = Info.getRAngleLoc();
566   NumTemplateArgs = Info.size();
567 
568   TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
569   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
570     Dependent = Dependent || Info[i].getArgument().isDependent();
571     InstantiationDependent = InstantiationDependent ||
572                              Info[i].getArgument().isInstantiationDependent();
573     ContainsUnexpandedParameterPack
574       = ContainsUnexpandedParameterPack ||
575         Info[i].getArgument().containsUnexpandedParameterPack();
576 
577     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
578   }
579 }
580 
copyInto(TemplateArgumentListInfo & Info) const581 void ASTTemplateArgumentListInfo::copyInto(
582                                       TemplateArgumentListInfo &Info) const {
583   Info.setLAngleLoc(LAngleLoc);
584   Info.setRAngleLoc(RAngleLoc);
585   for (unsigned I = 0; I != NumTemplateArgs; ++I)
586     Info.addArgument(getTemplateArgs()[I]);
587 }
588 
sizeFor(unsigned NumTemplateArgs)589 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
590   return sizeof(ASTTemplateArgumentListInfo) +
591          sizeof(TemplateArgumentLoc) * NumTemplateArgs;
592 }
593 
594 void
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info)595 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
596                                          const TemplateArgumentListInfo &Info) {
597   Base::initializeFrom(Info);
598   setTemplateKeywordLoc(TemplateKWLoc);
599 }
600 
601 void
602 ASTTemplateKWAndArgsInfo
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info,bool & Dependent,bool & InstantiationDependent,bool & ContainsUnexpandedParameterPack)603 ::initializeFrom(SourceLocation TemplateKWLoc,
604                  const TemplateArgumentListInfo &Info,
605                  bool &Dependent,
606                  bool &InstantiationDependent,
607                  bool &ContainsUnexpandedParameterPack) {
608   Base::initializeFrom(Info, Dependent, InstantiationDependent,
609                        ContainsUnexpandedParameterPack);
610   setTemplateKeywordLoc(TemplateKWLoc);
611 }
612 
613 void
initializeFrom(SourceLocation TemplateKWLoc)614 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
615   // No explicit template arguments, but template keyword loc is valid.
616   assert(TemplateKWLoc.isValid());
617   LAngleLoc = SourceLocation();
618   RAngleLoc = SourceLocation();
619   NumTemplateArgs = 0;
620   setTemplateKeywordLoc(TemplateKWLoc);
621 }
622 
623 std::size_t
sizeFor(unsigned NumTemplateArgs)624 ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
625   // Add space for the template keyword location.
626   return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
627 }
628 
629