TemplateBase.cpp revision bebbe0d9b7568ce43a464286bee49429489ef483
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 "llvm/ADT/FoldingSet.h"
16#include "clang/AST/TemplateBase.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/TypeLoc.h"
21#include "clang/Basic/Diagnostic.h"
22
23using namespace clang;
24
25//===----------------------------------------------------------------------===//
26// TemplateArgument Implementation
27//===----------------------------------------------------------------------===//
28
29bool TemplateArgument::isDependent() const {
30  switch (getKind()) {
31  case Null:
32    assert(false && "Should not have a NULL template argument");
33    return false;
34
35  case Type:
36    return getAsType()->isDependentType();
37
38  case Template:
39    return getAsTemplate().isDependent();
40
41  case Declaration:
42    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
43      return DC->isDependentContext();
44    return getAsDecl()->getDeclContext()->isDependentContext();
45
46  case Integral:
47    // Never dependent
48    return false;
49
50  case Expression:
51    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
52
53  case Pack:
54    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
55      if (P->isDependent())
56        return true;
57    }
58
59    return false;
60  }
61
62  return false;
63}
64
65bool TemplateArgument::containsUnexpandedParameterPack() const {
66  switch (getKind()) {
67  case Null:
68  case Declaration:
69  case Integral:
70    break;
71
72  case Type:
73    if (getAsType()->containsUnexpandedParameterPack())
74      return true;
75    break;
76
77  case Template:
78    if (getAsTemplate().containsUnexpandedParameterPack())
79      return true;
80    break;
81
82  case Expression:
83    if (getAsExpr()->containsUnexpandedParameterPack())
84      return true;
85    break;
86
87  case Pack:
88    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
89      if (P->containsUnexpandedParameterPack())
90        return true;
91
92    break;
93  }
94
95  return false;
96}
97
98void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
99                               ASTContext &Context) const {
100  ID.AddInteger(Kind);
101  switch (Kind) {
102  case Null:
103    break;
104
105  case Type:
106    getAsType().Profile(ID);
107    break;
108
109  case Declaration:
110    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
111    break;
112
113  case Template:
114    if (TemplateTemplateParmDecl *TTP
115          = dyn_cast_or_null<TemplateTemplateParmDecl>(
116                                       getAsTemplate().getAsTemplateDecl())) {
117      ID.AddBoolean(true);
118      ID.AddInteger(TTP->getDepth());
119      ID.AddInteger(TTP->getPosition());
120    } else {
121      ID.AddBoolean(false);
122      ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
123                      .getAsVoidPointer());
124    }
125    break;
126
127  case Integral:
128    getAsIntegral()->Profile(ID);
129    getIntegralType().Profile(ID);
130    break;
131
132  case Expression:
133    getAsExpr()->Profile(ID, Context, true);
134    break;
135
136  case Pack:
137    ID.AddInteger(Args.NumArgs);
138    for (unsigned I = 0; I != Args.NumArgs; ++I)
139      Args.Args[I].Profile(ID, Context);
140  }
141}
142
143bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
144  if (getKind() != Other.getKind()) return false;
145
146  switch (getKind()) {
147  case Null:
148  case Type:
149  case Declaration:
150  case Template:
151  case Expression:
152    return TypeOrValue == Other.TypeOrValue;
153
154  case Integral:
155    return getIntegralType() == Other.getIntegralType() &&
156           *getAsIntegral() == *Other.getAsIntegral();
157
158  case Pack:
159    if (Args.NumArgs != Other.Args.NumArgs) return false;
160    for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
161      if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
162        return false;
163    return true;
164  }
165
166  // Suppress warnings.
167  return false;
168}
169
170//===----------------------------------------------------------------------===//
171// TemplateArgumentLoc Implementation
172//===----------------------------------------------------------------------===//
173
174SourceRange TemplateArgumentLoc::getSourceRange() const {
175  switch (Argument.getKind()) {
176  case TemplateArgument::Expression:
177    return getSourceExpression()->getSourceRange();
178
179  case TemplateArgument::Declaration:
180    return getSourceDeclExpression()->getSourceRange();
181
182  case TemplateArgument::Type:
183    if (TypeSourceInfo *TSI = getTypeSourceInfo())
184      return TSI->getTypeLoc().getSourceRange();
185    else
186      return SourceRange();
187
188  case TemplateArgument::Template:
189    if (getTemplateQualifierRange().isValid())
190      return SourceRange(getTemplateQualifierRange().getBegin(),
191                         getTemplateNameLoc());
192    return SourceRange(getTemplateNameLoc());
193
194  case TemplateArgument::Integral:
195  case TemplateArgument::Pack:
196  case TemplateArgument::Null:
197    return SourceRange();
198  }
199
200  // Silence bonus gcc warning.
201  return SourceRange();
202}
203
204const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
205                                           const TemplateArgument &Arg) {
206  switch (Arg.getKind()) {
207  case TemplateArgument::Null:
208    // This is bad, but not as bad as crashing because of argument
209    // count mismatches.
210    return DB << "(null template argument)";
211
212  case TemplateArgument::Type:
213    return DB << Arg.getAsType();
214
215  case TemplateArgument::Declaration:
216    return DB << Arg.getAsDecl();
217
218  case TemplateArgument::Integral:
219    return DB << Arg.getAsIntegral()->toString(10);
220
221  case TemplateArgument::Template:
222    return DB << Arg.getAsTemplate();
223
224  case TemplateArgument::Expression: {
225    // This shouldn't actually ever happen, so it's okay that we're
226    // regurgitating an expression here.
227    // FIXME: We're guessing at LangOptions!
228    llvm::SmallString<32> Str;
229    llvm::raw_svector_ostream OS(Str);
230    LangOptions LangOpts;
231    LangOpts.CPlusPlus = true;
232    PrintingPolicy Policy(LangOpts);
233    Arg.getAsExpr()->printPretty(OS, 0, Policy);
234    return DB << OS.str();
235  }
236
237  case TemplateArgument::Pack:
238    // FIXME: Format arguments in a list!
239    return DB << "<parameter pack>";
240  }
241
242  return DB;
243}
244