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 "clang/AST/Type.h" 19 #include "clang/AST/TemplateName.h" 20 #include "llvm/ADT/APSInt.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/Support/Compiler.h" 23 #include "llvm/Support/ErrorHandling.h" 24 25 namespace llvm { 26 class FoldingSetNodeID; 27 } 28 29 namespace clang { 30 31 class Decl; 32 class DiagnosticBuilder; 33 class Expr; 34 struct PrintingPolicy; 35 class TypeSourceInfo; 36 37 /// \brief Represents a template argument within a class template 38 /// specialization. 39 class TemplateArgument { 40 public: 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 pack expansion of a template name that was 59 /// provided for a template template parameter. 60 TemplateExpansion, 61 /// The template argument is a value- or type-dependent expression 62 /// stored in an Expr*. 63 Expression, 64 /// The template argument is actually a parameter pack. Arguments are stored 65 /// in the Args struct. 66 Pack 67 }; 68 69 private: 70 /// \brief The kind of template argument we're storing. 71 unsigned Kind; 72 73 union { 74 uintptr_t TypeOrValue; 75 struct { 76 // We store a decomposed APSInt with the data allocated by ASTContext if 77 // BitWidth > 64. The memory may be shared between multiple 78 // TemplateArgument instances. 79 union { 80 uint64_t VAL; ///< Used to store the <= 64 bits integer value. 81 const uint64_t *pVal; ///< Used to store the >64 bits integer value. 82 }; 83 unsigned BitWidth : 31; 84 unsigned IsUnsigned : 1; 85 void *Type; 86 } Integer; 87 struct { 88 const TemplateArgument *Args; 89 unsigned NumArgs; 90 } Args; 91 struct { 92 void *Name; 93 unsigned NumExpansions; 94 } TemplateArg; 95 }; 96 97 TemplateArgument(TemplateName, bool); // DO NOT USE 98 99 public: 100 /// \brief Construct an empty, invalid template argument. TemplateArgument()101 TemplateArgument() : Kind(Null), TypeOrValue(0) { } 102 103 /// \brief Construct a template type argument. TemplateArgument(QualType T)104 TemplateArgument(QualType T) : Kind(Type) { 105 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); 106 } 107 108 /// \brief Construct a template argument that refers to a 109 /// declaration, which is either an external declaration or a 110 /// template declaration. TemplateArgument(Decl * D)111 TemplateArgument(Decl *D) : Kind(Declaration) { 112 TypeOrValue = reinterpret_cast<uintptr_t>(D); 113 } 114 115 /// \brief Construct an integral constant template argument. The memory to 116 /// store the value is allocated with Ctx. 117 TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); 118 119 /// \brief Construct an integral constant template argument with the same 120 /// value as Other but a different type. TemplateArgument(const TemplateArgument & Other,QualType Type)121 TemplateArgument(const TemplateArgument &Other, QualType Type) 122 : Kind(Integral) { 123 Integer = Other.Integer; 124 Integer.Type = Type.getAsOpaquePtr(); 125 } 126 127 /// \brief Construct a template argument that is a template. 128 /// 129 /// This form of template argument is generally used for template template 130 /// parameters. However, the template name could be a dependent template 131 /// name that ends up being instantiated to a function template whose address 132 /// is taken. 133 /// 134 /// \param Name The template name. TemplateArgument(TemplateName Name)135 TemplateArgument(TemplateName Name) : Kind(Template) 136 { 137 TemplateArg.Name = Name.getAsVoidPointer(); 138 TemplateArg.NumExpansions = 0; 139 } 140 141 /// \brief Construct a template argument that is a template pack expansion. 142 /// 143 /// This form of template argument is generally used for template template 144 /// parameters. However, the template name could be a dependent template 145 /// name that ends up being instantiated to a function template whose address 146 /// is taken. 147 /// 148 /// \param Name The template name. 149 /// 150 /// \param NumExpansions The number of expansions that will be generated by 151 /// instantiating TemplateArgument(TemplateName Name,llvm::Optional<unsigned> NumExpansions)152 TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) 153 : Kind(TemplateExpansion) 154 { 155 TemplateArg.Name = Name.getAsVoidPointer(); 156 if (NumExpansions) 157 TemplateArg.NumExpansions = *NumExpansions + 1; 158 else 159 TemplateArg.NumExpansions = 0; 160 } 161 162 /// \brief Construct a template argument that is an expression. 163 /// 164 /// This form of template argument only occurs in template argument 165 /// lists used for dependent types and for expression; it will not 166 /// occur in a non-dependent, canonical template argument list. TemplateArgument(Expr * E)167 TemplateArgument(Expr *E) : Kind(Expression) { 168 TypeOrValue = reinterpret_cast<uintptr_t>(E); 169 } 170 171 /// \brief Construct a template argument that is a template argument pack. 172 /// 173 /// We assume that storage for the template arguments provided 174 /// outlives the TemplateArgument itself. TemplateArgument(const TemplateArgument * Args,unsigned NumArgs)175 TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){ 176 this->Args.Args = Args; 177 this->Args.NumArgs = NumArgs; 178 } 179 180 /// \brief Create a new template argument pack by copying the given set of 181 /// template arguments. 182 static TemplateArgument CreatePackCopy(ASTContext &Context, 183 const TemplateArgument *Args, 184 unsigned NumArgs); 185 186 /// \brief Return the kind of stored template argument. getKind()187 ArgKind getKind() const { return (ArgKind)Kind; } 188 189 /// \brief Determine whether this template argument has no value. isNull()190 bool isNull() const { return Kind == Null; } 191 192 /// \brief Whether this template argument is dependent on a template 193 /// parameter such that its result can change from one instantiation to 194 /// another. 195 bool isDependent() const; 196 197 /// \brief Whether this template argument is dependent on a template 198 /// parameter. 199 bool isInstantiationDependent() const; 200 201 /// \brief Whether this template argument contains an unexpanded 202 /// parameter pack. 203 bool containsUnexpandedParameterPack() const; 204 205 /// \brief Determine whether this template argument is a pack expansion. 206 bool isPackExpansion() const; 207 208 /// \brief Retrieve the template argument as a type. getAsType()209 QualType getAsType() const { 210 if (Kind != Type) 211 return QualType(); 212 213 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); 214 } 215 216 /// \brief Retrieve the template argument as a declaration. getAsDecl()217 Decl *getAsDecl() const { 218 if (Kind != Declaration) 219 return 0; 220 return reinterpret_cast<Decl *>(TypeOrValue); 221 } 222 223 /// \brief Retrieve the template argument as a template name. getAsTemplate()224 TemplateName getAsTemplate() const { 225 if (Kind != Template) 226 return TemplateName(); 227 228 return TemplateName::getFromVoidPointer(TemplateArg.Name); 229 } 230 231 /// \brief Retrieve the template argument as a template name; if the argument 232 /// is a pack expansion, return the pattern as a template name. getAsTemplateOrTemplatePattern()233 TemplateName getAsTemplateOrTemplatePattern() const { 234 if (Kind != Template && Kind != TemplateExpansion) 235 return TemplateName(); 236 237 return TemplateName::getFromVoidPointer(TemplateArg.Name); 238 } 239 240 /// \brief Retrieve the number of expansions that a template template argument 241 /// expansion will produce, if known. 242 llvm::Optional<unsigned> getNumTemplateExpansions() const; 243 244 /// \brief Retrieve the template argument as an integral value. 245 // FIXME: Provide a way to read the integral data without copying the value. getAsIntegral()246 llvm::APSInt getAsIntegral() const { 247 using namespace llvm; 248 if (Integer.BitWidth <= 64) 249 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); 250 251 unsigned NumWords = APInt::getNumWords(Integer.BitWidth); 252 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), 253 Integer.IsUnsigned); 254 } 255 256 /// \brief Retrieve the type of the integral value. getIntegralType()257 QualType getIntegralType() const { 258 if (Kind != Integral) 259 return QualType(); 260 261 return QualType::getFromOpaquePtr(Integer.Type); 262 } 263 setIntegralType(QualType T)264 void setIntegralType(QualType T) { 265 assert(Kind == Integral && 266 "Cannot set the integral type of a non-integral template argument"); 267 Integer.Type = T.getAsOpaquePtr(); 268 } 269 270 /// \brief Retrieve the template argument as an expression. getAsExpr()271 Expr *getAsExpr() const { 272 if (Kind != Expression) 273 return 0; 274 275 return reinterpret_cast<Expr *>(TypeOrValue); 276 } 277 278 /// \brief Iterator that traverses the elements of a template argument pack. 279 typedef const TemplateArgument * pack_iterator; 280 281 /// \brief Iterator referencing the first argument of a template argument 282 /// pack. pack_begin()283 pack_iterator pack_begin() const { 284 assert(Kind == Pack); 285 return Args.Args; 286 } 287 288 /// \brief Iterator referencing one past the last argument of a template 289 /// argument pack. pack_end()290 pack_iterator pack_end() const { 291 assert(Kind == Pack); 292 return Args.Args + Args.NumArgs; 293 } 294 295 /// \brief The number of template arguments in the given template argument 296 /// pack. pack_size()297 unsigned pack_size() const { 298 assert(Kind == Pack); 299 return Args.NumArgs; 300 } 301 302 /// \brief Determines whether two template arguments are superficially the 303 /// same. 304 bool structurallyEquals(const TemplateArgument &Other) const; 305 306 /// \brief When the template argument is a pack expansion, returns 307 /// the pattern of the pack expansion. 308 TemplateArgument getPackExpansionPattern() const; 309 310 /// \brief Print this template argument to the given output stream. 311 void print(const PrintingPolicy &Policy, raw_ostream &Out) const; 312 313 /// \brief Used to insert TemplateArguments into FoldingSets. 314 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 315 }; 316 317 /// Location information for a TemplateArgument. 318 struct TemplateArgumentLocInfo { 319 private: 320 union { 321 Expr *Expression; 322 TypeSourceInfo *Declarator; 323 struct { 324 // FIXME: We'd like to just use the qualifier in the TemplateName, 325 // but template arguments get canonicalized too quickly. 326 NestedNameSpecifier *Qualifier; 327 void *QualifierLocData; 328 unsigned TemplateNameLoc; 329 unsigned EllipsisLoc; 330 } Template; 331 }; 332 333 public: 334 TemplateArgumentLocInfo(); 335 TemplateArgumentLocInfoTemplateArgumentLocInfo336 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 337 TemplateArgumentLocInfoTemplateArgumentLocInfo338 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 339 TemplateArgumentLocInfoTemplateArgumentLocInfo340 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, 341 SourceLocation TemplateNameLoc, 342 SourceLocation EllipsisLoc) 343 { 344 Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); 345 Template.QualifierLocData = QualifierLoc.getOpaqueData(); 346 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 347 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 348 } 349 getAsTypeSourceInfoTemplateArgumentLocInfo350 TypeSourceInfo *getAsTypeSourceInfo() const { 351 return Declarator; 352 } 353 getAsExprTemplateArgumentLocInfo354 Expr *getAsExpr() const { 355 return Expression; 356 } 357 getTemplateQualifierLocTemplateArgumentLocInfo358 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 359 return NestedNameSpecifierLoc(Template.Qualifier, 360 Template.QualifierLocData); 361 } 362 getTemplateNameLocTemplateArgumentLocInfo363 SourceLocation getTemplateNameLoc() const { 364 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 365 } 366 getTemplateEllipsisLocTemplateArgumentLocInfo367 SourceLocation getTemplateEllipsisLoc() const { 368 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 369 } 370 }; 371 372 /// Location wrapper for a TemplateArgument. TemplateArgument is to 373 /// TemplateArgumentLoc as Type is to TypeLoc. 374 class TemplateArgumentLoc { 375 TemplateArgument Argument; 376 TemplateArgumentLocInfo LocInfo; 377 378 public: TemplateArgumentLoc()379 TemplateArgumentLoc() {} 380 TemplateArgumentLoc(const TemplateArgument & Argument,TemplateArgumentLocInfo Opaque)381 TemplateArgumentLoc(const TemplateArgument &Argument, 382 TemplateArgumentLocInfo Opaque) 383 : Argument(Argument), LocInfo(Opaque) { 384 } 385 TemplateArgumentLoc(const TemplateArgument & Argument,TypeSourceInfo * TInfo)386 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 387 : Argument(Argument), LocInfo(TInfo) { 388 assert(Argument.getKind() == TemplateArgument::Type); 389 } 390 TemplateArgumentLoc(const TemplateArgument & Argument,Expr * E)391 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 392 : Argument(Argument), LocInfo(E) { 393 assert(Argument.getKind() == TemplateArgument::Expression); 394 } 395 396 TemplateArgumentLoc(const TemplateArgument &Argument, 397 NestedNameSpecifierLoc QualifierLoc, 398 SourceLocation TemplateNameLoc, 399 SourceLocation EllipsisLoc = SourceLocation()) Argument(Argument)400 : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { 401 assert(Argument.getKind() == TemplateArgument::Template || 402 Argument.getKind() == TemplateArgument::TemplateExpansion); 403 } 404 405 /// \brief - Fetches the primary location of the argument. getLocation()406 SourceLocation getLocation() const { 407 if (Argument.getKind() == TemplateArgument::Template || 408 Argument.getKind() == TemplateArgument::TemplateExpansion) 409 return getTemplateNameLoc(); 410 411 return getSourceRange().getBegin(); 412 } 413 414 /// \brief - Fetches the full source range of the argument. 415 SourceRange getSourceRange() const LLVM_READONLY; 416 getArgument()417 const TemplateArgument &getArgument() const { 418 return Argument; 419 } 420 getLocInfo()421 TemplateArgumentLocInfo getLocInfo() const { 422 return LocInfo; 423 } 424 getTypeSourceInfo()425 TypeSourceInfo *getTypeSourceInfo() const { 426 assert(Argument.getKind() == TemplateArgument::Type); 427 return LocInfo.getAsTypeSourceInfo(); 428 } 429 getSourceExpression()430 Expr *getSourceExpression() const { 431 assert(Argument.getKind() == TemplateArgument::Expression); 432 return LocInfo.getAsExpr(); 433 } 434 getSourceDeclExpression()435 Expr *getSourceDeclExpression() const { 436 assert(Argument.getKind() == TemplateArgument::Declaration); 437 return LocInfo.getAsExpr(); 438 } 439 getTemplateQualifierLoc()440 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 441 assert(Argument.getKind() == TemplateArgument::Template || 442 Argument.getKind() == TemplateArgument::TemplateExpansion); 443 return LocInfo.getTemplateQualifierLoc(); 444 } 445 getTemplateNameLoc()446 SourceLocation getTemplateNameLoc() const { 447 assert(Argument.getKind() == TemplateArgument::Template || 448 Argument.getKind() == TemplateArgument::TemplateExpansion); 449 return LocInfo.getTemplateNameLoc(); 450 } 451 getTemplateEllipsisLoc()452 SourceLocation getTemplateEllipsisLoc() const { 453 assert(Argument.getKind() == TemplateArgument::TemplateExpansion); 454 return LocInfo.getTemplateEllipsisLoc(); 455 } 456 457 /// \brief When the template argument is a pack expansion, returns 458 /// the pattern of the pack expansion. 459 /// 460 /// \param Ellipsis Will be set to the location of the ellipsis. 461 /// 462 /// \param NumExpansions Will be set to the number of expansions that will 463 /// be generated from this pack expansion, if known a priori. 464 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, 465 llvm::Optional<unsigned> &NumExpansions, 466 ASTContext &Context) const; 467 }; 468 469 /// A convenient class for passing around template argument 470 /// information. Designed to be passed by reference. 471 class TemplateArgumentListInfo { 472 SmallVector<TemplateArgumentLoc, 8> Arguments; 473 SourceLocation LAngleLoc; 474 SourceLocation RAngleLoc; 475 476 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo 477 // instead. 478 void* operator new(size_t bytes, ASTContext& C); 479 480 public: TemplateArgumentListInfo()481 TemplateArgumentListInfo() {} 482 TemplateArgumentListInfo(SourceLocation LAngleLoc,SourceLocation RAngleLoc)483 TemplateArgumentListInfo(SourceLocation LAngleLoc, 484 SourceLocation RAngleLoc) 485 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 486 getLAngleLoc()487 SourceLocation getLAngleLoc() const { return LAngleLoc; } getRAngleLoc()488 SourceLocation getRAngleLoc() const { return RAngleLoc; } 489 setLAngleLoc(SourceLocation Loc)490 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } setRAngleLoc(SourceLocation Loc)491 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 492 size()493 unsigned size() const { return Arguments.size(); } 494 getArgumentArray()495 const TemplateArgumentLoc *getArgumentArray() const { 496 return Arguments.data(); 497 } 498 499 const TemplateArgumentLoc &operator[](unsigned I) const { 500 return Arguments[I]; 501 } 502 addArgument(const TemplateArgumentLoc & Loc)503 void addArgument(const TemplateArgumentLoc &Loc) { 504 Arguments.push_back(Loc); 505 } 506 }; 507 508 /// \brief Represents an explicit template argument list in C++, e.g., 509 /// the "<int>" in "sort<int>". 510 /// This is safe to be used inside an AST node, in contrast with 511 /// TemplateArgumentListInfo. 512 struct ASTTemplateArgumentListInfo { 513 /// \brief The source location of the left angle bracket ('<'). 514 SourceLocation LAngleLoc; 515 516 /// \brief The source location of the right angle bracket ('>'). 517 SourceLocation RAngleLoc; 518 519 union { 520 /// \brief The number of template arguments in TemplateArgs. 521 /// The actual template arguments (if any) are stored after the 522 /// ExplicitTemplateArgumentList structure. 523 unsigned NumTemplateArgs; 524 525 /// Force ASTTemplateArgumentListInfo to the right alignment 526 /// for the following array of TemplateArgumentLocs. 527 void *Aligner; 528 }; 529 530 /// \brief Retrieve the template arguments getTemplateArgsASTTemplateArgumentListInfo531 TemplateArgumentLoc *getTemplateArgs() { 532 return reinterpret_cast<TemplateArgumentLoc *> (this + 1); 533 } 534 535 /// \brief Retrieve the template arguments getTemplateArgsASTTemplateArgumentListInfo536 const TemplateArgumentLoc *getTemplateArgs() const { 537 return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); 538 } 539 540 const TemplateArgumentLoc &operator[](unsigned I) const { 541 return getTemplateArgs()[I]; 542 } 543 544 static const ASTTemplateArgumentListInfo *Create(ASTContext &C, 545 const TemplateArgumentListInfo &List); 546 547 void initializeFrom(const TemplateArgumentListInfo &List); 548 void initializeFrom(const TemplateArgumentListInfo &List, 549 bool &Dependent, bool &InstantiationDependent, 550 bool &ContainsUnexpandedParameterPack); 551 void copyInto(TemplateArgumentListInfo &List) const; 552 static std::size_t sizeFor(unsigned NumTemplateArgs); 553 }; 554 555 /// \brief Extends ASTTemplateArgumentListInfo with the source location 556 /// information for the template keyword; this is used as part of the 557 /// representation of qualified identifiers, such as S<T>::template apply<T>. 558 struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo { 559 typedef ASTTemplateArgumentListInfo Base; 560 561 // NOTE: the source location of the (optional) template keyword is 562 // stored after all template arguments. 563 564 /// \brief Get the source location of the template keyword. getTemplateKeywordLocASTTemplateKWAndArgsInfo565 SourceLocation getTemplateKeywordLoc() const { 566 return *reinterpret_cast<const SourceLocation*> 567 (getTemplateArgs() + NumTemplateArgs); 568 } 569 570 /// \brief Sets the source location of the template keyword. setTemplateKeywordLocASTTemplateKWAndArgsInfo571 void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) { 572 *reinterpret_cast<SourceLocation*> 573 (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc; 574 } 575 576 static const ASTTemplateKWAndArgsInfo* 577 Create(ASTContext &C, SourceLocation TemplateKWLoc, 578 const TemplateArgumentListInfo &List); 579 580 void initializeFrom(SourceLocation TemplateKWLoc, 581 const TemplateArgumentListInfo &List); 582 void initializeFrom(SourceLocation TemplateKWLoc, 583 const TemplateArgumentListInfo &List, 584 bool &Dependent, bool &InstantiationDependent, 585 bool &ContainsUnexpandedParameterPack); 586 void initializeFrom(SourceLocation TemplateKWLoc); 587 588 static std::size_t sizeFor(unsigned NumTemplateArgs); 589 }; 590 591 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 592 const TemplateArgument &Arg); 593 594 inline TemplateSpecializationType::iterator end()595 TemplateSpecializationType::end() const { 596 return getArgs() + getNumArgs(); 597 } 598 599 inline DependentTemplateSpecializationType::iterator end()600 DependentTemplateSpecializationType::end() const { 601 return getArgs() + getNumArgs(); 602 } 603 604 inline const TemplateArgument & getArg(unsigned Idx)605 TemplateSpecializationType::getArg(unsigned Idx) const { 606 assert(Idx < getNumArgs() && "Template argument out of range"); 607 return getArgs()[Idx]; 608 } 609 610 inline const TemplateArgument & getArg(unsigned Idx)611 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 612 assert(Idx < getNumArgs() && "Template argument out of range"); 613 return getArgs()[Idx]; 614 } 615 616 } // end namespace clang 617 618 #endif 619