]> granicus.if.org Git - clang/blob - lib/AST/TemplateBase.cpp
Push nested-name-specifier source location information into template
[clang] / lib / AST / TemplateBase.cpp
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.
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
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
68 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
107 bool TemplateArgument::isPackExpansion() const {
108   switch (getKind()) {
109   case Null:
110   case Declaration:
111   case Integral:
112   case Pack:    
113   case Template:
114     return false;
115       
116   case TemplateExpansion:
117     return true;
118       
119   case Type:
120     return isa<PackExpansionType>(getAsType());
121           
122   case Expression:
123     return isa<PackExpansionExpr>(getAsExpr());
124   }
125   
126   return false;
127 }
128
129 bool TemplateArgument::containsUnexpandedParameterPack() const {
130   switch (getKind()) {
131   case Null:
132   case Declaration:
133   case Integral:
134   case TemplateExpansion:
135     break;
136
137   case Type:
138     if (getAsType()->containsUnexpandedParameterPack())
139       return true;
140     break;
141
142   case Template:
143     if (getAsTemplate().containsUnexpandedParameterPack())
144       return true;
145     break;
146         
147   case Expression:
148     if (getAsExpr()->containsUnexpandedParameterPack())
149       return true;
150     break;
151
152   case Pack:
153     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
154       if (P->containsUnexpandedParameterPack())
155         return true;
156
157     break;
158   }
159
160   return false;
161 }
162
163 llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
164   assert(Kind == TemplateExpansion);
165   if (TemplateArg.NumExpansions)
166     return TemplateArg.NumExpansions - 1;
167   
168   return llvm::Optional<unsigned>();
169 }
170
171 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
172                                const ASTContext &Context) const {
173   ID.AddInteger(Kind);
174   switch (Kind) {
175   case Null:
176     break;
177
178   case Type:
179     getAsType().Profile(ID);
180     break;
181
182   case Declaration:
183     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
184     break;
185
186   case Template:
187   case TemplateExpansion: {
188     TemplateName Template = getAsTemplateOrTemplatePattern();
189     if (TemplateTemplateParmDecl *TTP
190           = dyn_cast_or_null<TemplateTemplateParmDecl>(
191                                                 Template.getAsTemplateDecl())) {
192       ID.AddBoolean(true);
193       ID.AddInteger(TTP->getDepth());
194       ID.AddInteger(TTP->getPosition());
195       ID.AddBoolean(TTP->isParameterPack());
196     } else {
197       ID.AddBoolean(false);
198       ID.AddPointer(Context.getCanonicalTemplateName(Template)
199                                                           .getAsVoidPointer());
200     }
201     break;
202   }
203       
204   case Integral:
205     getAsIntegral()->Profile(ID);
206     getIntegralType().Profile(ID);
207     break;
208
209   case Expression:
210     getAsExpr()->Profile(ID, Context, true);
211     break;
212
213   case Pack:
214     ID.AddInteger(Args.NumArgs);
215     for (unsigned I = 0; I != Args.NumArgs; ++I)
216       Args.Args[I].Profile(ID, Context);
217   }
218 }
219
220 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
221   if (getKind() != Other.getKind()) return false;
222
223   switch (getKind()) {
224   case Null:
225   case Type:
226   case Declaration:
227   case Expression:      
228   case Template:
229   case TemplateExpansion:
230     return TypeOrValue == Other.TypeOrValue;
231
232   case Integral:
233     return getIntegralType() == Other.getIntegralType() &&
234            *getAsIntegral() == *Other.getAsIntegral();
235
236   case Pack:
237     if (Args.NumArgs != Other.Args.NumArgs) return false;
238     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
239       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
240         return false;
241     return true;
242   }
243
244   // Suppress warnings.
245   return false;
246 }
247
248 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
249   assert(isPackExpansion());
250   
251   switch (getKind()) {
252   case Type:
253     return getAsType()->getAs<PackExpansionType>()->getPattern();
254     
255   case Expression:
256     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
257     
258   case TemplateExpansion:
259     return TemplateArgument(getAsTemplateOrTemplatePattern());
260     
261   case Declaration:
262   case Integral:
263   case Pack:
264   case Null:
265   case Template:
266     return TemplateArgument();
267   }
268   
269   return TemplateArgument();
270 }
271
272 void TemplateArgument::print(const PrintingPolicy &Policy, 
273                              llvm::raw_ostream &Out) const {
274   switch (getKind()) {
275   case Null:
276     Out << "<no value>";
277     break;
278     
279   case Type: {
280     std::string TypeStr;
281     getAsType().getAsStringInternal(TypeStr, Policy);
282     Out << TypeStr;
283     break;
284   }
285     
286   case Declaration: {
287     bool Unnamed = true;
288     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
289       if (ND->getDeclName()) {
290         Unnamed = false;
291         Out << ND->getNameAsString();
292       }
293     }
294     
295     if (Unnamed) {
296       Out << "<anonymous>";
297     }
298     break;
299   }
300     
301   case Template:
302     getAsTemplate().print(Out, Policy);
303     break;
304
305   case TemplateExpansion:
306     getAsTemplateOrTemplatePattern().print(Out, Policy);
307     Out << "...";
308     break;
309       
310   case Integral: {
311     printIntegral(*this, Out);
312     break;
313   }
314     
315   case Expression:
316     getAsExpr()->printPretty(Out, 0, Policy);
317     break;
318     
319   case Pack:
320     Out << "<";
321     bool First = true;
322     for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
323          P != PEnd; ++P) {
324       if (First)
325         First = false;
326       else
327         Out << ", ";
328       
329       P->print(Policy, Out);
330     }
331     Out << ">";
332     break;        
333   }
334 }
335
336 //===----------------------------------------------------------------------===//
337 // TemplateArgumentLoc Implementation
338 //===----------------------------------------------------------------------===//
339
340 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
341   memset(this, 0, sizeof(TemplateArgumentLocInfo));
342 }
343
344 SourceRange TemplateArgumentLoc::getSourceRange() const {
345   switch (Argument.getKind()) {
346   case TemplateArgument::Expression:
347     return getSourceExpression()->getSourceRange();
348
349   case TemplateArgument::Declaration:
350     return getSourceDeclExpression()->getSourceRange();
351
352   case TemplateArgument::Type:
353     if (TypeSourceInfo *TSI = getTypeSourceInfo())
354       return TSI->getTypeLoc().getSourceRange();
355     else
356       return SourceRange();
357
358   case TemplateArgument::Template:
359     if (getTemplateQualifierLoc())
360       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
361                          getTemplateNameLoc());
362     return SourceRange(getTemplateNameLoc());
363
364   case TemplateArgument::TemplateExpansion:
365     if (getTemplateQualifierLoc())
366       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
367                          getTemplateEllipsisLoc());
368     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
369
370   case TemplateArgument::Integral:
371   case TemplateArgument::Pack:
372   case TemplateArgument::Null:
373     return SourceRange();
374   }
375
376   // Silence bonus gcc warning.
377   return SourceRange();
378 }
379
380 TemplateArgumentLoc 
381 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
382                                        llvm::Optional<unsigned> &NumExpansions,
383                                              ASTContext &Context) const {
384   assert(Argument.isPackExpansion());
385   
386   switch (Argument.getKind()) {
387   case TemplateArgument::Type: {
388     // FIXME: We shouldn't ever have to worry about missing
389     // type-source info!
390     TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
391     if (!ExpansionTSInfo)
392       ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
393                                                      getArgument().getAsType(),
394                                                          Ellipsis);
395     PackExpansionTypeLoc Expansion
396       = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
397     Ellipsis = Expansion.getEllipsisLoc();
398     
399     TypeLoc Pattern = Expansion.getPatternLoc();
400     NumExpansions = Expansion.getTypePtr()->getNumExpansions();
401     
402     // FIXME: This is horrible. We know where the source location data is for
403     // the pattern, and we have the pattern's type, but we are forced to copy
404     // them into an ASTContext because TypeSourceInfo bundles them together
405     // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
406     TypeSourceInfo *PatternTSInfo
407       = Context.CreateTypeSourceInfo(Pattern.getType(),
408                                      Pattern.getFullDataSize());
409     memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 
410            Pattern.getOpaqueData(), Pattern.getFullDataSize());
411     return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
412                                PatternTSInfo);
413   }
414       
415   case TemplateArgument::Expression: {
416     PackExpansionExpr *Expansion
417       = cast<PackExpansionExpr>(Argument.getAsExpr());
418     Expr *Pattern = Expansion->getPattern();
419     Ellipsis = Expansion->getEllipsisLoc();
420     NumExpansions = Expansion->getNumExpansions();
421     return TemplateArgumentLoc(Pattern, Pattern);
422   }
423
424   case TemplateArgument::TemplateExpansion:
425     Ellipsis = getTemplateEllipsisLoc();
426     NumExpansions = Argument.getNumTemplateExpansions();
427     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
428                                getTemplateQualifierLoc(),
429                                getTemplateNameLoc());
430     
431   case TemplateArgument::Declaration:
432   case TemplateArgument::Template:
433   case TemplateArgument::Integral:
434   case TemplateArgument::Pack:
435   case TemplateArgument::Null:
436     return TemplateArgumentLoc();
437   }
438   
439   return TemplateArgumentLoc();
440 }
441
442 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
443                                            const TemplateArgument &Arg) {
444   switch (Arg.getKind()) {
445   case TemplateArgument::Null:
446     // This is bad, but not as bad as crashing because of argument
447     // count mismatches.
448     return DB << "(null template argument)";
449       
450   case TemplateArgument::Type:
451     return DB << Arg.getAsType();
452       
453   case TemplateArgument::Declaration:
454     return DB << Arg.getAsDecl();
455       
456   case TemplateArgument::Integral:
457     return DB << Arg.getAsIntegral()->toString(10);
458       
459   case TemplateArgument::Template:
460     return DB << Arg.getAsTemplate();
461
462   case TemplateArgument::TemplateExpansion:
463     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
464
465   case TemplateArgument::Expression: {
466     // This shouldn't actually ever happen, so it's okay that we're
467     // regurgitating an expression here.
468     // FIXME: We're guessing at LangOptions!
469     llvm::SmallString<32> Str;
470     llvm::raw_svector_ostream OS(Str);
471     LangOptions LangOpts;
472     LangOpts.CPlusPlus = true;
473     PrintingPolicy Policy(LangOpts);
474     Arg.getAsExpr()->printPretty(OS, 0, Policy);
475     return DB << OS.str();
476   }
477       
478   case TemplateArgument::Pack: {
479     // FIXME: We're guessing at LangOptions!
480     llvm::SmallString<32> Str;
481     llvm::raw_svector_ostream OS(Str);
482     LangOptions LangOpts;
483     LangOpts.CPlusPlus = true;
484     PrintingPolicy Policy(LangOpts);
485     Arg.print(Policy, OS);
486     return DB << OS.str();
487   }
488   }
489   
490   return DB;
491 }