]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
Merge clang trunk r321017 to contrib/llvm/tools/clang.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / 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 /// \brief Represents a template argument.
51 class TemplateArgument {
52 public:
53   /// \brief The kind of template argument we're storing.
54   enum ArgKind {
55     /// \brief 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   /// \brief 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   /// \brief Construct an empty, invalid template argument.
142   constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
143
144   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief Return the kind of stored template argument.
235   ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
236
237   /// \brief Determine whether this template argument has no value.
238   bool isNull() const { return getKind() == Null; }
239
240   /// \brief 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   /// \brief Whether this template argument is dependent on a template
246   /// parameter.
247   bool isInstantiationDependent() const;
248
249   /// \brief Whether this template argument contains an unexpanded
250   /// parameter pack.
251   bool containsUnexpandedParameterPack() const;
252
253   /// \brief Determine whether this template argument is a pack expansion.
254   bool isPackExpansion() const;
255   
256   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief Retrieve the number of expansions that a template template argument
296   /// expansion will produce, if known.
297   Optional<unsigned> getNumTemplateExpansions() const;
298   
299   /// \brief 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   /// \brief 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   /// \brief If this is a non-type template argument, get its type. Otherwise,
326   /// returns a null QualType.
327   QualType getNonTypeTemplateArgumentType() const;
328
329   /// \brief 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   /// \brief Iterator that traverses the elements of a template argument pack.
336   using pack_iterator = const TemplateArgument *;
337
338   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief 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   /// \brief Determines whether two template arguments are superficially the
372   /// same.
373   bool structurallyEquals(const TemplateArgument &Other) const;
374
375   /// \brief When the template argument is a pack expansion, returns
376   /// the pattern of the pack expansion.
377   TemplateArgument getPackExpansionPattern() const;
378
379   /// \brief Print this template argument to the given output stream.
380   void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
381              
382   /// \brief Debugging aid that dumps the template argument.
383   void dump(raw_ostream &Out) const;
384
385   /// \brief Debugging aid that dumps the template argument to standard error.
386   void dump() const;
387              
388   /// \brief 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     assert(Argument.getKind() == TemplateArgument::Expression);
469   }
470
471   TemplateArgumentLoc(const TemplateArgument &Argument, 
472                       NestedNameSpecifierLoc QualifierLoc,
473                       SourceLocation TemplateNameLoc,
474                       SourceLocation EllipsisLoc = SourceLocation())
475       : Argument(Argument),
476         LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
477     assert(Argument.getKind() == TemplateArgument::Template ||
478            Argument.getKind() == TemplateArgument::TemplateExpansion);
479   }
480   
481   /// \brief - Fetches the primary location of the argument.
482   SourceLocation getLocation() const {
483     if (Argument.getKind() == TemplateArgument::Template ||
484         Argument.getKind() == TemplateArgument::TemplateExpansion)
485       return getTemplateNameLoc();
486     
487     return getSourceRange().getBegin();
488   }
489
490   /// \brief - Fetches the full source range of the argument.
491   SourceRange getSourceRange() const LLVM_READONLY;
492
493   const TemplateArgument &getArgument() const {
494     return Argument;
495   }
496
497   TemplateArgumentLocInfo getLocInfo() const {
498     return LocInfo;
499   }
500
501   TypeSourceInfo *getTypeSourceInfo() const {
502     assert(Argument.getKind() == TemplateArgument::Type);
503     return LocInfo.getAsTypeSourceInfo();
504   }
505
506   Expr *getSourceExpression() const {
507     assert(Argument.getKind() == TemplateArgument::Expression);
508     return LocInfo.getAsExpr();
509   }
510
511   Expr *getSourceDeclExpression() const {
512     assert(Argument.getKind() == TemplateArgument::Declaration);
513     return LocInfo.getAsExpr();
514   }
515
516   Expr *getSourceNullPtrExpression() const {
517     assert(Argument.getKind() == TemplateArgument::NullPtr);
518     return LocInfo.getAsExpr();
519   }
520
521   Expr *getSourceIntegralExpression() const {
522     assert(Argument.getKind() == TemplateArgument::Integral);
523     return LocInfo.getAsExpr();
524   }
525
526   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
527     assert(Argument.getKind() == TemplateArgument::Template ||
528            Argument.getKind() == TemplateArgument::TemplateExpansion);
529     return LocInfo.getTemplateQualifierLoc();
530   }
531   
532   SourceLocation getTemplateNameLoc() const {
533     assert(Argument.getKind() == TemplateArgument::Template ||
534            Argument.getKind() == TemplateArgument::TemplateExpansion);
535     return LocInfo.getTemplateNameLoc();
536   }  
537   
538   SourceLocation getTemplateEllipsisLoc() const {
539     assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
540     return LocInfo.getTemplateEllipsisLoc();
541   }
542 };
543
544 /// A convenient class for passing around template argument
545 /// information.  Designed to be passed by reference.
546 class TemplateArgumentListInfo {
547   SmallVector<TemplateArgumentLoc, 8> Arguments;
548   SourceLocation LAngleLoc;
549   SourceLocation RAngleLoc;
550
551 public:
552   TemplateArgumentListInfo() = default;
553
554   TemplateArgumentListInfo(SourceLocation LAngleLoc,
555                            SourceLocation RAngleLoc)
556       : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
557
558   // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
559   // instead.
560   void *operator new(size_t bytes, ASTContext &C) = delete;
561
562   SourceLocation getLAngleLoc() const { return LAngleLoc; }
563   SourceLocation getRAngleLoc() const { return RAngleLoc; }
564
565   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
566   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
567
568   unsigned size() const { return Arguments.size(); }
569
570   const TemplateArgumentLoc *getArgumentArray() const {
571     return Arguments.data();
572   }
573
574   llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
575     return Arguments;
576   }
577
578   const TemplateArgumentLoc &operator[](unsigned I) const {
579     return Arguments[I];
580   }
581
582   TemplateArgumentLoc &operator[](unsigned I) {
583     return Arguments[I];
584   }
585
586   void addArgument(const TemplateArgumentLoc &Loc) {
587     Arguments.push_back(Loc);
588   }
589 };
590
591 /// \brief Represents an explicit template argument list in C++, e.g.,
592 /// the "<int>" in "sort<int>".
593 /// This is safe to be used inside an AST node, in contrast with
594 /// TemplateArgumentListInfo.
595 struct ASTTemplateArgumentListInfo final
596     : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
597                                     TemplateArgumentLoc> {
598 private:
599   friend class ASTNodeImporter;
600   friend TrailingObjects;
601
602   ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
603
604 public:
605   /// \brief The source location of the left angle bracket ('<').
606   SourceLocation LAngleLoc;
607
608   /// \brief The source location of the right angle bracket ('>').
609   SourceLocation RAngleLoc;
610
611   /// \brief The number of template arguments in TemplateArgs.
612   unsigned NumTemplateArgs;
613
614   /// \brief Retrieve the template arguments
615   const TemplateArgumentLoc *getTemplateArgs() const {
616     return getTrailingObjects<TemplateArgumentLoc>();
617   }
618
619   llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
620     return llvm::makeArrayRef(getTemplateArgs(), NumTemplateArgs);
621   }
622
623   const TemplateArgumentLoc &operator[](unsigned I) const {
624     return getTemplateArgs()[I];
625   }
626
627   static const ASTTemplateArgumentListInfo *
628   Create(ASTContext &C, const TemplateArgumentListInfo &List);
629 };
630
631 /// \brief Represents an explicit template argument list in C++, e.g.,
632 /// the "<int>" in "sort<int>".
633 ///
634 /// It is intended to be used as a trailing object on AST nodes, and
635 /// as such, doesn't contain the array of TemplateArgumentLoc itself,
636 /// but expects the containing object to also provide storage for
637 /// that.
638 struct alignas(void *) ASTTemplateKWAndArgsInfo {
639   /// \brief The source location of the left angle bracket ('<').
640   SourceLocation LAngleLoc;
641
642   /// \brief The source location of the right angle bracket ('>').
643   SourceLocation RAngleLoc;
644
645   /// \brief The source location of the template keyword; this is used
646   /// as part of the representation of qualified identifiers, such as
647   /// S<T>::template apply<T>.  Will be empty if this expression does
648   /// not have a template keyword.
649   SourceLocation TemplateKWLoc;
650
651   /// \brief The number of template arguments in TemplateArgs.
652   unsigned NumTemplateArgs;
653
654   void initializeFrom(SourceLocation TemplateKWLoc,
655                       const TemplateArgumentListInfo &List,
656                       TemplateArgumentLoc *OutArgArray);
657   void initializeFrom(SourceLocation TemplateKWLoc,
658                       const TemplateArgumentListInfo &List,
659                       TemplateArgumentLoc *OutArgArray, bool &Dependent,
660                       bool &InstantiationDependent,
661                       bool &ContainsUnexpandedParameterPack);
662   void initializeFrom(SourceLocation TemplateKWLoc);
663
664   void copyInto(const TemplateArgumentLoc *ArgArray,
665                 TemplateArgumentListInfo &List) const;
666 };
667
668 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
669                                     const TemplateArgument &Arg);
670
671 inline TemplateSpecializationType::iterator
672     TemplateSpecializationType::end() const {
673   return getArgs() + getNumArgs();
674 }
675
676 inline DependentTemplateSpecializationType::iterator
677     DependentTemplateSpecializationType::end() const {
678   return getArgs() + getNumArgs();
679 }
680
681 inline const TemplateArgument &
682     TemplateSpecializationType::getArg(unsigned Idx) const {
683   assert(Idx < getNumArgs() && "Template argument out of range");
684   return getArgs()[Idx];
685 }
686
687 inline const TemplateArgument &
688     DependentTemplateSpecializationType::getArg(unsigned Idx) const {
689   assert(Idx < getNumArgs() && "Template argument out of range");
690   return getArgs()[Idx];
691 }
692   
693 } // namespace clang
694
695 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H