TemplateBase.h revision 6939fff69a3dfff2552261a1d7f1f609380fe6b0
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 286public: 287 TemplateArgumentLocInfo() : Expression(0) {} 288 289 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 290 291 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 292 293 TemplateArgumentLocInfo(SourceRange QualifierRange, 294 SourceLocation TemplateNameLoc) 295 { 296 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); 297 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); 298 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 299 } 300 301 TypeSourceInfo *getAsTypeSourceInfo() const { 302 return Declarator; 303 } 304 305 Expr *getAsExpr() const { 306 return Expression; 307 } 308 309 SourceRange getTemplateQualifierRange() const { 310 return SourceRange( 311 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), 312 SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); 313 } 314 315 SourceLocation getTemplateNameLoc() const { 316 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 317 } 318}; 319 320/// Location wrapper for a TemplateArgument. TemplateArgument is to 321/// TemplateArgumentLoc as Type is to TypeLoc. 322class TemplateArgumentLoc { 323 TemplateArgument Argument; 324 TemplateArgumentLocInfo LocInfo; 325 326public: 327 TemplateArgumentLoc() {} 328 329 TemplateArgumentLoc(const TemplateArgument &Argument, 330 TemplateArgumentLocInfo Opaque) 331 : Argument(Argument), LocInfo(Opaque) { 332 } 333 334 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 335 : Argument(Argument), LocInfo(TInfo) { 336 assert(Argument.getKind() == TemplateArgument::Type); 337 } 338 339 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 340 : Argument(Argument), LocInfo(E) { 341 assert(Argument.getKind() == TemplateArgument::Expression); 342 } 343 344 TemplateArgumentLoc(const TemplateArgument &Argument, 345 SourceRange QualifierRange, 346 SourceLocation TemplateNameLoc) 347 : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { 348 assert(Argument.getKind() == TemplateArgument::Template); 349 } 350 351 /// \brief - Fetches the primary location of the argument. 352 SourceLocation getLocation() const { 353 if (Argument.getKind() == TemplateArgument::Template) 354 return getTemplateNameLoc(); 355 356 return getSourceRange().getBegin(); 357 } 358 359 /// \brief - Fetches the full source range of the argument. 360 SourceRange getSourceRange() const; 361 362 const TemplateArgument &getArgument() const { 363 return Argument; 364 } 365 366 TemplateArgumentLocInfo getLocInfo() const { 367 return LocInfo; 368 } 369 370 TypeSourceInfo *getTypeSourceInfo() const { 371 assert(Argument.getKind() == TemplateArgument::Type); 372 return LocInfo.getAsTypeSourceInfo(); 373 } 374 375 Expr *getSourceExpression() const { 376 assert(Argument.getKind() == TemplateArgument::Expression); 377 return LocInfo.getAsExpr(); 378 } 379 380 Expr *getSourceDeclExpression() const { 381 assert(Argument.getKind() == TemplateArgument::Declaration); 382 return LocInfo.getAsExpr(); 383 } 384 385 SourceRange getTemplateQualifierRange() const { 386 assert(Argument.getKind() == TemplateArgument::Template); 387 return LocInfo.getTemplateQualifierRange(); 388 } 389 390 SourceLocation getTemplateNameLoc() const { 391 assert(Argument.getKind() == TemplateArgument::Template); 392 return LocInfo.getTemplateNameLoc(); 393 } 394}; 395 396/// A convenient class for passing around template argument 397/// information. Designed to be passed by reference. 398class TemplateArgumentListInfo { 399 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; 400 SourceLocation LAngleLoc; 401 SourceLocation RAngleLoc; 402 403public: 404 TemplateArgumentListInfo() {} 405 406 TemplateArgumentListInfo(SourceLocation LAngleLoc, 407 SourceLocation RAngleLoc) 408 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 409 410 SourceLocation getLAngleLoc() const { return LAngleLoc; } 411 SourceLocation getRAngleLoc() const { return RAngleLoc; } 412 413 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 414 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 415 416 unsigned size() const { return Arguments.size(); } 417 418 const TemplateArgumentLoc *getArgumentArray() const { 419 return Arguments.data(); 420 } 421 422 const TemplateArgumentLoc &operator[](unsigned I) const { 423 return Arguments[I]; 424 } 425 426 void addArgument(const TemplateArgumentLoc &Loc) { 427 Arguments.push_back(Loc); 428 } 429}; 430 431const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 432 const TemplateArgument &Arg); 433 434inline TemplateSpecializationType::iterator 435 TemplateSpecializationType::end() const { 436 return getArgs() + getNumArgs(); 437} 438 439inline DependentTemplateSpecializationType::iterator 440 DependentTemplateSpecializationType::end() const { 441 return getArgs() + getNumArgs(); 442} 443 444inline const TemplateArgument & 445 TemplateSpecializationType::getArg(unsigned Idx) const { 446 assert(Idx < getNumArgs() && "Template argument out of range"); 447 return getArgs()[Idx]; 448} 449 450inline const TemplateArgument & 451 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 452 assert(Idx < getNumArgs() && "Template argument out of range"); 453 return getArgs()[Idx]; 454} 455 456} // end namespace clang 457 458#endif 459