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