1 //===--- TemplateBase.cpp - Common template AST class implementation ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements common classes used throughout C++ template
13 //===----------------------------------------------------------------------===//
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"
28 using namespace clang;
30 /// \brief Print a template integral argument value.
32 /// \param TemplArg the TemplateArgument instance to print.
34 /// \param Out the raw_ostream instance to use for printing.
35 static void printIntegral(const TemplateArgument &TemplArg,
36 llvm::raw_ostream &Out) {
37 const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
38 const llvm::APSInt *Val = TemplArg.getAsIntegral();
40 if (T->isBooleanType()) {
41 Out << (Val->getBoolValue() ? "true" : "false");
42 } else if (T->isCharType()) {
43 const unsigned char Ch = Val->getZExtValue();
44 const std::string Str(1, Ch);
45 Out << ((Ch == '\'') ? "'\\" : "'");
46 Out.write_escaped(Str, /*UseHexEscapes=*/ true);
49 Out << Val->toString(10);
53 //===----------------------------------------------------------------------===//
54 // TemplateArgument Implementation
55 //===----------------------------------------------------------------------===//
57 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
58 const TemplateArgument *Args,
61 return TemplateArgument(0, 0);
63 TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
64 std::copy(Args, Args + NumArgs, Storage);
65 return TemplateArgument(Storage, NumArgs);
68 bool TemplateArgument::isDependent() const {
71 assert(false && "Should not have a NULL template argument");
75 return getAsType()->isDependentType();
78 return getAsTemplate().isDependent();
80 case TemplateExpansion:
84 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
85 return DC->isDependentContext();
86 return getAsDecl()->getDeclContext()->isDependentContext();
93 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
96 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
107 bool TemplateArgument::isPackExpansion() const {
116 case TemplateExpansion:
120 return isa<PackExpansionType>(getAsType());
123 return isa<PackExpansionExpr>(getAsExpr());
129 bool TemplateArgument::containsUnexpandedParameterPack() const {
134 case TemplateExpansion:
138 if (getAsType()->containsUnexpandedParameterPack())
143 if (getAsTemplate().containsUnexpandedParameterPack())
148 if (getAsExpr()->containsUnexpandedParameterPack())
153 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
154 if (P->containsUnexpandedParameterPack())
163 llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
164 assert(Kind == TemplateExpansion);
165 if (TemplateArg.NumExpansions)
166 return TemplateArg.NumExpansions - 1;
168 return llvm::Optional<unsigned>();
171 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
172 const ASTContext &Context) const {
179 getAsType().Profile(ID);
183 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
187 case TemplateExpansion: {
188 TemplateName Template = getAsTemplateOrTemplatePattern();
189 if (TemplateTemplateParmDecl *TTP
190 = dyn_cast_or_null<TemplateTemplateParmDecl>(
191 Template.getAsTemplateDecl())) {
193 ID.AddInteger(TTP->getDepth());
194 ID.AddInteger(TTP->getPosition());
195 ID.AddBoolean(TTP->isParameterPack());
197 ID.AddBoolean(false);
198 ID.AddPointer(Context.getCanonicalTemplateName(Template)
199 .getAsVoidPointer());
205 getAsIntegral()->Profile(ID);
206 getIntegralType().Profile(ID);
210 getAsExpr()->Profile(ID, Context, true);
214 ID.AddInteger(Args.NumArgs);
215 for (unsigned I = 0; I != Args.NumArgs; ++I)
216 Args.Args[I].Profile(ID, Context);
220 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
221 if (getKind() != Other.getKind()) return false;
229 case TemplateExpansion:
230 return TypeOrValue == Other.TypeOrValue;
233 return getIntegralType() == Other.getIntegralType() &&
234 *getAsIntegral() == *Other.getAsIntegral();
237 if (Args.NumArgs != Other.Args.NumArgs) return false;
238 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
239 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
244 // Suppress warnings.
248 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
249 assert(isPackExpansion());
253 return getAsType()->getAs<PackExpansionType>()->getPattern();
256 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
258 case TemplateExpansion:
259 return TemplateArgument(getAsTemplateOrTemplatePattern());
266 return TemplateArgument();
269 return TemplateArgument();
272 void TemplateArgument::print(const PrintingPolicy &Policy,
273 llvm::raw_ostream &Out) const {
281 getAsType().getAsStringInternal(TypeStr, Policy);
288 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
289 if (ND->getDeclName()) {
291 Out << ND->getNameAsString();
296 Out << "<anonymous>";
302 getAsTemplate().print(Out, Policy);
305 case TemplateExpansion:
306 getAsTemplateOrTemplatePattern().print(Out, Policy);
311 printIntegral(*this, Out);
316 getAsExpr()->printPretty(Out, 0, Policy);
322 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
329 P->print(Policy, Out);
336 //===----------------------------------------------------------------------===//
337 // TemplateArgumentLoc Implementation
338 //===----------------------------------------------------------------------===//
340 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
341 memset(this, 0, sizeof(TemplateArgumentLocInfo));
344 SourceRange TemplateArgumentLoc::getSourceRange() const {
345 switch (Argument.getKind()) {
346 case TemplateArgument::Expression:
347 return getSourceExpression()->getSourceRange();
349 case TemplateArgument::Declaration:
350 return getSourceDeclExpression()->getSourceRange();
352 case TemplateArgument::Type:
353 if (TypeSourceInfo *TSI = getTypeSourceInfo())
354 return TSI->getTypeLoc().getSourceRange();
356 return SourceRange();
358 case TemplateArgument::Template:
359 if (getTemplateQualifierLoc())
360 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
361 getTemplateNameLoc());
362 return SourceRange(getTemplateNameLoc());
364 case TemplateArgument::TemplateExpansion:
365 if (getTemplateQualifierLoc())
366 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
367 getTemplateEllipsisLoc());
368 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
370 case TemplateArgument::Integral:
371 case TemplateArgument::Pack:
372 case TemplateArgument::Null:
373 return SourceRange();
376 // Silence bonus gcc warning.
377 return SourceRange();
381 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
382 llvm::Optional<unsigned> &NumExpansions,
383 ASTContext &Context) const {
384 assert(Argument.isPackExpansion());
386 switch (Argument.getKind()) {
387 case TemplateArgument::Type: {
388 // FIXME: We shouldn't ever have to worry about missing
390 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
391 if (!ExpansionTSInfo)
392 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
393 getArgument().getAsType(),
395 PackExpansionTypeLoc Expansion
396 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
397 Ellipsis = Expansion.getEllipsisLoc();
399 TypeLoc Pattern = Expansion.getPatternLoc();
400 NumExpansions = Expansion.getTypePtr()->getNumExpansions();
402 // FIXME: This is horrible. We know where the source location data is for
403 // the pattern, and we have the pattern's type, but we are forced to copy
404 // them into an ASTContext because TypeSourceInfo bundles them together
405 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
406 TypeSourceInfo *PatternTSInfo
407 = Context.CreateTypeSourceInfo(Pattern.getType(),
408 Pattern.getFullDataSize());
409 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
410 Pattern.getOpaqueData(), Pattern.getFullDataSize());
411 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
415 case TemplateArgument::Expression: {
416 PackExpansionExpr *Expansion
417 = cast<PackExpansionExpr>(Argument.getAsExpr());
418 Expr *Pattern = Expansion->getPattern();
419 Ellipsis = Expansion->getEllipsisLoc();
420 NumExpansions = Expansion->getNumExpansions();
421 return TemplateArgumentLoc(Pattern, Pattern);
424 case TemplateArgument::TemplateExpansion:
425 Ellipsis = getTemplateEllipsisLoc();
426 NumExpansions = Argument.getNumTemplateExpansions();
427 return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
428 getTemplateQualifierLoc(),
429 getTemplateNameLoc());
431 case TemplateArgument::Declaration:
432 case TemplateArgument::Template:
433 case TemplateArgument::Integral:
434 case TemplateArgument::Pack:
435 case TemplateArgument::Null:
436 return TemplateArgumentLoc();
439 return TemplateArgumentLoc();
442 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
443 const TemplateArgument &Arg) {
444 switch (Arg.getKind()) {
445 case TemplateArgument::Null:
446 // This is bad, but not as bad as crashing because of argument
448 return DB << "(null template argument)";
450 case TemplateArgument::Type:
451 return DB << Arg.getAsType();
453 case TemplateArgument::Declaration:
454 return DB << Arg.getAsDecl();
456 case TemplateArgument::Integral:
457 return DB << Arg.getAsIntegral()->toString(10);
459 case TemplateArgument::Template:
460 return DB << Arg.getAsTemplate();
462 case TemplateArgument::TemplateExpansion:
463 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
465 case TemplateArgument::Expression: {
466 // This shouldn't actually ever happen, so it's okay that we're
467 // regurgitating an expression here.
468 // FIXME: We're guessing at LangOptions!
469 llvm::SmallString<32> Str;
470 llvm::raw_svector_ostream OS(Str);
471 LangOptions LangOpts;
472 LangOpts.CPlusPlus = true;
473 PrintingPolicy Policy(LangOpts);
474 Arg.getAsExpr()->printPretty(OS, 0, Policy);
475 return DB << OS.str();
478 case TemplateArgument::Pack: {
479 // FIXME: We're guessing at LangOptions!
480 llvm::SmallString<32> Str;
481 llvm::raw_svector_ostream OS(Str);
482 LangOptions LangOpts;
483 LangOpts.CPlusPlus = true;
484 PrintingPolicy Policy(LangOpts);
485 Arg.print(Policy, OS);
486 return DB << OS.str();