• 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 <algorithm>
26 #include <cctype>
27 
28 using namespace clang;
29 
30 /// \brief Print a template integral argument value.
31 ///
32 /// \param TemplArg the TemplateArgument instance to print.
33 ///
34 /// \param Out the raw_ostream instance to use for printing.
printIntegral(const TemplateArgument & TemplArg,llvm::raw_ostream & Out)35 static void printIntegral(const TemplateArgument &TemplArg,
36                           llvm::raw_ostream &Out) {
37   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
38   const llvm::APSInt *Val = TemplArg.getAsIntegral();
39 
40   if (T->isBooleanType()) {
41     Out << (Val->getBoolValue() ? "true" : "false");
42   } else if (T->isCharType()) {
43     const unsigned char Ch = Val->getZExtValue();
44     const std::string Str(1, Ch);
45     Out << ((Ch == '\'') ? "'\\" : "'");
46     Out.write_escaped(Str, /*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     assert(false && "Should not have a NULL template argument");
72     return false;
73 
74   case Type:
75     return getAsType()->isDependentType();
76 
77   case Template:
78     return getAsTemplate().isDependent();
79 
80   case TemplateExpansion:
81     return true;
82 
83   case Declaration:
84     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
85       return DC->isDependentContext();
86     return getAsDecl()->getDeclContext()->isDependentContext();
87 
88   case Integral:
89     // Never dependent
90     return false;
91 
92   case Expression:
93     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
94 
95   case Pack:
96     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
97       if (P->isDependent())
98         return true;
99     }
100 
101     return false;
102   }
103 
104   return false;
105 }
106 
isInstantiationDependent() const107 bool TemplateArgument::isInstantiationDependent() const {
108   switch (getKind()) {
109   case Null:
110     assert(false && "Should not have a NULL template argument");
111     return false;
112 
113   case Type:
114     return getAsType()->isInstantiationDependentType();
115 
116   case Template:
117     return getAsTemplate().isInstantiationDependent();
118 
119   case TemplateExpansion:
120     return true;
121 
122   case Declaration:
123     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
124       return DC->isDependentContext();
125     return getAsDecl()->getDeclContext()->isDependentContext();
126 
127   case Integral:
128     // Never dependent
129     return false;
130 
131   case Expression:
132     return getAsExpr()->isInstantiationDependent();
133 
134   case Pack:
135     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
136       if (P->isInstantiationDependent())
137         return true;
138     }
139 
140     return false;
141   }
142 
143   return false;
144 }
145 
isPackExpansion() const146 bool TemplateArgument::isPackExpansion() const {
147   switch (getKind()) {
148   case Null:
149   case Declaration:
150   case Integral:
151   case Pack:
152   case Template:
153     return false;
154 
155   case TemplateExpansion:
156     return true;
157 
158   case Type:
159     return isa<PackExpansionType>(getAsType());
160 
161   case Expression:
162     return isa<PackExpansionExpr>(getAsExpr());
163   }
164 
165   return false;
166 }
167 
containsUnexpandedParameterPack() const168 bool TemplateArgument::containsUnexpandedParameterPack() const {
169   switch (getKind()) {
170   case Null:
171   case Declaration:
172   case Integral:
173   case TemplateExpansion:
174     break;
175 
176   case Type:
177     if (getAsType()->containsUnexpandedParameterPack())
178       return true;
179     break;
180 
181   case Template:
182     if (getAsTemplate().containsUnexpandedParameterPack())
183       return true;
184     break;
185 
186   case Expression:
187     if (getAsExpr()->containsUnexpandedParameterPack())
188       return true;
189     break;
190 
191   case Pack:
192     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
193       if (P->containsUnexpandedParameterPack())
194         return true;
195 
196     break;
197   }
198 
199   return false;
200 }
201 
getNumTemplateExpansions() const202 llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
203   assert(Kind == TemplateExpansion);
204   if (TemplateArg.NumExpansions)
205     return TemplateArg.NumExpansions - 1;
206 
207   return llvm::Optional<unsigned>();
208 }
209 
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context) const210 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
211                                const ASTContext &Context) const {
212   ID.AddInteger(Kind);
213   switch (Kind) {
214   case Null:
215     break;
216 
217   case Type:
218     getAsType().Profile(ID);
219     break;
220 
221   case Declaration:
222     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
223     break;
224 
225   case Template:
226   case TemplateExpansion: {
227     TemplateName Template = getAsTemplateOrTemplatePattern();
228     if (TemplateTemplateParmDecl *TTP
229           = dyn_cast_or_null<TemplateTemplateParmDecl>(
230                                                 Template.getAsTemplateDecl())) {
231       ID.AddBoolean(true);
232       ID.AddInteger(TTP->getDepth());
233       ID.AddInteger(TTP->getPosition());
234       ID.AddBoolean(TTP->isParameterPack());
235     } else {
236       ID.AddBoolean(false);
237       ID.AddPointer(Context.getCanonicalTemplateName(Template)
238                                                           .getAsVoidPointer());
239     }
240     break;
241   }
242 
243   case Integral:
244     getAsIntegral()->Profile(ID);
245     getIntegralType().Profile(ID);
246     break;
247 
248   case Expression:
249     getAsExpr()->Profile(ID, Context, true);
250     break;
251 
252   case Pack:
253     ID.AddInteger(Args.NumArgs);
254     for (unsigned I = 0; I != Args.NumArgs; ++I)
255       Args.Args[I].Profile(ID, Context);
256   }
257 }
258 
structurallyEquals(const TemplateArgument & Other) const259 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
260   if (getKind() != Other.getKind()) return false;
261 
262   switch (getKind()) {
263   case Null:
264   case Type:
265   case Declaration:
266   case Expression:
267   case Template:
268   case TemplateExpansion:
269     return TypeOrValue == Other.TypeOrValue;
270 
271   case Integral:
272     return getIntegralType() == Other.getIntegralType() &&
273            *getAsIntegral() == *Other.getAsIntegral();
274 
275   case Pack:
276     if (Args.NumArgs != Other.Args.NumArgs) return false;
277     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
278       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
279         return false;
280     return true;
281   }
282 
283   // Suppress warnings.
284   return false;
285 }
286 
getPackExpansionPattern() const287 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
288   assert(isPackExpansion());
289 
290   switch (getKind()) {
291   case Type:
292     return getAsType()->getAs<PackExpansionType>()->getPattern();
293 
294   case Expression:
295     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
296 
297   case TemplateExpansion:
298     return TemplateArgument(getAsTemplateOrTemplatePattern());
299 
300   case Declaration:
301   case Integral:
302   case Pack:
303   case Null:
304   case Template:
305     return TemplateArgument();
306   }
307 
308   return TemplateArgument();
309 }
310 
print(const PrintingPolicy & Policy,llvm::raw_ostream & Out) const311 void TemplateArgument::print(const PrintingPolicy &Policy,
312                              llvm::raw_ostream &Out) const {
313   switch (getKind()) {
314   case Null:
315     Out << "<no value>";
316     break;
317 
318   case Type: {
319     PrintingPolicy SubPolicy(Policy);
320     SubPolicy.SuppressStrongLifetime = true;
321     std::string TypeStr;
322     getAsType().getAsStringInternal(TypeStr, SubPolicy);
323     Out << TypeStr;
324     break;
325   }
326 
327   case Declaration: {
328     bool Unnamed = true;
329     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
330       if (ND->getDeclName()) {
331         Unnamed = false;
332         Out << ND->getNameAsString();
333       }
334     }
335 
336     if (Unnamed) {
337       Out << "<anonymous>";
338     }
339     break;
340   }
341 
342   case Template:
343     getAsTemplate().print(Out, Policy);
344     break;
345 
346   case TemplateExpansion:
347     getAsTemplateOrTemplatePattern().print(Out, Policy);
348     Out << "...";
349     break;
350 
351   case Integral: {
352     printIntegral(*this, Out);
353     break;
354   }
355 
356   case Expression:
357     getAsExpr()->printPretty(Out, 0, Policy);
358     break;
359 
360   case Pack:
361     Out << "<";
362     bool First = true;
363     for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
364          P != PEnd; ++P) {
365       if (First)
366         First = false;
367       else
368         Out << ", ";
369 
370       P->print(Policy, Out);
371     }
372     Out << ">";
373     break;
374   }
375 }
376 
377 //===----------------------------------------------------------------------===//
378 // TemplateArgumentLoc Implementation
379 //===----------------------------------------------------------------------===//
380 
TemplateArgumentLocInfo()381 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
382   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
383 }
384 
getSourceRange() const385 SourceRange TemplateArgumentLoc::getSourceRange() const {
386   switch (Argument.getKind()) {
387   case TemplateArgument::Expression:
388     return getSourceExpression()->getSourceRange();
389 
390   case TemplateArgument::Declaration:
391     return getSourceDeclExpression()->getSourceRange();
392 
393   case TemplateArgument::Type:
394     if (TypeSourceInfo *TSI = getTypeSourceInfo())
395       return TSI->getTypeLoc().getSourceRange();
396     else
397       return SourceRange();
398 
399   case TemplateArgument::Template:
400     if (getTemplateQualifierLoc())
401       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
402                          getTemplateNameLoc());
403     return SourceRange(getTemplateNameLoc());
404 
405   case TemplateArgument::TemplateExpansion:
406     if (getTemplateQualifierLoc())
407       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
408                          getTemplateEllipsisLoc());
409     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
410 
411   case TemplateArgument::Integral:
412   case TemplateArgument::Pack:
413   case TemplateArgument::Null:
414     return SourceRange();
415   }
416 
417   // Silence bonus gcc warning.
418   return SourceRange();
419 }
420 
421 TemplateArgumentLoc
getPackExpansionPattern(SourceLocation & Ellipsis,llvm::Optional<unsigned> & NumExpansions,ASTContext & Context) const422 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
423                                        llvm::Optional<unsigned> &NumExpansions,
424                                              ASTContext &Context) const {
425   assert(Argument.isPackExpansion());
426 
427   switch (Argument.getKind()) {
428   case TemplateArgument::Type: {
429     // FIXME: We shouldn't ever have to worry about missing
430     // type-source info!
431     TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
432     if (!ExpansionTSInfo)
433       ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
434                                                      getArgument().getAsType(),
435                                                          Ellipsis);
436     PackExpansionTypeLoc Expansion
437       = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
438     Ellipsis = Expansion.getEllipsisLoc();
439 
440     TypeLoc Pattern = Expansion.getPatternLoc();
441     NumExpansions = Expansion.getTypePtr()->getNumExpansions();
442 
443     // FIXME: This is horrible. We know where the source location data is for
444     // the pattern, and we have the pattern's type, but we are forced to copy
445     // them into an ASTContext because TypeSourceInfo bundles them together
446     // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
447     TypeSourceInfo *PatternTSInfo
448       = Context.CreateTypeSourceInfo(Pattern.getType(),
449                                      Pattern.getFullDataSize());
450     memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
451            Pattern.getOpaqueData(), Pattern.getFullDataSize());
452     return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
453                                PatternTSInfo);
454   }
455 
456   case TemplateArgument::Expression: {
457     PackExpansionExpr *Expansion
458       = cast<PackExpansionExpr>(Argument.getAsExpr());
459     Expr *Pattern = Expansion->getPattern();
460     Ellipsis = Expansion->getEllipsisLoc();
461     NumExpansions = Expansion->getNumExpansions();
462     return TemplateArgumentLoc(Pattern, Pattern);
463   }
464 
465   case TemplateArgument::TemplateExpansion:
466     Ellipsis = getTemplateEllipsisLoc();
467     NumExpansions = Argument.getNumTemplateExpansions();
468     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
469                                getTemplateQualifierLoc(),
470                                getTemplateNameLoc());
471 
472   case TemplateArgument::Declaration:
473   case TemplateArgument::Template:
474   case TemplateArgument::Integral:
475   case TemplateArgument::Pack:
476   case TemplateArgument::Null:
477     return TemplateArgumentLoc();
478   }
479 
480   return TemplateArgumentLoc();
481 }
482 
operator <<(const DiagnosticBuilder & DB,const TemplateArgument & Arg)483 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
484                                            const TemplateArgument &Arg) {
485   switch (Arg.getKind()) {
486   case TemplateArgument::Null:
487     // This is bad, but not as bad as crashing because of argument
488     // count mismatches.
489     return DB << "(null template argument)";
490 
491   case TemplateArgument::Type:
492     return DB << Arg.getAsType();
493 
494   case TemplateArgument::Declaration:
495     return DB << Arg.getAsDecl();
496 
497   case TemplateArgument::Integral:
498     return DB << Arg.getAsIntegral()->toString(10);
499 
500   case TemplateArgument::Template:
501     return DB << Arg.getAsTemplate();
502 
503   case TemplateArgument::TemplateExpansion:
504     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
505 
506   case TemplateArgument::Expression: {
507     // This shouldn't actually ever happen, so it's okay that we're
508     // regurgitating an expression here.
509     // FIXME: We're guessing at LangOptions!
510     llvm::SmallString<32> Str;
511     llvm::raw_svector_ostream OS(Str);
512     LangOptions LangOpts;
513     LangOpts.CPlusPlus = true;
514     PrintingPolicy Policy(LangOpts);
515     Arg.getAsExpr()->printPretty(OS, 0, Policy);
516     return DB << OS.str();
517   }
518 
519   case TemplateArgument::Pack: {
520     // FIXME: We're guessing at LangOptions!
521     llvm::SmallString<32> Str;
522     llvm::raw_svector_ostream OS(Str);
523     LangOptions LangOpts;
524     LangOpts.CPlusPlus = true;
525     PrintingPolicy Policy(LangOpts);
526     Arg.print(Policy, OS);
527     return DB << OS.str();
528   }
529   }
530 
531   return DB;
532 }
533