]> granicus.if.org Git - clang/blob - lib/AST/TemplateBase.cpp
Objective-ARC++: infer template type arguments of
[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     PrintingPolicy SubPolicy(Policy);
281     SubPolicy.SuppressStrongLifetime = true;
282     std::string TypeStr;
283     getAsType().getAsStringInternal(TypeStr, SubPolicy);
284     Out << TypeStr;
285     break;
286   }
287     
288   case Declaration: {
289     bool Unnamed = true;
290     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
291       if (ND->getDeclName()) {
292         Unnamed = false;
293         Out << ND->getNameAsString();
294       }
295     }
296     
297     if (Unnamed) {
298       Out << "<anonymous>";
299     }
300     break;
301   }
302     
303   case Template:
304     getAsTemplate().print(Out, Policy);
305     break;
306
307   case TemplateExpansion:
308     getAsTemplateOrTemplatePattern().print(Out, Policy);
309     Out << "...";
310     break;
311       
312   case Integral: {
313     printIntegral(*this, Out);
314     break;
315   }
316     
317   case Expression:
318     getAsExpr()->printPretty(Out, 0, Policy);
319     break;
320     
321   case Pack:
322     Out << "<";
323     bool First = true;
324     for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
325          P != PEnd; ++P) {
326       if (First)
327         First = false;
328       else
329         Out << ", ";
330       
331       P->print(Policy, Out);
332     }
333     Out << ">";
334     break;        
335   }
336 }
337
338 //===----------------------------------------------------------------------===//
339 // TemplateArgumentLoc Implementation
340 //===----------------------------------------------------------------------===//
341
342 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
343   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
344 }
345
346 SourceRange TemplateArgumentLoc::getSourceRange() const {
347   switch (Argument.getKind()) {
348   case TemplateArgument::Expression:
349     return getSourceExpression()->getSourceRange();
350
351   case TemplateArgument::Declaration:
352     return getSourceDeclExpression()->getSourceRange();
353
354   case TemplateArgument::Type:
355     if (TypeSourceInfo *TSI = getTypeSourceInfo())
356       return TSI->getTypeLoc().getSourceRange();
357     else
358       return SourceRange();
359
360   case TemplateArgument::Template:
361     if (getTemplateQualifierLoc())
362       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
363                          getTemplateNameLoc());
364     return SourceRange(getTemplateNameLoc());
365
366   case TemplateArgument::TemplateExpansion:
367     if (getTemplateQualifierLoc())
368       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
369                          getTemplateEllipsisLoc());
370     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
371
372   case TemplateArgument::Integral:
373   case TemplateArgument::Pack:
374   case TemplateArgument::Null:
375     return SourceRange();
376   }
377
378   // Silence bonus gcc warning.
379   return SourceRange();
380 }
381
382 TemplateArgumentLoc 
383 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
384                                        llvm::Optional<unsigned> &NumExpansions,
385                                              ASTContext &Context) const {
386   assert(Argument.isPackExpansion());
387   
388   switch (Argument.getKind()) {
389   case TemplateArgument::Type: {
390     // FIXME: We shouldn't ever have to worry about missing
391     // type-source info!
392     TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
393     if (!ExpansionTSInfo)
394       ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
395                                                      getArgument().getAsType(),
396                                                          Ellipsis);
397     PackExpansionTypeLoc Expansion
398       = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
399     Ellipsis = Expansion.getEllipsisLoc();
400     
401     TypeLoc Pattern = Expansion.getPatternLoc();
402     NumExpansions = Expansion.getTypePtr()->getNumExpansions();
403     
404     // FIXME: This is horrible. We know where the source location data is for
405     // the pattern, and we have the pattern's type, but we are forced to copy
406     // them into an ASTContext because TypeSourceInfo bundles them together
407     // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
408     TypeSourceInfo *PatternTSInfo
409       = Context.CreateTypeSourceInfo(Pattern.getType(),
410                                      Pattern.getFullDataSize());
411     memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 
412            Pattern.getOpaqueData(), Pattern.getFullDataSize());
413     return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
414                                PatternTSInfo);
415   }
416       
417   case TemplateArgument::Expression: {
418     PackExpansionExpr *Expansion
419       = cast<PackExpansionExpr>(Argument.getAsExpr());
420     Expr *Pattern = Expansion->getPattern();
421     Ellipsis = Expansion->getEllipsisLoc();
422     NumExpansions = Expansion->getNumExpansions();
423     return TemplateArgumentLoc(Pattern, Pattern);
424   }
425
426   case TemplateArgument::TemplateExpansion:
427     Ellipsis = getTemplateEllipsisLoc();
428     NumExpansions = Argument.getNumTemplateExpansions();
429     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
430                                getTemplateQualifierLoc(),
431                                getTemplateNameLoc());
432     
433   case TemplateArgument::Declaration:
434   case TemplateArgument::Template:
435   case TemplateArgument::Integral:
436   case TemplateArgument::Pack:
437   case TemplateArgument::Null:
438     return TemplateArgumentLoc();
439   }
440   
441   return TemplateArgumentLoc();
442 }
443
444 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
445                                            const TemplateArgument &Arg) {
446   switch (Arg.getKind()) {
447   case TemplateArgument::Null:
448     // This is bad, but not as bad as crashing because of argument
449     // count mismatches.
450     return DB << "(null template argument)";
451       
452   case TemplateArgument::Type:
453     return DB << Arg.getAsType();
454       
455   case TemplateArgument::Declaration:
456     return DB << Arg.getAsDecl();
457       
458   case TemplateArgument::Integral:
459     return DB << Arg.getAsIntegral()->toString(10);
460       
461   case TemplateArgument::Template:
462     return DB << Arg.getAsTemplate();
463
464   case TemplateArgument::TemplateExpansion:
465     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
466
467   case TemplateArgument::Expression: {
468     // This shouldn't actually ever happen, so it's okay that we're
469     // regurgitating an expression here.
470     // FIXME: We're guessing at LangOptions!
471     llvm::SmallString<32> Str;
472     llvm::raw_svector_ostream OS(Str);
473     LangOptions LangOpts;
474     LangOpts.CPlusPlus = true;
475     PrintingPolicy Policy(LangOpts);
476     Arg.getAsExpr()->printPretty(OS, 0, Policy);
477     return DB << OS.str();
478   }
479       
480   case TemplateArgument::Pack: {
481     // FIXME: We're guessing at LangOptions!
482     llvm::SmallString<32> Str;
483     llvm::raw_svector_ostream OS(Str);
484     LangOptions LangOpts;
485     LangOpts.CPlusPlus = true;
486     PrintingPolicy Policy(LangOpts);
487     Arg.print(Policy, OS);
488     return DB << OS.str();
489   }
490   }
491   
492   return DB;
493 }