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 28 using 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. 35 static 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 57 TemplateArgument 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 68 bool 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 return false; 104 } 105 106 bool 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 return false; 142 } 143 144 bool 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 return false; 164 } 165 166 bool 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 200 llvm::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 208 void 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 257 bool 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 // Suppress warnings. 282 return false; 283 } 284 285 TemplateArgument TemplateArgument::getPackExpansionPattern() const { 286 assert(isPackExpansion()); 287 288 switch (getKind()) { 289 case Type: 290 return getAsType()->getAs<PackExpansionType>()->getPattern(); 291 292 case Expression: 293 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 294 295 case TemplateExpansion: 296 return TemplateArgument(getAsTemplateOrTemplatePattern()); 297 298 case Declaration: 299 case Integral: 300 case Pack: 301 case Null: 302 case Template: 303 return TemplateArgument(); 304 } 305 306 return TemplateArgument(); 307 } 308 309 void TemplateArgument::print(const PrintingPolicy &Policy, 310 raw_ostream &Out) const { 311 switch (getKind()) { 312 case Null: 313 Out << "<no value>"; 314 break; 315 316 case Type: { 317 PrintingPolicy SubPolicy(Policy); 318 SubPolicy.SuppressStrongLifetime = true; 319 std::string TypeStr; 320 getAsType().getAsStringInternal(TypeStr, SubPolicy); 321 Out << TypeStr; 322 break; 323 } 324 325 case Declaration: { 326 bool Unnamed = true; 327 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 328 if (ND->getDeclName()) { 329 Unnamed = false; 330 Out << ND->getNameAsString(); 331 } 332 } 333 334 if (Unnamed) { 335 Out << "<anonymous>"; 336 } 337 break; 338 } 339 340 case Template: 341 getAsTemplate().print(Out, Policy); 342 break; 343 344 case TemplateExpansion: 345 getAsTemplateOrTemplatePattern().print(Out, Policy); 346 Out << "..."; 347 break; 348 349 case Integral: { 350 printIntegral(*this, Out); 351 break; 352 } 353 354 case Expression: 355 getAsExpr()->printPretty(Out, 0, Policy); 356 break; 357 358 case Pack: 359 Out << "<"; 360 bool First = true; 361 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 362 P != PEnd; ++P) { 363 if (First) 364 First = false; 365 else 366 Out << ", "; 367 368 P->print(Policy, Out); 369 } 370 Out << ">"; 371 break; 372 } 373 } 374 375 //===----------------------------------------------------------------------===// 376 // TemplateArgumentLoc Implementation 377 //===----------------------------------------------------------------------===// 378 379 TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 380 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 381 } 382 383 SourceRange TemplateArgumentLoc::getSourceRange() const { 384 switch (Argument.getKind()) { 385 case TemplateArgument::Expression: 386 return getSourceExpression()->getSourceRange(); 387 388 case TemplateArgument::Declaration: 389 return getSourceDeclExpression()->getSourceRange(); 390 391 case TemplateArgument::Type: 392 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 393 return TSI->getTypeLoc().getSourceRange(); 394 else 395 return SourceRange(); 396 397 case TemplateArgument::Template: 398 if (getTemplateQualifierLoc()) 399 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 400 getTemplateNameLoc()); 401 return SourceRange(getTemplateNameLoc()); 402 403 case TemplateArgument::TemplateExpansion: 404 if (getTemplateQualifierLoc()) 405 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 406 getTemplateEllipsisLoc()); 407 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 408 409 case TemplateArgument::Integral: 410 case TemplateArgument::Pack: 411 case TemplateArgument::Null: 412 return SourceRange(); 413 } 414 415 // Silence bonus gcc warning. 416 return SourceRange(); 417 } 418 419 TemplateArgumentLoc 420 TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 421 llvm::Optional<unsigned> &NumExpansions, 422 ASTContext &Context) const { 423 assert(Argument.isPackExpansion()); 424 425 switch (Argument.getKind()) { 426 case TemplateArgument::Type: { 427 // FIXME: We shouldn't ever have to worry about missing 428 // type-source info! 429 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 430 if (!ExpansionTSInfo) 431 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 432 getArgument().getAsType(), 433 Ellipsis); 434 PackExpansionTypeLoc Expansion 435 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 436 Ellipsis = Expansion.getEllipsisLoc(); 437 438 TypeLoc Pattern = Expansion.getPatternLoc(); 439 NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 440 441 // FIXME: This is horrible. We know where the source location data is for 442 // the pattern, and we have the pattern's type, but we are forced to copy 443 // them into an ASTContext because TypeSourceInfo bundles them together 444 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 445 TypeSourceInfo *PatternTSInfo 446 = Context.CreateTypeSourceInfo(Pattern.getType(), 447 Pattern.getFullDataSize()); 448 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 449 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 450 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 451 PatternTSInfo); 452 } 453 454 case TemplateArgument::Expression: { 455 PackExpansionExpr *Expansion 456 = cast<PackExpansionExpr>(Argument.getAsExpr()); 457 Expr *Pattern = Expansion->getPattern(); 458 Ellipsis = Expansion->getEllipsisLoc(); 459 NumExpansions = Expansion->getNumExpansions(); 460 return TemplateArgumentLoc(Pattern, Pattern); 461 } 462 463 case TemplateArgument::TemplateExpansion: 464 Ellipsis = getTemplateEllipsisLoc(); 465 NumExpansions = Argument.getNumTemplateExpansions(); 466 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 467 getTemplateQualifierLoc(), 468 getTemplateNameLoc()); 469 470 case TemplateArgument::Declaration: 471 case TemplateArgument::Template: 472 case TemplateArgument::Integral: 473 case TemplateArgument::Pack: 474 case TemplateArgument::Null: 475 return TemplateArgumentLoc(); 476 } 477 478 return TemplateArgumentLoc(); 479 } 480 481 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 482 const TemplateArgument &Arg) { 483 switch (Arg.getKind()) { 484 case TemplateArgument::Null: 485 // This is bad, but not as bad as crashing because of argument 486 // count mismatches. 487 return DB << "(null template argument)"; 488 489 case TemplateArgument::Type: 490 return DB << Arg.getAsType(); 491 492 case TemplateArgument::Declaration: 493 return DB << Arg.getAsDecl(); 494 495 case TemplateArgument::Integral: 496 return DB << Arg.getAsIntegral()->toString(10); 497 498 case TemplateArgument::Template: 499 return DB << Arg.getAsTemplate(); 500 501 case TemplateArgument::TemplateExpansion: 502 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 503 504 case TemplateArgument::Expression: { 505 // This shouldn't actually ever happen, so it's okay that we're 506 // regurgitating an expression here. 507 // FIXME: We're guessing at LangOptions! 508 llvm::SmallString<32> Str; 509 llvm::raw_svector_ostream OS(Str); 510 LangOptions LangOpts; 511 LangOpts.CPlusPlus = true; 512 PrintingPolicy Policy(LangOpts); 513 Arg.getAsExpr()->printPretty(OS, 0, Policy); 514 return DB << OS.str(); 515 } 516 517 case TemplateArgument::Pack: { 518 // FIXME: We're guessing at LangOptions! 519 llvm::SmallString<32> Str; 520 llvm::raw_svector_ostream OS(Str); 521 LangOptions LangOpts; 522 LangOpts.CPlusPlus = true; 523 PrintingPolicy Policy(LangOpts); 524 Arg.print(Policy, OS); 525 return DB << OS.str(); 526 } 527 } 528 529 return DB; 530 } 531 532 const ASTTemplateArgumentListInfo * 533 ASTTemplateArgumentListInfo::Create(ASTContext &C, 534 const TemplateArgumentListInfo &List) { 535 std::size_t size = sizeof(CXXDependentScopeMemberExpr) + 536 ASTTemplateArgumentListInfo::sizeFor(List); 537 void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); 538 ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); 539 TAI->initializeFrom(List); 540 return TAI; 541 } 542 543 void ASTTemplateArgumentListInfo::initializeFrom( 544 const TemplateArgumentListInfo &Info) { 545 LAngleLoc = Info.getLAngleLoc(); 546 RAngleLoc = Info.getRAngleLoc(); 547 NumTemplateArgs = Info.size(); 548 549 TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); 550 for (unsigned i = 0; i != NumTemplateArgs; ++i) 551 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 552 } 553 554 void ASTTemplateArgumentListInfo::initializeFrom( 555 const TemplateArgumentListInfo &Info, 556 bool &Dependent, 557 bool &InstantiationDependent, 558 bool &ContainsUnexpandedParameterPack) { 559 LAngleLoc = Info.getLAngleLoc(); 560 RAngleLoc = Info.getRAngleLoc(); 561 NumTemplateArgs = Info.size(); 562 563 TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); 564 for (unsigned i = 0; i != NumTemplateArgs; ++i) { 565 Dependent = Dependent || Info[i].getArgument().isDependent(); 566 InstantiationDependent = InstantiationDependent || 567 Info[i].getArgument().isInstantiationDependent(); 568 ContainsUnexpandedParameterPack 569 = ContainsUnexpandedParameterPack || 570 Info[i].getArgument().containsUnexpandedParameterPack(); 571 572 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 573 } 574 } 575 576 void ASTTemplateArgumentListInfo::copyInto( 577 TemplateArgumentListInfo &Info) const { 578 Info.setLAngleLoc(LAngleLoc); 579 Info.setRAngleLoc(RAngleLoc); 580 for (unsigned I = 0; I != NumTemplateArgs; ++I) 581 Info.addArgument(getTemplateArgs()[I]); 582 } 583 584 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { 585 return sizeof(ASTTemplateArgumentListInfo) + 586 sizeof(TemplateArgumentLoc) * NumTemplateArgs; 587 } 588 589 std::size_t ASTTemplateArgumentListInfo::sizeFor( 590 const TemplateArgumentListInfo &Info) { 591 return sizeFor(Info.size()); 592 } 593