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