[TrailingObjects] Convert ASTTemplateKWAndArgsInfo and ASTTemplateArgumentListInfo.
[lldb.git] / 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 Retrieve the template argument as an expression.
305   Expr *getAsExpr() const {
306     assert(getKind() == Expression && "Unexpected kind");
307     return reinterpret_cast<Expr *>(TypeOrValue.V);
308   }
309
310   /// \brief Iterator that traverses the elements of a template argument pack.
311   typedef const TemplateArgument * pack_iterator;
312
313   /// \brief Iterator referencing the first argument of a template argument
314   /// pack.
315   pack_iterator pack_begin() const {
316     assert(getKind() == Pack);
317     return Args.Args;
318   }
319
320   /// \brief Iterator referencing one past the last argument of a template
321   /// argument pack.
322   pack_iterator pack_end() const {
323     assert(getKind() == Pack);
324     return Args.Args + Args.NumArgs;
325   }
326
327   /// \brief Iterator range referencing all of the elements of a template
328   /// argument pack.
329   llvm::iterator_range<pack_iterator> pack_elements() const {
330     return llvm::make_range(pack_begin(), pack_end());
331   }
332
333   /// \brief The number of template arguments in the given template argument
334   /// pack.
335   unsigned pack_size() const {
336     assert(getKind() == Pack);
337     return Args.NumArgs;
338   }
339
340   /// \brief Return the array of arguments in this template argument pack.
341   ArrayRef<TemplateArgument> getPackAsArray() const {
342     assert(getKind() == Pack);
343     return llvm::makeArrayRef(Args.Args, Args.NumArgs);
344   }
345
346   /// \brief Determines whether two template arguments are superficially the
347   /// same.
348   bool structurallyEquals(const TemplateArgument &Other) const;
349
350   /// \brief When the template argument is a pack expansion, returns
351   /// the pattern of the pack expansion.
352   TemplateArgument getPackExpansionPattern() const;
353
354   /// \brief Print this template argument to the given output stream.
355   void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
356              
357   /// \brief Used to insert TemplateArguments into FoldingSets.
358   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
359 };
360
361 /// Location information for a TemplateArgument.
362 struct TemplateArgumentLocInfo {
363 private:
364
365   struct T {
366     // FIXME: We'd like to just use the qualifier in the TemplateName,
367     // but template arguments get canonicalized too quickly.
368     NestedNameSpecifier *Qualifier;
369     void *QualifierLocData;
370     unsigned TemplateNameLoc;
371     unsigned EllipsisLoc;
372   };
373
374   union {
375     struct T Template;
376     Expr *Expression;
377     TypeSourceInfo *Declarator;
378   };
379
380 public:
381   TemplateArgumentLocInfo();
382   
383   TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
384   
385   TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
386   
387   TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
388                           SourceLocation TemplateNameLoc,
389                           SourceLocation EllipsisLoc)
390   {
391     Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
392     Template.QualifierLocData = QualifierLoc.getOpaqueData();
393     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
394     Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
395   }
396
397   TypeSourceInfo *getAsTypeSourceInfo() const {
398     return Declarator;
399   }
400
401   Expr *getAsExpr() const {
402     return Expression;
403   }
404
405   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
406     return NestedNameSpecifierLoc(Template.Qualifier, 
407                                   Template.QualifierLocData);
408   }
409   
410   SourceLocation getTemplateNameLoc() const {
411     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
412   }
413   
414   SourceLocation getTemplateEllipsisLoc() const {
415     return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
416   }
417 };
418
419 /// Location wrapper for a TemplateArgument.  TemplateArgument is to
420 /// TemplateArgumentLoc as Type is to TypeLoc.
421 class TemplateArgumentLoc {
422   TemplateArgument Argument;
423   TemplateArgumentLocInfo LocInfo;
424
425 public:
426   TemplateArgumentLoc() {}
427
428   TemplateArgumentLoc(const TemplateArgument &Argument,
429                       TemplateArgumentLocInfo Opaque)
430     : Argument(Argument), LocInfo(Opaque) {
431   }
432
433   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
434     : Argument(Argument), LocInfo(TInfo) {
435     assert(Argument.getKind() == TemplateArgument::Type);
436   }
437
438   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
439     : Argument(Argument), LocInfo(E) {
440     assert(Argument.getKind() == TemplateArgument::Expression);
441   }
442
443   TemplateArgumentLoc(const TemplateArgument &Argument, 
444                       NestedNameSpecifierLoc QualifierLoc,
445                       SourceLocation TemplateNameLoc,
446                       SourceLocation EllipsisLoc = SourceLocation())
447     : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
448     assert(Argument.getKind() == TemplateArgument::Template ||
449            Argument.getKind() == TemplateArgument::TemplateExpansion);
450   }
451   
452   /// \brief - Fetches the primary location of the argument.
453   SourceLocation getLocation() const {
454     if (Argument.getKind() == TemplateArgument::Template ||
455         Argument.getKind() == TemplateArgument::TemplateExpansion)
456       return getTemplateNameLoc();
457     
458     return getSourceRange().getBegin();
459   }
460
461   /// \brief - Fetches the full source range of the argument.
462   SourceRange getSourceRange() const LLVM_READONLY;
463
464   const TemplateArgument &getArgument() const {
465     return Argument;
466   }
467
468   TemplateArgumentLocInfo getLocInfo() const {
469     return LocInfo;
470   }
471
472   TypeSourceInfo *getTypeSourceInfo() const {
473     assert(Argument.getKind() == TemplateArgument::Type);
474     return LocInfo.getAsTypeSourceInfo();
475   }
476
477   Expr *getSourceExpression() const {
478     assert(Argument.getKind() == TemplateArgument::Expression);
479     return LocInfo.getAsExpr();
480   }
481
482   Expr *getSourceDeclExpression() const {
483     assert(Argument.getKind() == TemplateArgument::Declaration);
484     return LocInfo.getAsExpr();
485   }
486
487   Expr *getSourceNullPtrExpression() const {
488     assert(Argument.getKind() == TemplateArgument::NullPtr);
489     return LocInfo.getAsExpr();
490   }
491
492   Expr *getSourceIntegralExpression() const {
493     assert(Argument.getKind() == TemplateArgument::Integral);
494     return LocInfo.getAsExpr();
495   }
496
497   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
498     assert(Argument.getKind() == TemplateArgument::Template ||
499            Argument.getKind() == TemplateArgument::TemplateExpansion);
500     return LocInfo.getTemplateQualifierLoc();
501   }
502   
503   SourceLocation getTemplateNameLoc() const {
504     assert(Argument.getKind() == TemplateArgument::Template ||
505            Argument.getKind() == TemplateArgument::TemplateExpansion);
506     return LocInfo.getTemplateNameLoc();
507   }  
508   
509   SourceLocation getTemplateEllipsisLoc() const {
510     assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
511     return LocInfo.getTemplateEllipsisLoc();
512   }
513 };
514
515 /// A convenient class for passing around template argument
516 /// information.  Designed to be passed by reference.
517 class TemplateArgumentListInfo {
518   SmallVector<TemplateArgumentLoc, 8> Arguments;
519   SourceLocation LAngleLoc;
520   SourceLocation RAngleLoc;
521
522   // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
523   // instead.
524   void *operator new(size_t bytes, ASTContext &C) = delete;
525
526 public:
527   TemplateArgumentListInfo() {}
528
529   TemplateArgumentListInfo(SourceLocation LAngleLoc,
530                            SourceLocation RAngleLoc)
531     : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
532
533   SourceLocation getLAngleLoc() const { return LAngleLoc; }
534   SourceLocation getRAngleLoc() const { return RAngleLoc; }
535
536   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
537   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
538
539   unsigned size() const { return Arguments.size(); }
540
541   const TemplateArgumentLoc *getArgumentArray() const {
542     return Arguments.data();
543   }
544
545   llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
546     return Arguments;
547   }
548
549   const TemplateArgumentLoc &operator[](unsigned I) const {
550     return Arguments[I];
551   }
552
553   TemplateArgumentLoc &operator[](unsigned I) {
554     return Arguments[I];
555   }
556
557   void addArgument(const TemplateArgumentLoc &Loc) {
558     Arguments.push_back(Loc);
559   }
560 };
561
562 /// \brief Represents an explicit template argument list in C++, e.g.,
563 /// the "<int>" in "sort<int>".
564 /// This is safe to be used inside an AST node, in contrast with
565 /// TemplateArgumentListInfo.
566 struct ASTTemplateArgumentListInfo final
567     : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
568                                     TemplateArgumentLoc> {
569 private:
570   friend TrailingObjects;
571
572   ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
573
574 public:
575   /// \brief The source location of the left angle bracket ('<').
576   SourceLocation LAngleLoc;
577
578   /// \brief The source location of the right angle bracket ('>').
579   SourceLocation RAngleLoc;
580
581   /// \brief The number of template arguments in TemplateArgs.
582   unsigned NumTemplateArgs;
583
584   /// \brief Retrieve the template arguments
585   const TemplateArgumentLoc *getTemplateArgs() const {
586     return getTrailingObjects<TemplateArgumentLoc>();
587   }
588
589   const TemplateArgumentLoc &operator[](unsigned I) const {
590     return getTemplateArgs()[I];
591   }
592
593   static const ASTTemplateArgumentListInfo *
594   Create(ASTContext &C, const TemplateArgumentListInfo &List);
595 };
596
597 /// \brief Represents an explicit template argument list in C++, e.g.,
598 /// the "<int>" in "sort<int>".  This is safe to be used inside an AST
599 /// node, in contrast with TemplateArgumentListInfo.
600 ///
601 /// This is currently very similar to ASTTemplateArgumentListInfo
602 /// class, but a) has a extra member, TemplateKWLoc, and b) is
603 /// intended to be tacked on the end of some of the Expr classes, not
604 /// as a public interface.
605 struct ASTTemplateKWAndArgsInfo final
606     : private llvm::TrailingObjects<ASTTemplateKWAndArgsInfo,
607                                     TemplateArgumentLoc> {
608   friend TrailingObjects;
609
610   /// \brief The source location of the left angle bracket ('<').
611   SourceLocation LAngleLoc;
612
613   /// \brief The source location of the right angle bracket ('>').
614   SourceLocation RAngleLoc;
615
616   /// \brief The source location of the template keyword; this is used
617   /// as part of the representation of qualified identifiers, such as
618   /// S<T>::template apply<T>.  Will be empty if this expression does
619   /// not have a template keyword.
620   SourceLocation TemplateKWLoc;
621
622   /// \brief The number of template arguments in TemplateArgs.
623   unsigned NumTemplateArgs;
624
625   /// \brief Retrieve the template arguments
626   TemplateArgumentLoc *getTemplateArgs() {
627     return getTrailingObjects<TemplateArgumentLoc>();
628   }
629
630   /// \brief Retrieve the template arguments
631   const TemplateArgumentLoc *getTemplateArgs() const {
632     return getTrailingObjects<TemplateArgumentLoc>();
633   }
634
635   const TemplateArgumentLoc &operator[](unsigned I) const {
636     return getTemplateArgs()[I];
637   }
638
639   void initializeFrom(SourceLocation TemplateKWLoc,
640                       const TemplateArgumentListInfo &List);
641   void initializeFrom(SourceLocation TemplateKWLoc,
642                       const TemplateArgumentListInfo &List,
643                       bool &Dependent, bool &InstantiationDependent,
644                       bool &ContainsUnexpandedParameterPack);
645   void initializeFrom(SourceLocation TemplateKWLoc);
646
647   void copyInto(TemplateArgumentListInfo &List) const;
648   static std::size_t sizeFor(unsigned NumTemplateArgs);
649 };
650
651 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
652                                     const TemplateArgument &Arg);
653
654 inline TemplateSpecializationType::iterator
655     TemplateSpecializationType::end() const {
656   return getArgs() + getNumArgs();
657 }
658
659 inline DependentTemplateSpecializationType::iterator
660     DependentTemplateSpecializationType::end() const {
661   return getArgs() + getNumArgs();
662 }
663
664 inline const TemplateArgument &
665     TemplateSpecializationType::getArg(unsigned Idx) const {
666   assert(Idx < getNumArgs() && "Template argument out of range");
667   return getArgs()[Idx];
668 }
669
670 inline const TemplateArgument &
671     DependentTemplateSpecializationType::getArg(unsigned Idx) const {
672   assert(Idx < getNumArgs() && "Template argument out of range");
673   return getArgs()[Idx];
674 }
675   
676 } // end namespace clang
677
678 #endif