TemplateBase.h revision 2be29f423acad3bbe39099a78db2805acb5bdf17
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 24namespace llvm { 25 class FoldingSetNodeID; 26 class raw_ostream; 27} 28 29namespace clang { 30 31class Decl; 32class DiagnosticBuilder; 33class Expr; 34struct PrintingPolicy; 35class TypeSourceInfo; 36 37/// \brief Represents a template argument within a class template 38/// specialization. 39class TemplateArgument { 40public: 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 69private: 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 91public: 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. 239 bool isDependent() const; 240 241 /// \brief Whether this template argument contains an unexpanded 242 /// parameter pack. 243 bool containsUnexpandedParameterPack() const; 244 245 /// \brief Determine whether this template argument is a pack expansion. 246 bool isPackExpansion() const; 247 248 /// \brief Retrieve the template argument as a type. 249 QualType getAsType() const { 250 if (Kind != Type) 251 return QualType(); 252 253 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 254 } 255 256 /// \brief Retrieve the template argument as a declaration. 257 Decl *getAsDecl() const { 258 if (Kind != Declaration) 259 return 0; 260 return reinterpret_cast<Decl *>(TypeOrValue); 261 } 262 263 /// \brief Retrieve the template argument as a template name. 264 TemplateName getAsTemplate() const { 265 if (Kind != Template) 266 return TemplateName(); 267 268 return TemplateName::getFromVoidPointer(TemplateArg.Name); 269 } 270 271 /// \brief Retrieve the template argument as a template name; if the argument 272 /// is a pack expansion, return the pattern as a template name. 273 TemplateName getAsTemplateOrTemplatePattern() const { 274 if (Kind != Template && Kind != TemplateExpansion) 275 return TemplateName(); 276 277 return TemplateName::getFromVoidPointer(TemplateArg.Name); 278 } 279 280 /// \brief Retrieve the number of expansions that a template template argument 281 /// expansion will produce, if known. 282 llvm::Optional<unsigned> getNumTemplateExpansions() const; 283 284 /// \brief Retrieve the template argument as an integral value. 285 llvm::APSInt *getAsIntegral() { 286 if (Kind != Integral) 287 return 0; 288 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); 289 } 290 291 const llvm::APSInt *getAsIntegral() const { 292 return const_cast<TemplateArgument*>(this)->getAsIntegral(); 293 } 294 295 /// \brief Retrieve the type of the integral value. 296 QualType getIntegralType() const { 297 if (Kind != Integral) 298 return QualType(); 299 300 return QualType::getFromOpaquePtr(Integer.Type); 301 } 302 303 void setIntegralType(QualType T) { 304 assert(Kind == Integral && 305 "Cannot set the integral type of a non-integral template argument"); 306 Integer.Type = T.getAsOpaquePtr(); 307 } 308 309 /// \brief Retrieve the template argument as an expression. 310 Expr *getAsExpr() const { 311 if (Kind != Expression) 312 return 0; 313 314 return reinterpret_cast<Expr *>(TypeOrValue); 315 } 316 317 /// \brief Iterator that traverses the elements of a template argument pack. 318 typedef const TemplateArgument * pack_iterator; 319 320 /// \brief Iterator referencing the first argument of a template argument 321 /// pack. 322 pack_iterator pack_begin() const { 323 assert(Kind == Pack); 324 return Args.Args; 325 } 326 327 /// \brief Iterator referencing one past the last argument of a template 328 /// argument pack. 329 pack_iterator pack_end() const { 330 assert(Kind == Pack); 331 return Args.Args + Args.NumArgs; 332 } 333 334 /// \brief The number of template arguments in the given template argument 335 /// pack. 336 unsigned pack_size() const { 337 assert(Kind == Pack); 338 return Args.NumArgs; 339 } 340 341 /// Determines whether two template arguments are superficially the 342 /// same. 343 bool structurallyEquals(const TemplateArgument &Other) const; 344 345 /// \brief When the template argument is a pack expansion, returns 346 /// the pattern of the pack expansion. 347 /// 348 /// \param Ellipsis Will be set to the location of the ellipsis. 349 TemplateArgument getPackExpansionPattern() const; 350 351 /// \brief Print this template argument to the given output stream. 352 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const; 353 354 /// \brief Used to insert TemplateArguments into FoldingSets. 355 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 356}; 357 358/// Location information for a TemplateArgument. 359struct TemplateArgumentLocInfo { 360private: 361 union { 362 Expr *Expression; 363 TypeSourceInfo *Declarator; 364 struct { 365 unsigned QualifierRange[2]; 366 unsigned TemplateNameLoc; 367 unsigned EllipsisLoc; 368 } Template; 369 }; 370 371public: 372 TemplateArgumentLocInfo(); 373 374 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 375 376 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 377 378 TemplateArgumentLocInfo(SourceRange QualifierRange, 379 SourceLocation TemplateNameLoc, 380 SourceLocation EllipsisLoc) 381 { 382 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); 383 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); 384 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 385 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 386 } 387 388 TypeSourceInfo *getAsTypeSourceInfo() const { 389 return Declarator; 390 } 391 392 Expr *getAsExpr() const { 393 return Expression; 394 } 395 396 SourceRange getTemplateQualifierRange() const { 397 return SourceRange( 398 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), 399 SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); 400 } 401 402 SourceLocation getTemplateNameLoc() const { 403 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 404 } 405 406 SourceLocation getTemplateEllipsisLoc() const { 407 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 408 } 409}; 410 411/// Location wrapper for a TemplateArgument. TemplateArgument is to 412/// TemplateArgumentLoc as Type is to TypeLoc. 413class TemplateArgumentLoc { 414 TemplateArgument Argument; 415 TemplateArgumentLocInfo LocInfo; 416 417public: 418 TemplateArgumentLoc() {} 419 420 TemplateArgumentLoc(const TemplateArgument &Argument, 421 TemplateArgumentLocInfo Opaque) 422 : Argument(Argument), LocInfo(Opaque) { 423 } 424 425 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 426 : Argument(Argument), LocInfo(TInfo) { 427 assert(Argument.getKind() == TemplateArgument::Type); 428 } 429 430 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 431 : Argument(Argument), LocInfo(E) { 432 assert(Argument.getKind() == TemplateArgument::Expression); 433 } 434 435 TemplateArgumentLoc(const TemplateArgument &Argument, 436 SourceRange QualifierRange, 437 SourceLocation TemplateNameLoc, 438 SourceLocation EllipsisLoc = SourceLocation()) 439 : Argument(Argument), 440 LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { 441 assert(Argument.getKind() == TemplateArgument::Template || 442 Argument.getKind() == TemplateArgument::TemplateExpansion); 443 } 444 445 /// \brief - Fetches the primary location of the argument. 446 SourceLocation getLocation() const { 447 if (Argument.getKind() == TemplateArgument::Template || 448 Argument.getKind() == TemplateArgument::TemplateExpansion) 449 return getTemplateNameLoc(); 450 451 return getSourceRange().getBegin(); 452 } 453 454 /// \brief - Fetches the full source range of the argument. 455 SourceRange getSourceRange() const; 456 457 const TemplateArgument &getArgument() const { 458 return Argument; 459 } 460 461 TemplateArgumentLocInfo getLocInfo() const { 462 return LocInfo; 463 } 464 465 TypeSourceInfo *getTypeSourceInfo() const { 466 assert(Argument.getKind() == TemplateArgument::Type); 467 return LocInfo.getAsTypeSourceInfo(); 468 } 469 470 Expr *getSourceExpression() const { 471 assert(Argument.getKind() == TemplateArgument::Expression); 472 return LocInfo.getAsExpr(); 473 } 474 475 Expr *getSourceDeclExpression() const { 476 assert(Argument.getKind() == TemplateArgument::Declaration); 477 return LocInfo.getAsExpr(); 478 } 479 480 SourceRange getTemplateQualifierRange() const { 481 assert(Argument.getKind() == TemplateArgument::Template || 482 Argument.getKind() == TemplateArgument::TemplateExpansion); 483 return LocInfo.getTemplateQualifierRange(); 484 } 485 486 SourceLocation getTemplateNameLoc() const { 487 assert(Argument.getKind() == TemplateArgument::Template || 488 Argument.getKind() == TemplateArgument::TemplateExpansion); 489 return LocInfo.getTemplateNameLoc(); 490 } 491 492 SourceLocation getTemplateEllipsisLoc() const { 493 assert(Argument.getKind() == TemplateArgument::TemplateExpansion); 494 return LocInfo.getTemplateEllipsisLoc(); 495 } 496 497 /// \brief When the template argument is a pack expansion, returns 498 /// the pattern of the pack expansion. 499 /// 500 /// \param Ellipsis Will be set to the location of the ellipsis. 501 /// 502 /// \param NumExpansions Will be set to the number of expansions that will 503 /// be generated from this pack expansion, if known a priori. 504 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, 505 llvm::Optional<unsigned> &NumExpansions, 506 ASTContext &Context) const; 507}; 508 509/// A convenient class for passing around template argument 510/// information. Designed to be passed by reference. 511class TemplateArgumentListInfo { 512 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; 513 SourceLocation LAngleLoc; 514 SourceLocation RAngleLoc; 515 516public: 517 TemplateArgumentListInfo() {} 518 519 TemplateArgumentListInfo(SourceLocation LAngleLoc, 520 SourceLocation RAngleLoc) 521 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 522 523 SourceLocation getLAngleLoc() const { return LAngleLoc; } 524 SourceLocation getRAngleLoc() const { return RAngleLoc; } 525 526 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 527 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 528 529 unsigned size() const { return Arguments.size(); } 530 531 const TemplateArgumentLoc *getArgumentArray() const { 532 return Arguments.data(); 533 } 534 535 const TemplateArgumentLoc &operator[](unsigned I) const { 536 return Arguments[I]; 537 } 538 539 void addArgument(const TemplateArgumentLoc &Loc) { 540 Arguments.push_back(Loc); 541 } 542}; 543 544const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 545 const TemplateArgument &Arg); 546 547inline TemplateSpecializationType::iterator 548 TemplateSpecializationType::end() const { 549 return getArgs() + getNumArgs(); 550} 551 552inline DependentTemplateSpecializationType::iterator 553 DependentTemplateSpecializationType::end() const { 554 return getArgs() + getNumArgs(); 555} 556 557inline const TemplateArgument & 558 TemplateSpecializationType::getArg(unsigned Idx) const { 559 assert(Idx < getNumArgs() && "Template argument out of range"); 560 return getArgs()[Idx]; 561} 562 563inline const TemplateArgument & 564 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 565 assert(Idx < getNumArgs() && "Template argument out of range"); 566 return getArgs()[Idx]; 567} 568 569} // end namespace clang 570 571#endif 572