blob: bfc834f090030efdf9e1e1b6f62961100d90347b [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 Gregor87dd6972010-12-20 16:52:59 +0000194void TemplateArgument::print(const PrintingPolicy &Policy,
195 llvm::raw_ostream &Out) const {
196 switch (getKind()) {
197 case Null:
198 Out << "<no value>";
199 break;
200
201 case Type: {
202 std::string TypeStr;
203 getAsType().getAsStringInternal(TypeStr, Policy);
204 Out << TypeStr;
205 break;
206 }
207
208 case Declaration: {
209 bool Unnamed = true;
210 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
211 if (ND->getDeclName()) {
212 Unnamed = false;
213 Out << ND->getNameAsString();
214 }
215 }
216
217 if (Unnamed) {
218 Out << "<anonymous>";
219 }
220 break;
221 }
222
223 case Template: {
224 getAsTemplate().print(Out, Policy);
225 break;
226 }
227
228 case Integral: {
229 Out << getAsIntegral()->toString(10);
230 break;
231 }
232
233 case Expression: {
234 // FIXME: This is non-optimal, since we're regurgitating the
235 // expression we were given.
236 getAsExpr()->printPretty(Out, 0, Policy);
237 break;
238 }
239
240 case Pack:
241 Out << "<";
242 bool First = true;
243 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
244 P != PEnd; ++P) {
245 if (First)
246 First = false;
247 else
248 Out << ", ";
249
250 P->print(Policy, Out);
251 }
252 Out << ">";
253 break;
254 }
255}
256
John McCall833ca992009-10-29 08:12:44 +0000257//===----------------------------------------------------------------------===//
258// TemplateArgumentLoc Implementation
259//===----------------------------------------------------------------------===//
260
John McCall828bff22009-10-29 18:45:58 +0000261SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000262 switch (Argument.getKind()) {
263 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000264 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000265
John McCall833ca992009-10-29 08:12:44 +0000266 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000267 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000268
John McCall828bff22009-10-29 18:45:58 +0000269 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000270 if (TypeSourceInfo *TSI = getTypeSourceInfo())
271 return TSI->getTypeLoc().getSourceRange();
272 else
273 return SourceRange();
274
Douglas Gregor788cd062009-11-11 01:00:40 +0000275 case TemplateArgument::Template:
276 if (getTemplateQualifierRange().isValid())
277 return SourceRange(getTemplateQualifierRange().getBegin(),
278 getTemplateNameLoc());
279 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000280
John McCall833ca992009-10-29 08:12:44 +0000281 case TemplateArgument::Integral:
282 case TemplateArgument::Pack:
283 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000284 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000285 }
286
287 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000288 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000289}
Douglas Gregora9333192010-05-08 17:41:32 +0000290
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000291TemplateArgumentLoc
292TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
293 ASTContext &Context) const {
294 assert(Argument.isPackExpansion());
295
296 switch (Argument.getKind()) {
297 case TemplateArgument::Type: {
Douglas Gregor03491de2010-12-21 22:10:26 +0000298 // FIXME: We shouldn't ever have to worry about missing
299 // type-source info!
300 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
301 if (!ExpansionTSInfo)
302 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
303 getArgument().getAsType(),
304 Ellipsis);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000305 PackExpansionTypeLoc Expansion
Douglas Gregor03491de2010-12-21 22:10:26 +0000306 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000307 Ellipsis = Expansion.getEllipsisLoc();
308
309 TypeLoc Pattern = Expansion.getPatternLoc();
310
311 // FIXME: This is horrible. We know where the source location data is for
312 // the pattern, and we have the pattern's type, but we are forced to copy
313 // them into an ASTContext because TypeSourceInfo bundles them together
314 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
315 TypeSourceInfo *PatternTSInfo
316 = Context.CreateTypeSourceInfo(Pattern.getType(),
317 Pattern.getFullDataSize());
318 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
319 Pattern.getOpaqueData(), Pattern.getFullDataSize());
320 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
321 PatternTSInfo);
322 }
323
324 case TemplateArgument::Expression:
325 case TemplateArgument::Template:
326 // FIXME: Variadic templates.
327 llvm_unreachable("Expression and template pack expansions unsupported");
328
329 case TemplateArgument::Declaration:
330 case TemplateArgument::Integral:
331 case TemplateArgument::Pack:
332 case TemplateArgument::Null:
333 return TemplateArgumentLoc();
334 }
335
336 return TemplateArgumentLoc();
337}
338
Douglas Gregora9333192010-05-08 17:41:32 +0000339const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
340 const TemplateArgument &Arg) {
341 switch (Arg.getKind()) {
342 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000343 // This is bad, but not as bad as crashing because of argument
344 // count mismatches.
345 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000346
347 case TemplateArgument::Type:
348 return DB << Arg.getAsType();
349
350 case TemplateArgument::Declaration:
351 return DB << Arg.getAsDecl();
352
353 case TemplateArgument::Integral:
354 return DB << Arg.getAsIntegral()->toString(10);
355
356 case TemplateArgument::Template:
357 return DB << Arg.getAsTemplate();
358
359 case TemplateArgument::Expression: {
360 // This shouldn't actually ever happen, so it's okay that we're
361 // regurgitating an expression here.
362 // FIXME: We're guessing at LangOptions!
363 llvm::SmallString<32> Str;
364 llvm::raw_svector_ostream OS(Str);
365 LangOptions LangOpts;
366 LangOpts.CPlusPlus = true;
367 PrintingPolicy Policy(LangOpts);
368 Arg.getAsExpr()->printPretty(OS, 0, Policy);
369 return DB << OS.str();
370 }
371
Douglas Gregor87dd6972010-12-20 16:52:59 +0000372 case TemplateArgument::Pack: {
373 // FIXME: We're guessing at LangOptions!
374 llvm::SmallString<32> Str;
375 llvm::raw_svector_ostream OS(Str);
376 LangOptions LangOpts;
377 LangOpts.CPlusPlus = true;
378 PrintingPolicy Policy(LangOpts);
379 Arg.print(Policy, OS);
380 return DB << OS.str();
381 }
Douglas Gregora9333192010-05-08 17:41:32 +0000382 }
383
384 return DB;
385}