TemplateBase.cpp revision 218893
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> 27218893Sdim#include <iomanip> 28218893Sdim#include <sstream> 29198893Srdivacky 30198893Srdivackyusing namespace clang; 31198893Srdivacky 32218893Sdim/// \brief Print a template integral argument value. 33218893Sdim/// 34218893Sdim/// \param TemplArg the TemplateArgument instance to print. 35218893Sdim/// 36218893Sdim/// \param Out the raw_ostream instance to use for printing. 37218893Sdimstatic void printIntegral(const TemplateArgument &TemplArg, 38218893Sdim llvm::raw_ostream &Out) { 39218893Sdim const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); 40218893Sdim const llvm::APSInt *Val = TemplArg.getAsIntegral(); 41218893Sdim 42218893Sdim if (T->isBooleanType()) { 43218893Sdim Out << (Val->getBoolValue() ? "true" : "false"); 44218893Sdim } else if (T->isCharType()) { 45218893Sdim char Ch = Val->getSExtValue(); 46218893Sdim if (std::isprint(Ch)) { 47218893Sdim Out << "'"; 48218893Sdim if (Ch == '\'' || Ch == '\\') 49218893Sdim Out << '\\'; 50218893Sdim Out << Ch << "'"; 51218893Sdim } else { 52218893Sdim std::ostringstream Str; 53218893Sdim Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch; 54218893Sdim Out << "'\\x" << Str.str() << "'"; 55218893Sdim } 56218893Sdim } else { 57218893Sdim Out << Val->toString(10); 58218893Sdim } 59218893Sdim} 60218893Sdim 61198893Srdivacky//===----------------------------------------------------------------------===// 62198893Srdivacky// TemplateArgument Implementation 63198893Srdivacky//===----------------------------------------------------------------------===// 64198893Srdivacky 65218893SdimTemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, 66218893Sdim const TemplateArgument *Args, 67218893Sdim unsigned NumArgs) { 68218893Sdim if (NumArgs == 0) 69218893Sdim return TemplateArgument(0, 0); 70218893Sdim 71218893Sdim TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; 72218893Sdim std::copy(Args, Args + NumArgs, Storage); 73218893Sdim return TemplateArgument(Storage, NumArgs); 74218893Sdim} 75198893Srdivacky 76218893Sdimbool TemplateArgument::isDependent() const { 77218893Sdim switch (getKind()) { 78218893Sdim case Null: 79218893Sdim assert(false && "Should not have a NULL template argument"); 80218893Sdim return false; 81218893Sdim 82218893Sdim case Type: 83218893Sdim return getAsType()->isDependentType(); 84218893Sdim 85218893Sdim case Template: 86218893Sdim return getAsTemplate().isDependent(); 87218893Sdim 88218893Sdim case TemplateExpansion: 89218893Sdim return true; 90218893Sdim 91218893Sdim case Declaration: 92218893Sdim if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 93218893Sdim return DC->isDependentContext(); 94218893Sdim return getAsDecl()->getDeclContext()->isDependentContext(); 95218893Sdim 96218893Sdim case Integral: 97218893Sdim // Never dependent 98218893Sdim return false; 99218893Sdim 100218893Sdim case Expression: 101218893Sdim return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); 102218893Sdim 103218893Sdim case Pack: 104218893Sdim for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { 105218893Sdim if (P->isDependent()) 106218893Sdim return true; 107218893Sdim } 108218893Sdim 109218893Sdim return false; 110198893Srdivacky } 111198893Srdivacky 112218893Sdim return false; 113198893Srdivacky} 114198893Srdivacky 115218893Sdimbool TemplateArgument::isPackExpansion() const { 116218893Sdim switch (getKind()) { 117218893Sdim case Null: 118218893Sdim case Declaration: 119218893Sdim case Integral: 120218893Sdim case Pack: 121218893Sdim case Template: 122218893Sdim return false; 123218893Sdim 124218893Sdim case TemplateExpansion: 125218893Sdim return true; 126218893Sdim 127218893Sdim case Type: 128218893Sdim return isa<PackExpansionType>(getAsType()); 129218893Sdim 130218893Sdim case Expression: 131218893Sdim return isa<PackExpansionExpr>(getAsExpr()); 132218893Sdim } 133218893Sdim 134218893Sdim return false; 135218893Sdim} 136218893Sdim 137218893Sdimbool TemplateArgument::containsUnexpandedParameterPack() const { 138218893Sdim switch (getKind()) { 139218893Sdim case Null: 140218893Sdim case Declaration: 141218893Sdim case Integral: 142218893Sdim case TemplateExpansion: 143218893Sdim break; 144218893Sdim 145218893Sdim case Type: 146218893Sdim if (getAsType()->containsUnexpandedParameterPack()) 147218893Sdim return true; 148218893Sdim break; 149218893Sdim 150218893Sdim case Template: 151218893Sdim if (getAsTemplate().containsUnexpandedParameterPack()) 152218893Sdim return true; 153218893Sdim break; 154218893Sdim 155218893Sdim case Expression: 156218893Sdim if (getAsExpr()->containsUnexpandedParameterPack()) 157218893Sdim return true; 158218893Sdim break; 159218893Sdim 160218893Sdim case Pack: 161218893Sdim for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) 162218893Sdim if (P->containsUnexpandedParameterPack()) 163218893Sdim return true; 164218893Sdim 165218893Sdim break; 166218893Sdim } 167218893Sdim 168218893Sdim return false; 169218893Sdim} 170218893Sdim 171218893Sdimllvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 172218893Sdim assert(Kind == TemplateExpansion); 173218893Sdim if (TemplateArg.NumExpansions) 174218893Sdim return TemplateArg.NumExpansions - 1; 175218893Sdim 176218893Sdim return llvm::Optional<unsigned>(); 177218893Sdim} 178218893Sdim 179198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 180218893Sdim const ASTContext &Context) const { 181198893Srdivacky ID.AddInteger(Kind); 182198893Srdivacky switch (Kind) { 183198893Srdivacky case Null: 184198893Srdivacky break; 185198893Srdivacky 186198893Srdivacky case Type: 187198893Srdivacky getAsType().Profile(ID); 188198893Srdivacky break; 189198893Srdivacky 190198893Srdivacky case Declaration: 191198893Srdivacky ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 192198893Srdivacky break; 193198893Srdivacky 194199482Srdivacky case Template: 195218893Sdim case TemplateExpansion: { 196218893Sdim TemplateName Template = getAsTemplateOrTemplatePattern(); 197199990Srdivacky if (TemplateTemplateParmDecl *TTP 198199990Srdivacky = dyn_cast_or_null<TemplateTemplateParmDecl>( 199218893Sdim Template.getAsTemplateDecl())) { 200199990Srdivacky ID.AddBoolean(true); 201199990Srdivacky ID.AddInteger(TTP->getDepth()); 202199990Srdivacky ID.AddInteger(TTP->getPosition()); 203218893Sdim ID.AddBoolean(TTP->isParameterPack()); 204199990Srdivacky } else { 205199990Srdivacky ID.AddBoolean(false); 206218893Sdim ID.AddPointer(Context.getCanonicalTemplateName(Template) 207218893Sdim .getAsVoidPointer()); 208199990Srdivacky } 209199482Srdivacky break; 210218893Sdim } 211199482Srdivacky 212198893Srdivacky case Integral: 213198893Srdivacky getAsIntegral()->Profile(ID); 214198893Srdivacky getIntegralType().Profile(ID); 215198893Srdivacky break; 216198893Srdivacky 217198893Srdivacky case Expression: 218198893Srdivacky getAsExpr()->Profile(ID, Context, true); 219198893Srdivacky break; 220198893Srdivacky 221198893Srdivacky case Pack: 222198893Srdivacky ID.AddInteger(Args.NumArgs); 223198893Srdivacky for (unsigned I = 0; I != Args.NumArgs; ++I) 224198893Srdivacky Args.Args[I].Profile(ID, Context); 225198893Srdivacky } 226198893Srdivacky} 227198893Srdivacky 228210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 229210299Sed if (getKind() != Other.getKind()) return false; 230210299Sed 231210299Sed switch (getKind()) { 232210299Sed case Null: 233210299Sed case Type: 234210299Sed case Declaration: 235218893Sdim case Expression: 236210299Sed case Template: 237218893Sdim case TemplateExpansion: 238210299Sed return TypeOrValue == Other.TypeOrValue; 239210299Sed 240210299Sed case Integral: 241210299Sed return getIntegralType() == Other.getIntegralType() && 242210299Sed *getAsIntegral() == *Other.getAsIntegral(); 243210299Sed 244210299Sed case Pack: 245210299Sed if (Args.NumArgs != Other.Args.NumArgs) return false; 246210299Sed for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 247210299Sed if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 248210299Sed return false; 249210299Sed return true; 250210299Sed } 251210299Sed 252210299Sed // Suppress warnings. 253210299Sed return false; 254210299Sed} 255210299Sed 256218893SdimTemplateArgument TemplateArgument::getPackExpansionPattern() const { 257218893Sdim assert(isPackExpansion()); 258218893Sdim 259218893Sdim switch (getKind()) { 260218893Sdim case Type: 261218893Sdim return getAsType()->getAs<PackExpansionType>()->getPattern(); 262218893Sdim 263218893Sdim case Expression: 264218893Sdim return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 265218893Sdim 266218893Sdim case TemplateExpansion: 267218893Sdim return TemplateArgument(getAsTemplateOrTemplatePattern()); 268218893Sdim 269218893Sdim case Declaration: 270218893Sdim case Integral: 271218893Sdim case Pack: 272218893Sdim case Null: 273218893Sdim case Template: 274218893Sdim return TemplateArgument(); 275218893Sdim } 276218893Sdim 277218893Sdim return TemplateArgument(); 278218893Sdim} 279218893Sdim 280218893Sdimvoid TemplateArgument::print(const PrintingPolicy &Policy, 281218893Sdim llvm::raw_ostream &Out) const { 282218893Sdim switch (getKind()) { 283218893Sdim case Null: 284218893Sdim Out << "<no value>"; 285218893Sdim break; 286218893Sdim 287218893Sdim case Type: { 288218893Sdim std::string TypeStr; 289218893Sdim getAsType().getAsStringInternal(TypeStr, Policy); 290218893Sdim Out << TypeStr; 291218893Sdim break; 292218893Sdim } 293218893Sdim 294218893Sdim case Declaration: { 295218893Sdim bool Unnamed = true; 296218893Sdim if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 297218893Sdim if (ND->getDeclName()) { 298218893Sdim Unnamed = false; 299218893Sdim Out << ND->getNameAsString(); 300218893Sdim } 301218893Sdim } 302218893Sdim 303218893Sdim if (Unnamed) { 304218893Sdim Out << "<anonymous>"; 305218893Sdim } 306218893Sdim break; 307218893Sdim } 308218893Sdim 309218893Sdim case Template: 310218893Sdim getAsTemplate().print(Out, Policy); 311218893Sdim break; 312218893Sdim 313218893Sdim case TemplateExpansion: 314218893Sdim getAsTemplateOrTemplatePattern().print(Out, Policy); 315218893Sdim Out << "..."; 316218893Sdim break; 317218893Sdim 318218893Sdim case Integral: { 319218893Sdim printIntegral(*this, Out); 320218893Sdim break; 321218893Sdim } 322218893Sdim 323218893Sdim case Expression: 324218893Sdim getAsExpr()->printPretty(Out, 0, Policy); 325218893Sdim break; 326218893Sdim 327218893Sdim case Pack: 328218893Sdim Out << "<"; 329218893Sdim bool First = true; 330218893Sdim for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 331218893Sdim P != PEnd; ++P) { 332218893Sdim if (First) 333218893Sdim First = false; 334218893Sdim else 335218893Sdim Out << ", "; 336218893Sdim 337218893Sdim P->print(Policy, Out); 338218893Sdim } 339218893Sdim Out << ">"; 340218893Sdim break; 341218893Sdim } 342218893Sdim} 343218893Sdim 344198893Srdivacky//===----------------------------------------------------------------------===// 345198893Srdivacky// TemplateArgumentLoc Implementation 346198893Srdivacky//===----------------------------------------------------------------------===// 347198893Srdivacky 348218893SdimTemplateArgumentLocInfo::TemplateArgumentLocInfo() { 349218893Sdim memset(this, 0, sizeof(TemplateArgumentLocInfo)); 350218893Sdim} 351218893Sdim 352198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const { 353198893Srdivacky switch (Argument.getKind()) { 354198893Srdivacky case TemplateArgument::Expression: 355198893Srdivacky return getSourceExpression()->getSourceRange(); 356212904Sdim 357198893Srdivacky case TemplateArgument::Declaration: 358198893Srdivacky return getSourceDeclExpression()->getSourceRange(); 359212904Sdim 360198893Srdivacky case TemplateArgument::Type: 361212904Sdim if (TypeSourceInfo *TSI = getTypeSourceInfo()) 362212904Sdim return TSI->getTypeLoc().getSourceRange(); 363212904Sdim else 364212904Sdim return SourceRange(); 365212904Sdim 366199482Srdivacky case TemplateArgument::Template: 367199482Srdivacky if (getTemplateQualifierRange().isValid()) 368218893Sdim return SourceRange(getTemplateQualifierRange().getBegin(), 369199482Srdivacky getTemplateNameLoc()); 370199482Srdivacky return SourceRange(getTemplateNameLoc()); 371212904Sdim 372218893Sdim case TemplateArgument::TemplateExpansion: 373218893Sdim if (getTemplateQualifierRange().isValid()) 374218893Sdim return SourceRange(getTemplateQualifierRange().getBegin(), 375218893Sdim getTemplateEllipsisLoc()); 376218893Sdim return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 377218893Sdim 378198893Srdivacky case TemplateArgument::Integral: 379198893Srdivacky case TemplateArgument::Pack: 380198893Srdivacky case TemplateArgument::Null: 381198893Srdivacky return SourceRange(); 382198893Srdivacky } 383198893Srdivacky 384198893Srdivacky // Silence bonus gcc warning. 385198893Srdivacky return SourceRange(); 386198893Srdivacky} 387208600Srdivacky 388218893SdimTemplateArgumentLoc 389218893SdimTemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 390218893Sdim llvm::Optional<unsigned> &NumExpansions, 391218893Sdim ASTContext &Context) const { 392218893Sdim assert(Argument.isPackExpansion()); 393218893Sdim 394218893Sdim switch (Argument.getKind()) { 395218893Sdim case TemplateArgument::Type: { 396218893Sdim // FIXME: We shouldn't ever have to worry about missing 397218893Sdim // type-source info! 398218893Sdim TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 399218893Sdim if (!ExpansionTSInfo) 400218893Sdim ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 401218893Sdim getArgument().getAsType(), 402218893Sdim Ellipsis); 403218893Sdim PackExpansionTypeLoc Expansion 404218893Sdim = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 405218893Sdim Ellipsis = Expansion.getEllipsisLoc(); 406218893Sdim 407218893Sdim TypeLoc Pattern = Expansion.getPatternLoc(); 408218893Sdim NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 409218893Sdim 410218893Sdim // FIXME: This is horrible. We know where the source location data is for 411218893Sdim // the pattern, and we have the pattern's type, but we are forced to copy 412218893Sdim // them into an ASTContext because TypeSourceInfo bundles them together 413218893Sdim // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 414218893Sdim TypeSourceInfo *PatternTSInfo 415218893Sdim = Context.CreateTypeSourceInfo(Pattern.getType(), 416218893Sdim Pattern.getFullDataSize()); 417218893Sdim memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 418218893Sdim Pattern.getOpaqueData(), Pattern.getFullDataSize()); 419218893Sdim return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 420218893Sdim PatternTSInfo); 421218893Sdim } 422218893Sdim 423218893Sdim case TemplateArgument::Expression: { 424218893Sdim PackExpansionExpr *Expansion 425218893Sdim = cast<PackExpansionExpr>(Argument.getAsExpr()); 426218893Sdim Expr *Pattern = Expansion->getPattern(); 427218893Sdim Ellipsis = Expansion->getEllipsisLoc(); 428218893Sdim NumExpansions = Expansion->getNumExpansions(); 429218893Sdim return TemplateArgumentLoc(Pattern, Pattern); 430218893Sdim } 431218893Sdim 432218893Sdim case TemplateArgument::TemplateExpansion: 433218893Sdim Ellipsis = getTemplateEllipsisLoc(); 434218893Sdim NumExpansions = Argument.getNumTemplateExpansions(); 435218893Sdim return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 436218893Sdim getTemplateQualifierRange(), 437218893Sdim getTemplateNameLoc()); 438218893Sdim 439218893Sdim case TemplateArgument::Declaration: 440218893Sdim case TemplateArgument::Template: 441218893Sdim case TemplateArgument::Integral: 442218893Sdim case TemplateArgument::Pack: 443218893Sdim case TemplateArgument::Null: 444218893Sdim return TemplateArgumentLoc(); 445218893Sdim } 446218893Sdim 447218893Sdim return TemplateArgumentLoc(); 448218893Sdim} 449218893Sdim 450208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 451208600Srdivacky const TemplateArgument &Arg) { 452208600Srdivacky switch (Arg.getKind()) { 453208600Srdivacky case TemplateArgument::Null: 454212904Sdim // This is bad, but not as bad as crashing because of argument 455212904Sdim // count mismatches. 456212904Sdim return DB << "(null template argument)"; 457208600Srdivacky 458208600Srdivacky case TemplateArgument::Type: 459208600Srdivacky return DB << Arg.getAsType(); 460208600Srdivacky 461208600Srdivacky case TemplateArgument::Declaration: 462208600Srdivacky return DB << Arg.getAsDecl(); 463208600Srdivacky 464208600Srdivacky case TemplateArgument::Integral: 465208600Srdivacky return DB << Arg.getAsIntegral()->toString(10); 466208600Srdivacky 467208600Srdivacky case TemplateArgument::Template: 468208600Srdivacky return DB << Arg.getAsTemplate(); 469218893Sdim 470218893Sdim case TemplateArgument::TemplateExpansion: 471218893Sdim return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 472218893Sdim 473208600Srdivacky case TemplateArgument::Expression: { 474208600Srdivacky // This shouldn't actually ever happen, so it's okay that we're 475208600Srdivacky // regurgitating an expression here. 476208600Srdivacky // FIXME: We're guessing at LangOptions! 477208600Srdivacky llvm::SmallString<32> Str; 478208600Srdivacky llvm::raw_svector_ostream OS(Str); 479208600Srdivacky LangOptions LangOpts; 480208600Srdivacky LangOpts.CPlusPlus = true; 481208600Srdivacky PrintingPolicy Policy(LangOpts); 482208600Srdivacky Arg.getAsExpr()->printPretty(OS, 0, Policy); 483208600Srdivacky return DB << OS.str(); 484208600Srdivacky } 485208600Srdivacky 486218893Sdim case TemplateArgument::Pack: { 487218893Sdim // FIXME: We're guessing at LangOptions! 488218893Sdim llvm::SmallString<32> Str; 489218893Sdim llvm::raw_svector_ostream OS(Str); 490218893Sdim LangOptions LangOpts; 491218893Sdim LangOpts.CPlusPlus = true; 492218893Sdim PrintingPolicy Policy(LangOpts); 493218893Sdim Arg.print(Policy, OS); 494218893Sdim return DB << OS.str(); 495208600Srdivacky } 496218893Sdim } 497208600Srdivacky 498208600Srdivacky return DB; 499208600Srdivacky} 500