TemplateBase.h revision e02e26293cf8e3bad1059b39cea75c6582896da6
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 class raw_ostream; 27} 28 29namespace clang { 30 31class Decl; 32class DiagnosticBuilder; 33class Expr; 34struct PrintingPolicy; 35class TypeSourceInfo; 36 37/// \brief Represents a template argument within a class template 38/// specialization. 39class TemplateArgument { 40public: 41 /// \brief The kind of template argument we're storing. 42 enum ArgKind { 43 /// \brief Represents an empty template argument, e.g., one that has not 44 /// been deduced. 45 Null = 0, 46 /// The template argument is a type. Its value is stored in the 47 /// TypeOrValue field. 48 Type, 49 /// The template argument is a declaration that was provided for a pointer 50 /// or reference non-type template parameter. 51 Declaration, 52 /// The template argument is an integral value stored in an llvm::APSInt 53 /// that was provided for an integral non-type template parameter. 54 Integral, 55 /// The template argument is a template name that was provided for a 56 /// template template parameter. 57 Template, 58 /// The template argument is a value- or type-dependent expression 59 /// stored in an Expr*. 60 Expression, 61 /// The template argument is actually a parameter pack. Arguments are stored 62 /// in the Args struct. 63 Pack 64 }; 65 66private: 67 /// \brief The kind of template argument we're storing. 68 unsigned Kind; 69 70 union { 71 uintptr_t TypeOrValue; 72 struct { 73 char Value[sizeof(llvm::APSInt)]; 74 void *Type; 75 } Integer; 76 struct { 77 TemplateArgument *Args; 78 unsigned NumArgs; 79 } Args; 80 }; 81 82public: 83 /// \brief Construct an empty, invalid template argument. 84 TemplateArgument() : Kind(Null), TypeOrValue(0) { } 85 86 /// \brief Construct a template type argument. 87 TemplateArgument(QualType T) : Kind(Type) { 88 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); 89 } 90 91 /// \brief Construct a template argument that refers to a 92 /// declaration, which is either an external declaration or a 93 /// template declaration. 94 TemplateArgument(Decl *D) : Kind(Declaration) { 95 // FIXME: Need to be sure we have the "canonical" declaration! 96 TypeOrValue = reinterpret_cast<uintptr_t>(D); 97 } 98 99 /// \brief Construct an integral constant template argument. 100 TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { 101 // FIXME: Large integral values will get leaked. Do something 102 // similar to what we did with IntegerLiteral. 103 new (Integer.Value) llvm::APSInt(Value); 104 Integer.Type = Type.getAsOpaquePtr(); 105 } 106 107 /// \brief Construct a template argument that is a template. 108 /// 109 /// This form of template argument is generally used for template template 110 /// parameters. However, the template name could be a dependent template 111 /// name that ends up being instantiated to a function template whose address 112 /// is taken. 113 TemplateArgument(TemplateName Name) : Kind(Template) { 114 TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); 115 } 116 117 /// \brief Construct a template argument that is an expression. 118 /// 119 /// This form of template argument only occurs in template argument 120 /// lists used for dependent types and for expression; it will not 121 /// occur in a non-dependent, canonical template argument list. 122 TemplateArgument(Expr *E) : Kind(Expression) { 123 TypeOrValue = reinterpret_cast<uintptr_t>(E); 124 } 125 126 /// \brief Construct a template argument that is a template argument pack. 127 /// 128 /// We assume that storage for the template arguments provided 129 /// outlives the TemplateArgument itself. 130 TemplateArgument(TemplateArgument *Args, unsigned NumArgs) : Kind(Pack) { 131 this->Args.Args = Args; 132 this->Args.NumArgs = NumArgs; 133 } 134 135 /// \brief Copy constructor for a template argument. 136 TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { 137 // FIXME: Large integral values will get leaked. Do something 138 // similar to what we did with IntegerLiteral. 139 if (Kind == Integral) { 140 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 141 Integer.Type = Other.Integer.Type; 142 } else if (Kind == Pack) { 143 Args.NumArgs = Other.Args.NumArgs; 144 Args.Args = Other.Args.Args; 145 } 146 else 147 TypeOrValue = Other.TypeOrValue; 148 } 149 150 TemplateArgument& operator=(const TemplateArgument& Other) { 151 using llvm::APSInt; 152 153 if (Kind == Other.Kind && Kind == Integral) { 154 // Copy integral values. 155 *this->getAsIntegral() = *Other.getAsIntegral(); 156 Integer.Type = Other.Integer.Type; 157 return *this; 158 } 159 160 // Destroy the current integral value, if that's what we're holding. 161 if (Kind == Integral) 162 getAsIntegral()->~APSInt(); 163 164 Kind = Other.Kind; 165 166 if (Other.Kind == Integral) { 167 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 168 Integer.Type = Other.Integer.Type; 169 } else if (Other.Kind == Pack) { 170 Args.NumArgs = Other.Args.NumArgs; 171 Args.Args = Other.Args.Args; 172 } else { 173 TypeOrValue = Other.TypeOrValue; 174 } 175 176 return *this; 177 } 178 179 ~TemplateArgument() { 180 using llvm::APSInt; 181 182 if (Kind == Integral) 183 getAsIntegral()->~APSInt(); 184 } 185 186 /// \brief Return the kind of stored template argument. 187 ArgKind getKind() const { return (ArgKind)Kind; } 188 189 /// \brief Determine whether this template argument has no value. 190 bool isNull() const { return Kind == Null; } 191 192 /// \brief Whether this template argument is dependent on a template 193 /// parameter. 194 bool isDependent() const; 195 196 /// \brief Whether this template argument contains an unexpanded 197 /// parameter pack. 198 bool containsUnexpandedParameterPack() const; 199 200 /// \brief Determine whether this template argument is a pack expansion. 201 bool isPackExpansion() const; 202 203 /// \brief Retrieve the template argument as a type. 204 QualType getAsType() const { 205 if (Kind != Type) 206 return QualType(); 207 208 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 209 } 210 211 /// \brief Retrieve the template argument as a declaration. 212 Decl *getAsDecl() const { 213 if (Kind != Declaration) 214 return 0; 215 return reinterpret_cast<Decl *>(TypeOrValue); 216 } 217 218 /// \brief Retrieve the template argument as a template name. 219 TemplateName getAsTemplate() const { 220 if (Kind != Template) 221 return TemplateName(); 222 223 return TemplateName::getFromVoidPointer( 224 reinterpret_cast<void *> (TypeOrValue)); 225 } 226 227 /// \brief Retrieve the template argument as an integral value. 228 llvm::APSInt *getAsIntegral() { 229 if (Kind != Integral) 230 return 0; 231 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); 232 } 233 234 const llvm::APSInt *getAsIntegral() const { 235 return const_cast<TemplateArgument*>(this)->getAsIntegral(); 236 } 237 238 /// \brief Retrieve the type of the integral value. 239 QualType getIntegralType() const { 240 if (Kind != Integral) 241 return QualType(); 242 243 return QualType::getFromOpaquePtr(Integer.Type); 244 } 245 246 void setIntegralType(QualType T) { 247 assert(Kind == Integral && 248 "Cannot set the integral type of a non-integral template argument"); 249 Integer.Type = T.getAsOpaquePtr(); 250 } 251 252 /// \brief Retrieve the template argument as an expression. 253 Expr *getAsExpr() const { 254 if (Kind != Expression) 255 return 0; 256 257 return reinterpret_cast<Expr *>(TypeOrValue); 258 } 259 260 /// \brief Iterator that traverses the elements of a template argument pack. 261 typedef const TemplateArgument * pack_iterator; 262 263 /// \brief Iterator referencing the first argument of a template argument 264 /// pack. 265 pack_iterator pack_begin() const { 266 assert(Kind == Pack); 267 return Args.Args; 268 } 269 270 /// \brief Iterator referencing one past the last argument of a template 271 /// argument pack. 272 pack_iterator pack_end() const { 273 assert(Kind == Pack); 274 return Args.Args + Args.NumArgs; 275 } 276 277 /// \brief The number of template arguments in the given template argument 278 /// pack. 279 unsigned pack_size() const { 280 assert(Kind == Pack); 281 return Args.NumArgs; 282 } 283 284 /// Determines whether two template arguments are superficially the 285 /// same. 286 bool structurallyEquals(const TemplateArgument &Other) const; 287 288 /// \brief When the template argument is a pack expansion, returns 289 /// the pattern of the pack expansion. 290 /// 291 /// \param Ellipsis Will be set to the location of the ellipsis. 292 TemplateArgument getPackExpansionPattern() const; 293 294 /// \brief Print this template argument to the given output stream. 295 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const; 296 297 /// \brief Used to insert TemplateArguments into FoldingSets. 298 void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; 299}; 300 301/// Location information for a TemplateArgument. 302struct TemplateArgumentLocInfo { 303private: 304 union { 305 Expr *Expression; 306 TypeSourceInfo *Declarator; 307 struct { 308 unsigned QualifierRange[2]; 309 unsigned TemplateNameLoc; 310 } Template; 311 }; 312 313public: 314 TemplateArgumentLocInfo() : Expression(0) {} 315 316 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 317 318 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 319 320 TemplateArgumentLocInfo(SourceRange QualifierRange, 321 SourceLocation TemplateNameLoc) 322 { 323 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); 324 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); 325 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 326 } 327 328 TypeSourceInfo *getAsTypeSourceInfo() const { 329 return Declarator; 330 } 331 332 Expr *getAsExpr() const { 333 return Expression; 334 } 335 336 SourceRange getTemplateQualifierRange() const { 337 return SourceRange( 338 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), 339 SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); 340 } 341 342 SourceLocation getTemplateNameLoc() const { 343 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 344 } 345}; 346 347/// Location wrapper for a TemplateArgument. TemplateArgument is to 348/// TemplateArgumentLoc as Type is to TypeLoc. 349class TemplateArgumentLoc { 350 TemplateArgument Argument; 351 TemplateArgumentLocInfo LocInfo; 352 353public: 354 TemplateArgumentLoc() {} 355 356 TemplateArgumentLoc(const TemplateArgument &Argument, 357 TemplateArgumentLocInfo Opaque) 358 : Argument(Argument), LocInfo(Opaque) { 359 } 360 361 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 362 : Argument(Argument), LocInfo(TInfo) { 363 assert(Argument.getKind() == TemplateArgument::Type); 364 } 365 366 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 367 : Argument(Argument), LocInfo(E) { 368 assert(Argument.getKind() == TemplateArgument::Expression); 369 } 370 371 TemplateArgumentLoc(const TemplateArgument &Argument, 372 SourceRange QualifierRange, 373 SourceLocation TemplateNameLoc) 374 : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { 375 assert(Argument.getKind() == TemplateArgument::Template); 376 } 377 378 /// \brief - Fetches the primary location of the argument. 379 SourceLocation getLocation() const { 380 if (Argument.getKind() == TemplateArgument::Template) 381 return getTemplateNameLoc(); 382 383 return getSourceRange().getBegin(); 384 } 385 386 /// \brief - Fetches the full source range of the argument. 387 SourceRange getSourceRange() const; 388 389 const TemplateArgument &getArgument() const { 390 return Argument; 391 } 392 393 TemplateArgumentLocInfo getLocInfo() const { 394 return LocInfo; 395 } 396 397 TypeSourceInfo *getTypeSourceInfo() const { 398 assert(Argument.getKind() == TemplateArgument::Type); 399 return LocInfo.getAsTypeSourceInfo(); 400 } 401 402 Expr *getSourceExpression() const { 403 assert(Argument.getKind() == TemplateArgument::Expression); 404 return LocInfo.getAsExpr(); 405 } 406 407 Expr *getSourceDeclExpression() const { 408 assert(Argument.getKind() == TemplateArgument::Declaration); 409 return LocInfo.getAsExpr(); 410 } 411 412 SourceRange getTemplateQualifierRange() const { 413 assert(Argument.getKind() == TemplateArgument::Template); 414 return LocInfo.getTemplateQualifierRange(); 415 } 416 417 SourceLocation getTemplateNameLoc() const { 418 assert(Argument.getKind() == TemplateArgument::Template); 419 return LocInfo.getTemplateNameLoc(); 420 } 421 422 /// \brief When the template argument is a pack expansion, returns 423 /// the pattern of the pack expansion. 424 /// 425 /// \param Ellipsis Will be set to the location of the ellipsis. 426 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, 427 ASTContext &Context) const; 428}; 429 430/// A convenient class for passing around template argument 431/// information. Designed to be passed by reference. 432class TemplateArgumentListInfo { 433 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; 434 SourceLocation LAngleLoc; 435 SourceLocation RAngleLoc; 436 437public: 438 TemplateArgumentListInfo() {} 439 440 TemplateArgumentListInfo(SourceLocation LAngleLoc, 441 SourceLocation RAngleLoc) 442 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 443 444 SourceLocation getLAngleLoc() const { return LAngleLoc; } 445 SourceLocation getRAngleLoc() const { return RAngleLoc; } 446 447 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 448 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 449 450 unsigned size() const { return Arguments.size(); } 451 452 const TemplateArgumentLoc *getArgumentArray() const { 453 return Arguments.data(); 454 } 455 456 const TemplateArgumentLoc &operator[](unsigned I) const { 457 return Arguments[I]; 458 } 459 460 void addArgument(const TemplateArgumentLoc &Loc) { 461 Arguments.push_back(Loc); 462 } 463}; 464 465const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 466 const TemplateArgument &Arg); 467 468inline TemplateSpecializationType::iterator 469 TemplateSpecializationType::end() const { 470 return getArgs() + getNumArgs(); 471} 472 473inline DependentTemplateSpecializationType::iterator 474 DependentTemplateSpecializationType::end() const { 475 return getArgs() + getNumArgs(); 476} 477 478inline const TemplateArgument & 479 TemplateSpecializationType::getArg(unsigned Idx) const { 480 assert(Idx < getNumArgs() && "Template argument out of range"); 481 return getArgs()[Idx]; 482} 483 484inline const TemplateArgument & 485 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 486 assert(Idx < getNumArgs() && "Template argument out of range"); 487 return getArgs()[Idx]; 488} 489 490} // end namespace clang 491 492#endif 493