1 //===--- 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
15 #include "clang/AST/TemplateBase.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/Type.h"
22 #include "clang/AST/TypeLoc.h"
23 #include "clang/Basic/Diagnostic.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/ADT/SmallString.h"
26 #include <algorithm>
27 #include <cctype>
28
29 using namespace clang;
30
31 /// \brief Print a template integral argument value.
32 ///
33 /// \param TemplArg the TemplateArgument instance to print.
34 ///
35 /// \param Out the raw_ostream instance to use for printing.
printIntegral(const TemplateArgument & TemplArg,raw_ostream & Out)36 static void printIntegral(const TemplateArgument &TemplArg,
37 raw_ostream &Out) {
38 const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
39 const llvm::APSInt *Val = TemplArg.getAsIntegral();
40
41 if (T->isBooleanType()) {
42 Out << (Val->getBoolValue() ? "true" : "false");
43 } else if (T->isCharType()) {
44 const char Ch = Val->getZExtValue();
45 Out << ((Ch == '\'') ? "'\\" : "'");
46 Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
47 Out << "'";
48 } else {
49 Out << Val->toString(10);
50 }
51 }
52
53 //===----------------------------------------------------------------------===//
54 // TemplateArgument Implementation
55 //===----------------------------------------------------------------------===//
56
CreatePackCopy(ASTContext & Context,const TemplateArgument * Args,unsigned NumArgs)57 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
58 const TemplateArgument *Args,
59 unsigned NumArgs) {
60 if (NumArgs == 0)
61 return TemplateArgument(0, 0);
62
63 TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
64 std::copy(Args, Args + NumArgs, Storage);
65 return TemplateArgument(Storage, NumArgs);
66 }
67
isDependent() const68 bool TemplateArgument::isDependent() const {
69 switch (getKind()) {
70 case Null:
71 llvm_unreachable("Should not have a NULL template argument");
72
73 case Type:
74 return getAsType()->isDependentType();
75
76 case Template:
77 return getAsTemplate().isDependent();
78
79 case TemplateExpansion:
80 return true;
81
82 case Declaration:
83 if (Decl *D = getAsDecl()) {
84 if (DeclContext *DC = dyn_cast<DeclContext>(D))
85 return DC->isDependentContext();
86 return D->getDeclContext()->isDependentContext();
87 }
88
89 return false;
90
91 case Integral:
92 // Never dependent
93 return false;
94
95 case Expression:
96 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
97
98 case Pack:
99 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
100 if (P->isDependent())
101 return true;
102 }
103
104 return false;
105 }
106
107 llvm_unreachable("Invalid TemplateArgument Kind!");
108 }
109
isInstantiationDependent() const110 bool TemplateArgument::isInstantiationDependent() const {
111 switch (getKind()) {
112 case Null:
113 llvm_unreachable("Should not have a NULL template argument");
114
115 case Type:
116 return getAsType()->isInstantiationDependentType();
117
118 case Template:
119 return getAsTemplate().isInstantiationDependent();
120
121 case TemplateExpansion:
122 return true;
123
124 case Declaration:
125 if (Decl *D = getAsDecl()) {
126 if (DeclContext *DC = dyn_cast<DeclContext>(D))
127 return DC->isDependentContext();
128 return D->getDeclContext()->isDependentContext();
129 }
130 return false;
131
132 case Integral:
133 // Never dependent
134 return false;
135
136 case Expression:
137 return getAsExpr()->isInstantiationDependent();
138
139 case Pack:
140 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
141 if (P->isInstantiationDependent())
142 return true;
143 }
144
145 return false;
146 }
147
148 llvm_unreachable("Invalid TemplateArgument Kind!");
149 }
150
isPackExpansion() const151 bool TemplateArgument::isPackExpansion() const {
152 switch (getKind()) {
153 case Null:
154 case Declaration:
155 case Integral:
156 case Pack:
157 case Template:
158 return false;
159
160 case TemplateExpansion:
161 return true;
162
163 case Type:
164 return isa<PackExpansionType>(getAsType());
165
166 case Expression:
167 return isa<PackExpansionExpr>(getAsExpr());
168 }
169
170 llvm_unreachable("Invalid TemplateArgument Kind!");
171 }
172
containsUnexpandedParameterPack() const173 bool TemplateArgument::containsUnexpandedParameterPack() const {
174 switch (getKind()) {
175 case Null:
176 case Declaration:
177 case Integral:
178 case TemplateExpansion:
179 break;
180
181 case Type:
182 if (getAsType()->containsUnexpandedParameterPack())
183 return true;
184 break;
185
186 case Template:
187 if (getAsTemplate().containsUnexpandedParameterPack())
188 return true;
189 break;
190
191 case Expression:
192 if (getAsExpr()->containsUnexpandedParameterPack())
193 return true;
194 break;
195
196 case Pack:
197 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
198 if (P->containsUnexpandedParameterPack())
199 return true;
200
201 break;
202 }
203
204 return false;
205 }
206
getNumTemplateExpansions() const207 llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
208 assert(Kind == TemplateExpansion);
209 if (TemplateArg.NumExpansions)
210 return TemplateArg.NumExpansions - 1;
211
212 return llvm::Optional<unsigned>();
213 }
214
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context) const215 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
216 const ASTContext &Context) const {
217 ID.AddInteger(Kind);
218 switch (Kind) {
219 case Null:
220 break;
221
222 case Type:
223 getAsType().Profile(ID);
224 break;
225
226 case Declaration:
227 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
228 break;
229
230 case Template:
231 case TemplateExpansion: {
232 TemplateName Template = getAsTemplateOrTemplatePattern();
233 if (TemplateTemplateParmDecl *TTP
234 = dyn_cast_or_null<TemplateTemplateParmDecl>(
235 Template.getAsTemplateDecl())) {
236 ID.AddBoolean(true);
237 ID.AddInteger(TTP->getDepth());
238 ID.AddInteger(TTP->getPosition());
239 ID.AddBoolean(TTP->isParameterPack());
240 } else {
241 ID.AddBoolean(false);
242 ID.AddPointer(Context.getCanonicalTemplateName(Template)
243 .getAsVoidPointer());
244 }
245 break;
246 }
247
248 case Integral:
249 getAsIntegral()->Profile(ID);
250 getIntegralType().Profile(ID);
251 break;
252
253 case Expression:
254 getAsExpr()->Profile(ID, Context, true);
255 break;
256
257 case Pack:
258 ID.AddInteger(Args.NumArgs);
259 for (unsigned I = 0; I != Args.NumArgs; ++I)
260 Args.Args[I].Profile(ID, Context);
261 }
262 }
263
structurallyEquals(const TemplateArgument & Other) const264 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
265 if (getKind() != Other.getKind()) return false;
266
267 switch (getKind()) {
268 case Null:
269 case Type:
270 case Declaration:
271 case Expression:
272 case Template:
273 case TemplateExpansion:
274 return TypeOrValue == Other.TypeOrValue;
275
276 case Integral:
277 return getIntegralType() == Other.getIntegralType() &&
278 *getAsIntegral() == *Other.getAsIntegral();
279
280 case Pack:
281 if (Args.NumArgs != Other.Args.NumArgs) return false;
282 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
283 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
284 return false;
285 return true;
286 }
287
288 llvm_unreachable("Invalid TemplateArgument Kind!");
289 }
290
getPackExpansionPattern() const291 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
292 assert(isPackExpansion());
293
294 switch (getKind()) {
295 case Type:
296 return getAsType()->getAs<PackExpansionType>()->getPattern();
297
298 case Expression:
299 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
300
301 case TemplateExpansion:
302 return TemplateArgument(getAsTemplateOrTemplatePattern());
303
304 case Declaration:
305 case Integral:
306 case Pack:
307 case Null:
308 case Template:
309 return TemplateArgument();
310 }
311
312 llvm_unreachable("Invalid TemplateArgument Kind!");
313 }
314
print(const PrintingPolicy & Policy,raw_ostream & Out) const315 void TemplateArgument::print(const PrintingPolicy &Policy,
316 raw_ostream &Out) const {
317 switch (getKind()) {
318 case Null:
319 Out << "<no value>";
320 break;
321
322 case Type: {
323 PrintingPolicy SubPolicy(Policy);
324 SubPolicy.SuppressStrongLifetime = true;
325 std::string TypeStr;
326 getAsType().getAsStringInternal(TypeStr, SubPolicy);
327 Out << TypeStr;
328 break;
329 }
330
331 case Declaration: {
332 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
333 if (ND->getDeclName()) {
334 Out << *ND;
335 } else {
336 Out << "<anonymous>";
337 }
338 } else {
339 Out << "nullptr";
340 }
341 break;
342 }
343
344 case Template:
345 getAsTemplate().print(Out, Policy);
346 break;
347
348 case TemplateExpansion:
349 getAsTemplateOrTemplatePattern().print(Out, Policy);
350 Out << "...";
351 break;
352
353 case Integral: {
354 printIntegral(*this, Out);
355 break;
356 }
357
358 case Expression:
359 getAsExpr()->printPretty(Out, 0, Policy);
360 break;
361
362 case Pack:
363 Out << "<";
364 bool First = true;
365 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
366 P != PEnd; ++P) {
367 if (First)
368 First = false;
369 else
370 Out << ", ";
371
372 P->print(Policy, Out);
373 }
374 Out << ">";
375 break;
376 }
377 }
378
379 //===----------------------------------------------------------------------===//
380 // TemplateArgumentLoc Implementation
381 //===----------------------------------------------------------------------===//
382
TemplateArgumentLocInfo()383 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
384 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
385 }
386
getSourceRange() const387 SourceRange TemplateArgumentLoc::getSourceRange() const {
388 switch (Argument.getKind()) {
389 case TemplateArgument::Expression:
390 return getSourceExpression()->getSourceRange();
391
392 case TemplateArgument::Declaration:
393 return getSourceDeclExpression()->getSourceRange();
394
395 case TemplateArgument::Type:
396 if (TypeSourceInfo *TSI = getTypeSourceInfo())
397 return TSI->getTypeLoc().getSourceRange();
398 else
399 return SourceRange();
400
401 case TemplateArgument::Template:
402 if (getTemplateQualifierLoc())
403 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
404 getTemplateNameLoc());
405 return SourceRange(getTemplateNameLoc());
406
407 case TemplateArgument::TemplateExpansion:
408 if (getTemplateQualifierLoc())
409 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
410 getTemplateEllipsisLoc());
411 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
412
413 case TemplateArgument::Integral:
414 case TemplateArgument::Pack:
415 case TemplateArgument::Null:
416 return SourceRange();
417 }
418
419 llvm_unreachable("Invalid TemplateArgument Kind!");
420 }
421
422 TemplateArgumentLoc
getPackExpansionPattern(SourceLocation & Ellipsis,llvm::Optional<unsigned> & NumExpansions,ASTContext & Context) const423 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
424 llvm::Optional<unsigned> &NumExpansions,
425 ASTContext &Context) const {
426 assert(Argument.isPackExpansion());
427
428 switch (Argument.getKind()) {
429 case TemplateArgument::Type: {
430 // FIXME: We shouldn't ever have to worry about missing
431 // type-source info!
432 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
433 if (!ExpansionTSInfo)
434 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
435 getArgument().getAsType(),
436 Ellipsis);
437 PackExpansionTypeLoc Expansion
438 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
439 Ellipsis = Expansion.getEllipsisLoc();
440
441 TypeLoc Pattern = Expansion.getPatternLoc();
442 NumExpansions = Expansion.getTypePtr()->getNumExpansions();
443
444 // FIXME: This is horrible. We know where the source location data is for
445 // the pattern, and we have the pattern's type, but we are forced to copy
446 // them into an ASTContext because TypeSourceInfo bundles them together
447 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
448 TypeSourceInfo *PatternTSInfo
449 = Context.CreateTypeSourceInfo(Pattern.getType(),
450 Pattern.getFullDataSize());
451 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
452 Pattern.getOpaqueData(), Pattern.getFullDataSize());
453 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
454 PatternTSInfo);
455 }
456
457 case TemplateArgument::Expression: {
458 PackExpansionExpr *Expansion
459 = cast<PackExpansionExpr>(Argument.getAsExpr());
460 Expr *Pattern = Expansion->getPattern();
461 Ellipsis = Expansion->getEllipsisLoc();
462 NumExpansions = Expansion->getNumExpansions();
463 return TemplateArgumentLoc(Pattern, Pattern);
464 }
465
466 case TemplateArgument::TemplateExpansion:
467 Ellipsis = getTemplateEllipsisLoc();
468 NumExpansions = Argument.getNumTemplateExpansions();
469 return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
470 getTemplateQualifierLoc(),
471 getTemplateNameLoc());
472
473 case TemplateArgument::Declaration:
474 case TemplateArgument::Template:
475 case TemplateArgument::Integral:
476 case TemplateArgument::Pack:
477 case TemplateArgument::Null:
478 return TemplateArgumentLoc();
479 }
480
481 llvm_unreachable("Invalid TemplateArgument Kind!");
482 }
483
operator <<(const DiagnosticBuilder & DB,const TemplateArgument & Arg)484 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
485 const TemplateArgument &Arg) {
486 switch (Arg.getKind()) {
487 case TemplateArgument::Null:
488 // This is bad, but not as bad as crashing because of argument
489 // count mismatches.
490 return DB << "(null template argument)";
491
492 case TemplateArgument::Type:
493 return DB << Arg.getAsType();
494
495 case TemplateArgument::Declaration:
496 if (Decl *D = Arg.getAsDecl())
497 return DB << D;
498 return DB << "nullptr";
499
500 case TemplateArgument::Integral:
501 return DB << Arg.getAsIntegral()->toString(10);
502
503 case TemplateArgument::Template:
504 return DB << Arg.getAsTemplate();
505
506 case TemplateArgument::TemplateExpansion:
507 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
508
509 case TemplateArgument::Expression: {
510 // This shouldn't actually ever happen, so it's okay that we're
511 // regurgitating an expression here.
512 // FIXME: We're guessing at LangOptions!
513 SmallString<32> Str;
514 llvm::raw_svector_ostream OS(Str);
515 LangOptions LangOpts;
516 LangOpts.CPlusPlus = true;
517 PrintingPolicy Policy(LangOpts);
518 Arg.getAsExpr()->printPretty(OS, 0, Policy);
519 return DB << OS.str();
520 }
521
522 case TemplateArgument::Pack: {
523 // FIXME: We're guessing at LangOptions!
524 SmallString<32> Str;
525 llvm::raw_svector_ostream OS(Str);
526 LangOptions LangOpts;
527 LangOpts.CPlusPlus = true;
528 PrintingPolicy Policy(LangOpts);
529 Arg.print(Policy, OS);
530 return DB << OS.str();
531 }
532 }
533
534 llvm_unreachable("Invalid TemplateArgument Kind!");
535 }
536
537 const ASTTemplateArgumentListInfo *
Create(ASTContext & C,const TemplateArgumentListInfo & List)538 ASTTemplateArgumentListInfo::Create(ASTContext &C,
539 const TemplateArgumentListInfo &List) {
540 std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
541 ASTTemplateArgumentListInfo::sizeFor(List.size());
542 void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
543 ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
544 TAI->initializeFrom(List);
545 return TAI;
546 }
547
initializeFrom(const TemplateArgumentListInfo & Info)548 void ASTTemplateArgumentListInfo::initializeFrom(
549 const TemplateArgumentListInfo &Info) {
550 LAngleLoc = Info.getLAngleLoc();
551 RAngleLoc = Info.getRAngleLoc();
552 NumTemplateArgs = Info.size();
553
554 TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
555 for (unsigned i = 0; i != NumTemplateArgs; ++i)
556 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
557 }
558
initializeFrom(const TemplateArgumentListInfo & Info,bool & Dependent,bool & InstantiationDependent,bool & ContainsUnexpandedParameterPack)559 void ASTTemplateArgumentListInfo::initializeFrom(
560 const TemplateArgumentListInfo &Info,
561 bool &Dependent,
562 bool &InstantiationDependent,
563 bool &ContainsUnexpandedParameterPack) {
564 LAngleLoc = Info.getLAngleLoc();
565 RAngleLoc = Info.getRAngleLoc();
566 NumTemplateArgs = Info.size();
567
568 TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
569 for (unsigned i = 0; i != NumTemplateArgs; ++i) {
570 Dependent = Dependent || Info[i].getArgument().isDependent();
571 InstantiationDependent = InstantiationDependent ||
572 Info[i].getArgument().isInstantiationDependent();
573 ContainsUnexpandedParameterPack
574 = ContainsUnexpandedParameterPack ||
575 Info[i].getArgument().containsUnexpandedParameterPack();
576
577 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
578 }
579 }
580
copyInto(TemplateArgumentListInfo & Info) const581 void ASTTemplateArgumentListInfo::copyInto(
582 TemplateArgumentListInfo &Info) const {
583 Info.setLAngleLoc(LAngleLoc);
584 Info.setRAngleLoc(RAngleLoc);
585 for (unsigned I = 0; I != NumTemplateArgs; ++I)
586 Info.addArgument(getTemplateArgs()[I]);
587 }
588
sizeFor(unsigned NumTemplateArgs)589 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
590 return sizeof(ASTTemplateArgumentListInfo) +
591 sizeof(TemplateArgumentLoc) * NumTemplateArgs;
592 }
593
594 void
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info)595 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
596 const TemplateArgumentListInfo &Info) {
597 Base::initializeFrom(Info);
598 setTemplateKeywordLoc(TemplateKWLoc);
599 }
600
601 void
602 ASTTemplateKWAndArgsInfo
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info,bool & Dependent,bool & InstantiationDependent,bool & ContainsUnexpandedParameterPack)603 ::initializeFrom(SourceLocation TemplateKWLoc,
604 const TemplateArgumentListInfo &Info,
605 bool &Dependent,
606 bool &InstantiationDependent,
607 bool &ContainsUnexpandedParameterPack) {
608 Base::initializeFrom(Info, Dependent, InstantiationDependent,
609 ContainsUnexpandedParameterPack);
610 setTemplateKeywordLoc(TemplateKWLoc);
611 }
612
613 void
initializeFrom(SourceLocation TemplateKWLoc)614 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
615 // No explicit template arguments, but template keyword loc is valid.
616 assert(TemplateKWLoc.isValid());
617 LAngleLoc = SourceLocation();
618 RAngleLoc = SourceLocation();
619 NumTemplateArgs = 0;
620 setTemplateKeywordLoc(TemplateKWLoc);
621 }
622
623 std::size_t
sizeFor(unsigned NumTemplateArgs)624 ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
625 // Add space for the template keyword location.
626 return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
627 }
628
629