clang API Documentation
00001 //===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides definitions which are common for all kinds of 00011 // template representation. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H 00016 #define LLVM_CLANG_AST_TEMPLATEBASE_H 00017 00018 #include "clang/AST/Type.h" 00019 #include "clang/AST/TemplateName.h" 00020 #include "llvm/ADT/APSInt.h" 00021 #include "llvm/ADT/SmallVector.h" 00022 #include "llvm/Support/Compiler.h" 00023 #include "llvm/Support/ErrorHandling.h" 00024 00025 namespace llvm { 00026 class FoldingSetNodeID; 00027 } 00028 00029 namespace clang { 00030 00031 class Decl; 00032 class DiagnosticBuilder; 00033 class Expr; 00034 struct PrintingPolicy; 00035 class TypeSourceInfo; 00036 00037 /// \brief Represents a template argument within a class template 00038 /// specialization. 00039 class TemplateArgument { 00040 public: 00041 /// \brief The kind of template argument we're storing. 00042 enum ArgKind { 00043 /// \brief Represents an empty template argument, e.g., one that has not 00044 /// been deduced. 00045 Null = 0, 00046 /// The template argument is a type. Its value is stored in the 00047 /// TypeOrValue field. 00048 Type, 00049 /// The template argument is a declaration that was provided for a pointer 00050 /// or reference non-type template parameter. 00051 Declaration, 00052 /// The template argument is an integral value stored in an llvm::APSInt 00053 /// that was provided for an integral non-type template parameter. 00054 Integral, 00055 /// The template argument is a template name that was provided for a 00056 /// template template parameter. 00057 Template, 00058 /// The template argument is a pack expansion of a template name that was 00059 /// provided for a template template parameter. 00060 TemplateExpansion, 00061 /// The template argument is a value- or type-dependent expression 00062 /// stored in an Expr*. 00063 Expression, 00064 /// The template argument is actually a parameter pack. Arguments are stored 00065 /// in the Args struct. 00066 Pack 00067 }; 00068 00069 private: 00070 /// \brief The kind of template argument we're storing. 00071 unsigned Kind; 00072 00073 union { 00074 uintptr_t TypeOrValue; 00075 struct { 00076 char Value[sizeof(llvm::APSInt)]; 00077 void *Type; 00078 } Integer; 00079 struct { 00080 const TemplateArgument *Args; 00081 unsigned NumArgs; 00082 } Args; 00083 struct { 00084 void *Name; 00085 unsigned NumExpansions; 00086 } TemplateArg; 00087 }; 00088 00089 TemplateArgument(TemplateName, bool); // DO NOT USE 00090 00091 public: 00092 /// \brief Construct an empty, invalid template argument. 00093 TemplateArgument() : Kind(Null), TypeOrValue(0) { } 00094 00095 /// \brief Construct a template type argument. 00096 TemplateArgument(QualType T) : Kind(Type) { 00097 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); 00098 } 00099 00100 /// \brief Construct a template argument that refers to a 00101 /// declaration, which is either an external declaration or a 00102 /// template declaration. 00103 TemplateArgument(Decl *D) : Kind(Declaration) { 00104 TypeOrValue = reinterpret_cast<uintptr_t>(D); 00105 } 00106 00107 /// \brief Construct an integral constant template argument. 00108 TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { 00109 // FIXME: Large integral values will get leaked. Do something 00110 // similar to what we did with IntegerLiteral. 00111 new (Integer.Value) llvm::APSInt(Value); 00112 Integer.Type = Type.getAsOpaquePtr(); 00113 } 00114 00115 /// \brief Construct a template argument that is a template. 00116 /// 00117 /// This form of template argument is generally used for template template 00118 /// parameters. However, the template name could be a dependent template 00119 /// name that ends up being instantiated to a function template whose address 00120 /// is taken. 00121 /// 00122 /// \param Name The template name. 00123 TemplateArgument(TemplateName Name) : Kind(Template) 00124 { 00125 TemplateArg.Name = Name.getAsVoidPointer(); 00126 TemplateArg.NumExpansions = 0; 00127 } 00128 00129 /// \brief Construct a template argument that is a template pack expansion. 00130 /// 00131 /// This form of template argument is generally used for template template 00132 /// parameters. However, the template name could be a dependent template 00133 /// name that ends up being instantiated to a function template whose address 00134 /// is taken. 00135 /// 00136 /// \param Name The template name. 00137 /// 00138 /// \param NumExpansions The number of expansions that will be generated by 00139 /// instantiating 00140 TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) 00141 : Kind(TemplateExpansion) 00142 { 00143 TemplateArg.Name = Name.getAsVoidPointer(); 00144 if (NumExpansions) 00145 TemplateArg.NumExpansions = *NumExpansions + 1; 00146 else 00147 TemplateArg.NumExpansions = 0; 00148 } 00149 00150 /// \brief Construct a template argument that is an expression. 00151 /// 00152 /// This form of template argument only occurs in template argument 00153 /// lists used for dependent types and for expression; it will not 00154 /// occur in a non-dependent, canonical template argument list. 00155 TemplateArgument(Expr *E) : Kind(Expression) { 00156 TypeOrValue = reinterpret_cast<uintptr_t>(E); 00157 } 00158 00159 /// \brief Construct a template argument that is a template argument pack. 00160 /// 00161 /// We assume that storage for the template arguments provided 00162 /// outlives the TemplateArgument itself. 00163 TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){ 00164 this->Args.Args = Args; 00165 this->Args.NumArgs = NumArgs; 00166 } 00167 00168 /// \brief Copy constructor for a template argument. 00169 TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { 00170 // FIXME: Large integral values will get leaked. Do something 00171 // similar to what we did with IntegerLiteral. 00172 if (Kind == Integral) { 00173 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 00174 Integer.Type = Other.Integer.Type; 00175 } else if (Kind == Pack) { 00176 Args.NumArgs = Other.Args.NumArgs; 00177 Args.Args = Other.Args.Args; 00178 } else if (Kind == Template || Kind == TemplateExpansion) { 00179 TemplateArg.Name = Other.TemplateArg.Name; 00180 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; 00181 } else 00182 TypeOrValue = Other.TypeOrValue; 00183 } 00184 00185 TemplateArgument& operator=(const TemplateArgument& Other) { 00186 using llvm::APSInt; 00187 00188 if (Kind == Other.Kind && Kind == Integral) { 00189 // Copy integral values. 00190 *this->getAsIntegral() = *Other.getAsIntegral(); 00191 Integer.Type = Other.Integer.Type; 00192 return *this; 00193 } 00194 00195 // Destroy the current integral value, if that's what we're holding. 00196 if (Kind == Integral) 00197 getAsIntegral()->~APSInt(); 00198 00199 Kind = Other.Kind; 00200 00201 if (Other.Kind == Integral) { 00202 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); 00203 Integer.Type = Other.Integer.Type; 00204 } else if (Other.Kind == Pack) { 00205 Args.NumArgs = Other.Args.NumArgs; 00206 Args.Args = Other.Args.Args; 00207 } else if (Kind == Template || Kind == TemplateExpansion) { 00208 TemplateArg.Name = Other.TemplateArg.Name; 00209 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; 00210 } else { 00211 TypeOrValue = Other.TypeOrValue; 00212 } 00213 00214 return *this; 00215 } 00216 00217 ~TemplateArgument() { 00218 using llvm::APSInt; 00219 00220 if (Kind == Integral) 00221 getAsIntegral()->~APSInt(); 00222 } 00223 00224 /// \brief Create a new template argument pack by copying the given set of 00225 /// template arguments. 00226 static TemplateArgument CreatePackCopy(ASTContext &Context, 00227 const TemplateArgument *Args, 00228 unsigned NumArgs); 00229 00230 /// \brief Return the kind of stored template argument. 00231 ArgKind getKind() const { return (ArgKind)Kind; } 00232 00233 /// \brief Determine whether this template argument has no value. 00234 bool isNull() const { return Kind == Null; } 00235 00236 /// \brief Whether this template argument is dependent on a template 00237 /// parameter such that its result can change from one instantiation to 00238 /// another. 00239 bool isDependent() const; 00240 00241 /// \brief Whether this template argument is dependent on a template 00242 /// parameter. 00243 bool isInstantiationDependent() const; 00244 00245 /// \brief Whether this template argument contains an unexpanded 00246 /// parameter pack. 00247 bool containsUnexpandedParameterPack() const; 00248 00249 /// \brief Determine whether this template argument is a pack expansion. 00250 bool isPackExpansion() const; 00251 00252 /// \brief Retrieve the template argument as a type. 00253 QualType getAsType() const { 00254 if (Kind != Type) 00255 return QualType(); 00256 00257 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 00258 } 00259 00260 /// \brief Retrieve the template argument as a declaration. 00261 Decl *getAsDecl() const { 00262 if (Kind != Declaration) 00263 return 0; 00264 return reinterpret_cast<Decl *>(TypeOrValue); 00265 } 00266 00267 /// \brief Retrieve the template argument as a template name. 00268 TemplateName getAsTemplate() const { 00269 if (Kind != Template) 00270 return TemplateName(); 00271 00272 return TemplateName::getFromVoidPointer(TemplateArg.Name); 00273 } 00274 00275 /// \brief Retrieve the template argument as a template name; if the argument 00276 /// is a pack expansion, return the pattern as a template name. 00277 TemplateName getAsTemplateOrTemplatePattern() const { 00278 if (Kind != Template && Kind != TemplateExpansion) 00279 return TemplateName(); 00280 00281 return TemplateName::getFromVoidPointer(TemplateArg.Name); 00282 } 00283 00284 /// \brief Retrieve the number of expansions that a template template argument 00285 /// expansion will produce, if known. 00286 llvm::Optional<unsigned> getNumTemplateExpansions() const; 00287 00288 /// \brief Retrieve the template argument as an integral value. 00289 llvm::APSInt *getAsIntegral() { 00290 if (Kind != Integral) 00291 return 0; 00292 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); 00293 } 00294 00295 const llvm::APSInt *getAsIntegral() const { 00296 return const_cast<TemplateArgument*>(this)->getAsIntegral(); 00297 } 00298 00299 /// \brief Retrieve the type of the integral value. 00300 QualType getIntegralType() const { 00301 if (Kind != Integral) 00302 return QualType(); 00303 00304 return QualType::getFromOpaquePtr(Integer.Type); 00305 } 00306 00307 void setIntegralType(QualType T) { 00308 assert(Kind == Integral && 00309 "Cannot set the integral type of a non-integral template argument"); 00310 Integer.Type = T.getAsOpaquePtr(); 00311 } 00312 00313 /// \brief Retrieve the template argument as an expression. 00314 Expr *getAsExpr() const { 00315 if (Kind != Expression) 00316 return 0; 00317 00318 return reinterpret_cast<Expr *>(TypeOrValue); 00319 } 00320 00321 /// \brief Iterator that traverses the elements of a template argument pack. 00322 typedef const TemplateArgument * pack_iterator; 00323 00324 /// \brief Iterator referencing the first argument of a template argument 00325 /// pack. 00326 pack_iterator pack_begin() const { 00327 assert(Kind == Pack); 00328 return Args.Args; 00329 } 00330 00331 /// \brief Iterator referencing one past the last argument of a template 00332 /// argument pack. 00333 pack_iterator pack_end() const { 00334 assert(Kind == Pack); 00335 return Args.Args + Args.NumArgs; 00336 } 00337 00338 /// \brief The number of template arguments in the given template argument 00339 /// pack. 00340 unsigned pack_size() const { 00341 assert(Kind == Pack); 00342 return Args.NumArgs; 00343 } 00344 00345 /// Determines whether two template arguments are superficially the 00346 /// same. 00347 bool structurallyEquals(const TemplateArgument &Other) const; 00348 00349 /// \brief When the template argument is a pack expansion, returns 00350 /// the pattern of the pack expansion. 00351 /// 00352 /// \param Ellipsis Will be set to the location of the ellipsis. 00353 TemplateArgument getPackExpansionPattern() const; 00354 00355 /// \brief Print this template argument to the given output stream. 00356 void print(const PrintingPolicy &Policy, raw_ostream &Out) const; 00357 00358 /// \brief Used to insert TemplateArguments into FoldingSets. 00359 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 00360 }; 00361 00362 /// Location information for a TemplateArgument. 00363 struct TemplateArgumentLocInfo { 00364 private: 00365 union { 00366 Expr *Expression; 00367 TypeSourceInfo *Declarator; 00368 struct { 00369 // FIXME: We'd like to just use the qualifier in the TemplateName, 00370 // but template arguments get canonicalized too quickly. 00371 NestedNameSpecifier *Qualifier; 00372 void *QualifierLocData; 00373 unsigned TemplateNameLoc; 00374 unsigned EllipsisLoc; 00375 } Template; 00376 }; 00377 00378 public: 00379 TemplateArgumentLocInfo(); 00380 00381 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 00382 00383 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 00384 00385 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, 00386 SourceLocation TemplateNameLoc, 00387 SourceLocation EllipsisLoc) 00388 { 00389 Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); 00390 Template.QualifierLocData = QualifierLoc.getOpaqueData(); 00391 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 00392 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 00393 } 00394 00395 TypeSourceInfo *getAsTypeSourceInfo() const { 00396 return Declarator; 00397 } 00398 00399 Expr *getAsExpr() const { 00400 return Expression; 00401 } 00402 00403 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 00404 return NestedNameSpecifierLoc(Template.Qualifier, 00405 Template.QualifierLocData); 00406 } 00407 00408 SourceLocation getTemplateNameLoc() const { 00409 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 00410 } 00411 00412 SourceLocation getTemplateEllipsisLoc() const { 00413 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 00414 } 00415 }; 00416 00417 /// Location wrapper for a TemplateArgument. TemplateArgument is to 00418 /// TemplateArgumentLoc as Type is to TypeLoc. 00419 class TemplateArgumentLoc { 00420 TemplateArgument Argument; 00421 TemplateArgumentLocInfo LocInfo; 00422 00423 public: 00424 TemplateArgumentLoc() {} 00425 00426 TemplateArgumentLoc(const TemplateArgument &Argument, 00427 TemplateArgumentLocInfo Opaque) 00428 : Argument(Argument), LocInfo(Opaque) { 00429 } 00430 00431 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 00432 : Argument(Argument), LocInfo(TInfo) { 00433 assert(Argument.getKind() == TemplateArgument::Type); 00434 } 00435 00436 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 00437 : Argument(Argument), LocInfo(E) { 00438 assert(Argument.getKind() == TemplateArgument::Expression); 00439 } 00440 00441 TemplateArgumentLoc(const TemplateArgument &Argument, 00442 NestedNameSpecifierLoc QualifierLoc, 00443 SourceLocation TemplateNameLoc, 00444 SourceLocation EllipsisLoc = SourceLocation()) 00445 : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { 00446 assert(Argument.getKind() == TemplateArgument::Template || 00447 Argument.getKind() == TemplateArgument::TemplateExpansion); 00448 } 00449 00450 /// \brief - Fetches the primary location of the argument. 00451 SourceLocation getLocation() const { 00452 if (Argument.getKind() == TemplateArgument::Template || 00453 Argument.getKind() == TemplateArgument::TemplateExpansion) 00454 return getTemplateNameLoc(); 00455 00456 return getSourceRange().getBegin(); 00457 } 00458 00459 /// \brief - Fetches the full source range of the argument. 00460 SourceRange getSourceRange() const LLVM_READONLY; 00461 00462 const TemplateArgument &getArgument() const { 00463 return Argument; 00464 } 00465 00466 TemplateArgumentLocInfo getLocInfo() const { 00467 return LocInfo; 00468 } 00469 00470 TypeSourceInfo *getTypeSourceInfo() const { 00471 assert(Argument.getKind() == TemplateArgument::Type); 00472 return LocInfo.getAsTypeSourceInfo(); 00473 } 00474 00475 Expr *getSourceExpression() const { 00476 assert(Argument.getKind() == TemplateArgument::Expression); 00477 return LocInfo.getAsExpr(); 00478 } 00479 00480 Expr *getSourceDeclExpression() const { 00481 assert(Argument.getKind() == TemplateArgument::Declaration); 00482 return LocInfo.getAsExpr(); 00483 } 00484 00485 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 00486 assert(Argument.getKind() == TemplateArgument::Template || 00487 Argument.getKind() == TemplateArgument::TemplateExpansion); 00488 return LocInfo.getTemplateQualifierLoc(); 00489 } 00490 00491 SourceLocation getTemplateNameLoc() const { 00492 assert(Argument.getKind() == TemplateArgument::Template || 00493 Argument.getKind() == TemplateArgument::TemplateExpansion); 00494 return LocInfo.getTemplateNameLoc(); 00495 } 00496 00497 SourceLocation getTemplateEllipsisLoc() const { 00498 assert(Argument.getKind() == TemplateArgument::TemplateExpansion); 00499 return LocInfo.getTemplateEllipsisLoc(); 00500 } 00501 00502 /// \brief When the template argument is a pack expansion, returns 00503 /// the pattern of the pack expansion. 00504 /// 00505 /// \param Ellipsis Will be set to the location of the ellipsis. 00506 /// 00507 /// \param NumExpansions Will be set to the number of expansions that will 00508 /// be generated from this pack expansion, if known a priori. 00509 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, 00510 llvm::Optional<unsigned> &NumExpansions, 00511 ASTContext &Context) const; 00512 }; 00513 00514 /// A convenient class for passing around template argument 00515 /// information. Designed to be passed by reference. 00516 class TemplateArgumentListInfo { 00517 SmallVector<TemplateArgumentLoc, 8> Arguments; 00518 SourceLocation LAngleLoc; 00519 SourceLocation RAngleLoc; 00520 00521 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo 00522 // instead. 00523 void* operator new(size_t bytes, ASTContext& C); 00524 00525 public: 00526 TemplateArgumentListInfo() {} 00527 00528 TemplateArgumentListInfo(SourceLocation LAngleLoc, 00529 SourceLocation RAngleLoc) 00530 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 00531 00532 SourceLocation getLAngleLoc() const { return LAngleLoc; } 00533 SourceLocation getRAngleLoc() const { return RAngleLoc; } 00534 00535 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 00536 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 00537 00538 unsigned size() const { return Arguments.size(); } 00539 00540 const TemplateArgumentLoc *getArgumentArray() const { 00541 return Arguments.data(); 00542 } 00543 00544 const TemplateArgumentLoc &operator[](unsigned I) const { 00545 return Arguments[I]; 00546 } 00547 00548 void addArgument(const TemplateArgumentLoc &Loc) { 00549 Arguments.push_back(Loc); 00550 } 00551 }; 00552 00553 /// \brief Represents an explicit template argument list in C++, e.g., 00554 /// the "<int>" in "sort<int>". 00555 /// This is safe to be used inside an AST node, in contrast with 00556 /// TemplateArgumentListInfo. 00557 struct ASTTemplateArgumentListInfo { 00558 /// \brief The source location of the left angle bracket ('<'); 00559 SourceLocation LAngleLoc; 00560 00561 /// \brief The source location of the right angle bracket ('>'); 00562 SourceLocation RAngleLoc; 00563 00564 /// \brief The number of template arguments in TemplateArgs. 00565 /// The actual template arguments (if any) are stored after the 00566 /// ExplicitTemplateArgumentList structure. 00567 unsigned NumTemplateArgs; 00568 00569 /// \brief Retrieve the template arguments 00570 TemplateArgumentLoc *getTemplateArgs() { 00571 return reinterpret_cast<TemplateArgumentLoc *> (this + 1); 00572 } 00573 00574 /// \brief Retrieve the template arguments 00575 const TemplateArgumentLoc *getTemplateArgs() const { 00576 return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); 00577 } 00578 00579 const TemplateArgumentLoc &operator[](unsigned I) const { 00580 return getTemplateArgs()[I]; 00581 } 00582 00583 static const ASTTemplateArgumentListInfo *Create(ASTContext &C, 00584 const TemplateArgumentListInfo &List); 00585 00586 void initializeFrom(const TemplateArgumentListInfo &List); 00587 void initializeFrom(const TemplateArgumentListInfo &List, 00588 bool &Dependent, bool &InstantiationDependent, 00589 bool &ContainsUnexpandedParameterPack); 00590 void copyInto(TemplateArgumentListInfo &List) const; 00591 static std::size_t sizeFor(unsigned NumTemplateArgs); 00592 }; 00593 00594 /// \brief Extends ASTTemplateArgumentListInfo with the source location 00595 /// information for the template keyword; this is used as part of the 00596 /// representation of qualified identifiers, such as S<T>::template apply<T>. 00597 struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo { 00598 typedef ASTTemplateArgumentListInfo Base; 00599 00600 // NOTE: the source location of the (optional) template keyword is 00601 // stored after all template arguments. 00602 00603 /// \brief Get the source location of the template keyword. 00604 SourceLocation getTemplateKeywordLoc() const { 00605 return *reinterpret_cast<const SourceLocation*> 00606 (getTemplateArgs() + NumTemplateArgs); 00607 } 00608 00609 /// \brief Sets the source location of the template keyword. 00610 void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) { 00611 *reinterpret_cast<SourceLocation*> 00612 (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc; 00613 } 00614 00615 static const ASTTemplateKWAndArgsInfo* 00616 Create(ASTContext &C, SourceLocation TemplateKWLoc, 00617 const TemplateArgumentListInfo &List); 00618 00619 void initializeFrom(SourceLocation TemplateKWLoc, 00620 const TemplateArgumentListInfo &List); 00621 void initializeFrom(SourceLocation TemplateKWLoc, 00622 const TemplateArgumentListInfo &List, 00623 bool &Dependent, bool &InstantiationDependent, 00624 bool &ContainsUnexpandedParameterPack); 00625 void initializeFrom(SourceLocation TemplateKWLoc); 00626 00627 static std::size_t sizeFor(unsigned NumTemplateArgs); 00628 }; 00629 00630 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 00631 const TemplateArgument &Arg); 00632 00633 inline TemplateSpecializationType::iterator 00634 TemplateSpecializationType::end() const { 00635 return getArgs() + getNumArgs(); 00636 } 00637 00638 inline DependentTemplateSpecializationType::iterator 00639 DependentTemplateSpecializationType::end() const { 00640 return getArgs() + getNumArgs(); 00641 } 00642 00643 inline const TemplateArgument & 00644 TemplateSpecializationType::getArg(unsigned Idx) const { 00645 assert(Idx < getNumArgs() && "Template argument out of range"); 00646 return getArgs()[Idx]; 00647 } 00648 00649 inline const TemplateArgument & 00650 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 00651 assert(Idx < getNumArgs() && "Template argument out of range"); 00652 return getArgs()[Idx]; 00653 } 00654 00655 } // end namespace clang 00656 00657 #endif