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 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 247 const ASTContext &Context) const { 248 ID.AddInteger(getKind()); 249 switch (getKind()) { 250 case Null: 251 break; 252 253 case Type: 254 getAsType().Profile(ID); 255 break; 256 257 case NullPtr: 258 getNullPtrType().Profile(ID); 259 break; 260 261 case Declaration: 262 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); 263 break; 264 265 case Template: 266 case TemplateExpansion: { 267 TemplateName Template = getAsTemplateOrTemplatePattern(); 268 if (TemplateTemplateParmDecl *TTP 269 = dyn_cast_or_null<TemplateTemplateParmDecl>( 270 Template.getAsTemplateDecl())) { 271 ID.AddBoolean(true); 272 ID.AddInteger(TTP->getDepth()); 273 ID.AddInteger(TTP->getPosition()); 274 ID.AddBoolean(TTP->isParameterPack()); 275 } else { 276 ID.AddBoolean(false); 277 ID.AddPointer(Context.getCanonicalTemplateName(Template) 278 .getAsVoidPointer()); 279 } 280 break; 281 } 282 283 case Integral: 284 getAsIntegral().Profile(ID); 285 getIntegralType().Profile(ID); 286 break; 287 288 case Expression: 289 getAsExpr()->Profile(ID, Context, true); 290 break; 291 292 case Pack: 293 ID.AddInteger(Args.NumArgs); 294 for (unsigned I = 0; I != Args.NumArgs; ++I) 295 Args.Args[I].Profile(ID, Context); 296 } 297 } 298 299 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 300 if (getKind() != Other.getKind()) return false; 301 302 switch (getKind()) { 303 case Null: 304 case Type: 305 case Expression: 306 case Template: 307 case TemplateExpansion: 308 case NullPtr: 309 return TypeOrValue.V == Other.TypeOrValue.V; 310 311 case Declaration: 312 return getAsDecl() == Other.getAsDecl(); 313 314 case Integral: 315 return getIntegralType() == Other.getIntegralType() && 316 getAsIntegral() == Other.getAsIntegral(); 317 318 case Pack: 319 if (Args.NumArgs != Other.Args.NumArgs) return false; 320 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 321 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 322 return false; 323 return true; 324 } 325 326 llvm_unreachable("Invalid TemplateArgument Kind!"); 327 } 328 329 TemplateArgument TemplateArgument::getPackExpansionPattern() const { 330 assert(isPackExpansion()); 331 332 switch (getKind()) { 333 case Type: 334 return getAsType()->getAs<PackExpansionType>()->getPattern(); 335 336 case Expression: 337 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 338 339 case TemplateExpansion: 340 return TemplateArgument(getAsTemplateOrTemplatePattern()); 341 342 case Declaration: 343 case Integral: 344 case Pack: 345 case Null: 346 case Template: 347 case NullPtr: 348 return TemplateArgument(); 349 } 350 351 llvm_unreachable("Invalid TemplateArgument Kind!"); 352 } 353 354 void TemplateArgument::print(const PrintingPolicy &Policy, 355 raw_ostream &Out) const { 356 switch (getKind()) { 357 case Null: 358 Out << "(no value)"; 359 break; 360 361 case Type: { 362 PrintingPolicy SubPolicy(Policy); 363 SubPolicy.SuppressStrongLifetime = true; 364 getAsType().print(Out, SubPolicy); 365 break; 366 } 367 368 case Declaration: { 369 NamedDecl *ND = cast<NamedDecl>(getAsDecl()); 370 Out << '&'; 371 if (ND->getDeclName()) { 372 // FIXME: distinguish between pointer and reference args? 373 ND->printQualifiedName(Out); 374 } else { 375 Out << "(anonymous)"; 376 } 377 break; 378 } 379 380 case NullPtr: 381 Out << "nullptr"; 382 break; 383 384 case Template: 385 getAsTemplate().print(Out, Policy); 386 break; 387 388 case TemplateExpansion: 389 getAsTemplateOrTemplatePattern().print(Out, Policy); 390 Out << "..."; 391 break; 392 393 case Integral: { 394 printIntegral(*this, Out, Policy); 395 break; 396 } 397 398 case Expression: 399 getAsExpr()->printPretty(Out, nullptr, Policy); 400 break; 401 402 case Pack: 403 Out << "<"; 404 bool First = true; 405 for (const auto &P : pack_elements()) { 406 if (First) 407 First = false; 408 else 409 Out << ", "; 410 411 P.print(Policy, Out); 412 } 413 Out << ">"; 414 break; 415 } 416 } 417 418 void TemplateArgument::dump(raw_ostream &Out) const { 419 LangOptions LO; // FIXME! see also TemplateName::dump(). 420 LO.CPlusPlus = true; 421 LO.Bool = true; 422 print(PrintingPolicy(LO), Out); 423 } 424 425 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } 426 427 //===----------------------------------------------------------------------===// 428 // TemplateArgumentLoc Implementation 429 //===----------------------------------------------------------------------===// 430 431 TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 432 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 433 } 434 435 SourceRange TemplateArgumentLoc::getSourceRange() const { 436 switch (Argument.getKind()) { 437 case TemplateArgument::Expression: 438 return getSourceExpression()->getSourceRange(); 439 440 case TemplateArgument::Declaration: 441 return getSourceDeclExpression()->getSourceRange(); 442 443 case TemplateArgument::NullPtr: 444 return getSourceNullPtrExpression()->getSourceRange(); 445 446 case TemplateArgument::Type: 447 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 448 return TSI->getTypeLoc().getSourceRange(); 449 else 450 return SourceRange(); 451 452 case TemplateArgument::Template: 453 if (getTemplateQualifierLoc()) 454 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 455 getTemplateNameLoc()); 456 return SourceRange(getTemplateNameLoc()); 457 458 case TemplateArgument::TemplateExpansion: 459 if (getTemplateQualifierLoc()) 460 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 461 getTemplateEllipsisLoc()); 462 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 463 464 case TemplateArgument::Integral: 465 return getSourceIntegralExpression()->getSourceRange(); 466 467 case TemplateArgument::Pack: 468 case TemplateArgument::Null: 469 return SourceRange(); 470 } 471 472 llvm_unreachable("Invalid TemplateArgument Kind!"); 473 } 474 475 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 476 const TemplateArgument &Arg) { 477 switch (Arg.getKind()) { 478 case TemplateArgument::Null: 479 // This is bad, but not as bad as crashing because of argument 480 // count mismatches. 481 return DB << "(null template argument)"; 482 483 case TemplateArgument::Type: 484 return DB << Arg.getAsType(); 485 486 case TemplateArgument::Declaration: 487 return DB << Arg.getAsDecl(); 488 489 case TemplateArgument::NullPtr: 490 return DB << "nullptr"; 491 492 case TemplateArgument::Integral: 493 return DB << Arg.getAsIntegral().toString(10); 494 495 case TemplateArgument::Template: 496 return DB << Arg.getAsTemplate(); 497 498 case TemplateArgument::TemplateExpansion: 499 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 500 501 case TemplateArgument::Expression: { 502 // This shouldn't actually ever happen, so it's okay that we're 503 // regurgitating an expression here. 504 // FIXME: We're guessing at LangOptions! 505 SmallString<32> Str; 506 llvm::raw_svector_ostream OS(Str); 507 LangOptions LangOpts; 508 LangOpts.CPlusPlus = true; 509 PrintingPolicy Policy(LangOpts); 510 Arg.getAsExpr()->printPretty(OS, nullptr, Policy); 511 return DB << OS.str(); 512 } 513 514 case TemplateArgument::Pack: { 515 // FIXME: We're guessing at LangOptions! 516 SmallString<32> Str; 517 llvm::raw_svector_ostream OS(Str); 518 LangOptions LangOpts; 519 LangOpts.CPlusPlus = true; 520 PrintingPolicy Policy(LangOpts); 521 Arg.print(Policy, OS); 522 return DB << OS.str(); 523 } 524 } 525 526 llvm_unreachable("Invalid TemplateArgument Kind!"); 527 } 528 529 const ASTTemplateArgumentListInfo * 530 ASTTemplateArgumentListInfo::Create(ASTContext &C, 531 const TemplateArgumentListInfo &List) { 532 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); 533 void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); 534 return new (Mem) ASTTemplateArgumentListInfo(List); 535 } 536 537 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( 538 const TemplateArgumentListInfo &Info) { 539 LAngleLoc = Info.getLAngleLoc(); 540 RAngleLoc = Info.getRAngleLoc(); 541 NumTemplateArgs = Info.size(); 542 543 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); 544 for (unsigned i = 0; i != NumTemplateArgs; ++i) 545 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 546 } 547 548 void ASTTemplateKWAndArgsInfo::initializeFrom( 549 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 550 TemplateArgumentLoc *OutArgArray) { 551 this->TemplateKWLoc = TemplateKWLoc; 552 LAngleLoc = Info.getLAngleLoc(); 553 RAngleLoc = Info.getRAngleLoc(); 554 NumTemplateArgs = Info.size(); 555 556 for (unsigned i = 0; i != NumTemplateArgs; ++i) 557 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 558 } 559 560 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { 561 assert(TemplateKWLoc.isValid()); 562 LAngleLoc = SourceLocation(); 563 RAngleLoc = SourceLocation(); 564 this->TemplateKWLoc = TemplateKWLoc; 565 NumTemplateArgs = 0; 566 } 567 568 void ASTTemplateKWAndArgsInfo::initializeFrom( 569 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 570 TemplateArgumentLoc *OutArgArray, bool &Dependent, 571 bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) { 572 this->TemplateKWLoc = TemplateKWLoc; 573 LAngleLoc = Info.getLAngleLoc(); 574 RAngleLoc = Info.getRAngleLoc(); 575 NumTemplateArgs = Info.size(); 576 577 for (unsigned i = 0; i != NumTemplateArgs; ++i) { 578 Dependent = Dependent || Info[i].getArgument().isDependent(); 579 InstantiationDependent = InstantiationDependent || 580 Info[i].getArgument().isInstantiationDependent(); 581 ContainsUnexpandedParameterPack = 582 ContainsUnexpandedParameterPack || 583 Info[i].getArgument().containsUnexpandedParameterPack(); 584 585 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 586 } 587 } 588 589 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, 590 TemplateArgumentListInfo &Info) const { 591 Info.setLAngleLoc(LAngleLoc); 592 Info.setRAngleLoc(RAngleLoc); 593 for (unsigned I = 0; I != NumTemplateArgs; ++I) 594 Info.addArgument(ArgArray[I]); 595 } 596