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