TemplateBase.h revision 87dd697dcc8ecb64df73ae64d61b8c80ff0c157c
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 Retrieve the template argument as a type. 201 QualType getAsType() const { 202 if (Kind != Type) 203 return QualType(); 204 205 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 206 } 207 208 /// \brief Retrieve the template argument as a declaration. 209 Decl *getAsDecl() const { 210 if (Kind != Declaration) 211 return 0; 212 return reinterpret_cast<Decl *>(TypeOrValue); 213 } 214 215 /// \brief Retrieve the template argument as a template name. 216 TemplateName getAsTemplate() const { 217 if (Kind != Template) 218 return TemplateName(); 219 220 return TemplateName::getFromVoidPointer( 221 reinterpret_cast<void *> (TypeOrValue)); 222 } 223 224 /// \brief Retrieve the template argument as an integral value. 225 llvm::APSInt *getAsIntegral() { 226 if (Kind != Integral) 227 return 0; 228 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); 229 } 230 231 const llvm::APSInt *getAsIntegral() const { 232 return const_cast<TemplateArgument*>(this)->getAsIntegral(); 233 } 234 235 /// \brief Retrieve the type of the integral value. 236 QualType getIntegralType() const { 237 if (Kind != Integral) 238 return QualType(); 239 240 return QualType::getFromOpaquePtr(Integer.Type); 241 } 242 243 void setIntegralType(QualType T) { 244 assert(Kind == Integral && 245 "Cannot set the integral type of a non-integral template argument"); 246 Integer.Type = T.getAsOpaquePtr(); 247 } 248 249 /// \brief Retrieve the template argument as an expression. 250 Expr *getAsExpr() const { 251 if (Kind != Expression) 252 return 0; 253 254 return reinterpret_cast<Expr *>(TypeOrValue); 255 } 256 257 /// \brief Iterator that traverses the elements of a template argument pack. 258 typedef const TemplateArgument * pack_iterator; 259 260 /// \brief Iterator referencing the first argument of a template argument 261 /// pack. 262 pack_iterator pack_begin() const { 263 assert(Kind == Pack); 264 return Args.Args; 265 } 266 267 /// \brief Iterator referencing one past the last argument of a template 268 /// argument pack. 269 pack_iterator pack_end() const { 270 assert(Kind == Pack); 271 return Args.Args + Args.NumArgs; 272 } 273 274 /// \brief The number of template arguments in the given template argument 275 /// pack. 276 unsigned pack_size() const { 277 assert(Kind == Pack); 278 return Args.NumArgs; 279 } 280 281 /// Determines whether two template arguments are superficially the 282 /// same. 283 bool structurallyEquals(const TemplateArgument &Other) const; 284 285 /// \brief Print this template argument to the given output stream. 286 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const; 287 288 /// \brief Used to insert TemplateArguments into FoldingSets. 289 void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; 290}; 291 292/// Location information for a TemplateArgument. 293struct TemplateArgumentLocInfo { 294private: 295 union { 296 Expr *Expression; 297 TypeSourceInfo *Declarator; 298 struct { 299 unsigned QualifierRange[2]; 300 unsigned TemplateNameLoc; 301 } Template; 302 }; 303 304public: 305 TemplateArgumentLocInfo() : Expression(0) {} 306 307 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 308 309 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 310 311 TemplateArgumentLocInfo(SourceRange QualifierRange, 312 SourceLocation TemplateNameLoc) 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 return Declarator; 321 } 322 323 Expr *getAsExpr() const { 324 return Expression; 325 } 326 327 SourceRange getTemplateQualifierRange() const { 328 return SourceRange( 329 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), 330 SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); 331 } 332 333 SourceLocation getTemplateNameLoc() const { 334 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 335 } 336}; 337 338/// Location wrapper for a TemplateArgument. TemplateArgument is to 339/// TemplateArgumentLoc as Type is to TypeLoc. 340class TemplateArgumentLoc { 341 TemplateArgument Argument; 342 TemplateArgumentLocInfo LocInfo; 343 344public: 345 TemplateArgumentLoc() {} 346 347 TemplateArgumentLoc(const TemplateArgument &Argument, 348 TemplateArgumentLocInfo Opaque) 349 : Argument(Argument), LocInfo(Opaque) { 350 } 351 352 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 353 : Argument(Argument), LocInfo(TInfo) { 354 assert(Argument.getKind() == TemplateArgument::Type); 355 } 356 357 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 358 : Argument(Argument), LocInfo(E) { 359 assert(Argument.getKind() == TemplateArgument::Expression); 360 } 361 362 TemplateArgumentLoc(const TemplateArgument &Argument, 363 SourceRange QualifierRange, 364 SourceLocation TemplateNameLoc) 365 : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { 366 assert(Argument.getKind() == TemplateArgument::Template); 367 } 368 369 /// \brief - Fetches the primary location of the argument. 370 SourceLocation getLocation() const { 371 if (Argument.getKind() == TemplateArgument::Template) 372 return getTemplateNameLoc(); 373 374 return getSourceRange().getBegin(); 375 } 376 377 /// \brief - Fetches the full source range of the argument. 378 SourceRange getSourceRange() const; 379 380 const TemplateArgument &getArgument() const { 381 return Argument; 382 } 383 384 TemplateArgumentLocInfo getLocInfo() const { 385 return LocInfo; 386 } 387 388 TypeSourceInfo *getTypeSourceInfo() const { 389 assert(Argument.getKind() == TemplateArgument::Type); 390 return LocInfo.getAsTypeSourceInfo(); 391 } 392 393 Expr *getSourceExpression() const { 394 assert(Argument.getKind() == TemplateArgument::Expression); 395 return LocInfo.getAsExpr(); 396 } 397 398 Expr *getSourceDeclExpression() const { 399 assert(Argument.getKind() == TemplateArgument::Declaration); 400 return LocInfo.getAsExpr(); 401 } 402 403 SourceRange getTemplateQualifierRange() const { 404 assert(Argument.getKind() == TemplateArgument::Template); 405 return LocInfo.getTemplateQualifierRange(); 406 } 407 408 SourceLocation getTemplateNameLoc() const { 409 assert(Argument.getKind() == TemplateArgument::Template); 410 return LocInfo.getTemplateNameLoc(); 411 } 412}; 413 414/// A convenient class for passing around template argument 415/// information. Designed to be passed by reference. 416class TemplateArgumentListInfo { 417 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; 418 SourceLocation LAngleLoc; 419 SourceLocation RAngleLoc; 420 421public: 422 TemplateArgumentListInfo() {} 423 424 TemplateArgumentListInfo(SourceLocation LAngleLoc, 425 SourceLocation RAngleLoc) 426 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 427 428 SourceLocation getLAngleLoc() const { return LAngleLoc; } 429 SourceLocation getRAngleLoc() const { return RAngleLoc; } 430 431 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 432 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 433 434 unsigned size() const { return Arguments.size(); } 435 436 const TemplateArgumentLoc *getArgumentArray() const { 437 return Arguments.data(); 438 } 439 440 const TemplateArgumentLoc &operator[](unsigned I) const { 441 return Arguments[I]; 442 } 443 444 void addArgument(const TemplateArgumentLoc &Loc) { 445 Arguments.push_back(Loc); 446 } 447}; 448 449const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 450 const TemplateArgument &Arg); 451 452inline TemplateSpecializationType::iterator 453 TemplateSpecializationType::end() const { 454 return getArgs() + getNumArgs(); 455} 456 457inline DependentTemplateSpecializationType::iterator 458 DependentTemplateSpecializationType::end() const { 459 return getArgs() + getNumArgs(); 460} 461 462inline const TemplateArgument & 463 TemplateSpecializationType::getArg(unsigned Idx) const { 464 assert(Idx < getNumArgs() && "Template argument out of range"); 465 return getArgs()[Idx]; 466} 467 468inline const TemplateArgument & 469 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 470 assert(Idx < getNumArgs() && "Template argument out of range"); 471 return getArgs()[Idx]; 472} 473 474} // end namespace clang 475 476#endif 477