blob: 04e8a389cfb030189bd013e3989f1d9b43cfa080 [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 Gregor8491ffe2010-12-20 22:05:00 +000066bool TemplateArgument::isPackExpansion() const {
67 switch (getKind()) {
68 case Null:
69 case Declaration:
70 case Integral:
71 case Pack:
72 return false;
73
74 case Type:
75 return llvm::isa<PackExpansionType>(getAsType());
76
77 case Template:
78 // FIXME: Template template pack expansions.
79 break;
80
81 case Expression:
82 // FIXME: Expansion pack expansions.
83 break;
84 }
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:
202 case Template:
203 // FIXME: Variadic templates.
204 llvm_unreachable("Expression and template pack expansions unsupported");
205
206 case Declaration:
207 case Integral:
208 case Pack:
209 case Null:
210 return TemplateArgument();
211 }
212
213 return TemplateArgument();
214}
215
Douglas Gregor87dd6972010-12-20 16:52:59 +0000216void TemplateArgument::print(const PrintingPolicy &Policy,
217 llvm::raw_ostream &Out) const {
218 switch (getKind()) {
219 case Null:
220 Out << "<no value>";
221 break;
222
223 case Type: {
224 std::string TypeStr;
225 getAsType().getAsStringInternal(TypeStr, Policy);
226 Out << TypeStr;
227 break;
228 }
229
230 case Declaration: {
231 bool Unnamed = true;
232 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
233 if (ND->getDeclName()) {
234 Unnamed = false;
235 Out << ND->getNameAsString();
236 }
237 }
238
239 if (Unnamed) {
240 Out << "<anonymous>";
241 }
242 break;
243 }
244
245 case Template: {
246 getAsTemplate().print(Out, Policy);
247 break;
248 }
249
250 case Integral: {
251 Out << getAsIntegral()->toString(10);
252 break;
253 }
254
255 case Expression: {
256 // FIXME: This is non-optimal, since we're regurgitating the
257 // expression we were given.
258 getAsExpr()->printPretty(Out, 0, Policy);
259 break;
260 }
261
262 case Pack:
263 Out << "<";
264 bool First = true;
265 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
266 P != PEnd; ++P) {
267 if (First)
268 First = false;
269 else
270 Out << ", ";
271
272 P->print(Policy, Out);
273 }
274 Out << ">";
275 break;
276 }
277}
278
John McCall833ca992009-10-29 08:12:44 +0000279//===----------------------------------------------------------------------===//
280// TemplateArgumentLoc Implementation
281//===----------------------------------------------------------------------===//
282
John McCall828bff22009-10-29 18:45:58 +0000283SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000284 switch (Argument.getKind()) {
285 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000286 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000287
John McCall833ca992009-10-29 08:12:44 +0000288 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000289 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000290
John McCall828bff22009-10-29 18:45:58 +0000291 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000292 if (TypeSourceInfo *TSI = getTypeSourceInfo())
293 return TSI->getTypeLoc().getSourceRange();
294 else
295 return SourceRange();
296
Douglas Gregor788cd062009-11-11 01:00:40 +0000297 case TemplateArgument::Template:
298 if (getTemplateQualifierRange().isValid())
299 return SourceRange(getTemplateQualifierRange().getBegin(),
300 getTemplateNameLoc());
301 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000302
John McCall833ca992009-10-29 08:12:44 +0000303 case TemplateArgument::Integral:
304 case TemplateArgument::Pack:
305 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000306 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000307 }
308
309 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000310 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000311}
Douglas Gregora9333192010-05-08 17:41:32 +0000312
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000313TemplateArgumentLoc
314TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
315 ASTContext &Context) const {
316 assert(Argument.isPackExpansion());
317
318 switch (Argument.getKind()) {
319 case TemplateArgument::Type: {
Douglas Gregor03491de2010-12-21 22:10:26 +0000320 // FIXME: We shouldn't ever have to worry about missing
321 // type-source info!
322 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
323 if (!ExpansionTSInfo)
324 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
325 getArgument().getAsType(),
326 Ellipsis);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000327 PackExpansionTypeLoc Expansion
Douglas Gregor03491de2010-12-21 22:10:26 +0000328 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000329 Ellipsis = Expansion.getEllipsisLoc();
330
331 TypeLoc Pattern = Expansion.getPatternLoc();
332
333 // FIXME: This is horrible. We know where the source location data is for
334 // the pattern, and we have the pattern's type, but we are forced to copy
335 // them into an ASTContext because TypeSourceInfo bundles them together
336 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
337 TypeSourceInfo *PatternTSInfo
338 = Context.CreateTypeSourceInfo(Pattern.getType(),
339 Pattern.getFullDataSize());
340 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
341 Pattern.getOpaqueData(), Pattern.getFullDataSize());
342 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
343 PatternTSInfo);
344 }
345
346 case TemplateArgument::Expression:
347 case TemplateArgument::Template:
348 // FIXME: Variadic templates.
349 llvm_unreachable("Expression and template pack expansions unsupported");
350
351 case TemplateArgument::Declaration:
352 case TemplateArgument::Integral:
353 case TemplateArgument::Pack:
354 case TemplateArgument::Null:
355 return TemplateArgumentLoc();
356 }
357
358 return TemplateArgumentLoc();
359}
360
Douglas Gregora9333192010-05-08 17:41:32 +0000361const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
362 const TemplateArgument &Arg) {
363 switch (Arg.getKind()) {
364 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000365 // This is bad, but not as bad as crashing because of argument
366 // count mismatches.
367 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000368
369 case TemplateArgument::Type:
370 return DB << Arg.getAsType();
371
372 case TemplateArgument::Declaration:
373 return DB << Arg.getAsDecl();
374
375 case TemplateArgument::Integral:
376 return DB << Arg.getAsIntegral()->toString(10);
377
378 case TemplateArgument::Template:
379 return DB << Arg.getAsTemplate();
380
381 case TemplateArgument::Expression: {
382 // This shouldn't actually ever happen, so it's okay that we're
383 // regurgitating an expression here.
384 // FIXME: We're guessing at LangOptions!
385 llvm::SmallString<32> Str;
386 llvm::raw_svector_ostream OS(Str);
387 LangOptions LangOpts;
388 LangOpts.CPlusPlus = true;
389 PrintingPolicy Policy(LangOpts);
390 Arg.getAsExpr()->printPretty(OS, 0, Policy);
391 return DB << OS.str();
392 }
393
Douglas Gregor87dd6972010-12-20 16:52:59 +0000394 case TemplateArgument::Pack: {
395 // FIXME: We're guessing at LangOptions!
396 llvm::SmallString<32> Str;
397 llvm::raw_svector_ostream OS(Str);
398 LangOptions LangOpts;
399 LangOpts.CPlusPlus = true;
400 PrintingPolicy Policy(LangOpts);
401 Arg.print(Policy, OS);
402 return DB << OS.str();
403 }
Douglas Gregora9333192010-05-08 17:41:32 +0000404 }
405
406 return DB;
407}