blob: 6eae6a4192f8b7477743c36708d859543f2d4302 [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();
42
43 case Declaration:
44 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
45 return DC->isDependentContext();
46 return getAsDecl()->getDeclContext()->isDependentContext();
47
48 case Integral:
49 // Never dependent
50 return false;
51
52 case Expression:
53 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
54
55 case Pack:
56 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
57 if (P->isDependent())
58 return true;
59 }
60
61 return false;
62 }
63
64 return false;
65}
66
Douglas Gregor8491ffe2010-12-20 22:05:00 +000067bool TemplateArgument::isPackExpansion() const {
68 switch (getKind()) {
69 case Null:
70 case Declaration:
71 case Integral:
72 case Pack:
73 return false;
74
75 case Type:
Douglas Gregorbe230c32011-01-03 17:17:50 +000076 return isa<PackExpansionType>(getAsType());
Douglas Gregor8491ffe2010-12-20 22:05:00 +000077
78 case Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +000079 return TemplateArg.PackExpansion;
Douglas Gregor8491ffe2010-12-20 22:05:00 +000080
81 case Expression:
Douglas Gregorbe230c32011-01-03 17:17:50 +000082 return isa<PackExpansionExpr>(getAsExpr());
Douglas Gregor8491ffe2010-12-20 22:05:00 +000083 }
84
85 return false;
86}
87
Douglas Gregord0937222010-12-13 22:49:22 +000088bool TemplateArgument::containsUnexpandedParameterPack() const {
89 switch (getKind()) {
90 case Null:
91 case Declaration:
92 case Integral:
93 break;
94
95 case Type:
96 if (getAsType()->containsUnexpandedParameterPack())
97 return true;
98 break;
99
100 case Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000101 if (!TemplateArg.PackExpansion &&
102 getAsTemplate().containsUnexpandedParameterPack())
Douglas Gregord0937222010-12-13 22:49:22 +0000103 return true;
104 break;
105
106 case Expression:
107 if (getAsExpr()->containsUnexpandedParameterPack())
108 return true;
109 break;
110
111 case Pack:
112 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
113 if (P->containsUnexpandedParameterPack())
114 return true;
115
116 break;
117 }
118
119 return false;
120}
121
John McCall275c10a2009-10-29 07:48:15 +0000122void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
123 ASTContext &Context) const {
124 ID.AddInteger(Kind);
125 switch (Kind) {
126 case Null:
127 break;
128
129 case Type:
130 getAsType().Profile(ID);
131 break;
132
133 case Declaration:
134 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
135 break;
136
Douglas Gregor788cd062009-11-11 01:00:40 +0000137 case Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000138 ID.AddBoolean(TemplateArg.PackExpansion);
Douglas Gregor74295b32009-11-23 12:52:47 +0000139 if (TemplateTemplateParmDecl *TTP
140 = dyn_cast_or_null<TemplateTemplateParmDecl>(
141 getAsTemplate().getAsTemplateDecl())) {
142 ID.AddBoolean(true);
143 ID.AddInteger(TTP->getDepth());
144 ID.AddInteger(TTP->getPosition());
Douglas Gregorba68eca2011-01-05 17:40:24 +0000145 ID.AddBoolean(TTP->isParameterPack());
Douglas Gregor74295b32009-11-23 12:52:47 +0000146 } else {
147 ID.AddBoolean(false);
148 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
149 .getAsVoidPointer());
150 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000151 break;
152
John McCall275c10a2009-10-29 07:48:15 +0000153 case Integral:
154 getAsIntegral()->Profile(ID);
155 getIntegralType().Profile(ID);
156 break;
157
158 case Expression:
159 getAsExpr()->Profile(ID, Context, true);
160 break;
161
162 case Pack:
163 ID.AddInteger(Args.NumArgs);
164 for (unsigned I = 0; I != Args.NumArgs; ++I)
165 Args.Args[I].Profile(ID, Context);
166 }
167}
John McCall833ca992009-10-29 08:12:44 +0000168
John McCall33500952010-06-11 00:33:02 +0000169bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
170 if (getKind() != Other.getKind()) return false;
171
172 switch (getKind()) {
173 case Null:
174 case Type:
175 case Declaration:
John McCall33500952010-06-11 00:33:02 +0000176 case Expression:
177 return TypeOrValue == Other.TypeOrValue;
178
Douglas Gregorba68eca2011-01-05 17:40:24 +0000179 case Template:
180 return TemplateArg.Template == Other.TemplateArg.Template &&
181 TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
182
John McCall33500952010-06-11 00:33:02 +0000183 case Integral:
184 return getIntegralType() == Other.getIntegralType() &&
185 *getAsIntegral() == *Other.getAsIntegral();
186
187 case Pack:
188 if (Args.NumArgs != Other.Args.NumArgs) return false;
189 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
190 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
191 return false;
192 return true;
193 }
194
195 // Suppress warnings.
196 return false;
197}
198
Douglas Gregore02e2622010-12-22 21:19:48 +0000199TemplateArgument TemplateArgument::getPackExpansionPattern() const {
200 assert(isPackExpansion());
201
202 switch (getKind()) {
Douglas Gregorba68eca2011-01-05 17:40:24 +0000203 case Type:
204 return getAsType()->getAs<PackExpansionType>()->getPattern();
205
206 case Expression:
207 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
208
209 case Template:
210 return TemplateArgument(getAsTemplate(), false);
211
212 case Declaration:
213 case Integral:
214 case Pack:
215 case Null:
216 return TemplateArgument();
Douglas Gregore02e2622010-12-22 21:19:48 +0000217 }
218
219 return TemplateArgument();
220}
221
Douglas Gregor87dd6972010-12-20 16:52:59 +0000222void TemplateArgument::print(const PrintingPolicy &Policy,
223 llvm::raw_ostream &Out) const {
224 switch (getKind()) {
225 case Null:
226 Out << "<no value>";
227 break;
228
229 case Type: {
230 std::string TypeStr;
231 getAsType().getAsStringInternal(TypeStr, Policy);
232 Out << TypeStr;
233 break;
234 }
235
236 case Declaration: {
237 bool Unnamed = true;
238 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
239 if (ND->getDeclName()) {
240 Unnamed = false;
241 Out << ND->getNameAsString();
242 }
243 }
244
245 if (Unnamed) {
246 Out << "<anonymous>";
247 }
248 break;
249 }
250
251 case Template: {
252 getAsTemplate().print(Out, Policy);
Douglas Gregorba68eca2011-01-05 17:40:24 +0000253 if (TemplateArg.PackExpansion)
254 Out << "...";
Douglas Gregor87dd6972010-12-20 16:52:59 +0000255 break;
256 }
257
258 case Integral: {
259 Out << getAsIntegral()->toString(10);
260 break;
261 }
262
Douglas Gregorba68eca2011-01-05 17:40:24 +0000263 case Expression:
Douglas Gregor87dd6972010-12-20 16:52:59 +0000264 getAsExpr()->printPretty(Out, 0, Policy);
265 break;
Douglas Gregor87dd6972010-12-20 16:52:59 +0000266
267 case Pack:
268 Out << "<";
269 bool First = true;
270 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
271 P != PEnd; ++P) {
272 if (First)
273 First = false;
274 else
275 Out << ", ";
276
277 P->print(Policy, Out);
278 }
279 Out << ">";
280 break;
281 }
282}
283
John McCall833ca992009-10-29 08:12:44 +0000284//===----------------------------------------------------------------------===//
285// TemplateArgumentLoc Implementation
286//===----------------------------------------------------------------------===//
287
John McCall828bff22009-10-29 18:45:58 +0000288SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000289 switch (Argument.getKind()) {
290 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000291 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000292
John McCall833ca992009-10-29 08:12:44 +0000293 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000294 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000295
John McCall828bff22009-10-29 18:45:58 +0000296 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000297 if (TypeSourceInfo *TSI = getTypeSourceInfo())
298 return TSI->getTypeLoc().getSourceRange();
299 else
300 return SourceRange();
301
Douglas Gregorba68eca2011-01-05 17:40:24 +0000302 case TemplateArgument::Template: {
303 SourceLocation End = getTemplateNameLoc();
304 if (getTemplateEllipsisLoc().isValid())
305 End = getTemplateEllipsisLoc();
Douglas Gregor788cd062009-11-11 01:00:40 +0000306 if (getTemplateQualifierRange().isValid())
Douglas Gregorba68eca2011-01-05 17:40:24 +0000307 return SourceRange(getTemplateQualifierRange().getBegin(), End);
308 return SourceRange(getTemplateNameLoc(), End);
309 }
310
John McCall833ca992009-10-29 08:12:44 +0000311 case TemplateArgument::Integral:
312 case TemplateArgument::Pack:
313 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000314 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000315 }
316
317 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000318 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000319}
Douglas Gregora9333192010-05-08 17:41:32 +0000320
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000321TemplateArgumentLoc
322TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
323 ASTContext &Context) const {
324 assert(Argument.isPackExpansion());
325
326 switch (Argument.getKind()) {
327 case TemplateArgument::Type: {
Douglas Gregor03491de2010-12-21 22:10:26 +0000328 // FIXME: We shouldn't ever have to worry about missing
329 // type-source info!
330 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
331 if (!ExpansionTSInfo)
332 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
333 getArgument().getAsType(),
334 Ellipsis);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000335 PackExpansionTypeLoc Expansion
Douglas Gregor03491de2010-12-21 22:10:26 +0000336 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000337 Ellipsis = Expansion.getEllipsisLoc();
338
339 TypeLoc Pattern = Expansion.getPatternLoc();
340
341 // FIXME: This is horrible. We know where the source location data is for
342 // the pattern, and we have the pattern's type, but we are forced to copy
343 // them into an ASTContext because TypeSourceInfo bundles them together
344 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
345 TypeSourceInfo *PatternTSInfo
346 = Context.CreateTypeSourceInfo(Pattern.getType(),
347 Pattern.getFullDataSize());
348 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
349 Pattern.getOpaqueData(), Pattern.getFullDataSize());
350 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
351 PatternTSInfo);
352 }
353
Douglas Gregorbe230c32011-01-03 17:17:50 +0000354 case TemplateArgument::Expression: {
355 Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
356 return TemplateArgumentLoc(Pattern, Pattern);
357 }
358
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000359 case TemplateArgument::Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000360 return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
361 getTemplateQualifierRange(),
362 getTemplateNameLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000363
364 case TemplateArgument::Declaration:
365 case TemplateArgument::Integral:
366 case TemplateArgument::Pack:
367 case TemplateArgument::Null:
368 return TemplateArgumentLoc();
369 }
370
371 return TemplateArgumentLoc();
372}
373
Douglas Gregora9333192010-05-08 17:41:32 +0000374const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
375 const TemplateArgument &Arg) {
376 switch (Arg.getKind()) {
377 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000378 // This is bad, but not as bad as crashing because of argument
379 // count mismatches.
380 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000381
382 case TemplateArgument::Type:
383 return DB << Arg.getAsType();
384
385 case TemplateArgument::Declaration:
386 return DB << Arg.getAsDecl();
387
388 case TemplateArgument::Integral:
389 return DB << Arg.getAsIntegral()->toString(10);
390
391 case TemplateArgument::Template:
Douglas Gregorba68eca2011-01-05 17:40:24 +0000392 DB << Arg.getAsTemplate();
393 if (Arg.isPackExpansion())
394 DB << "...";
395 return DB;
Douglas Gregora9333192010-05-08 17:41:32 +0000396
397 case TemplateArgument::Expression: {
398 // This shouldn't actually ever happen, so it's okay that we're
399 // regurgitating an expression here.
400 // FIXME: We're guessing at LangOptions!
401 llvm::SmallString<32> Str;
402 llvm::raw_svector_ostream OS(Str);
403 LangOptions LangOpts;
404 LangOpts.CPlusPlus = true;
405 PrintingPolicy Policy(LangOpts);
406 Arg.getAsExpr()->printPretty(OS, 0, Policy);
407 return DB << OS.str();
408 }
409
Douglas Gregor87dd6972010-12-20 16:52:59 +0000410 case TemplateArgument::Pack: {
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.print(Policy, OS);
418 return DB << OS.str();
419 }
Douglas Gregora9333192010-05-08 17:41:32 +0000420 }
421
422 return DB;
423}