blob: ee404852262cbb71d610457519226740dd30431f [file] [log] [blame]
John McCall275c10a2009-10-29 07:48:15 +00001//===--- 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
John McCall275c10a2009-10-29 07:48:15 +000015#include "clang/AST/TemplateBase.h"
Douglas Gregor87dd6972010-12-20 16:52:59 +000016#include "clang/AST/ASTContext.h"
John McCall275c10a2009-10-29 07:48:15 +000017#include "clang/AST/DeclBase.h"
Douglas Gregor74295b32009-11-23 12:52:47 +000018#include "clang/AST/DeclTemplate.h"
John McCall275c10a2009-10-29 07:48:15 +000019#include "clang/AST/Expr.h"
John McCall833ca992009-10-29 08:12:44 +000020#include "clang/AST/TypeLoc.h"
Douglas Gregora9333192010-05-08 17:41:32 +000021#include "clang/Basic/Diagnostic.h"
Douglas Gregor87dd6972010-12-20 16:52:59 +000022#include "llvm/ADT/FoldingSet.h"
John McCall275c10a2009-10-29 07:48:15 +000023
24using namespace clang;
25
26//===----------------------------------------------------------------------===//
27// TemplateArgument Implementation
28//===----------------------------------------------------------------------===//
29
Douglas Gregorbebbe0d2010-12-15 01:34:56 +000030bool TemplateArgument::isDependent() const {
31 switch (getKind()) {
32 case Null:
33 assert(false && "Should not have a NULL template argument");
34 return false;
35
36 case Type:
37 return getAsType()->isDependentType();
38
39 case Template:
40 return getAsTemplate().isDependent();
41
42 case Declaration:
43 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
44 return DC->isDependentContext();
45 return getAsDecl()->getDeclContext()->isDependentContext();
46
47 case Integral:
48 // Never dependent
49 return false;
50
51 case Expression:
52 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
53
54 case Pack:
55 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
56 if (P->isDependent())
57 return true;
58 }
59
60 return false;
61 }
62
63 return false;
64}
65
Douglas Gregord0937222010-12-13 22:49:22 +000066bool TemplateArgument::containsUnexpandedParameterPack() const {
67 switch (getKind()) {
68 case Null:
69 case Declaration:
70 case Integral:
71 break;
72
73 case Type:
74 if (getAsType()->containsUnexpandedParameterPack())
75 return true;
76 break;
77
78 case Template:
79 if (getAsTemplate().containsUnexpandedParameterPack())
80 return true;
81 break;
82
83 case Expression:
84 if (getAsExpr()->containsUnexpandedParameterPack())
85 return true;
86 break;
87
88 case Pack:
89 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
90 if (P->containsUnexpandedParameterPack())
91 return true;
92
93 break;
94 }
95
96 return false;
97}
98
John McCall275c10a2009-10-29 07:48:15 +000099void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
100 ASTContext &Context) const {
101 ID.AddInteger(Kind);
102 switch (Kind) {
103 case Null:
104 break;
105
106 case Type:
107 getAsType().Profile(ID);
108 break;
109
110 case Declaration:
111 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
112 break;
113
Douglas Gregor788cd062009-11-11 01:00:40 +0000114 case Template:
Douglas Gregor74295b32009-11-23 12:52:47 +0000115 if (TemplateTemplateParmDecl *TTP
116 = dyn_cast_or_null<TemplateTemplateParmDecl>(
117 getAsTemplate().getAsTemplateDecl())) {
118 ID.AddBoolean(true);
119 ID.AddInteger(TTP->getDepth());
120 ID.AddInteger(TTP->getPosition());
121 } else {
122 ID.AddBoolean(false);
123 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
124 .getAsVoidPointer());
125 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000126 break;
127
John McCall275c10a2009-10-29 07:48:15 +0000128 case Integral:
129 getAsIntegral()->Profile(ID);
130 getIntegralType().Profile(ID);
131 break;
132
133 case Expression:
134 getAsExpr()->Profile(ID, Context, true);
135 break;
136
137 case Pack:
138 ID.AddInteger(Args.NumArgs);
139 for (unsigned I = 0; I != Args.NumArgs; ++I)
140 Args.Args[I].Profile(ID, Context);
141 }
142}
John McCall833ca992009-10-29 08:12:44 +0000143
John McCall33500952010-06-11 00:33:02 +0000144bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
145 if (getKind() != Other.getKind()) return false;
146
147 switch (getKind()) {
148 case Null:
149 case Type:
150 case Declaration:
151 case Template:
152 case Expression:
153 return TypeOrValue == Other.TypeOrValue;
154
155 case Integral:
156 return getIntegralType() == Other.getIntegralType() &&
157 *getAsIntegral() == *Other.getAsIntegral();
158
159 case Pack:
160 if (Args.NumArgs != Other.Args.NumArgs) return false;
161 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
162 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
163 return false;
164 return true;
165 }
166
167 // Suppress warnings.
168 return false;
169}
170
Douglas Gregor87dd6972010-12-20 16:52:59 +0000171void TemplateArgument::print(const PrintingPolicy &Policy,
172 llvm::raw_ostream &Out) const {
173 switch (getKind()) {
174 case Null:
175 Out << "<no value>";
176 break;
177
178 case Type: {
179 std::string TypeStr;
180 getAsType().getAsStringInternal(TypeStr, Policy);
181 Out << TypeStr;
182 break;
183 }
184
185 case Declaration: {
186 bool Unnamed = true;
187 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
188 if (ND->getDeclName()) {
189 Unnamed = false;
190 Out << ND->getNameAsString();
191 }
192 }
193
194 if (Unnamed) {
195 Out << "<anonymous>";
196 }
197 break;
198 }
199
200 case Template: {
201 getAsTemplate().print(Out, Policy);
202 break;
203 }
204
205 case Integral: {
206 Out << getAsIntegral()->toString(10);
207 break;
208 }
209
210 case Expression: {
211 // FIXME: This is non-optimal, since we're regurgitating the
212 // expression we were given.
213 getAsExpr()->printPretty(Out, 0, Policy);
214 break;
215 }
216
217 case Pack:
218 Out << "<";
219 bool First = true;
220 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
221 P != PEnd; ++P) {
222 if (First)
223 First = false;
224 else
225 Out << ", ";
226
227 P->print(Policy, Out);
228 }
229 Out << ">";
230 break;
231 }
232}
233
John McCall833ca992009-10-29 08:12:44 +0000234//===----------------------------------------------------------------------===//
235// TemplateArgumentLoc Implementation
236//===----------------------------------------------------------------------===//
237
John McCall828bff22009-10-29 18:45:58 +0000238SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000239 switch (Argument.getKind()) {
240 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000241 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000242
John McCall833ca992009-10-29 08:12:44 +0000243 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000244 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000245
John McCall828bff22009-10-29 18:45:58 +0000246 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000247 if (TypeSourceInfo *TSI = getTypeSourceInfo())
248 return TSI->getTypeLoc().getSourceRange();
249 else
250 return SourceRange();
251
Douglas Gregor788cd062009-11-11 01:00:40 +0000252 case TemplateArgument::Template:
253 if (getTemplateQualifierRange().isValid())
254 return SourceRange(getTemplateQualifierRange().getBegin(),
255 getTemplateNameLoc());
256 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000257
John McCall833ca992009-10-29 08:12:44 +0000258 case TemplateArgument::Integral:
259 case TemplateArgument::Pack:
260 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000261 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000262 }
263
264 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000265 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000266}
Douglas Gregora9333192010-05-08 17:41:32 +0000267
268const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
269 const TemplateArgument &Arg) {
270 switch (Arg.getKind()) {
271 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000272 // This is bad, but not as bad as crashing because of argument
273 // count mismatches.
274 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000275
276 case TemplateArgument::Type:
277 return DB << Arg.getAsType();
278
279 case TemplateArgument::Declaration:
280 return DB << Arg.getAsDecl();
281
282 case TemplateArgument::Integral:
283 return DB << Arg.getAsIntegral()->toString(10);
284
285 case TemplateArgument::Template:
286 return DB << Arg.getAsTemplate();
287
288 case TemplateArgument::Expression: {
289 // This shouldn't actually ever happen, so it's okay that we're
290 // regurgitating an expression here.
291 // FIXME: We're guessing at LangOptions!
292 llvm::SmallString<32> Str;
293 llvm::raw_svector_ostream OS(Str);
294 LangOptions LangOpts;
295 LangOpts.CPlusPlus = true;
296 PrintingPolicy Policy(LangOpts);
297 Arg.getAsExpr()->printPretty(OS, 0, Policy);
298 return DB << OS.str();
299 }
300
Douglas Gregor87dd6972010-12-20 16:52:59 +0000301 case TemplateArgument::Pack: {
302 // FIXME: We're guessing at LangOptions!
303 llvm::SmallString<32> Str;
304 llvm::raw_svector_ostream OS(Str);
305 LangOptions LangOpts;
306 LangOpts.CPlusPlus = true;
307 PrintingPolicy Policy(LangOpts);
308 Arg.print(Policy, OS);
309 return DB << OS.str();
310 }
Douglas Gregora9333192010-05-08 17:41:32 +0000311 }
312
313 return DB;
314}