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