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