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