TemplateBase.h revision cbe12738371bec6ff20372e1d3426cffc85d8323
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 union { 243 Expr *Expression; 244 DeclaratorInfo *Declarator; 245 }; 246 247#ifndef NDEBUG 248 enum Kind { 249 K_None, 250 K_DeclaratorInfo, 251 K_Expression 252 } Kind; 253#endif 254 255public: 256 TemplateArgumentLocInfo() 257 : Expression(0) 258#ifndef NDEBUG 259 , Kind(K_None) 260#endif 261 {} 262 263 TemplateArgumentLocInfo(DeclaratorInfo *DInfo) 264 : Declarator(DInfo) 265#ifndef NDEBUG 266 , Kind(K_DeclaratorInfo) 267#endif 268 {} 269 270 TemplateArgumentLocInfo(Expr *E) 271 : Expression(E) 272#ifndef NDEBUG 273 , Kind(K_Expression) 274#endif 275 {} 276 277 DeclaratorInfo *getAsDeclaratorInfo() const { 278 assert(Kind == K_DeclaratorInfo); 279 return Declarator; 280 } 281 282 Expr *getAsExpr() const { 283 assert(Kind == K_Expression); 284 return Expression; 285 } 286 287#ifndef NDEBUG 288 void validateForArgument(const TemplateArgument &Arg) { 289 switch (Arg.getKind()) { 290 case TemplateArgument::Type: 291 assert(Kind == K_DeclaratorInfo); 292 break; 293 case TemplateArgument::Expression: 294 case TemplateArgument::Declaration: 295 assert(Kind == K_Expression); 296 break; 297 case TemplateArgument::Integral: 298 case TemplateArgument::Pack: 299 assert(Kind == K_None); 300 break; 301 case TemplateArgument::Null: 302 llvm::llvm_unreachable("source info for null template argument?"); 303 } 304 } 305#endif 306}; 307 308/// Location wrapper for a TemplateArgument. TemplateArgument is to 309/// TemplateArgumentLoc as Type is to TypeLoc. 310class TemplateArgumentLoc { 311 TemplateArgument Argument; 312 TemplateArgumentLocInfo LocInfo; 313 314public: 315 TemplateArgumentLoc() {} 316 317 TemplateArgumentLoc(const TemplateArgument &Argument, 318 TemplateArgumentLocInfo Opaque) 319 : Argument(Argument), LocInfo(Opaque) { 320 } 321 322 TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo) 323 : Argument(Argument), LocInfo(DInfo) { 324 assert(Argument.getKind() == TemplateArgument::Type); 325 } 326 327 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 328 : Argument(Argument), LocInfo(E) { 329 assert(Argument.getKind() == TemplateArgument::Expression); 330 } 331 332 /// \brief - Fetches the start location of the argument. 333 SourceLocation getLocation() const { 334 return getSourceRange().getBegin(); 335 } 336 337 /// \brief - Fetches the full source range of the argument. 338 SourceRange getSourceRange() const; 339 340 const TemplateArgument &getArgument() const { 341 return Argument; 342 } 343 344 TemplateArgumentLocInfo getLocInfo() const { 345 return LocInfo; 346 } 347 348 DeclaratorInfo *getSourceDeclaratorInfo() const { 349 assert(Argument.getKind() == TemplateArgument::Type); 350 return LocInfo.getAsDeclaratorInfo(); 351 } 352 353 Expr *getSourceExpression() const { 354 assert(Argument.getKind() == TemplateArgument::Expression); 355 return LocInfo.getAsExpr(); 356 } 357 358 Expr *getSourceDeclExpression() const { 359 assert(Argument.getKind() == TemplateArgument::Declaration); 360 return LocInfo.getAsExpr(); 361 } 362}; 363 364} 365 366#endif 367