TemplateBase.cpp revision a7fc901a2e39bfe55bfcff5934b2d9fdf9656491
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
25using namespace clang;
26
27//===----------------------------------------------------------------------===//
28// TemplateArgument Implementation
29//===----------------------------------------------------------------------===//
30
31bool 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
70bool 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
92bool 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
126void 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
175bool 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
203TemplateArgument 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
227void 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
295SourceRange TemplateArgumentLoc::getSourceRange() const {
296  switch (Argument.getKind()) {
297  case TemplateArgument::Expression:
298    return getSourceExpression()->getSourceRange();
299
300  case TemplateArgument::Declaration:
301    return getSourceDeclExpression()->getSourceRange();
302
303  case TemplateArgument::Type:
304    if (TypeSourceInfo *TSI = getTypeSourceInfo())
305      return TSI->getTypeLoc().getSourceRange();
306    else
307      return SourceRange();
308
309  case TemplateArgument::Template:
310    if (getTemplateQualifierRange().isValid())
311      return SourceRange(getTemplateQualifierRange().getBegin(),
312                         getTemplateNameLoc());
313    return SourceRange(getTemplateNameLoc());
314
315  case TemplateArgument::TemplateExpansion:
316    if (getTemplateQualifierRange().isValid())
317      return SourceRange(getTemplateQualifierRange().getBegin(),
318                         getTemplateEllipsisLoc());
319    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
320
321  case TemplateArgument::Integral:
322  case TemplateArgument::Pack:
323  case TemplateArgument::Null:
324    return SourceRange();
325  }
326
327  // Silence bonus gcc warning.
328  return SourceRange();
329}
330
331TemplateArgumentLoc
332TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
333                                             ASTContext &Context) const {
334  assert(Argument.isPackExpansion());
335
336  switch (Argument.getKind()) {
337  case TemplateArgument::Type: {
338    // FIXME: We shouldn't ever have to worry about missing
339    // type-source info!
340    TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
341    if (!ExpansionTSInfo)
342      ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
343                                                     getArgument().getAsType(),
344                                                         Ellipsis);
345    PackExpansionTypeLoc Expansion
346      = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
347    Ellipsis = Expansion.getEllipsisLoc();
348
349    TypeLoc Pattern = Expansion.getPatternLoc();
350
351    // FIXME: This is horrible. We know where the source location data is for
352    // the pattern, and we have the pattern's type, but we are forced to copy
353    // them into an ASTContext because TypeSourceInfo bundles them together
354    // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
355    TypeSourceInfo *PatternTSInfo
356      = Context.CreateTypeSourceInfo(Pattern.getType(),
357                                     Pattern.getFullDataSize());
358    memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
359           Pattern.getOpaqueData(), Pattern.getFullDataSize());
360    return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
361                               PatternTSInfo);
362  }
363
364  case TemplateArgument::Expression: {
365    Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
366    return TemplateArgumentLoc(Pattern, Pattern);
367  }
368
369  case TemplateArgument::TemplateExpansion:
370    return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
371                               getTemplateQualifierRange(),
372                               getTemplateNameLoc());
373
374  case TemplateArgument::Declaration:
375  case TemplateArgument::Template:
376  case TemplateArgument::Integral:
377  case TemplateArgument::Pack:
378  case TemplateArgument::Null:
379    return TemplateArgumentLoc();
380  }
381
382  return TemplateArgumentLoc();
383}
384
385const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
386                                           const TemplateArgument &Arg) {
387  switch (Arg.getKind()) {
388  case TemplateArgument::Null:
389    // This is bad, but not as bad as crashing because of argument
390    // count mismatches.
391    return DB << "(null template argument)";
392
393  case TemplateArgument::Type:
394    return DB << Arg.getAsType();
395
396  case TemplateArgument::Declaration:
397    return DB << Arg.getAsDecl();
398
399  case TemplateArgument::Integral:
400    return DB << Arg.getAsIntegral()->toString(10);
401
402  case TemplateArgument::Template:
403    return DB << Arg.getAsTemplate();
404
405  case TemplateArgument::TemplateExpansion:
406    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
407
408  case TemplateArgument::Expression: {
409    // This shouldn't actually ever happen, so it's okay that we're
410    // regurgitating an expression here.
411    // FIXME: We're guessing at LangOptions!
412    llvm::SmallString<32> Str;
413    llvm::raw_svector_ostream OS(Str);
414    LangOptions LangOpts;
415    LangOpts.CPlusPlus = true;
416    PrintingPolicy Policy(LangOpts);
417    Arg.getAsExpr()->printPretty(OS, 0, Policy);
418    return DB << OS.str();
419  }
420
421  case TemplateArgument::Pack: {
422    // FIXME: We're guessing at LangOptions!
423    llvm::SmallString<32> Str;
424    llvm::raw_svector_ostream OS(Str);
425    LangOptions LangOpts;
426    LangOpts.CPlusPlus = true;
427    PrintingPolicy Policy(LangOpts);
428    Arg.print(Policy, OS);
429    return DB << OS.str();
430  }
431  }
432
433  return DB;
434}
435