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