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