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/DependenceFlags.h" 18 #include "clang/AST/NestedNameSpecifier.h" 19 #include "clang/AST/TemplateName.h" 20 #include "clang/AST/Type.h" 21 #include "clang/Basic/LLVM.h" 22 #include "clang/Basic/SourceLocation.h" 23 #include "llvm/ADT/APInt.h" 24 #include "llvm/ADT/APSInt.h" 25 #include "llvm/ADT/ArrayRef.h" 26 #include "llvm/ADT/None.h" 27 #include "llvm/ADT/Optional.h" 28 #include "llvm/ADT/SmallVector.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/TrailingObjects.h" 31 #include <cassert> 32 #include <cstddef> 33 #include <cstdint> 34 35 namespace llvm { 36 37 class FoldingSetNodeID; 38 39 } // namespace llvm 40 41 namespace clang { 42 43 class ASTContext; 44 class DiagnosticBuilder; 45 class Expr; 46 struct PrintingPolicy; 47 class TypeSourceInfo; 48 class ValueDecl; 49 50 /// Represents a template argument. 51 class TemplateArgument { 52 public: 53 /// The kind of template argument we're storing. 54 enum ArgKind { 55 /// Represents an empty template argument, e.g., one that has not 56 /// been deduced. 57 Null = 0, 58 59 /// The template argument is a type. 60 Type, 61 62 /// The template argument is a declaration that was provided for a pointer, 63 /// reference, or pointer to member non-type template parameter. 64 Declaration, 65 66 /// The template argument is a null pointer or null pointer to member that 67 /// was provided for a non-type template parameter. 68 NullPtr, 69 70 /// The template argument is an integral value stored in an llvm::APSInt 71 /// that was provided for an integral non-type template parameter. 72 Integral, 73 74 /// The template argument is a template name that was provided for a 75 /// template template parameter. 76 Template, 77 78 /// The template argument is a pack expansion of a template name that was 79 /// provided for a template template parameter. 80 TemplateExpansion, 81 82 /// The template argument is an expression, and we've not resolved it to one 83 /// of the other forms yet, either because it's dependent or because we're 84 /// representing a non-canonical template argument (for instance, in a 85 /// TemplateSpecializationType). 86 Expression, 87 88 /// The template argument is actually a parameter pack. Arguments are stored 89 /// in the Args struct. 90 Pack 91 }; 92 93 private: 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 139 public: 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 TemplateArgumentDependence getDependence() const; 240 241 /// Whether this template argument is dependent on a template 242 /// parameter such that its result can change from one instantiation to 243 /// another. 244 bool isDependent() const; 245 246 /// Whether this template argument is dependent on a template 247 /// parameter. 248 bool isInstantiationDependent() const; 249 250 /// Whether this template argument contains an unexpanded 251 /// parameter pack. 252 bool containsUnexpandedParameterPack() const; 253 254 /// Determine whether this template argument is a pack expansion. 255 bool isPackExpansion() const; 256 257 /// Retrieve the type for a type template argument. 258 QualType getAsType() const { 259 assert(getKind() == Type && "Unexpected kind"); 260 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); 261 } 262 263 /// Retrieve the declaration for a declaration non-type 264 /// template argument. 265 ValueDecl *getAsDecl() const { 266 assert(getKind() == Declaration && "Unexpected kind"); 267 return DeclArg.D; 268 } 269 270 QualType getParamTypeForDecl() const { 271 assert(getKind() == Declaration && "Unexpected kind"); 272 return QualType::getFromOpaquePtr(DeclArg.QT); 273 } 274 275 /// Retrieve the type for null non-type template argument. 276 QualType getNullPtrType() const { 277 assert(getKind() == NullPtr && "Unexpected kind"); 278 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); 279 } 280 281 /// Retrieve the template name for a template name argument. 282 TemplateName getAsTemplate() const { 283 assert(getKind() == Template && "Unexpected kind"); 284 return TemplateName::getFromVoidPointer(TemplateArg.Name); 285 } 286 287 /// Retrieve the template argument as a template name; if the argument 288 /// is a pack expansion, return the pattern as a template name. 289 TemplateName getAsTemplateOrTemplatePattern() const { 290 assert((getKind() == Template || getKind() == TemplateExpansion) && 291 "Unexpected kind"); 292 293 return TemplateName::getFromVoidPointer(TemplateArg.Name); 294 } 295 296 /// Retrieve the number of expansions that a template template argument 297 /// expansion will produce, if known. 298 Optional<unsigned> getNumTemplateExpansions() const; 299 300 /// Retrieve the template argument as an integral value. 301 // FIXME: Provide a way to read the integral data without copying the value. 302 llvm::APSInt getAsIntegral() const { 303 assert(getKind() == Integral && "Unexpected kind"); 304 305 using namespace llvm; 306 307 if (Integer.BitWidth <= 64) 308 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); 309 310 unsigned NumWords = APInt::getNumWords(Integer.BitWidth); 311 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), 312 Integer.IsUnsigned); 313 } 314 315 /// Retrieve the type of the integral value. 316 QualType getIntegralType() const { 317 assert(getKind() == Integral && "Unexpected kind"); 318 return QualType::getFromOpaquePtr(Integer.Type); 319 } 320 321 void setIntegralType(QualType T) { 322 assert(getKind() == Integral && "Unexpected kind"); 323 Integer.Type = T.getAsOpaquePtr(); 324 } 325 326 /// If this is a non-type template argument, get its type. Otherwise, 327 /// returns a null QualType. 328 QualType getNonTypeTemplateArgumentType() const; 329 330 /// Retrieve the template argument as an expression. 331 Expr *getAsExpr() const { 332 assert(getKind() == Expression && "Unexpected kind"); 333 return reinterpret_cast<Expr *>(TypeOrValue.V); 334 } 335 336 /// Iterator that traverses the elements of a template argument pack. 337 using pack_iterator = const TemplateArgument *; 338 339 /// Iterator referencing the first argument of a template argument 340 /// pack. 341 pack_iterator pack_begin() const { 342 assert(getKind() == Pack); 343 return Args.Args; 344 } 345 346 /// Iterator referencing one past the last argument of a template 347 /// argument pack. 348 pack_iterator pack_end() const { 349 assert(getKind() == Pack); 350 return Args.Args + Args.NumArgs; 351 } 352 353 /// Iterator range referencing all of the elements of a template 354 /// argument pack. 355 ArrayRef<TemplateArgument> pack_elements() const { 356 return llvm::makeArrayRef(pack_begin(), pack_end()); 357 } 358 359 /// The number of template arguments in the given template argument 360 /// pack. 361 unsigned pack_size() const { 362 assert(getKind() == Pack); 363 return Args.NumArgs; 364 } 365 366 /// Return the array of arguments in this template argument pack. 367 ArrayRef<TemplateArgument> getPackAsArray() const { 368 assert(getKind() == Pack); 369 return llvm::makeArrayRef(Args.Args, Args.NumArgs); 370 } 371 372 /// Determines whether two template arguments are superficially the 373 /// same. 374 bool structurallyEquals(const TemplateArgument &Other) const; 375 376 /// When the template argument is a pack expansion, returns 377 /// the pattern of the pack expansion. 378 TemplateArgument getPackExpansionPattern() const; 379 380 /// Print this template argument to the given output stream. 381 void print(const PrintingPolicy &Policy, raw_ostream &Out) const; 382 383 /// Debugging aid that dumps the template argument. 384 void dump(raw_ostream &Out) const; 385 386 /// Debugging aid that dumps the template argument to standard error. 387 void dump() const; 388 389 /// Used to insert TemplateArguments into FoldingSets. 390 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; 391 }; 392 393 /// Location information for a TemplateArgument. 394 struct TemplateArgumentLocInfo { 395 private: 396 struct T { 397 // FIXME: We'd like to just use the qualifier in the TemplateName, 398 // but template arguments get canonicalized too quickly. 399 NestedNameSpecifier *Qualifier; 400 void *QualifierLocData; 401 unsigned TemplateNameLoc; 402 unsigned EllipsisLoc; 403 }; 404 405 union { 406 struct T Template; 407 Expr *Expression; 408 TypeSourceInfo *Declarator; 409 }; 410 411 public: 412 constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {} 413 414 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} 415 416 TemplateArgumentLocInfo(Expr *E) : Expression(E) {} 417 418 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, 419 SourceLocation TemplateNameLoc, 420 SourceLocation EllipsisLoc) { 421 Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); 422 Template.QualifierLocData = QualifierLoc.getOpaqueData(); 423 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); 424 Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); 425 } 426 427 TypeSourceInfo *getAsTypeSourceInfo() const { 428 return Declarator; 429 } 430 431 Expr *getAsExpr() const { 432 return Expression; 433 } 434 435 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 436 return NestedNameSpecifierLoc(Template.Qualifier, 437 Template.QualifierLocData); 438 } 439 440 SourceLocation getTemplateNameLoc() const { 441 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); 442 } 443 444 SourceLocation getTemplateEllipsisLoc() const { 445 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); 446 } 447 }; 448 449 /// Location wrapper for a TemplateArgument. TemplateArgument is to 450 /// TemplateArgumentLoc as Type is to TypeLoc. 451 class TemplateArgumentLoc { 452 TemplateArgument Argument; 453 TemplateArgumentLocInfo LocInfo; 454 455 public: 456 constexpr TemplateArgumentLoc() {} 457 458 TemplateArgumentLoc(const TemplateArgument &Argument, 459 TemplateArgumentLocInfo Opaque) 460 : Argument(Argument), LocInfo(Opaque) {} 461 462 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) 463 : Argument(Argument), LocInfo(TInfo) { 464 assert(Argument.getKind() == TemplateArgument::Type); 465 } 466 467 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) 468 : Argument(Argument), LocInfo(E) { 469 470 // Permit any kind of template argument that can be represented with an 471 // expression. 472 assert(Argument.getKind() == TemplateArgument::NullPtr || 473 Argument.getKind() == TemplateArgument::Integral || 474 Argument.getKind() == TemplateArgument::Declaration || 475 Argument.getKind() == TemplateArgument::Expression); 476 } 477 478 TemplateArgumentLoc(const TemplateArgument &Argument, 479 NestedNameSpecifierLoc QualifierLoc, 480 SourceLocation TemplateNameLoc, 481 SourceLocation EllipsisLoc = SourceLocation()) 482 : Argument(Argument), 483 LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { 484 assert(Argument.getKind() == TemplateArgument::Template || 485 Argument.getKind() == TemplateArgument::TemplateExpansion); 486 } 487 488 /// - Fetches the primary location of the argument. 489 SourceLocation getLocation() const { 490 if (Argument.getKind() == TemplateArgument::Template || 491 Argument.getKind() == TemplateArgument::TemplateExpansion) 492 return getTemplateNameLoc(); 493 494 return getSourceRange().getBegin(); 495 } 496 497 /// - Fetches the full source range of the argument. 498 SourceRange getSourceRange() const LLVM_READONLY; 499 500 const TemplateArgument &getArgument() const { 501 return Argument; 502 } 503 504 TemplateArgumentLocInfo getLocInfo() const { 505 return LocInfo; 506 } 507 508 TypeSourceInfo *getTypeSourceInfo() const { 509 assert(Argument.getKind() == TemplateArgument::Type); 510 return LocInfo.getAsTypeSourceInfo(); 511 } 512 513 Expr *getSourceExpression() const { 514 assert(Argument.getKind() == TemplateArgument::Expression); 515 return LocInfo.getAsExpr(); 516 } 517 518 Expr *getSourceDeclExpression() const { 519 assert(Argument.getKind() == TemplateArgument::Declaration); 520 return LocInfo.getAsExpr(); 521 } 522 523 Expr *getSourceNullPtrExpression() const { 524 assert(Argument.getKind() == TemplateArgument::NullPtr); 525 return LocInfo.getAsExpr(); 526 } 527 528 Expr *getSourceIntegralExpression() const { 529 assert(Argument.getKind() == TemplateArgument::Integral); 530 return LocInfo.getAsExpr(); 531 } 532 533 NestedNameSpecifierLoc getTemplateQualifierLoc() const { 534 if (Argument.getKind() != TemplateArgument::Template && 535 Argument.getKind() != TemplateArgument::TemplateExpansion) 536 return NestedNameSpecifierLoc(); 537 return LocInfo.getTemplateQualifierLoc(); 538 } 539 540 SourceLocation getTemplateNameLoc() const { 541 if (Argument.getKind() != TemplateArgument::Template && 542 Argument.getKind() != TemplateArgument::TemplateExpansion) 543 return SourceLocation(); 544 return LocInfo.getTemplateNameLoc(); 545 } 546 547 SourceLocation getTemplateEllipsisLoc() const { 548 if (Argument.getKind() != TemplateArgument::TemplateExpansion) 549 return SourceLocation(); 550 return LocInfo.getTemplateEllipsisLoc(); 551 } 552 }; 553 554 /// A convenient class for passing around template argument 555 /// information. Designed to be passed by reference. 556 class TemplateArgumentListInfo { 557 SmallVector<TemplateArgumentLoc, 8> Arguments; 558 SourceLocation LAngleLoc; 559 SourceLocation RAngleLoc; 560 561 public: 562 TemplateArgumentListInfo() = default; 563 564 TemplateArgumentListInfo(SourceLocation LAngleLoc, 565 SourceLocation RAngleLoc) 566 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} 567 568 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo 569 // instead. 570 void *operator new(size_t bytes, ASTContext &C) = delete; 571 572 SourceLocation getLAngleLoc() const { return LAngleLoc; } 573 SourceLocation getRAngleLoc() const { return RAngleLoc; } 574 575 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } 576 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } 577 578 unsigned size() const { return Arguments.size(); } 579 580 const TemplateArgumentLoc *getArgumentArray() const { 581 return Arguments.data(); 582 } 583 584 llvm::ArrayRef<TemplateArgumentLoc> arguments() const { 585 return Arguments; 586 } 587 588 const TemplateArgumentLoc &operator[](unsigned I) const { 589 return Arguments[I]; 590 } 591 592 TemplateArgumentLoc &operator[](unsigned I) { 593 return Arguments[I]; 594 } 595 596 void addArgument(const TemplateArgumentLoc &Loc) { 597 Arguments.push_back(Loc); 598 } 599 }; 600 601 /// Represents an explicit template argument list in C++, e.g., 602 /// the "<int>" in "sort<int>". 603 /// This is safe to be used inside an AST node, in contrast with 604 /// TemplateArgumentListInfo. 605 struct ASTTemplateArgumentListInfo final 606 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, 607 TemplateArgumentLoc> { 608 private: 609 friend class ASTNodeImporter; 610 friend TrailingObjects; 611 612 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); 613 614 public: 615 /// The source location of the left angle bracket ('<'). 616 SourceLocation LAngleLoc; 617 618 /// The source location of the right angle bracket ('>'). 619 SourceLocation RAngleLoc; 620 621 /// The number of template arguments in TemplateArgs. 622 unsigned NumTemplateArgs; 623 624 SourceLocation getLAngleLoc() const { return LAngleLoc; } 625 SourceLocation getRAngleLoc() const { return RAngleLoc; } 626 627 /// Retrieve the template arguments 628 const TemplateArgumentLoc *getTemplateArgs() const { 629 return getTrailingObjects<TemplateArgumentLoc>(); 630 } 631 unsigned getNumTemplateArgs() const { return NumTemplateArgs; } 632 633 llvm::ArrayRef<TemplateArgumentLoc> arguments() const { 634 return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs()); 635 } 636 637 const TemplateArgumentLoc &operator[](unsigned I) const { 638 return getTemplateArgs()[I]; 639 } 640 641 static const ASTTemplateArgumentListInfo * 642 Create(const ASTContext &C, const TemplateArgumentListInfo &List); 643 }; 644 645 /// Represents an explicit template argument list in C++, e.g., 646 /// the "<int>" in "sort<int>". 647 /// 648 /// It is intended to be used as a trailing object on AST nodes, and 649 /// as such, doesn't contain the array of TemplateArgumentLoc itself, 650 /// but expects the containing object to also provide storage for 651 /// that. 652 struct alignas(void *) ASTTemplateKWAndArgsInfo { 653 /// The source location of the left angle bracket ('<'). 654 SourceLocation LAngleLoc; 655 656 /// The source location of the right angle bracket ('>'). 657 SourceLocation RAngleLoc; 658 659 /// The source location of the template keyword; this is used 660 /// as part of the representation of qualified identifiers, such as 661 /// S<T>::template apply<T>. Will be empty if this expression does 662 /// not have a template keyword. 663 SourceLocation TemplateKWLoc; 664 665 /// The number of template arguments in TemplateArgs. 666 unsigned NumTemplateArgs; 667 668 void initializeFrom(SourceLocation TemplateKWLoc, 669 const TemplateArgumentListInfo &List, 670 TemplateArgumentLoc *OutArgArray); 671 // FIXME: The parameter Deps is the result populated by this method, the 672 // caller doesn't need it since it is populated by computeDependence. remove 673 // it. 674 void initializeFrom(SourceLocation TemplateKWLoc, 675 const TemplateArgumentListInfo &List, 676 TemplateArgumentLoc *OutArgArray, 677 TemplateArgumentDependence &Deps); 678 void initializeFrom(SourceLocation TemplateKWLoc); 679 680 void copyInto(const TemplateArgumentLoc *ArgArray, 681 TemplateArgumentListInfo &List) const; 682 }; 683 684 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 685 const TemplateArgument &Arg); 686 687 inline TemplateSpecializationType::iterator 688 TemplateSpecializationType::end() const { 689 return getArgs() + getNumArgs(); 690 } 691 692 inline DependentTemplateSpecializationType::iterator 693 DependentTemplateSpecializationType::end() const { 694 return getArgs() + getNumArgs(); 695 } 696 697 inline const TemplateArgument & 698 TemplateSpecializationType::getArg(unsigned Idx) const { 699 assert(Idx < getNumArgs() && "Template argument out of range"); 700 return getArgs()[Idx]; 701 } 702 703 inline const TemplateArgument & 704 DependentTemplateSpecializationType::getArg(unsigned Idx) const { 705 assert(Idx < getNumArgs() && "Template argument out of range"); 706 return getArgs()[Idx]; 707 } 708 709 inline const TemplateArgument &AutoType::getArg(unsigned Idx) const { 710 assert(Idx < getNumArgs() && "Template argument out of range"); 711 return getArgs()[Idx]; 712 } 713 714 } // namespace clang 715 716 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H 717