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