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