1 //===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// 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 provides definitions which are common for all kinds of 11 // template representation. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H 16 #define LLVM_CLANG_AST_TEMPLATEBASE_H 17 18 #include "llvm/ADT/APSInt.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "clang/AST/Type.h" 22 #include "clang/AST/TemplateName.h" 23 24 namespace llvm { 25 class FoldingSetNodeID; 26 class raw_ostream; 27 } 28 29 namespace clang { 30 31 class Decl; 32 class DiagnosticBuilder; 33 class Expr; 34 struct PrintingPolicy; 35 class TypeSourceInfo; 36 37 /// \brief Represents a template argument within a class template 38 /// specialization. 39 class TemplateArgument { 40 public: 41 /// \brief The kind of template argument we're storing. 42 enum ArgKind { 43 /// \brief Represents an empty template argument, e.g., one that has not 44 /// been deduced. 45 Null = 0, 46 /// The template argument is a type. Its value is stored in the 47 /// TypeOrValue field. 48 Type, 49 /// The template argument is a declaration that was provided for a pointer 50 /// or reference non-type template parameter. 51 Declaration, 52 /// The template argument is an integral value stored in an llvm::APSInt 53 /// that was provided for an integral non-type template parameter. 54 Integral, 55 /// The template argument is a template name that was provided for a 56 /// template template parameter. 57 Template, 58 /// The template argument is a pack expansion of a template name that was 59 /// provided for a template template parameter. 60 TemplateExpansion, 61 /// The template argument is a value- or type-dependent expression 62 /// stored in an Expr*. 63 Expression, 64 /// The template argument is actually a parameter pack. Arguments are stored 65 /// in the Args struct. 66 Pack 67 }; 68 69 private: 70 /// \brief The kind of template argument we're storing. 71 unsigned Kind; 72 73 union { 74 uintptr_t TypeOrValue; 75 struct { 76 char Value[sizeof(llvm::APSInt)]; 77 void *Type; 78 } Integer; 79 struct { 80 const TemplateArgument *Args; 81 unsigned NumArgs; 82 } Args; 83 struct { 84 void *Name; 85 unsigned NumExpansions; 86 } TemplateArg; 87 }; 88 89 TemplateArgument(TemplateName, bool); // DO NOT USE 90 91 public: 92 /// \brief Construct an empty, invalid template argument. 93 TemplateArgument() : Kind(Null), TypeOrValue(0) { } 94 95 /// \brief Construct a template type argument. 96 TemplateArgument(QualType T) : Kind(Type) { 97 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); 98 } 99 100 /// \brief Construct a template argument that refers to a 101 /// declaration, which is either an external declaration or a 102 /// template declaration. 103 TemplateArgument(Decl *D) : Kind(Declaration) { 104 // FIXME: Need to be sure we have the "canonical" declaration! 105 TypeOrValue = reinterpret_cast<uintptr_t>(D); 106 } 107 108 /// \brief Construct an integral constant template argument. 109 TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { 110 // FIXME: Large integral values will get leaked. Do something 111 // similar to what we did with IntegerLiteral. 112 new (Integer.Value) llvm::APSInt(Value); 113 Integer.Type = Type.getAsOpaquePtr(); 114 } 115 116 /// \brief Construct a template argument that is a template. 117 /// 118 /// This form of template argument is generally used for template template 119 /// parameters. However, the template name could be a dependent template 120 /// name that ends up being instantiated to a function template whose address 121 /// is taken. 122 /// 123 /// \param Name The template name. 124 TemplateArgument(TemplateName Name) : Kind(Template) 125 { 126 TemplateArg.Name = Name.getAsVoidPointer(); 127 TemplateArg.NumExpansions = 0; 128 } 129 130 /// \brief Construct a template argument that is a template pack expansion. 131 /// 132 /// This form of template argument is generally used for template template 133 /// parameters. However, the template name could be a dependent template 134 /// name that ends up being instantiated to a function template whose address 135 /// is taken. 136 /// 137 /// \param Name The template name. 138 /// 139 /// \param NumExpansions The number of expansions that will be generated by 140 /// instantiating 141 TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) 142 : Kind(TemplateExpansion) 143 { 144 TemplateArg.Name = Name.getAsVoidPointer(); 145 if (NumExpansions) 146 TemplateArg.NumExpansions = *NumExpansions + 1; 147 else 148 TemplateArg.NumExpansions = 0; 149 } 150 151 /// \brief Construct a template argument that is an expression. 152 /// 153 /// This form of template argument only occurs in template argument 154 /// lists used for dependent types and for expression; it will not 155 /// occur in a non-dependent, canonical template argument list. 156 TemplateArgument(Expr *E) : Kind(Expression) { 157 TypeOrValue = reinterpret_cast<uintptr_t>(E); 158 } 159 160 /// \brief Construct a template argument that is a template argument pack. 161 /// 162 /// We assume that storage for the template arguments provided 163 /// outlives the TemplateArgument itself. 164 TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){ 165 this->Args.Args = Args; 166 this->Args.NumArgs = NumArgs; 167 } 168 169 /// \brief Copy constructor for a template argument. 170 TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { 171 // FIXME: Large integral values will get leaked. Do something 172 // similar to what we did with IntegerLiteral. 173 if (Kind == Integral) { 174 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 175 Integer.Type = Other.Integer.Type; 176 } else if (Kind == Pack) { 177 Args.NumArgs = Other.Args.NumArgs; 178 Args.Args = Other.Args.Args; 179 } else if (Kind == Template || Kind == TemplateExpansion) { 180 TemplateArg.Name = Other.TemplateArg.Name; 181 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; 182 } else 183 TypeOrValue = Other.TypeOrValue; 184 } 185 186 TemplateArgument& operator=(const TemplateArgument& Other) { 187 using llvm::APSInt; 188 189 if (Kind == Other.Kind && Kind == Integral) { 190 // Copy integral values. 191 *this->getAsIntegral() = *Other.getAsIntegral(); 192 Integer.Type = Other.Integer.Type; 193 return *this; 194 } 195 196 // Destroy the current integral value, if that's what we're holding. 197 if (Kind == Integral) 198 getAsIntegral()->~APSInt(); 199 200 Kind = Other.Kind; 201 202 if (Other.Kind == Integral) { 203 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 204 Integer.Type = Other.Integer.Type; 205 } else if (Other.Kind == Pack) { 206 Args.NumArgs = Other.Args.NumArgs; 207 Args.Args = Other.Args.Args; 208 } else if (Kind == Template || Kind == TemplateExpansion) { 209 TemplateArg.Name = Other.TemplateArg.Name; 210 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; 211 } else { 212 TypeOrValue = Other.TypeOrValue; 213 } 214 215 return *this; 216 } 217 218 ~TemplateArgument() { 219 using llvm::APSInt; 220 221 if (Kind == Integral) 222 getAsIntegral()->~APSInt(); 223 } 224 225 /// \brief Create a new template argument pack by copying the given set of 226 /// template arguments. 227 static TemplateArgument CreatePackCopy(ASTContext &Context, 228 const TemplateArgument *Args, 229 unsigned NumArgs); 230 231 /// \brief Return the kind of stored template argument. 232 ArgKind getKind() const { return (ArgKind)Kind; } 233 234 /// \brief Determine whether this template argument has no value. 235 bool isNull() const { return Kind == Null; } 236 237 /// \brief Whether this template argument is dependent on a template 238 /// parameter such that its result can change from one instantiation to 239 /// another. 240 bool isDependent() const; 241 242 /// \brief Whether this template argument is dependent on a template 243 /// parameter. 244 bool isInstantiationDependent() const; 245 246 /// \brief Whether this template argument contains an unexpanded 247 /// parameter pack. 248 bool containsUnexpandedParameterPack() const; 249 250 /// \brief Determine whether this template argument is a pack expansion. 251 bool isPackExpansion() const; 252 253 /// \brief Retrieve the template argument as a type. 254 QualType getAsType() const { 255 if (Kind != Type) 256 return QualType(); 257 258 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 259 } 260 261 /// \brief Retrieve the template argument as a declaration. 262 Decl *getAsDecl() const { 263 if (Kind != Declaration) 264 return 0; 265 return reinterpret_cast<Decl *>(TypeOrValue); 266 } 267 268 /// \brief Retrieve the template argument as a template name. 269 TemplateName getAsTemplate() const { 270 if (Kind != Template) 271 return TemplateName(); 272 273 return TemplateName::getFromVoidPointer(TemplateArg.Name); 274 } 275 276 /// \brief Retrieve the template argument as a template name; if the argument 277 /// is a pack expansion, return the pattern as a template name. 278 TemplateName getAsTemplateOrTemplatePattern() const { 279 if (Kind != Template && Kind != TemplateExpansion) 280 return TemplateName(); 281 282 return TemplateName::getFromVoidPointer(TemplateArg.Name); 283 } 284 285 /// \brief Retrieve the number of expansions that a template template argument 286 /// expansion will produce, if known. 287 llvm::Optional<unsigned> getNumTemplateExpansions() const; 288 289 /// \brief Retrieve the template argument as an integral value. 290 llvm::APSInt *getAsIntegral() { 291 if (Kind != Integral) 292 return 0; 293 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); 294 } 295 296 const llvm::APSInt *getAsIntegral() const { 297 return const_cast<TemplateArgument*>(this)->getAsIntegral(); 298 } 299 300 /// \brief Retrieve the type of the integral value. 301 QualType getIntegralType() const { 302 if (Kind != Integral) 303 return QualType(); 304 305 return QualType::getFromOpaquePtr(Integer.Type); 306 } 307 308 void setIntegralType(QualType T) { 309 assert(Kind == Integral && 310 "Cannot set the integral type of a non-integral template argument"); 311 Integer.Type = T.getAsOpaquePtr(); 312 } 313 314 /// \brief Retrieve the template argument as an expression. 315 Expr *getAsExpr() const { 316 if (Kind != Expression) 317 return 0; 318 319 return reinterpret_cast<Expr *>(TypeOrValue); 320 } 321 322 /// \brief Iterator that traverses the elements of a template argument pack. 323 typedef const TemplateArgument * pack_iterator; 324 325 /// \brief Iterator referencing the first argument of a template argument 326 /// pack. 327 pack_iterator pack_begin() const { 328 assert(Kind == Pack); 329 return Args.Args; 330 } 331 332 /// \brief Iterator referencing one past the last argument of a template 333 /// argument pack. 334 pack_iterator pack_end() const { 335 assert(Kind == Pack); 336 return Args.Args + Args.NumArgs; 337 } 338 339 /// \brief The number of template arguments in the given template argument 340 /// pack. 341 unsigned pack_size() const { 342 assert(Kind == Pack); 343 return Args.NumArgs; 344 } 345 346 /// Determines whether two template arguments are superficially the 347 /// same. 348 bool structurallyEquals(const TemplateArgument &Other) const; 349 350 /// \brief When the template argument is a pack expansion, returns 351 /// the pattern of the pack expansion. 352 /// 353 /// \param Ellipsis Will be set to the location of the ellipsis. 354 TemplateArgument getPackExpansionPattern() const; 355 356 /// \brief Print this template argument to the given output stream. 357 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const; 358 359 /// \brief Used to insert TemplateArguments into FoldingSets. 360 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 361 }; 362 363 /// Location information for a TemplateArgument. 364 struct TemplateArgumentLocInfo { 365 private: 366 union { 367 Expr *Expression; 368 TypeSourceInfo *Declarator; 369 struct { 370 // FIXME: We'd like to just use the qualifier in the TemplateName, 371 // but template arguments get canonicalized too quickly. 372 NestedNameSpecifier *Qualifier; 373 void *QualifierLocData; 374 unsigned TemplateNameLoc; 375 unsigned EllipsisLoc; 376 } Template; 377 }; 378 379 public: 380 TemplateArgumentLocInfo(); 381 382 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 383 384 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 385 386 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, 387 SourceLocation TemplateNameLoc, 388 SourceLocation EllipsisLoc) 389 { 390 Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); 391 Template.QualifierLocData = QualifierLoc.getOpaqueData(); 392 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 393 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 394 } 395 396 TypeSourceInfo *getAsTypeSourceInfo() const { 397 return Declarator; 398 } 399 400 Expr *getAsExpr() const { 401 return Expression; 402 } 403 404 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 405 return NestedNameSpecifierLoc(Template.Qualifier, 406 Template.QualifierLocData); 407 } 408 409 SourceLocation getTemplateNameLoc() const { 410 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 411 } 412 413 SourceLocation getTemplateEllipsisLoc() const { 414 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 415 } 416 }; 417 418 /// Location wrapper for a TemplateArgument. TemplateArgument is to 419 /// TemplateArgumentLoc as Type is to TypeLoc. 420 class TemplateArgumentLoc { 421 TemplateArgument Argument; 422 TemplateArgumentLocInfo LocInfo; 423 424 public: 425 TemplateArgumentLoc() {} 426 427 TemplateArgumentLoc(const TemplateArgument &Argument, 428 TemplateArgumentLocInfo Opaque) 429 : Argument(Argument), LocInfo(Opaque) { 430 } 431 432 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 433 : Argument(Argument), LocInfo(TInfo) { 434 assert(Argument.getKind() == TemplateArgument::Type); 435 } 436 437 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 438 : Argument(Argument), LocInfo(E) { 439 assert(Argument.getKind() == TemplateArgument::Expression); 440 } 441 442 TemplateArgumentLoc(const TemplateArgument &Argument, 443 NestedNameSpecifierLoc QualifierLoc, 444 SourceLocation TemplateNameLoc, 445 SourceLocation EllipsisLoc = SourceLocation()) 446 : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { 447 assert(Argument.getKind() == TemplateArgument::Template || 448 Argument.getKind() == TemplateArgument::TemplateExpansion); 449 } 450 451 /// \brief - Fetches the primary location of the argument. 452 SourceLocation getLocation() const { 453 if (Argument.getKind() == TemplateArgument::Template || 454 Argument.getKind() == TemplateArgument::TemplateExpansion) 455 return getTemplateNameLoc(); 456 457 return getSourceRange().getBegin(); 458 } 459 460 /// \brief - Fetches the full source range of the argument. 461 SourceRange getSourceRange() const; 462 463 const TemplateArgument &getArgument() const { 464 return Argument; 465 } 466 467 TemplateArgumentLocInfo getLocInfo() const { 468 return LocInfo; 469 } 470 471 TypeSourceInfo *getTypeSourceInfo() const { 472 assert(Argument.getKind() == TemplateArgument::Type); 473 return LocInfo.getAsTypeSourceInfo(); 474 } 475 476 Expr *getSourceExpression() const { 477 assert(Argument.getKind() == TemplateArgument::Expression); 478 return LocInfo.getAsExpr(); 479 } 480 481 Expr *getSourceDeclExpression() const { 482 assert(Argument.getKind() == TemplateArgument::Declaration); 483 return LocInfo.getAsExpr(); 484 } 485 486 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 487 assert(Argument.getKind() == TemplateArgument::Template || 488 Argument.getKind() == TemplateArgument::TemplateExpansion); 489 return LocInfo.getTemplateQualifierLoc(); 490 } 491 492 SourceLocation getTemplateNameLoc() const { 493 assert(Argument.getKind() == TemplateArgument::Template || 494 Argument.getKind() == TemplateArgument::TemplateExpansion); 495 return LocInfo.getTemplateNameLoc(); 496 } 497 498 SourceLocation getTemplateEllipsisLoc() const { 499 assert(Argument.getKind() == TemplateArgument::TemplateExpansion); 500 return LocInfo.getTemplateEllipsisLoc(); 501 } 502 503 /// \brief When the template argument is a pack expansion, returns 504 /// the pattern of the pack expansion. 505 /// 506 /// \param Ellipsis Will be set to the location of the ellipsis. 507 /// 508 /// \param NumExpansions Will be set to the number of expansions that will 509 /// be generated from this pack expansion, if known a priori. 510 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, 511 llvm::Optional<unsigned> &NumExpansions, 512 ASTContext &Context) const; 513 }; 514 515 /// A convenient class for passing around template argument 516 /// information. Designed to be passed by reference. 517 class TemplateArgumentListInfo { 518 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; 519 SourceLocation LAngleLoc; 520 SourceLocation RAngleLoc; 521 522 public: 523 TemplateArgumentListInfo() {} 524 525 TemplateArgumentListInfo(SourceLocation LAngleLoc, 526 SourceLocation RAngleLoc) 527 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 528 529 SourceLocation getLAngleLoc() const { return LAngleLoc; } 530 SourceLocation getRAngleLoc() const { return RAngleLoc; } 531 532 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 533 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 534 535 unsigned size() const { return Arguments.size(); } 536 537 const TemplateArgumentLoc *getArgumentArray() const { 538 return Arguments.data(); 539 } 540 541 const TemplateArgumentLoc &operator[](unsigned I) const { 542 return Arguments[I]; 543 } 544 545 void addArgument(const TemplateArgumentLoc &Loc) { 546 Arguments.push_back(Loc); 547 } 548 }; 549 550 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 551 const TemplateArgument &Arg); 552 553 inline TemplateSpecializationType::iterator 554 TemplateSpecializationType::end() const { 555 return getArgs() + getNumArgs(); 556 } 557 558 inline DependentTemplateSpecializationType::iterator 559 DependentTemplateSpecializationType::end() const { 560 return getArgs() + getNumArgs(); 561 } 562 563 inline const TemplateArgument & 564 TemplateSpecializationType::getArg(unsigned Idx) const { 565 assert(Idx < getNumArgs() && "Template argument out of range"); 566 return getArgs()[Idx]; 567 } 568 569 inline const TemplateArgument & 570 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 571 assert(Idx < getNumArgs() && "Template argument out of range"); 572 return getArgs()[Idx]; 573 } 574 575 } // end namespace clang 576 577 #endif 578