blob: c9715199612b0d1670c10c5350c74d8bb9a4da22 [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:
79 // FIXME: Template template pack expansions.
80 break;
81
82 case Expression:
Douglas Gregorbe230c32011-01-03 17:17:50 +000083 return isa<PackExpansionExpr>(getAsExpr());
Douglas Gregor8491ffe2010-12-20 22:05:00 +000084 }
85
86 return false;
87}
88
Douglas Gregord0937222010-12-13 22:49:22 +000089bool TemplateArgument::containsUnexpandedParameterPack() const {
90 switch (getKind()) {
91 case Null:
92 case Declaration:
93 case Integral:
94 break;
95
96 case Type:
97 if (getAsType()->containsUnexpandedParameterPack())
98 return true;
99 break;
100
101 case Template:
102 if (getAsTemplate().containsUnexpandedParameterPack())
103 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 Gregor74295b32009-11-23 12:52:47 +0000138 if (TemplateTemplateParmDecl *TTP
139 = dyn_cast_or_null<TemplateTemplateParmDecl>(
140 getAsTemplate().getAsTemplateDecl())) {
141 ID.AddBoolean(true);
142 ID.AddInteger(TTP->getDepth());
143 ID.AddInteger(TTP->getPosition());
144 } else {
145 ID.AddBoolean(false);
146 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
147 .getAsVoidPointer());
148 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000149 break;
150
John McCall275c10a2009-10-29 07:48:15 +0000151 case Integral:
152 getAsIntegral()->Profile(ID);
153 getIntegralType().Profile(ID);
154 break;
155
156 case Expression:
157 getAsExpr()->Profile(ID, Context, true);
158 break;
159
160 case Pack:
161 ID.AddInteger(Args.NumArgs);
162 for (unsigned I = 0; I != Args.NumArgs; ++I)
163 Args.Args[I].Profile(ID, Context);
164 }
165}
John McCall833ca992009-10-29 08:12:44 +0000166
John McCall33500952010-06-11 00:33:02 +0000167bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
168 if (getKind() != Other.getKind()) return false;
169
170 switch (getKind()) {
171 case Null:
172 case Type:
173 case Declaration:
174 case Template:
175 case Expression:
176 return TypeOrValue == Other.TypeOrValue;
177
178 case Integral:
179 return getIntegralType() == Other.getIntegralType() &&
180 *getAsIntegral() == *Other.getAsIntegral();
181
182 case Pack:
183 if (Args.NumArgs != Other.Args.NumArgs) return false;
184 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
185 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
186 return false;
187 return true;
188 }
189
190 // Suppress warnings.
191 return false;
192}
193
Douglas Gregore02e2622010-12-22 21:19:48 +0000194TemplateArgument TemplateArgument::getPackExpansionPattern() const {
195 assert(isPackExpansion());
196
197 switch (getKind()) {
198 case Type:
199 return getAsType()->getAs<PackExpansionType>()->getPattern();
200
201 case Expression:
Douglas Gregorbe230c32011-01-03 17:17:50 +0000202 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
203
Douglas Gregore02e2622010-12-22 21:19:48 +0000204 case Template:
205 // FIXME: Variadic templates.
Douglas Gregorbe230c32011-01-03 17:17:50 +0000206 llvm_unreachable("Template pack expansions unsupported");
Douglas Gregore02e2622010-12-22 21:19:48 +0000207
208 case Declaration:
209 case Integral:
210 case Pack:
211 case Null:
212 return TemplateArgument();
213 }
214
215 return TemplateArgument();
216}
217
Douglas Gregor87dd6972010-12-20 16:52:59 +0000218void TemplateArgument::print(const PrintingPolicy &Policy,
219 llvm::raw_ostream &Out) const {
220 switch (getKind()) {
221 case Null:
222 Out << "<no value>";
223 break;
224
225 case Type: {
226 std::string TypeStr;
227 getAsType().getAsStringInternal(TypeStr, Policy);
228 Out << TypeStr;
229 break;
230 }
231
232 case Declaration: {
233 bool Unnamed = true;
234 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
235 if (ND->getDeclName()) {
236 Unnamed = false;
237 Out << ND->getNameAsString();
238 }
239 }
240
241 if (Unnamed) {
242 Out << "<anonymous>";
243 }
244 break;
245 }
246
247 case Template: {
248 getAsTemplate().print(Out, Policy);
249 break;
250 }
251
252 case Integral: {
253 Out << getAsIntegral()->toString(10);
254 break;
255 }
256
257 case Expression: {
258 // FIXME: This is non-optimal, since we're regurgitating the
259 // expression we were given.
260 getAsExpr()->printPretty(Out, 0, Policy);
261 break;
262 }
263
264 case Pack:
265 Out << "<";
266 bool First = true;
267 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
268 P != PEnd; ++P) {
269 if (First)
270 First = false;
271 else
272 Out << ", ";
273
274 P->print(Policy, Out);
275 }
276 Out << ">";
277 break;
278 }
279}
280
John McCall833ca992009-10-29 08:12:44 +0000281//===----------------------------------------------------------------------===//
282// TemplateArgumentLoc Implementation
283//===----------------------------------------------------------------------===//
284
John McCall828bff22009-10-29 18:45:58 +0000285SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000286 switch (Argument.getKind()) {
287 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000288 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000289
John McCall833ca992009-10-29 08:12:44 +0000290 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000291 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000292
John McCall828bff22009-10-29 18:45:58 +0000293 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000294 if (TypeSourceInfo *TSI = getTypeSourceInfo())
295 return TSI->getTypeLoc().getSourceRange();
296 else
297 return SourceRange();
298
Douglas Gregor788cd062009-11-11 01:00:40 +0000299 case TemplateArgument::Template:
300 if (getTemplateQualifierRange().isValid())
301 return SourceRange(getTemplateQualifierRange().getBegin(),
302 getTemplateNameLoc());
303 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000304
John McCall833ca992009-10-29 08:12:44 +0000305 case TemplateArgument::Integral:
306 case TemplateArgument::Pack:
307 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000308 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000309 }
310
311 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000312 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000313}
Douglas Gregora9333192010-05-08 17:41:32 +0000314
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000315TemplateArgumentLoc
316TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
317 ASTContext &Context) const {
318 assert(Argument.isPackExpansion());
319
320 switch (Argument.getKind()) {
321 case TemplateArgument::Type: {
Douglas Gregor03491de2010-12-21 22:10:26 +0000322 // FIXME: We shouldn't ever have to worry about missing
323 // type-source info!
324 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
325 if (!ExpansionTSInfo)
326 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
327 getArgument().getAsType(),
328 Ellipsis);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000329 PackExpansionTypeLoc Expansion
Douglas Gregor03491de2010-12-21 22:10:26 +0000330 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000331 Ellipsis = Expansion.getEllipsisLoc();
332
333 TypeLoc Pattern = Expansion.getPatternLoc();
334
335 // FIXME: This is horrible. We know where the source location data is for
336 // the pattern, and we have the pattern's type, but we are forced to copy
337 // them into an ASTContext because TypeSourceInfo bundles them together
338 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
339 TypeSourceInfo *PatternTSInfo
340 = Context.CreateTypeSourceInfo(Pattern.getType(),
341 Pattern.getFullDataSize());
342 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
343 Pattern.getOpaqueData(), Pattern.getFullDataSize());
344 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
345 PatternTSInfo);
346 }
347
Douglas Gregorbe230c32011-01-03 17:17:50 +0000348 case TemplateArgument::Expression: {
349 Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
350 return TemplateArgumentLoc(Pattern, Pattern);
351 }
352
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000353 case TemplateArgument::Template:
354 // FIXME: Variadic templates.
Douglas Gregorbe230c32011-01-03 17:17:50 +0000355 llvm_unreachable("Template pack expansions unsupported");
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000356
357 case TemplateArgument::Declaration:
358 case TemplateArgument::Integral:
359 case TemplateArgument::Pack:
360 case TemplateArgument::Null:
361 return TemplateArgumentLoc();
362 }
363
364 return TemplateArgumentLoc();
365}
366
Douglas Gregora9333192010-05-08 17:41:32 +0000367const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
368 const TemplateArgument &Arg) {
369 switch (Arg.getKind()) {
370 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000371 // This is bad, but not as bad as crashing because of argument
372 // count mismatches.
373 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000374
375 case TemplateArgument::Type:
376 return DB << Arg.getAsType();
377
378 case TemplateArgument::Declaration:
379 return DB << Arg.getAsDecl();
380
381 case TemplateArgument::Integral:
382 return DB << Arg.getAsIntegral()->toString(10);
383
384 case TemplateArgument::Template:
385 return DB << Arg.getAsTemplate();
386
387 case TemplateArgument::Expression: {
388 // This shouldn't actually ever happen, so it's okay that we're
389 // regurgitating an expression here.
390 // FIXME: We're guessing at LangOptions!
391 llvm::SmallString<32> Str;
392 llvm::raw_svector_ostream OS(Str);
393 LangOptions LangOpts;
394 LangOpts.CPlusPlus = true;
395 PrintingPolicy Policy(LangOpts);
396 Arg.getAsExpr()->printPretty(OS, 0, Policy);
397 return DB << OS.str();
398 }
399
Douglas Gregor87dd6972010-12-20 16:52:59 +0000400 case TemplateArgument::Pack: {
401 // FIXME: We're guessing at LangOptions!
402 llvm::SmallString<32> Str;
403 llvm::raw_svector_ostream OS(Str);
404 LangOptions LangOpts;
405 LangOpts.CPlusPlus = true;
406 PrintingPolicy Policy(LangOpts);
407 Arg.print(Policy, OS);
408 return DB << OS.str();
409 }
Douglas Gregora9333192010-05-08 17:41:32 +0000410 }
411
412 return DB;
413}