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