]> granicus.if.org Git - clang/blob - lib/AST/TemplateBase.cpp
When default-initializing a TemplateArgumentLocInfo, make sure that we
[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/TypeLoc.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "llvm/ADT/FoldingSet.h"
24
25 using namespace clang;
26
27 //===----------------------------------------------------------------------===//
28 // TemplateArgument Implementation
29 //===----------------------------------------------------------------------===//
30
31 bool TemplateArgument::isDependent() const {
32   switch (getKind()) {
33   case Null:
34     assert(false && "Should not have a NULL template argument");
35     return false;
36
37   case Type:
38     return getAsType()->isDependentType();
39
40   case Template:
41     return getAsTemplate().isDependent();
42
43   case TemplateExpansion:
44     return true;
45
46   case Declaration:
47     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
48       return DC->isDependentContext();
49     return getAsDecl()->getDeclContext()->isDependentContext();
50
51   case Integral:
52     // Never dependent
53     return false;
54
55   case Expression:
56     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
57
58   case Pack:
59     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
60       if (P->isDependent())
61         return true;
62     }
63
64     return false;
65   }
66
67   return false;
68 }
69
70 bool TemplateArgument::isPackExpansion() const {
71   switch (getKind()) {
72   case Null:
73   case Declaration:
74   case Integral:
75   case Pack:    
76   case Template:
77     return false;
78       
79   case TemplateExpansion:
80     return true;
81       
82   case Type:
83     return isa<PackExpansionType>(getAsType());
84           
85   case Expression:
86     return isa<PackExpansionExpr>(getAsExpr());
87   }
88   
89   return false;
90 }
91
92 bool TemplateArgument::containsUnexpandedParameterPack() const {
93   switch (getKind()) {
94   case Null:
95   case Declaration:
96   case Integral:
97   case TemplateExpansion:
98     break;
99
100   case Type:
101     if (getAsType()->containsUnexpandedParameterPack())
102       return true;
103     break;
104
105   case Template:
106     if (getAsTemplate().containsUnexpandedParameterPack())
107       return true;
108     break;
109         
110   case Expression:
111     if (getAsExpr()->containsUnexpandedParameterPack())
112       return true;
113     break;
114
115   case Pack:
116     for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
117       if (P->containsUnexpandedParameterPack())
118         return true;
119
120     break;
121   }
122
123   return false;
124 }
125
126 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
127                                ASTContext &Context) const {
128   ID.AddInteger(Kind);
129   switch (Kind) {
130   case Null:
131     break;
132
133   case Type:
134     getAsType().Profile(ID);
135     break;
136
137   case Declaration:
138     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
139     break;
140
141   case Template:
142   case TemplateExpansion: {
143     TemplateName Template = getAsTemplateOrTemplatePattern();
144     if (TemplateTemplateParmDecl *TTP
145           = dyn_cast_or_null<TemplateTemplateParmDecl>(
146                                                 Template.getAsTemplateDecl())) {
147       ID.AddBoolean(true);
148       ID.AddInteger(TTP->getDepth());
149       ID.AddInteger(TTP->getPosition());
150       ID.AddBoolean(TTP->isParameterPack());
151     } else {
152       ID.AddBoolean(false);
153       ID.AddPointer(Context.getCanonicalTemplateName(Template)
154                                                           .getAsVoidPointer());
155     }
156     break;
157   }
158       
159   case Integral:
160     getAsIntegral()->Profile(ID);
161     getIntegralType().Profile(ID);
162     break;
163
164   case Expression:
165     getAsExpr()->Profile(ID, Context, true);
166     break;
167
168   case Pack:
169     ID.AddInteger(Args.NumArgs);
170     for (unsigned I = 0; I != Args.NumArgs; ++I)
171       Args.Args[I].Profile(ID, Context);
172   }
173 }
174
175 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
176   if (getKind() != Other.getKind()) return false;
177
178   switch (getKind()) {
179   case Null:
180   case Type:
181   case Declaration:
182   case Expression:      
183   case Template:
184   case TemplateExpansion:
185     return TypeOrValue == Other.TypeOrValue;
186
187   case Integral:
188     return getIntegralType() == Other.getIntegralType() &&
189            *getAsIntegral() == *Other.getAsIntegral();
190
191   case Pack:
192     if (Args.NumArgs != Other.Args.NumArgs) return false;
193     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
194       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
195         return false;
196     return true;
197   }
198
199   // Suppress warnings.
200   return false;
201 }
202
203 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
204   assert(isPackExpansion());
205   
206   switch (getKind()) {
207   case Type:
208     return getAsType()->getAs<PackExpansionType>()->getPattern();
209     
210   case Expression:
211     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
212     
213   case TemplateExpansion:
214     return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
215     
216   case Declaration:
217   case Integral:
218   case Pack:
219   case Null:
220   case Template:
221     return TemplateArgument();
222   }
223   
224   return TemplateArgument();
225 }
226
227 void TemplateArgument::print(const PrintingPolicy &Policy, 
228                              llvm::raw_ostream &Out) const {
229   switch (getKind()) {
230   case Null:
231     Out << "<no value>";
232     break;
233     
234   case Type: {
235     std::string TypeStr;
236     getAsType().getAsStringInternal(TypeStr, Policy);
237     Out << TypeStr;
238     break;
239   }
240     
241   case Declaration: {
242     bool Unnamed = true;
243     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
244       if (ND->getDeclName()) {
245         Unnamed = false;
246         Out << ND->getNameAsString();
247       }
248     }
249     
250     if (Unnamed) {
251       Out << "<anonymous>";
252     }
253     break;
254   }
255     
256   case Template:
257     getAsTemplate().print(Out, Policy);
258     break;
259
260   case TemplateExpansion:
261     getAsTemplateOrTemplatePattern().print(Out, Policy);
262     Out << "...";
263     break;
264       
265   case Integral: {
266     Out << getAsIntegral()->toString(10);
267     break;
268   }
269     
270   case Expression:
271     getAsExpr()->printPretty(Out, 0, Policy);
272     break;
273     
274   case Pack:
275     Out << "<";
276     bool First = true;
277     for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
278          P != PEnd; ++P) {
279       if (First)
280         First = false;
281       else
282         Out << ", ";
283       
284       P->print(Policy, Out);
285     }
286     Out << ">";
287     break;        
288   }
289 }
290
291 //===----------------------------------------------------------------------===//
292 // TemplateArgumentLoc Implementation
293 //===----------------------------------------------------------------------===//
294
295 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
296   memset(this, 0, sizeof(TemplateArgumentLocInfo));
297 }
298
299 SourceRange TemplateArgumentLoc::getSourceRange() const {
300   switch (Argument.getKind()) {
301   case TemplateArgument::Expression:
302     return getSourceExpression()->getSourceRange();
303
304   case TemplateArgument::Declaration:
305     return getSourceDeclExpression()->getSourceRange();
306
307   case TemplateArgument::Type:
308     if (TypeSourceInfo *TSI = getTypeSourceInfo())
309       return TSI->getTypeLoc().getSourceRange();
310     else
311       return SourceRange();
312
313   case TemplateArgument::Template:
314     if (getTemplateQualifierRange().isValid())
315       return SourceRange(getTemplateQualifierRange().getBegin(), 
316                          getTemplateNameLoc());
317     return SourceRange(getTemplateNameLoc());
318
319   case TemplateArgument::TemplateExpansion:
320     if (getTemplateQualifierRange().isValid())
321       return SourceRange(getTemplateQualifierRange().getBegin(), 
322                          getTemplateEllipsisLoc());
323     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
324
325   case TemplateArgument::Integral:
326   case TemplateArgument::Pack:
327   case TemplateArgument::Null:
328     return SourceRange();
329   }
330
331   // Silence bonus gcc warning.
332   return SourceRange();
333 }
334
335 TemplateArgumentLoc 
336 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
337                                              ASTContext &Context) const {
338   assert(Argument.isPackExpansion());
339   
340   switch (Argument.getKind()) {
341   case TemplateArgument::Type: {
342     // FIXME: We shouldn't ever have to worry about missing
343     // type-source info!
344     TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
345     if (!ExpansionTSInfo)
346       ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
347                                                      getArgument().getAsType(),
348                                                          Ellipsis);
349     PackExpansionTypeLoc Expansion
350       = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
351     Ellipsis = Expansion.getEllipsisLoc();
352     
353     TypeLoc Pattern = Expansion.getPatternLoc();
354     
355     // FIXME: This is horrible. We know where the source location data is for
356     // the pattern, and we have the pattern's type, but we are forced to copy
357     // them into an ASTContext because TypeSourceInfo bundles them together
358     // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
359     TypeSourceInfo *PatternTSInfo
360       = Context.CreateTypeSourceInfo(Pattern.getType(),
361                                      Pattern.getFullDataSize());
362     memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 
363            Pattern.getOpaqueData(), Pattern.getFullDataSize());
364     return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
365                                PatternTSInfo);
366   }
367       
368   case TemplateArgument::Expression: {
369     PackExpansionExpr *Expansion
370       = cast<PackExpansionExpr>(Argument.getAsExpr());
371     Expr *Pattern = Expansion->getPattern();
372     Ellipsis = Expansion->getEllipsisLoc();
373     return TemplateArgumentLoc(Pattern, Pattern);
374   }
375
376   case TemplateArgument::TemplateExpansion:
377     Ellipsis = getTemplateEllipsisLoc();
378     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
379                                getTemplateQualifierRange(),
380                                getTemplateNameLoc());
381     
382   case TemplateArgument::Declaration:
383   case TemplateArgument::Template:
384   case TemplateArgument::Integral:
385   case TemplateArgument::Pack:
386   case TemplateArgument::Null:
387     return TemplateArgumentLoc();
388   }
389   
390   return TemplateArgumentLoc();
391 }
392
393 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
394                                            const TemplateArgument &Arg) {
395   switch (Arg.getKind()) {
396   case TemplateArgument::Null:
397     // This is bad, but not as bad as crashing because of argument
398     // count mismatches.
399     return DB << "(null template argument)";
400       
401   case TemplateArgument::Type:
402     return DB << Arg.getAsType();
403       
404   case TemplateArgument::Declaration:
405     return DB << Arg.getAsDecl();
406       
407   case TemplateArgument::Integral:
408     return DB << Arg.getAsIntegral()->toString(10);
409       
410   case TemplateArgument::Template:
411     return DB << Arg.getAsTemplate();
412
413   case TemplateArgument::TemplateExpansion:
414     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
415
416   case TemplateArgument::Expression: {
417     // This shouldn't actually ever happen, so it's okay that we're
418     // regurgitating an expression here.
419     // FIXME: We're guessing at LangOptions!
420     llvm::SmallString<32> Str;
421     llvm::raw_svector_ostream OS(Str);
422     LangOptions LangOpts;
423     LangOpts.CPlusPlus = true;
424     PrintingPolicy Policy(LangOpts);
425     Arg.getAsExpr()->printPretty(OS, 0, Policy);
426     return DB << OS.str();
427   }
428       
429   case TemplateArgument::Pack: {
430     // FIXME: We're guessing at LangOptions!
431     llvm::SmallString<32> Str;
432     llvm::raw_svector_ostream OS(Str);
433     LangOptions LangOpts;
434     LangOpts.CPlusPlus = true;
435     PrintingPolicy Policy(LangOpts);
436     Arg.print(Policy, OS);
437     return DB << OS.str();
438   }
439   }
440   
441   return DB;
442 }