blob: de5531f0f715af369c487fd259192dc502949850 [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"
Douglas Gregorbe230c32011-01-03 17:17:50 +000020#include "clang/AST/ExprCXX.h"
John McCall833ca992009-10-29 08:12:44 +000021#include "clang/AST/TypeLoc.h"
Douglas Gregora9333192010-05-08 17:41:32 +000022#include "clang/Basic/Diagnostic.h"
Douglas Gregor87dd6972010-12-20 16:52:59 +000023#include "llvm/ADT/FoldingSet.h"
John McCall275c10a2009-10-29 07:48:15 +000024
25using namespace clang;
26
27//===----------------------------------------------------------------------===//
28// TemplateArgument Implementation
29//===----------------------------------------------------------------------===//
30
Douglas Gregorbebbe0d2010-12-15 01:34:56 +000031bool 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();
Douglas Gregora7fc9012011-01-05 18:58:31 +000042
43 case TemplateExpansion:
44 return true;
45
Douglas Gregorbebbe0d2010-12-15 01:34:56 +000046 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
Douglas Gregor8491ffe2010-12-20 22:05:00 +000070bool TemplateArgument::isPackExpansion() const {
71 switch (getKind()) {
72 case Null:
73 case Declaration:
74 case Integral:
75 case Pack:
Douglas Gregora7fc9012011-01-05 18:58:31 +000076 case Template:
Douglas Gregor8491ffe2010-12-20 22:05:00 +000077 return false;
78
Douglas Gregora7fc9012011-01-05 18:58:31 +000079 case TemplateExpansion:
80 return true;
81
Douglas Gregor8491ffe2010-12-20 22:05:00 +000082 case Type:
Douglas Gregorbe230c32011-01-03 17:17:50 +000083 return isa<PackExpansionType>(getAsType());
Douglas Gregora7fc9012011-01-05 18:58:31 +000084
Douglas Gregor8491ffe2010-12-20 22:05:00 +000085 case Expression:
Douglas Gregorbe230c32011-01-03 17:17:50 +000086 return isa<PackExpansionExpr>(getAsExpr());
Douglas Gregor8491ffe2010-12-20 22:05:00 +000087 }
88
89 return false;
90}
91
Douglas Gregord0937222010-12-13 22:49:22 +000092bool TemplateArgument::containsUnexpandedParameterPack() const {
93 switch (getKind()) {
94 case Null:
95 case Declaration:
96 case Integral:
Douglas Gregora7fc9012011-01-05 18:58:31 +000097 case TemplateExpansion:
Douglas Gregord0937222010-12-13 22:49:22 +000098 break;
99
100 case Type:
101 if (getAsType()->containsUnexpandedParameterPack())
102 return true;
103 break;
104
105 case Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000106 if (getAsTemplate().containsUnexpandedParameterPack())
Douglas Gregord0937222010-12-13 22:49:22 +0000107 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
John McCall275c10a2009-10-29 07:48:15 +0000126void 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
Douglas Gregor788cd062009-11-11 01:00:40 +0000141 case Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000142 case TemplateExpansion: {
143 TemplateName Template = getAsTemplateOrTemplatePattern();
Douglas Gregor74295b32009-11-23 12:52:47 +0000144 if (TemplateTemplateParmDecl *TTP
145 = dyn_cast_or_null<TemplateTemplateParmDecl>(
Douglas Gregora7fc9012011-01-05 18:58:31 +0000146 Template.getAsTemplateDecl())) {
Douglas Gregor74295b32009-11-23 12:52:47 +0000147 ID.AddBoolean(true);
148 ID.AddInteger(TTP->getDepth());
149 ID.AddInteger(TTP->getPosition());
Douglas Gregorba68eca2011-01-05 17:40:24 +0000150 ID.AddBoolean(TTP->isParameterPack());
Douglas Gregor74295b32009-11-23 12:52:47 +0000151 } else {
152 ID.AddBoolean(false);
Douglas Gregora7fc9012011-01-05 18:58:31 +0000153 ID.AddPointer(Context.getCanonicalTemplateName(Template)
154 .getAsVoidPointer());
Douglas Gregor74295b32009-11-23 12:52:47 +0000155 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000156 break;
Douglas Gregora7fc9012011-01-05 18:58:31 +0000157 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000158
John McCall275c10a2009-10-29 07:48:15 +0000159 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}
John McCall833ca992009-10-29 08:12:44 +0000174
John McCall33500952010-06-11 00:33:02 +0000175bool 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:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000182 case Expression:
183 case Template:
184 case TemplateExpansion:
John McCall33500952010-06-11 00:33:02 +0000185 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
Douglas Gregore02e2622010-12-22 21:19:48 +0000203TemplateArgument TemplateArgument::getPackExpansionPattern() const {
204 assert(isPackExpansion());
205
206 switch (getKind()) {
Douglas Gregorba68eca2011-01-05 17:40:24 +0000207 case Type:
208 return getAsType()->getAs<PackExpansionType>()->getPattern();
209
210 case Expression:
211 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
212
Douglas Gregora7fc9012011-01-05 18:58:31 +0000213 case TemplateExpansion:
214 return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
Douglas Gregorba68eca2011-01-05 17:40:24 +0000215
216 case Declaration:
217 case Integral:
218 case Pack:
219 case Null:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000220 case Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000221 return TemplateArgument();
Douglas Gregore02e2622010-12-22 21:19:48 +0000222 }
223
224 return TemplateArgument();
225}
226
Douglas Gregor87dd6972010-12-20 16:52:59 +0000227void 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
Douglas Gregora7fc9012011-01-05 18:58:31 +0000256 case Template:
Douglas Gregor87dd6972010-12-20 16:52:59 +0000257 getAsTemplate().print(Out, Policy);
258 break;
Douglas Gregora7fc9012011-01-05 18:58:31 +0000259
260 case TemplateExpansion:
261 getAsTemplateOrTemplatePattern().print(Out, Policy);
262 Out << "...";
263 break;
264
Douglas Gregor87dd6972010-12-20 16:52:59 +0000265 case Integral: {
266 Out << getAsIntegral()->toString(10);
267 break;
268 }
269
Douglas Gregorba68eca2011-01-05 17:40:24 +0000270 case Expression:
Douglas Gregor87dd6972010-12-20 16:52:59 +0000271 getAsExpr()->printPretty(Out, 0, Policy);
272 break;
Douglas Gregor87dd6972010-12-20 16:52:59 +0000273
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
John McCall833ca992009-10-29 08:12:44 +0000291//===----------------------------------------------------------------------===//
292// TemplateArgumentLoc Implementation
293//===----------------------------------------------------------------------===//
294
John McCall828bff22009-10-29 18:45:58 +0000295SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000296 switch (Argument.getKind()) {
297 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000298 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000299
John McCall833ca992009-10-29 08:12:44 +0000300 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000301 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000302
John McCall828bff22009-10-29 18:45:58 +0000303 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000304 if (TypeSourceInfo *TSI = getTypeSourceInfo())
305 return TSI->getTypeLoc().getSourceRange();
306 else
307 return SourceRange();
308
Douglas Gregora7fc9012011-01-05 18:58:31 +0000309 case TemplateArgument::Template:
Douglas Gregor788cd062009-11-11 01:00:40 +0000310 if (getTemplateQualifierRange().isValid())
Douglas Gregora7fc9012011-01-05 18:58:31 +0000311 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
John McCall833ca992009-10-29 08:12:44 +0000321 case TemplateArgument::Integral:
322 case TemplateArgument::Pack:
323 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000324 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000325 }
326
327 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000328 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000329}
Douglas Gregora9333192010-05-08 17:41:32 +0000330
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000331TemplateArgumentLoc
332TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
333 ASTContext &Context) const {
334 assert(Argument.isPackExpansion());
335
336 switch (Argument.getKind()) {
337 case TemplateArgument::Type: {
Douglas Gregor03491de2010-12-21 22:10:26 +0000338 // 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);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000345 PackExpansionTypeLoc Expansion
Douglas Gregor03491de2010-12-21 22:10:26 +0000346 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000347 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
Douglas Gregorbe230c32011-01-03 17:17:50 +0000364 case TemplateArgument::Expression: {
365 Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
366 return TemplateArgumentLoc(Pattern, Pattern);
367 }
Douglas Gregora7fc9012011-01-05 18:58:31 +0000368
369 case TemplateArgument::TemplateExpansion:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000370 return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
371 getTemplateQualifierRange(),
372 getTemplateNameLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000373
374 case TemplateArgument::Declaration:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000375 case TemplateArgument::Template:
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000376 case TemplateArgument::Integral:
377 case TemplateArgument::Pack:
378 case TemplateArgument::Null:
379 return TemplateArgumentLoc();
380 }
381
382 return TemplateArgumentLoc();
383}
384
Douglas Gregora9333192010-05-08 17:41:32 +0000385const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
386 const TemplateArgument &Arg) {
387 switch (Arg.getKind()) {
388 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000389 // This is bad, but not as bad as crashing because of argument
390 // count mismatches.
391 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000392
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:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000403 return DB << Arg.getAsTemplate();
404
405 case TemplateArgument::TemplateExpansion:
406 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
407
Douglas Gregora9333192010-05-08 17:41:32 +0000408 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
Douglas Gregor87dd6972010-12-20 16:52:59 +0000421 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 }
Douglas Gregora9333192010-05-08 17:41:32 +0000431 }
432
433 return DB;
434}