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