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 "llvm/Support/raw_ostream.h" 27 #include <algorithm> 28 29 using 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. 36 /// 37 /// \param Policy the printing policy for EnumConstantDecl printing. 38 static void printIntegral(const TemplateArgument &TemplArg, 39 raw_ostream &Out, const PrintingPolicy& Policy) { 40 const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); 41 const llvm::APSInt &Val = TemplArg.getAsIntegral(); 42 43 if (const EnumType *ET = T->getAs<EnumType>()) { 44 for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { 45 // In Sema::CheckTemplateArugment, enum template arguments value are 46 // extended to the size of the integer underlying the enum type. This 47 // may create a size difference between the enum value and template 48 // argument value, requiring isSameValue here instead of operator==. 49 if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { 50 ECD->printQualifiedName(Out, Policy); 51 return; 52 } 53 } 54 } 55 56 if (T->isBooleanType() && !Policy.MSVCFormatting) { 57 Out << (Val.getBoolValue() ? "true" : "false"); 58 } else if (T->isCharType()) { 59 const char Ch = Val.getZExtValue(); 60 Out << ((Ch == '\'') ? "'\\" : "'"); 61 Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); 62 Out << "'"; 63 } else { 64 Out << Val; 65 } 66 } 67 68 //===----------------------------------------------------------------------===// 69 // TemplateArgument Implementation 70 //===----------------------------------------------------------------------===// 71 72 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, 73 QualType Type) { 74 Integer.Kind = Integral; 75 // Copy the APSInt value into our decomposed form. 76 Integer.BitWidth = Value.getBitWidth(); 77 Integer.IsUnsigned = Value.isUnsigned(); 78 // If the value is large, we have to get additional memory from the ASTContext 79 unsigned NumWords = Value.getNumWords(); 80 if (NumWords > 1) { 81 void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); 82 std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); 83 Integer.pVal = static_cast<uint64_t *>(Mem); 84 } else { 85 Integer.VAL = Value.getZExtValue(); 86 } 87 88 Integer.Type = Type.getAsOpaquePtr(); 89 } 90 91 TemplateArgument 92 TemplateArgument::CreatePackCopy(ASTContext &Context, 93 ArrayRef<TemplateArgument> Args) { 94 if (Args.empty()) 95 return getEmptyPack(); 96 97 return TemplateArgument(Args.copy(Context)); 98 } 99 100 bool TemplateArgument::isDependent() const { 101 switch (getKind()) { 102 case Null: 103 llvm_unreachable("Should not have a NULL template argument"); 104 105 case Type: 106 return getAsType()->isDependentType() || 107 isa<PackExpansionType>(getAsType()); 108 109 case Template: 110 return getAsTemplate().isDependent(); 111 112 case TemplateExpansion: 113 return true; 114 115 case Declaration: 116 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 117 return DC->isDependentContext(); 118 return getAsDecl()->getDeclContext()->isDependentContext(); 119 120 case NullPtr: 121 return false; 122 123 case Integral: 124 // Never dependent 125 return false; 126 127 case Expression: 128 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() || 129 isa<PackExpansionExpr>(getAsExpr())); 130 131 case Pack: 132 for (const auto &P : pack_elements()) 133 if (P.isDependent()) 134 return true; 135 return false; 136 } 137 138 llvm_unreachable("Invalid TemplateArgument Kind!"); 139 } 140 141 bool TemplateArgument::isInstantiationDependent() const { 142 switch (getKind()) { 143 case Null: 144 llvm_unreachable("Should not have a NULL template argument"); 145 146 case Type: 147 return getAsType()->isInstantiationDependentType(); 148 149 case Template: 150 return getAsTemplate().isInstantiationDependent(); 151 152 case TemplateExpansion: 153 return true; 154 155 case Declaration: 156 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 157 return DC->isDependentContext(); 158 return getAsDecl()->getDeclContext()->isDependentContext(); 159 160 case NullPtr: 161 return false; 162 163 case Integral: 164 // Never dependent 165 return false; 166 167 case Expression: 168 return getAsExpr()->isInstantiationDependent(); 169 170 case Pack: 171 for (const auto &P : pack_elements()) 172 if (P.isInstantiationDependent()) 173 return true; 174 return false; 175 } 176 177 llvm_unreachable("Invalid TemplateArgument Kind!"); 178 } 179 180 bool TemplateArgument::isPackExpansion() const { 181 switch (getKind()) { 182 case Null: 183 case Declaration: 184 case Integral: 185 case Pack: 186 case Template: 187 case NullPtr: 188 return false; 189 190 case TemplateExpansion: 191 return true; 192 193 case Type: 194 return isa<PackExpansionType>(getAsType()); 195 196 case Expression: 197 return isa<PackExpansionExpr>(getAsExpr()); 198 } 199 200 llvm_unreachable("Invalid TemplateArgument Kind!"); 201 } 202 203 bool TemplateArgument::containsUnexpandedParameterPack() const { 204 switch (getKind()) { 205 case Null: 206 case Declaration: 207 case Integral: 208 case TemplateExpansion: 209 case NullPtr: 210 break; 211 212 case Type: 213 if (getAsType()->containsUnexpandedParameterPack()) 214 return true; 215 break; 216 217 case Template: 218 if (getAsTemplate().containsUnexpandedParameterPack()) 219 return true; 220 break; 221 222 case Expression: 223 if (getAsExpr()->containsUnexpandedParameterPack()) 224 return true; 225 break; 226 227 case Pack: 228 for (const auto &P : pack_elements()) 229 if (P.containsUnexpandedParameterPack()) 230 return true; 231 232 break; 233 } 234 235 return false; 236 } 237 238 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 239 assert(getKind() == TemplateExpansion); 240 if (TemplateArg.NumExpansions) 241 return TemplateArg.NumExpansions - 1; 242 243 return None; 244 } 245 246 QualType TemplateArgument::getNonTypeTemplateArgumentType() const { 247 switch (getKind()) { 248 case TemplateArgument::Null: 249 case TemplateArgument::Type: 250 case TemplateArgument::Template: 251 case TemplateArgument::TemplateExpansion: 252 case TemplateArgument::Pack: 253 return QualType(); 254 255 case TemplateArgument::Integral: 256 return getIntegralType(); 257 258 case TemplateArgument::Expression: 259 return getAsExpr()->getType(); 260 261 case TemplateArgument::Declaration: 262 return getParamTypeForDecl(); 263 264 case TemplateArgument::NullPtr: 265 return getNullPtrType(); 266 } 267 268 llvm_unreachable("Invalid TemplateArgument Kind!"); 269 } 270 271 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 272 const ASTContext &Context) const { 273 ID.AddInteger(getKind()); 274 switch (getKind()) { 275 case Null: 276 break; 277 278 case Type: 279 getAsType().Profile(ID); 280 break; 281 282 case NullPtr: 283 getNullPtrType().Profile(ID); 284 break; 285 286 case Declaration: 287 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); 288 break; 289 290 case Template: 291 case TemplateExpansion: { 292 TemplateName Template = getAsTemplateOrTemplatePattern(); 293 if (TemplateTemplateParmDecl *TTP 294 = dyn_cast_or_null<TemplateTemplateParmDecl>( 295 Template.getAsTemplateDecl())) { 296 ID.AddBoolean(true); 297 ID.AddInteger(TTP->getDepth()); 298 ID.AddInteger(TTP->getPosition()); 299 ID.AddBoolean(TTP->isParameterPack()); 300 } else { 301 ID.AddBoolean(false); 302 ID.AddPointer(Context.getCanonicalTemplateName(Template) 303 .getAsVoidPointer()); 304 } 305 break; 306 } 307 308 case Integral: 309 getAsIntegral().Profile(ID); 310 getIntegralType().Profile(ID); 311 break; 312 313 case Expression: 314 getAsExpr()->Profile(ID, Context, true); 315 break; 316 317 case Pack: 318 ID.AddInteger(Args.NumArgs); 319 for (unsigned I = 0; I != Args.NumArgs; ++I) 320 Args.Args[I].Profile(ID, Context); 321 } 322 } 323 324 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 325 if (getKind() != Other.getKind()) return false; 326 327 switch (getKind()) { 328 case Null: 329 case Type: 330 case Expression: 331 case Template: 332 case TemplateExpansion: 333 case NullPtr: 334 return TypeOrValue.V == Other.TypeOrValue.V; 335 336 case Declaration: 337 return getAsDecl() == Other.getAsDecl(); 338 339 case Integral: 340 return getIntegralType() == Other.getIntegralType() && 341 getAsIntegral() == Other.getAsIntegral(); 342 343 case Pack: 344 if (Args.NumArgs != Other.Args.NumArgs) return false; 345 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 346 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 347 return false; 348 return true; 349 } 350 351 llvm_unreachable("Invalid TemplateArgument Kind!"); 352 } 353 354 TemplateArgument TemplateArgument::getPackExpansionPattern() const { 355 assert(isPackExpansion()); 356 357 switch (getKind()) { 358 case Type: 359 return getAsType()->getAs<PackExpansionType>()->getPattern(); 360 361 case Expression: 362 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 363 364 case TemplateExpansion: 365 return TemplateArgument(getAsTemplateOrTemplatePattern()); 366 367 case Declaration: 368 case Integral: 369 case Pack: 370 case Null: 371 case Template: 372 case NullPtr: 373 return TemplateArgument(); 374 } 375 376 llvm_unreachable("Invalid TemplateArgument Kind!"); 377 } 378 379 void TemplateArgument::print(const PrintingPolicy &Policy, 380 raw_ostream &Out) const { 381 switch (getKind()) { 382 case Null: 383 Out << "(no value)"; 384 break; 385 386 case Type: { 387 PrintingPolicy SubPolicy(Policy); 388 SubPolicy.SuppressStrongLifetime = true; 389 getAsType().print(Out, SubPolicy); 390 break; 391 } 392 393 case Declaration: { 394 NamedDecl *ND = cast<NamedDecl>(getAsDecl()); 395 Out << '&'; 396 if (ND->getDeclName()) { 397 // FIXME: distinguish between pointer and reference args? 398 ND->printQualifiedName(Out); 399 } else { 400 Out << "(anonymous)"; 401 } 402 break; 403 } 404 405 case NullPtr: 406 Out << "nullptr"; 407 break; 408 409 case Template: 410 getAsTemplate().print(Out, Policy); 411 break; 412 413 case TemplateExpansion: 414 getAsTemplateOrTemplatePattern().print(Out, Policy); 415 Out << "..."; 416 break; 417 418 case Integral: { 419 printIntegral(*this, Out, Policy); 420 break; 421 } 422 423 case Expression: 424 getAsExpr()->printPretty(Out, nullptr, Policy); 425 break; 426 427 case Pack: 428 Out << "<"; 429 bool First = true; 430 for (const auto &P : pack_elements()) { 431 if (First) 432 First = false; 433 else 434 Out << ", "; 435 436 P.print(Policy, Out); 437 } 438 Out << ">"; 439 break; 440 } 441 } 442 443 void TemplateArgument::dump(raw_ostream &Out) const { 444 LangOptions LO; // FIXME! see also TemplateName::dump(). 445 LO.CPlusPlus = true; 446 LO.Bool = true; 447 print(PrintingPolicy(LO), Out); 448 } 449 450 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } 451 452 //===----------------------------------------------------------------------===// 453 // TemplateArgumentLoc Implementation 454 //===----------------------------------------------------------------------===// 455 456 TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 457 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 458 } 459 460 SourceRange TemplateArgumentLoc::getSourceRange() const { 461 switch (Argument.getKind()) { 462 case TemplateArgument::Expression: 463 return getSourceExpression()->getSourceRange(); 464 465 case TemplateArgument::Declaration: 466 return getSourceDeclExpression()->getSourceRange(); 467 468 case TemplateArgument::NullPtr: 469 return getSourceNullPtrExpression()->getSourceRange(); 470 471 case TemplateArgument::Type: 472 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 473 return TSI->getTypeLoc().getSourceRange(); 474 else 475 return SourceRange(); 476 477 case TemplateArgument::Template: 478 if (getTemplateQualifierLoc()) 479 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 480 getTemplateNameLoc()); 481 return SourceRange(getTemplateNameLoc()); 482 483 case TemplateArgument::TemplateExpansion: 484 if (getTemplateQualifierLoc()) 485 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 486 getTemplateEllipsisLoc()); 487 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 488 489 case TemplateArgument::Integral: 490 return getSourceIntegralExpression()->getSourceRange(); 491 492 case TemplateArgument::Pack: 493 case TemplateArgument::Null: 494 return SourceRange(); 495 } 496 497 llvm_unreachable("Invalid TemplateArgument Kind!"); 498 } 499 500 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 501 const TemplateArgument &Arg) { 502 switch (Arg.getKind()) { 503 case TemplateArgument::Null: 504 // This is bad, but not as bad as crashing because of argument 505 // count mismatches. 506 return DB << "(null template argument)"; 507 508 case TemplateArgument::Type: 509 return DB << Arg.getAsType(); 510 511 case TemplateArgument::Declaration: 512 return DB << Arg.getAsDecl(); 513 514 case TemplateArgument::NullPtr: 515 return DB << "nullptr"; 516 517 case TemplateArgument::Integral: 518 return DB << Arg.getAsIntegral().toString(10); 519 520 case TemplateArgument::Template: 521 return DB << Arg.getAsTemplate(); 522 523 case TemplateArgument::TemplateExpansion: 524 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 525 526 case TemplateArgument::Expression: { 527 // This shouldn't actually ever happen, so it's okay that we're 528 // regurgitating an expression here. 529 // FIXME: We're guessing at LangOptions! 530 SmallString<32> Str; 531 llvm::raw_svector_ostream OS(Str); 532 LangOptions LangOpts; 533 LangOpts.CPlusPlus = true; 534 PrintingPolicy Policy(LangOpts); 535 Arg.getAsExpr()->printPretty(OS, nullptr, Policy); 536 return DB << OS.str(); 537 } 538 539 case TemplateArgument::Pack: { 540 // FIXME: We're guessing at LangOptions! 541 SmallString<32> Str; 542 llvm::raw_svector_ostream OS(Str); 543 LangOptions LangOpts; 544 LangOpts.CPlusPlus = true; 545 PrintingPolicy Policy(LangOpts); 546 Arg.print(Policy, OS); 547 return DB << OS.str(); 548 } 549 } 550 551 llvm_unreachable("Invalid TemplateArgument Kind!"); 552 } 553 554 const ASTTemplateArgumentListInfo * 555 ASTTemplateArgumentListInfo::Create(ASTContext &C, 556 const TemplateArgumentListInfo &List) { 557 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); 558 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); 559 return new (Mem) ASTTemplateArgumentListInfo(List); 560 } 561 562 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( 563 const TemplateArgumentListInfo &Info) { 564 LAngleLoc = Info.getLAngleLoc(); 565 RAngleLoc = Info.getRAngleLoc(); 566 NumTemplateArgs = Info.size(); 567 568 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); 569 for (unsigned i = 0; i != NumTemplateArgs; ++i) 570 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 571 } 572 573 void ASTTemplateKWAndArgsInfo::initializeFrom( 574 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 575 TemplateArgumentLoc *OutArgArray) { 576 this->TemplateKWLoc = TemplateKWLoc; 577 LAngleLoc = Info.getLAngleLoc(); 578 RAngleLoc = Info.getRAngleLoc(); 579 NumTemplateArgs = Info.size(); 580 581 for (unsigned i = 0; i != NumTemplateArgs; ++i) 582 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 583 } 584 585 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { 586 assert(TemplateKWLoc.isValid()); 587 LAngleLoc = SourceLocation(); 588 RAngleLoc = SourceLocation(); 589 this->TemplateKWLoc = TemplateKWLoc; 590 NumTemplateArgs = 0; 591 } 592 593 void ASTTemplateKWAndArgsInfo::initializeFrom( 594 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 595 TemplateArgumentLoc *OutArgArray, bool &Dependent, 596 bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) { 597 this->TemplateKWLoc = TemplateKWLoc; 598 LAngleLoc = Info.getLAngleLoc(); 599 RAngleLoc = Info.getRAngleLoc(); 600 NumTemplateArgs = Info.size(); 601 602 for (unsigned i = 0; i != NumTemplateArgs; ++i) { 603 Dependent = Dependent || Info[i].getArgument().isDependent(); 604 InstantiationDependent = InstantiationDependent || 605 Info[i].getArgument().isInstantiationDependent(); 606 ContainsUnexpandedParameterPack = 607 ContainsUnexpandedParameterPack || 608 Info[i].getArgument().containsUnexpandedParameterPack(); 609 610 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 611 } 612 } 613 614 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, 615 TemplateArgumentListInfo &Info) const { 616 Info.setLAngleLoc(LAngleLoc); 617 Info.setRAngleLoc(RAngleLoc); 618 for (unsigned I = 0; I != NumTemplateArgs; ++I) 619 Info.addArgument(ArgArray[I]); 620 } 621