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 {
280 PrintingPolicy SubPolicy(Policy);
281 SubPolicy.SuppressStrongLifetime = true;
283 getAsType().getAsStringInternal(TypeStr, SubPolicy);
290 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
291 if (ND->getDeclName()) {
293 Out << ND->getNameAsString();
298 Out << "<anonymous>";
304 getAsTemplate().print(Out, Policy);
307 case TemplateExpansion:
308 getAsTemplateOrTemplatePattern().print(Out, Policy);
313 printIntegral(*this, Out);
318 getAsExpr()->printPretty(Out, 0, Policy);
324 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
331 P->print(Policy, Out);
338 //===----------------------------------------------------------------------===//
339 // TemplateArgumentLoc Implementation
340 //===----------------------------------------------------------------------===//
342 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
343 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
346 SourceRange TemplateArgumentLoc::getSourceRange() const {
347 switch (Argument.getKind()) {
348 case TemplateArgument::Expression:
349 return getSourceExpression()->getSourceRange();
351 case TemplateArgument::Declaration:
352 return getSourceDeclExpression()->getSourceRange();
354 case TemplateArgument::Type:
355 if (TypeSourceInfo *TSI = getTypeSourceInfo())
356 return TSI->getTypeLoc().getSourceRange();
358 return SourceRange();
360 case TemplateArgument::Template:
361 if (getTemplateQualifierLoc())
362 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
363 getTemplateNameLoc());
364 return SourceRange(getTemplateNameLoc());
366 case TemplateArgument::TemplateExpansion:
367 if (getTemplateQualifierLoc())
368 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
369 getTemplateEllipsisLoc());
370 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
372 case TemplateArgument::Integral:
373 case TemplateArgument::Pack:
374 case TemplateArgument::Null:
375 return SourceRange();
378 // Silence bonus gcc warning.
379 return SourceRange();
383 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
384 llvm::Optional<unsigned> &NumExpansions,
385 ASTContext &Context) const {
386 assert(Argument.isPackExpansion());
388 switch (Argument.getKind()) {
389 case TemplateArgument::Type: {
390 // FIXME: We shouldn't ever have to worry about missing
392 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
393 if (!ExpansionTSInfo)
394 ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
395 getArgument().getAsType(),
397 PackExpansionTypeLoc Expansion
398 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
399 Ellipsis = Expansion.getEllipsisLoc();
401 TypeLoc Pattern = Expansion.getPatternLoc();
402 NumExpansions = Expansion.getTypePtr()->getNumExpansions();
404 // FIXME: This is horrible. We know where the source location data is for
405 // the pattern, and we have the pattern's type, but we are forced to copy
406 // them into an ASTContext because TypeSourceInfo bundles them together
407 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
408 TypeSourceInfo *PatternTSInfo
409 = Context.CreateTypeSourceInfo(Pattern.getType(),
410 Pattern.getFullDataSize());
411 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
412 Pattern.getOpaqueData(), Pattern.getFullDataSize());
413 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
417 case TemplateArgument::Expression: {
418 PackExpansionExpr *Expansion
419 = cast<PackExpansionExpr>(Argument.getAsExpr());
420 Expr *Pattern = Expansion->getPattern();
421 Ellipsis = Expansion->getEllipsisLoc();
422 NumExpansions = Expansion->getNumExpansions();
423 return TemplateArgumentLoc(Pattern, Pattern);
426 case TemplateArgument::TemplateExpansion:
427 Ellipsis = getTemplateEllipsisLoc();
428 NumExpansions = Argument.getNumTemplateExpansions();
429 return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
430 getTemplateQualifierLoc(),
431 getTemplateNameLoc());
433 case TemplateArgument::Declaration:
434 case TemplateArgument::Template:
435 case TemplateArgument::Integral:
436 case TemplateArgument::Pack:
437 case TemplateArgument::Null:
438 return TemplateArgumentLoc();
441 return TemplateArgumentLoc();
444 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
445 const TemplateArgument &Arg) {
446 switch (Arg.getKind()) {
447 case TemplateArgument::Null:
448 // This is bad, but not as bad as crashing because of argument
450 return DB << "(null template argument)";
452 case TemplateArgument::Type:
453 return DB << Arg.getAsType();
455 case TemplateArgument::Declaration:
456 return DB << Arg.getAsDecl();
458 case TemplateArgument::Integral:
459 return DB << Arg.getAsIntegral()->toString(10);
461 case TemplateArgument::Template:
462 return DB << Arg.getAsTemplate();
464 case TemplateArgument::TemplateExpansion:
465 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
467 case TemplateArgument::Expression: {
468 // This shouldn't actually ever happen, so it's okay that we're
469 // regurgitating an expression here.
470 // FIXME: We're guessing at LangOptions!
471 llvm::SmallString<32> Str;
472 llvm::raw_svector_ostream OS(Str);
473 LangOptions LangOpts;
474 LangOpts.CPlusPlus = true;
475 PrintingPolicy Policy(LangOpts);
476 Arg.getAsExpr()->printPretty(OS, 0, Policy);
477 return DB << OS.str();
480 case TemplateArgument::Pack: {
481 // FIXME: We're guessing at LangOptions!
482 llvm::SmallString<32> Str;
483 llvm::raw_svector_ostream OS(Str);
484 LangOptions LangOpts;
485 LangOpts.CPlusPlus = true;
486 PrintingPolicy Policy(LangOpts);
487 Arg.print(Policy, OS);
488 return DB << OS.str();