TemplateBase.h revision 360784
1//===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file provides definitions which are common for all kinds of 10// template representation. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H 15#define LLVM_CLANG_AST_TEMPLATEBASE_H 16 17#include "clang/AST/NestedNameSpecifier.h" 18#include "clang/AST/TemplateName.h" 19#include "clang/AST/Type.h" 20#include "clang/Basic/LLVM.h" 21#include "clang/Basic/SourceLocation.h" 22#include "llvm/ADT/APInt.h" 23#include "llvm/ADT/APSInt.h" 24#include "llvm/ADT/ArrayRef.h" 25#include "llvm/ADT/None.h" 26#include "llvm/ADT/Optional.h" 27#include "llvm/ADT/SmallVector.h" 28#include "llvm/Support/Compiler.h" 29#include "llvm/Support/TrailingObjects.h" 30#include <cassert> 31#include <cstddef> 32#include <cstdint> 33 34namespace llvm { 35 36class FoldingSetNodeID; 37 38} // namespace llvm 39 40namespace clang { 41 42class ASTContext; 43class DiagnosticBuilder; 44class Expr; 45struct PrintingPolicy; 46class TypeSourceInfo; 47class ValueDecl; 48 49/// Represents a template argument. 50class TemplateArgument { 51public: 52 /// The kind of template argument we're storing. 53 enum ArgKind { 54 /// Represents an empty template argument, e.g., one that has not 55 /// been deduced. 56 Null = 0, 57 58 /// The template argument is a type. 59 Type, 60 61 /// The template argument is a declaration that was provided for a pointer, 62 /// reference, or pointer to member non-type template parameter. 63 Declaration, 64 65 /// The template argument is a null pointer or null pointer to member that 66 /// was provided for a non-type template parameter. 67 NullPtr, 68 69 /// The template argument is an integral value stored in an llvm::APSInt 70 /// that was provided for an integral non-type template parameter. 71 Integral, 72 73 /// The template argument is a template name that was provided for a 74 /// template template parameter. 75 Template, 76 77 /// The template argument is a pack expansion of a template name that was 78 /// provided for a template template parameter. 79 TemplateExpansion, 80 81 /// The template argument is an expression, and we've not resolved it to one 82 /// of the other forms yet, either because it's dependent or because we're 83 /// representing a non-canonical template argument (for instance, in a 84 /// TemplateSpecializationType). Also used to represent a non-dependent 85 /// __uuidof expression (a Microsoft extension). 86 Expression, 87 88 /// The template argument is actually a parameter pack. Arguments are stored 89 /// in the Args struct. 90 Pack 91 }; 92 93private: 94 /// The kind of template argument we're storing. 95 96 struct DA { 97 unsigned Kind; 98 void *QT; 99 ValueDecl *D; 100 }; 101 struct I { 102 unsigned Kind; 103 // We store a decomposed APSInt with the data allocated by ASTContext if 104 // BitWidth > 64. The memory may be shared between multiple 105 // TemplateArgument instances. 106 unsigned BitWidth : 31; 107 unsigned IsUnsigned : 1; 108 union { 109 /// Used to store the <= 64 bits integer value. 110 uint64_t VAL; 111 112 /// Used to store the >64 bits integer value. 113 const uint64_t *pVal; 114 }; 115 void *Type; 116 }; 117 struct A { 118 unsigned Kind; 119 unsigned NumArgs; 120 const TemplateArgument *Args; 121 }; 122 struct TA { 123 unsigned Kind; 124 unsigned NumExpansions; 125 void *Name; 126 }; 127 struct TV { 128 unsigned Kind; 129 uintptr_t V; 130 }; 131 union { 132 struct DA DeclArg; 133 struct I Integer; 134 struct A Args; 135 struct TA TemplateArg; 136 struct TV TypeOrValue; 137 }; 138 139public: 140 /// Construct an empty, invalid template argument. 141 constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} 142 143 /// Construct a template type argument. 144 TemplateArgument(QualType T, bool isNullPtr = false) { 145 TypeOrValue.Kind = isNullPtr ? NullPtr : Type; 146 TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); 147 } 148 149 /// Construct a template argument that refers to a 150 /// declaration, which is either an external declaration or a 151 /// template declaration. 152 TemplateArgument(ValueDecl *D, QualType QT) { 153 assert(D && "Expected decl"); 154 DeclArg.Kind = Declaration; 155 DeclArg.QT = QT.getAsOpaquePtr(); 156 DeclArg.D = D; 157 } 158 159 /// Construct an integral constant template argument. The memory to 160 /// store the value is allocated with Ctx. 161 TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); 162 163 /// Construct an integral constant template argument with the same 164 /// value as Other but a different type. 165 TemplateArgument(const TemplateArgument &Other, QualType Type) { 166 Integer = Other.Integer; 167 Integer.Type = Type.getAsOpaquePtr(); 168 } 169 170 /// Construct a template argument that is a template. 171 /// 172 /// This form of template argument is generally used for template template 173 /// parameters. However, the template name could be a dependent template 174 /// name that ends up being instantiated to a function template whose address 175 /// is taken. 176 /// 177 /// \param Name The template name. 178 TemplateArgument(TemplateName Name) { 179 TemplateArg.Kind = Template; 180 TemplateArg.Name = Name.getAsVoidPointer(); 181 TemplateArg.NumExpansions = 0; 182 } 183 184 /// Construct a template argument that is a template pack expansion. 185 /// 186 /// This form of template argument is generally used for template template 187 /// parameters. However, the template name could be a dependent template 188 /// name that ends up being instantiated to a function template whose address 189 /// is taken. 190 /// 191 /// \param Name The template name. 192 /// 193 /// \param NumExpansions The number of expansions that will be generated by 194 /// instantiating 195 TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) { 196 TemplateArg.Kind = TemplateExpansion; 197 TemplateArg.Name = Name.getAsVoidPointer(); 198 if (NumExpansions) 199 TemplateArg.NumExpansions = *NumExpansions + 1; 200 else 201 TemplateArg.NumExpansions = 0; 202 } 203 204 /// Construct a template argument that is an expression. 205 /// 206 /// This form of template argument only occurs in template argument 207 /// lists used for dependent types and for expression; it will not 208 /// occur in a non-dependent, canonical template argument list. 209 TemplateArgument(Expr *E) { 210 TypeOrValue.Kind = Expression; 211 TypeOrValue.V = reinterpret_cast<uintptr_t>(E); 212 } 213 214 /// Construct a template argument that is a template argument pack. 215 /// 216 /// We assume that storage for the template arguments provided 217 /// outlives the TemplateArgument itself. 218 explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { 219 this->Args.Kind = Pack; 220 this->Args.Args = Args.data(); 221 this->Args.NumArgs = Args.size(); 222 } 223 224 TemplateArgument(TemplateName, bool) = delete; 225 226 static TemplateArgument getEmptyPack() { return TemplateArgument(None); } 227 228 /// Create a new template argument pack by copying the given set of 229 /// template arguments. 230 static TemplateArgument CreatePackCopy(ASTContext &Context, 231 ArrayRef<TemplateArgument> Args); 232 233 /// Return the kind of stored template argument. 234 ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } 235 236 /// Determine whether this template argument has no value. 237 bool isNull() const { return getKind() == Null; } 238 239 /// Whether this template argument is dependent on a template 240 /// parameter such that its result can change from one instantiation to 241 /// another. 242 bool isDependent() const; 243 244 /// Whether this template argument is dependent on a template 245 /// parameter. 246 bool isInstantiationDependent() const; 247 248 /// Whether this template argument contains an unexpanded 249 /// parameter pack. 250 bool containsUnexpandedParameterPack() const; 251 252 /// Determine whether this template argument is a pack expansion. 253 bool isPackExpansion() const; 254 255 /// Retrieve the type for a type template argument. 256 QualType getAsType() const { 257 assert(getKind() == Type && "Unexpected kind"); 258 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); 259 } 260 261 /// Retrieve the declaration for a declaration non-type 262 /// template argument. 263 ValueDecl *getAsDecl() const { 264 assert(getKind() == Declaration && "Unexpected kind"); 265 return DeclArg.D; 266 } 267 268 QualType getParamTypeForDecl() const { 269 assert(getKind() == Declaration && "Unexpected kind"); 270 return QualType::getFromOpaquePtr(DeclArg.QT); 271 } 272 273 /// Retrieve the type for null non-type template argument. 274 QualType getNullPtrType() const { 275 assert(getKind() == NullPtr && "Unexpected kind"); 276 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); 277 } 278 279 /// Retrieve the template name for a template name argument. 280 TemplateName getAsTemplate() const { 281 assert(getKind() == Template && "Unexpected kind"); 282 return TemplateName::getFromVoidPointer(TemplateArg.Name); 283 } 284 285 /// Retrieve the template argument as a template name; if the argument 286 /// is a pack expansion, return the pattern as a template name. 287 TemplateName getAsTemplateOrTemplatePattern() const { 288 assert((getKind() == Template || getKind() == TemplateExpansion) && 289 "Unexpected kind"); 290 291 return TemplateName::getFromVoidPointer(TemplateArg.Name); 292 } 293 294 /// Retrieve the number of expansions that a template template argument 295 /// expansion will produce, if known. 296 Optional<unsigned> getNumTemplateExpansions() const; 297 298 /// Retrieve the template argument as an integral value. 299 // FIXME: Provide a way to read the integral data without copying the value. 300 llvm::APSInt getAsIntegral() const { 301 assert(getKind() == Integral && "Unexpected kind"); 302 303 using namespace llvm; 304 305 if (Integer.BitWidth <= 64) 306 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); 307 308 unsigned NumWords = APInt::getNumWords(Integer.BitWidth); 309 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), 310 Integer.IsUnsigned); 311 } 312 313 /// Retrieve the type of the integral value. 314 QualType getIntegralType() const { 315 assert(getKind() == Integral && "Unexpected kind"); 316 return QualType::getFromOpaquePtr(Integer.Type); 317 } 318 319 void setIntegralType(QualType T) { 320 assert(getKind() == Integral && "Unexpected kind"); 321 Integer.Type = T.getAsOpaquePtr(); 322 } 323 324 /// If this is a non-type template argument, get its type. Otherwise, 325 /// returns a null QualType. 326 QualType getNonTypeTemplateArgumentType() const; 327 328 /// Retrieve the template argument as an expression. 329 Expr *getAsExpr() const { 330 assert(getKind() == Expression && "Unexpected kind"); 331 return reinterpret_cast<Expr *>(TypeOrValue.V); 332 } 333 334 /// Iterator that traverses the elements of a template argument pack. 335 using pack_iterator = const TemplateArgument *; 336 337 /// Iterator referencing the first argument of a template argument 338 /// pack. 339 pack_iterator pack_begin() const { 340 assert(getKind() == Pack); 341 return Args.Args; 342 } 343 344 /// Iterator referencing one past the last argument of a template 345 /// argument pack. 346 pack_iterator pack_end() const { 347 assert(getKind() == Pack); 348 return Args.Args + Args.NumArgs; 349 } 350 351 /// Iterator range referencing all of the elements of a template 352 /// argument pack. 353 ArrayRef<TemplateArgument> pack_elements() const { 354 return llvm::makeArrayRef(pack_begin(), pack_end()); 355 } 356 357 /// The number of template arguments in the given template argument 358 /// pack. 359 unsigned pack_size() const { 360 assert(getKind() == Pack); 361 return Args.NumArgs; 362 } 363 364 /// Return the array of arguments in this template argument pack. 365 ArrayRef<TemplateArgument> getPackAsArray() const { 366 assert(getKind() == Pack); 367 return llvm::makeArrayRef(Args.Args, Args.NumArgs); 368 } 369 370 /// Determines whether two template arguments are superficially the 371 /// same. 372 bool structurallyEquals(const TemplateArgument &Other) const; 373 374 /// When the template argument is a pack expansion, returns 375 /// the pattern of the pack expansion. 376 TemplateArgument getPackExpansionPattern() const; 377 378 /// Print this template argument to the given output stream. 379 void print(const PrintingPolicy &Policy, raw_ostream &Out) const; 380 381 /// Debugging aid that dumps the template argument. 382 void dump(raw_ostream &Out) const; 383 384 /// Debugging aid that dumps the template argument to standard error. 385 void dump() const; 386 387 /// Used to insert TemplateArguments into FoldingSets. 388 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 389}; 390 391/// Location information for a TemplateArgument. 392struct TemplateArgumentLocInfo { 393private: 394 struct T { 395 // FIXME: We'd like to just use the qualifier in the TemplateName, 396 // but template arguments get canonicalized too quickly. 397 NestedNameSpecifier *Qualifier; 398 void *QualifierLocData; 399 unsigned TemplateNameLoc; 400 unsigned EllipsisLoc; 401 }; 402 403 union { 404 struct T Template; 405 Expr *Expression; 406 TypeSourceInfo *Declarator; 407 }; 408 409public: 410 constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {} 411 412 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 413 414 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 415 416 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, 417 SourceLocation TemplateNameLoc, 418 SourceLocation EllipsisLoc) { 419 Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); 420 Template.QualifierLocData = QualifierLoc.getOpaqueData(); 421 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 422 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 423 } 424 425 TypeSourceInfo *getAsTypeSourceInfo() const { 426 return Declarator; 427 } 428 429 Expr *getAsExpr() const { 430 return Expression; 431 } 432 433 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 434 return NestedNameSpecifierLoc(Template.Qualifier, 435 Template.QualifierLocData); 436 } 437 438 SourceLocation getTemplateNameLoc() const { 439 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 440 } 441 442 SourceLocation getTemplateEllipsisLoc() const { 443 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 444 } 445}; 446 447/// Location wrapper for a TemplateArgument. TemplateArgument is to 448/// TemplateArgumentLoc as Type is to TypeLoc. 449class TemplateArgumentLoc { 450 TemplateArgument Argument; 451 TemplateArgumentLocInfo LocInfo; 452 453public: 454 constexpr TemplateArgumentLoc() {} 455 456 TemplateArgumentLoc(const TemplateArgument &Argument, 457 TemplateArgumentLocInfo Opaque) 458 : Argument(Argument), LocInfo(Opaque) {} 459 460 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 461 : Argument(Argument), LocInfo(TInfo) { 462 assert(Argument.getKind() == TemplateArgument::Type); 463 } 464 465 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 466 : Argument(Argument), LocInfo(E) { 467 468 // Permit any kind of template argument that can be represented with an 469 // expression. 470 assert(Argument.getKind() == TemplateArgument::NullPtr || 471 Argument.getKind() == TemplateArgument::Integral || 472 Argument.getKind() == TemplateArgument::Declaration || 473 Argument.getKind() == TemplateArgument::Expression); 474 } 475 476 TemplateArgumentLoc(const TemplateArgument &Argument, 477 NestedNameSpecifierLoc QualifierLoc, 478 SourceLocation TemplateNameLoc, 479 SourceLocation EllipsisLoc = SourceLocation()) 480 : Argument(Argument), 481 LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { 482 assert(Argument.getKind() == TemplateArgument::Template || 483 Argument.getKind() == TemplateArgument::TemplateExpansion); 484 } 485 486 /// - Fetches the primary location of the argument. 487 SourceLocation getLocation() const { 488 if (Argument.getKind() == TemplateArgument::Template || 489 Argument.getKind() == TemplateArgument::TemplateExpansion) 490 return getTemplateNameLoc(); 491 492 return getSourceRange().getBegin(); 493 } 494 495 /// - Fetches the full source range of the argument. 496 SourceRange getSourceRange() const LLVM_READONLY; 497 498 const TemplateArgument &getArgument() const { 499 return Argument; 500 } 501 502 TemplateArgumentLocInfo getLocInfo() const { 503 return LocInfo; 504 } 505 506 TypeSourceInfo *getTypeSourceInfo() const { 507 assert(Argument.getKind() == TemplateArgument::Type); 508 return LocInfo.getAsTypeSourceInfo(); 509 } 510 511 Expr *getSourceExpression() const { 512 assert(Argument.getKind() == TemplateArgument::Expression); 513 return LocInfo.getAsExpr(); 514 } 515 516 Expr *getSourceDeclExpression() const { 517 assert(Argument.getKind() == TemplateArgument::Declaration); 518 return LocInfo.getAsExpr(); 519 } 520 521 Expr *getSourceNullPtrExpression() const { 522 assert(Argument.getKind() == TemplateArgument::NullPtr); 523 return LocInfo.getAsExpr(); 524 } 525 526 Expr *getSourceIntegralExpression() const { 527 assert(Argument.getKind() == TemplateArgument::Integral); 528 return LocInfo.getAsExpr(); 529 } 530 531 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 532 if (Argument.getKind() != TemplateArgument::Template && 533 Argument.getKind() != TemplateArgument::TemplateExpansion) 534 return NestedNameSpecifierLoc(); 535 return LocInfo.getTemplateQualifierLoc(); 536 } 537 538 SourceLocation getTemplateNameLoc() const { 539 if (Argument.getKind() != TemplateArgument::Template && 540 Argument.getKind() != TemplateArgument::TemplateExpansion) 541 return SourceLocation(); 542 return LocInfo.getTemplateNameLoc(); 543 } 544 545 SourceLocation getTemplateEllipsisLoc() const { 546 if (Argument.getKind() != TemplateArgument::TemplateExpansion) 547 return SourceLocation(); 548 return LocInfo.getTemplateEllipsisLoc(); 549 } 550}; 551 552/// A convenient class for passing around template argument 553/// information. Designed to be passed by reference. 554class TemplateArgumentListInfo { 555 SmallVector<TemplateArgumentLoc, 8> Arguments; 556 SourceLocation LAngleLoc; 557 SourceLocation RAngleLoc; 558 559public: 560 TemplateArgumentListInfo() = default; 561 562 TemplateArgumentListInfo(SourceLocation LAngleLoc, 563 SourceLocation RAngleLoc) 564 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 565 566 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo 567 // instead. 568 void *operator new(size_t bytes, ASTContext &C) = delete; 569 570 SourceLocation getLAngleLoc() const { return LAngleLoc; } 571 SourceLocation getRAngleLoc() const { return RAngleLoc; } 572 573 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 574 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 575 576 unsigned size() const { return Arguments.size(); } 577 578 const TemplateArgumentLoc *getArgumentArray() const { 579 return Arguments.data(); 580 } 581 582 llvm::ArrayRef<TemplateArgumentLoc> arguments() const { 583 return Arguments; 584 } 585 586 const TemplateArgumentLoc &operator[](unsigned I) const { 587 return Arguments[I]; 588 } 589 590 TemplateArgumentLoc &operator[](unsigned I) { 591 return Arguments[I]; 592 } 593 594 void addArgument(const TemplateArgumentLoc &Loc) { 595 Arguments.push_back(Loc); 596 } 597}; 598 599/// Represents an explicit template argument list in C++, e.g., 600/// the "<int>" in "sort<int>". 601/// This is safe to be used inside an AST node, in contrast with 602/// TemplateArgumentListInfo. 603struct ASTTemplateArgumentListInfo final 604 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, 605 TemplateArgumentLoc> { 606private: 607 friend class ASTNodeImporter; 608 friend TrailingObjects; 609 610 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); 611 612public: 613 /// The source location of the left angle bracket ('<'). 614 SourceLocation LAngleLoc; 615 616 /// The source location of the right angle bracket ('>'). 617 SourceLocation RAngleLoc; 618 619 /// The number of template arguments in TemplateArgs. 620 unsigned NumTemplateArgs; 621 622 SourceLocation getLAngleLoc() const { return LAngleLoc; } 623 SourceLocation getRAngleLoc() const { return RAngleLoc; } 624 625 /// Retrieve the template arguments 626 const TemplateArgumentLoc *getTemplateArgs() const { 627 return getTrailingObjects<TemplateArgumentLoc>(); 628 } 629 unsigned getNumTemplateArgs() const { return NumTemplateArgs; } 630 631 llvm::ArrayRef<TemplateArgumentLoc> arguments() const { 632 return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs()); 633 } 634 635 const TemplateArgumentLoc &operator[](unsigned I) const { 636 return getTemplateArgs()[I]; 637 } 638 639 static const ASTTemplateArgumentListInfo * 640 Create(const ASTContext &C, const TemplateArgumentListInfo &List); 641}; 642 643/// Represents an explicit template argument list in C++, e.g., 644/// the "<int>" in "sort<int>". 645/// 646/// It is intended to be used as a trailing object on AST nodes, and 647/// as such, doesn't contain the array of TemplateArgumentLoc itself, 648/// but expects the containing object to also provide storage for 649/// that. 650struct alignas(void *) ASTTemplateKWAndArgsInfo { 651 /// The source location of the left angle bracket ('<'). 652 SourceLocation LAngleLoc; 653 654 /// The source location of the right angle bracket ('>'). 655 SourceLocation RAngleLoc; 656 657 /// The source location of the template keyword; this is used 658 /// as part of the representation of qualified identifiers, such as 659 /// S<T>::template apply<T>. Will be empty if this expression does 660 /// not have a template keyword. 661 SourceLocation TemplateKWLoc; 662 663 /// The number of template arguments in TemplateArgs. 664 unsigned NumTemplateArgs; 665 666 void initializeFrom(SourceLocation TemplateKWLoc, 667 const TemplateArgumentListInfo &List, 668 TemplateArgumentLoc *OutArgArray); 669 void initializeFrom(SourceLocation TemplateKWLoc, 670 const TemplateArgumentListInfo &List, 671 TemplateArgumentLoc *OutArgArray, bool &Dependent, 672 bool &InstantiationDependent, 673 bool &ContainsUnexpandedParameterPack); 674 void initializeFrom(SourceLocation TemplateKWLoc); 675 676 void copyInto(const TemplateArgumentLoc *ArgArray, 677 TemplateArgumentListInfo &List) const; 678}; 679 680const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 681 const TemplateArgument &Arg); 682 683inline TemplateSpecializationType::iterator 684 TemplateSpecializationType::end() const { 685 return getArgs() + getNumArgs(); 686} 687 688inline DependentTemplateSpecializationType::iterator 689 DependentTemplateSpecializationType::end() const { 690 return getArgs() + getNumArgs(); 691} 692 693inline const TemplateArgument & 694 TemplateSpecializationType::getArg(unsigned Idx) const { 695 assert(Idx < getNumArgs() && "Template argument out of range"); 696 return getArgs()[Idx]; 697} 698 699inline const TemplateArgument & 700 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 701 assert(Idx < getNumArgs() && "Template argument out of range"); 702 return getArgs()[Idx]; 703} 704 705inline const TemplateArgument &AutoType::getArg(unsigned Idx) const { 706 assert(Idx < getNumArgs() && "Template argument out of range"); 707 return getArgs()[Idx]; 708} 709 710} // namespace clang 711 712#endif // LLVM_CLANG_AST_TEMPLATEBASE_H 713