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