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