TemplateBase.cpp revision 221345
1198893Srdivacky//===--- TemplateBase.cpp - Common template AST class implementation ------===// 2198893Srdivacky// 3198893Srdivacky// The LLVM Compiler Infrastructure 4198893Srdivacky// 5198893Srdivacky// This file is distributed under the University of Illinois Open Source 6198893Srdivacky// License. See LICENSE.TXT for details. 7198893Srdivacky// 8198893Srdivacky//===----------------------------------------------------------------------===// 9198893Srdivacky// 10198893Srdivacky// This file implements common classes used throughout C++ template 11198893Srdivacky// representations. 12198893Srdivacky// 13198893Srdivacky//===----------------------------------------------------------------------===// 14198893Srdivacky 15198893Srdivacky#include "clang/AST/TemplateBase.h" 16218893Sdim#include "clang/AST/ASTContext.h" 17198893Srdivacky#include "clang/AST/DeclBase.h" 18199990Srdivacky#include "clang/AST/DeclTemplate.h" 19198893Srdivacky#include "clang/AST/Expr.h" 20218893Sdim#include "clang/AST/ExprCXX.h" 21218893Sdim#include "clang/AST/Type.h" 22198893Srdivacky#include "clang/AST/TypeLoc.h" 23208600Srdivacky#include "clang/Basic/Diagnostic.h" 24218893Sdim#include "llvm/ADT/FoldingSet.h" 25218893Sdim#include <algorithm> 26218893Sdim#include <cctype> 27198893Srdivacky 28198893Srdivackyusing namespace clang; 29198893Srdivacky 30218893Sdim/// \brief Print a template integral argument value. 31218893Sdim/// 32218893Sdim/// \param TemplArg the TemplateArgument instance to print. 33218893Sdim/// 34218893Sdim/// \param Out the raw_ostream instance to use for printing. 35218893Sdimstatic void printIntegral(const TemplateArgument &TemplArg, 36218893Sdim llvm::raw_ostream &Out) { 37218893Sdim const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); 38218893Sdim const llvm::APSInt *Val = TemplArg.getAsIntegral(); 39218893Sdim 40218893Sdim if (T->isBooleanType()) { 41218893Sdim Out << (Val->getBoolValue() ? "true" : "false"); 42218893Sdim } else if (T->isCharType()) { 43219077Sdim const unsigned char Ch = Val->getZExtValue(); 44219077Sdim const std::string Str(1, Ch); 45219077Sdim Out << ((Ch == '\'') ? "'\\" : "'"); 46219077Sdim Out.write_escaped(Str, /*UseHexEscapes=*/ true); 47219077Sdim Out << "'"; 48218893Sdim } else { 49218893Sdim Out << Val->toString(10); 50218893Sdim } 51218893Sdim} 52218893Sdim 53198893Srdivacky//===----------------------------------------------------------------------===// 54198893Srdivacky// TemplateArgument Implementation 55198893Srdivacky//===----------------------------------------------------------------------===// 56198893Srdivacky 57218893SdimTemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, 58218893Sdim const TemplateArgument *Args, 59218893Sdim unsigned NumArgs) { 60218893Sdim if (NumArgs == 0) 61218893Sdim return TemplateArgument(0, 0); 62218893Sdim 63218893Sdim TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; 64218893Sdim std::copy(Args, Args + NumArgs, Storage); 65218893Sdim return TemplateArgument(Storage, NumArgs); 66218893Sdim} 67198893Srdivacky 68218893Sdimbool TemplateArgument::isDependent() const { 69218893Sdim switch (getKind()) { 70218893Sdim case Null: 71218893Sdim assert(false && "Should not have a NULL template argument"); 72218893Sdim return false; 73218893Sdim 74218893Sdim case Type: 75218893Sdim return getAsType()->isDependentType(); 76218893Sdim 77218893Sdim case Template: 78218893Sdim return getAsTemplate().isDependent(); 79218893Sdim 80218893Sdim case TemplateExpansion: 81218893Sdim return true; 82218893Sdim 83218893Sdim case Declaration: 84218893Sdim if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 85218893Sdim return DC->isDependentContext(); 86218893Sdim return getAsDecl()->getDeclContext()->isDependentContext(); 87218893Sdim 88218893Sdim case Integral: 89218893Sdim // Never dependent 90218893Sdim return false; 91218893Sdim 92218893Sdim case Expression: 93218893Sdim return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); 94218893Sdim 95218893Sdim case Pack: 96218893Sdim for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { 97218893Sdim if (P->isDependent()) 98218893Sdim return true; 99218893Sdim } 100218893Sdim 101218893Sdim return false; 102198893Srdivacky } 103198893Srdivacky 104218893Sdim return false; 105198893Srdivacky} 106198893Srdivacky 107218893Sdimbool TemplateArgument::isPackExpansion() const { 108218893Sdim switch (getKind()) { 109218893Sdim case Null: 110218893Sdim case Declaration: 111218893Sdim case Integral: 112218893Sdim case Pack: 113218893Sdim case Template: 114218893Sdim return false; 115218893Sdim 116218893Sdim case TemplateExpansion: 117218893Sdim return true; 118218893Sdim 119218893Sdim case Type: 120218893Sdim return isa<PackExpansionType>(getAsType()); 121218893Sdim 122218893Sdim case Expression: 123218893Sdim return isa<PackExpansionExpr>(getAsExpr()); 124218893Sdim } 125218893Sdim 126218893Sdim return false; 127218893Sdim} 128218893Sdim 129218893Sdimbool TemplateArgument::containsUnexpandedParameterPack() const { 130218893Sdim switch (getKind()) { 131218893Sdim case Null: 132218893Sdim case Declaration: 133218893Sdim case Integral: 134218893Sdim case TemplateExpansion: 135218893Sdim break; 136218893Sdim 137218893Sdim case Type: 138218893Sdim if (getAsType()->containsUnexpandedParameterPack()) 139218893Sdim return true; 140218893Sdim break; 141218893Sdim 142218893Sdim case Template: 143218893Sdim if (getAsTemplate().containsUnexpandedParameterPack()) 144218893Sdim return true; 145218893Sdim break; 146218893Sdim 147218893Sdim case Expression: 148218893Sdim if (getAsExpr()->containsUnexpandedParameterPack()) 149218893Sdim return true; 150218893Sdim break; 151218893Sdim 152218893Sdim case Pack: 153218893Sdim for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) 154218893Sdim if (P->containsUnexpandedParameterPack()) 155218893Sdim return true; 156218893Sdim 157218893Sdim break; 158218893Sdim } 159218893Sdim 160218893Sdim return false; 161218893Sdim} 162218893Sdim 163218893Sdimllvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 164218893Sdim assert(Kind == TemplateExpansion); 165218893Sdim if (TemplateArg.NumExpansions) 166218893Sdim return TemplateArg.NumExpansions - 1; 167218893Sdim 168218893Sdim return llvm::Optional<unsigned>(); 169218893Sdim} 170218893Sdim 171198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 172218893Sdim const ASTContext &Context) const { 173198893Srdivacky ID.AddInteger(Kind); 174198893Srdivacky switch (Kind) { 175198893Srdivacky case Null: 176198893Srdivacky break; 177198893Srdivacky 178198893Srdivacky case Type: 179198893Srdivacky getAsType().Profile(ID); 180198893Srdivacky break; 181198893Srdivacky 182198893Srdivacky case Declaration: 183198893Srdivacky ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 184198893Srdivacky break; 185198893Srdivacky 186199482Srdivacky case Template: 187218893Sdim case TemplateExpansion: { 188218893Sdim TemplateName Template = getAsTemplateOrTemplatePattern(); 189199990Srdivacky if (TemplateTemplateParmDecl *TTP 190199990Srdivacky = dyn_cast_or_null<TemplateTemplateParmDecl>( 191218893Sdim Template.getAsTemplateDecl())) { 192199990Srdivacky ID.AddBoolean(true); 193199990Srdivacky ID.AddInteger(TTP->getDepth()); 194199990Srdivacky ID.AddInteger(TTP->getPosition()); 195218893Sdim ID.AddBoolean(TTP->isParameterPack()); 196199990Srdivacky } else { 197199990Srdivacky ID.AddBoolean(false); 198218893Sdim ID.AddPointer(Context.getCanonicalTemplateName(Template) 199218893Sdim .getAsVoidPointer()); 200199990Srdivacky } 201199482Srdivacky break; 202218893Sdim } 203199482Srdivacky 204198893Srdivacky case Integral: 205198893Srdivacky getAsIntegral()->Profile(ID); 206198893Srdivacky getIntegralType().Profile(ID); 207198893Srdivacky break; 208198893Srdivacky 209198893Srdivacky case Expression: 210198893Srdivacky getAsExpr()->Profile(ID, Context, true); 211198893Srdivacky break; 212198893Srdivacky 213198893Srdivacky case Pack: 214198893Srdivacky ID.AddInteger(Args.NumArgs); 215198893Srdivacky for (unsigned I = 0; I != Args.NumArgs; ++I) 216198893Srdivacky Args.Args[I].Profile(ID, Context); 217198893Srdivacky } 218198893Srdivacky} 219198893Srdivacky 220210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 221210299Sed if (getKind() != Other.getKind()) return false; 222210299Sed 223210299Sed switch (getKind()) { 224210299Sed case Null: 225210299Sed case Type: 226210299Sed case Declaration: 227218893Sdim case Expression: 228210299Sed case Template: 229218893Sdim case TemplateExpansion: 230210299Sed return TypeOrValue == Other.TypeOrValue; 231210299Sed 232210299Sed case Integral: 233210299Sed return getIntegralType() == Other.getIntegralType() && 234210299Sed *getAsIntegral() == *Other.getAsIntegral(); 235210299Sed 236210299Sed case Pack: 237210299Sed if (Args.NumArgs != Other.Args.NumArgs) return false; 238210299Sed for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 239210299Sed if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 240210299Sed return false; 241210299Sed return true; 242210299Sed } 243210299Sed 244210299Sed // Suppress warnings. 245210299Sed return false; 246210299Sed} 247210299Sed 248218893SdimTemplateArgument TemplateArgument::getPackExpansionPattern() const { 249218893Sdim assert(isPackExpansion()); 250218893Sdim 251218893Sdim switch (getKind()) { 252218893Sdim case Type: 253218893Sdim return getAsType()->getAs<PackExpansionType>()->getPattern(); 254218893Sdim 255218893Sdim case Expression: 256218893Sdim return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 257218893Sdim 258218893Sdim case TemplateExpansion: 259218893Sdim return TemplateArgument(getAsTemplateOrTemplatePattern()); 260218893Sdim 261218893Sdim case Declaration: 262218893Sdim case Integral: 263218893Sdim case Pack: 264218893Sdim case Null: 265218893Sdim case Template: 266218893Sdim return TemplateArgument(); 267218893Sdim } 268218893Sdim 269218893Sdim return TemplateArgument(); 270218893Sdim} 271218893Sdim 272218893Sdimvoid TemplateArgument::print(const PrintingPolicy &Policy, 273218893Sdim llvm::raw_ostream &Out) const { 274218893Sdim switch (getKind()) { 275218893Sdim case Null: 276218893Sdim Out << "<no value>"; 277218893Sdim break; 278218893Sdim 279218893Sdim case Type: { 280218893Sdim std::string TypeStr; 281218893Sdim getAsType().getAsStringInternal(TypeStr, Policy); 282218893Sdim Out << TypeStr; 283218893Sdim break; 284218893Sdim } 285218893Sdim 286218893Sdim case Declaration: { 287218893Sdim bool Unnamed = true; 288218893Sdim if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 289218893Sdim if (ND->getDeclName()) { 290218893Sdim Unnamed = false; 291218893Sdim Out << ND->getNameAsString(); 292218893Sdim } 293218893Sdim } 294218893Sdim 295218893Sdim if (Unnamed) { 296218893Sdim Out << "<anonymous>"; 297218893Sdim } 298218893Sdim break; 299218893Sdim } 300218893Sdim 301218893Sdim case Template: 302218893Sdim getAsTemplate().print(Out, Policy); 303218893Sdim break; 304218893Sdim 305218893Sdim case TemplateExpansion: 306218893Sdim getAsTemplateOrTemplatePattern().print(Out, Policy); 307218893Sdim Out << "..."; 308218893Sdim break; 309218893Sdim 310218893Sdim case Integral: { 311218893Sdim printIntegral(*this, Out); 312218893Sdim break; 313218893Sdim } 314218893Sdim 315218893Sdim case Expression: 316218893Sdim getAsExpr()->printPretty(Out, 0, Policy); 317218893Sdim break; 318218893Sdim 319218893Sdim case Pack: 320218893Sdim Out << "<"; 321218893Sdim bool First = true; 322218893Sdim for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 323218893Sdim P != PEnd; ++P) { 324218893Sdim if (First) 325218893Sdim First = false; 326218893Sdim else 327218893Sdim Out << ", "; 328218893Sdim 329218893Sdim P->print(Policy, Out); 330218893Sdim } 331218893Sdim Out << ">"; 332218893Sdim break; 333218893Sdim } 334218893Sdim} 335218893Sdim 336198893Srdivacky//===----------------------------------------------------------------------===// 337198893Srdivacky// TemplateArgumentLoc Implementation 338198893Srdivacky//===----------------------------------------------------------------------===// 339198893Srdivacky 340218893SdimTemplateArgumentLocInfo::TemplateArgumentLocInfo() { 341221345Sdim memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 342218893Sdim} 343218893Sdim 344198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const { 345198893Srdivacky switch (Argument.getKind()) { 346198893Srdivacky case TemplateArgument::Expression: 347198893Srdivacky return getSourceExpression()->getSourceRange(); 348212904Sdim 349198893Srdivacky case TemplateArgument::Declaration: 350198893Srdivacky return getSourceDeclExpression()->getSourceRange(); 351212904Sdim 352198893Srdivacky case TemplateArgument::Type: 353212904Sdim if (TypeSourceInfo *TSI = getTypeSourceInfo()) 354212904Sdim return TSI->getTypeLoc().getSourceRange(); 355212904Sdim else 356212904Sdim return SourceRange(); 357212904Sdim 358199482Srdivacky case TemplateArgument::Template: 359221345Sdim if (getTemplateQualifierLoc()) 360221345Sdim return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 361199482Srdivacky getTemplateNameLoc()); 362199482Srdivacky return SourceRange(getTemplateNameLoc()); 363212904Sdim 364218893Sdim case TemplateArgument::TemplateExpansion: 365221345Sdim if (getTemplateQualifierLoc()) 366221345Sdim return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 367218893Sdim getTemplateEllipsisLoc()); 368218893Sdim return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 369218893Sdim 370198893Srdivacky case TemplateArgument::Integral: 371198893Srdivacky case TemplateArgument::Pack: 372198893Srdivacky case TemplateArgument::Null: 373198893Srdivacky return SourceRange(); 374198893Srdivacky } 375198893Srdivacky 376198893Srdivacky // Silence bonus gcc warning. 377198893Srdivacky return SourceRange(); 378198893Srdivacky} 379208600Srdivacky 380218893SdimTemplateArgumentLoc 381218893SdimTemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 382218893Sdim llvm::Optional<unsigned> &NumExpansions, 383218893Sdim ASTContext &Context) const { 384218893Sdim assert(Argument.isPackExpansion()); 385218893Sdim 386218893Sdim switch (Argument.getKind()) { 387218893Sdim case TemplateArgument::Type: { 388218893Sdim // FIXME: We shouldn't ever have to worry about missing 389218893Sdim // type-source info! 390218893Sdim TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 391218893Sdim if (!ExpansionTSInfo) 392218893Sdim ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 393218893Sdim getArgument().getAsType(), 394218893Sdim Ellipsis); 395218893Sdim PackExpansionTypeLoc Expansion 396218893Sdim = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 397218893Sdim Ellipsis = Expansion.getEllipsisLoc(); 398218893Sdim 399218893Sdim TypeLoc Pattern = Expansion.getPatternLoc(); 400218893Sdim NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 401218893Sdim 402218893Sdim // FIXME: This is horrible. We know where the source location data is for 403218893Sdim // the pattern, and we have the pattern's type, but we are forced to copy 404218893Sdim // them into an ASTContext because TypeSourceInfo bundles them together 405218893Sdim // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 406218893Sdim TypeSourceInfo *PatternTSInfo 407218893Sdim = Context.CreateTypeSourceInfo(Pattern.getType(), 408218893Sdim Pattern.getFullDataSize()); 409218893Sdim memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 410218893Sdim Pattern.getOpaqueData(), Pattern.getFullDataSize()); 411218893Sdim return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 412218893Sdim PatternTSInfo); 413218893Sdim } 414218893Sdim 415218893Sdim case TemplateArgument::Expression: { 416218893Sdim PackExpansionExpr *Expansion 417218893Sdim = cast<PackExpansionExpr>(Argument.getAsExpr()); 418218893Sdim Expr *Pattern = Expansion->getPattern(); 419218893Sdim Ellipsis = Expansion->getEllipsisLoc(); 420218893Sdim NumExpansions = Expansion->getNumExpansions(); 421218893Sdim return TemplateArgumentLoc(Pattern, Pattern); 422218893Sdim } 423218893Sdim 424218893Sdim case TemplateArgument::TemplateExpansion: 425218893Sdim Ellipsis = getTemplateEllipsisLoc(); 426218893Sdim NumExpansions = Argument.getNumTemplateExpansions(); 427218893Sdim return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 428221345Sdim getTemplateQualifierLoc(), 429218893Sdim getTemplateNameLoc()); 430218893Sdim 431218893Sdim case TemplateArgument::Declaration: 432218893Sdim case TemplateArgument::Template: 433218893Sdim case TemplateArgument::Integral: 434218893Sdim case TemplateArgument::Pack: 435218893Sdim case TemplateArgument::Null: 436218893Sdim return TemplateArgumentLoc(); 437218893Sdim } 438218893Sdim 439218893Sdim return TemplateArgumentLoc(); 440218893Sdim} 441218893Sdim 442208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 443208600Srdivacky const TemplateArgument &Arg) { 444208600Srdivacky switch (Arg.getKind()) { 445208600Srdivacky case TemplateArgument::Null: 446212904Sdim // This is bad, but not as bad as crashing because of argument 447212904Sdim // count mismatches. 448212904Sdim return DB << "(null template argument)"; 449208600Srdivacky 450208600Srdivacky case TemplateArgument::Type: 451208600Srdivacky return DB << Arg.getAsType(); 452208600Srdivacky 453208600Srdivacky case TemplateArgument::Declaration: 454208600Srdivacky return DB << Arg.getAsDecl(); 455208600Srdivacky 456208600Srdivacky case TemplateArgument::Integral: 457208600Srdivacky return DB << Arg.getAsIntegral()->toString(10); 458208600Srdivacky 459208600Srdivacky case TemplateArgument::Template: 460208600Srdivacky return DB << Arg.getAsTemplate(); 461218893Sdim 462218893Sdim case TemplateArgument::TemplateExpansion: 463218893Sdim return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 464218893Sdim 465208600Srdivacky case TemplateArgument::Expression: { 466208600Srdivacky // This shouldn't actually ever happen, so it's okay that we're 467208600Srdivacky // regurgitating an expression here. 468208600Srdivacky // FIXME: We're guessing at LangOptions! 469208600Srdivacky llvm::SmallString<32> Str; 470208600Srdivacky llvm::raw_svector_ostream OS(Str); 471208600Srdivacky LangOptions LangOpts; 472208600Srdivacky LangOpts.CPlusPlus = true; 473208600Srdivacky PrintingPolicy Policy(LangOpts); 474208600Srdivacky Arg.getAsExpr()->printPretty(OS, 0, Policy); 475208600Srdivacky return DB << OS.str(); 476208600Srdivacky } 477208600Srdivacky 478218893Sdim case TemplateArgument::Pack: { 479218893Sdim // FIXME: We're guessing at LangOptions! 480218893Sdim llvm::SmallString<32> Str; 481218893Sdim llvm::raw_svector_ostream OS(Str); 482218893Sdim LangOptions LangOpts; 483218893Sdim LangOpts.CPlusPlus = true; 484218893Sdim PrintingPolicy Policy(LangOpts); 485218893Sdim Arg.print(Policy, OS); 486218893Sdim return DB << OS.str(); 487208600Srdivacky } 488218893Sdim } 489208600Srdivacky 490208600Srdivacky return DB; 491208600Srdivacky} 492