TemplateBase.cpp revision 67fd1251aad51bb80d050b7fa5e506fef0ec8e02
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
26using namespace clang;
27
28//===----------------------------------------------------------------------===//
29// TemplateArgument Implementation
30//===----------------------------------------------------------------------===//
31
32TemplateArgument 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
43bool 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
82bool 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
104bool 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
138void 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
187bool 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
215TemplateArgument 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
239void 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
307TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
308  memset(this, 0, sizeof(TemplateArgumentLocInfo));
309}
310
311SourceRange 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
347TemplateArgumentLoc
348TemplateArgumentLoc::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
409const 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}
459