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