]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / AST / TemplateBase.h
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/NestedNameSpecifier.h"
18 #include "clang/AST/TemplateName.h"
19 #include "clang/AST/Type.h"
20 #include "clang/Basic/LLVM.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "llvm/ADT/APInt.h"
23 #include "llvm/ADT/APSInt.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/None.h"
26 #include "llvm/ADT/Optional.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/TrailingObjects.h"
30 #include <cassert>
31 #include <cstddef>
32 #include <cstdint>
33
34 namespace llvm {
35
36 class FoldingSetNodeID;
37
38 } // namespace llvm
39
40 namespace clang {
41
42 class ASTContext;
43 class DiagnosticBuilder;
44 class Expr;
45 struct PrintingPolicy;
46 class TypeSourceInfo;
47 class ValueDecl;
48
49 /// Represents a template argument.
50 class TemplateArgument {
51 public:
52   /// The kind of template argument we're storing.
53   enum ArgKind {
54     /// Represents an empty template argument, e.g., one that has not
55     /// been deduced.
56     Null = 0,
57
58     /// The template argument is a type.
59     Type,
60
61     /// The template argument is a declaration that was provided for a pointer,
62     /// reference, or pointer to member non-type template parameter.
63     Declaration,
64
65     /// The template argument is a null pointer or null pointer to member that
66     /// was provided for a non-type template parameter.
67     NullPtr,
68
69     /// The template argument is an integral value stored in an llvm::APSInt
70     /// that was provided for an integral non-type template parameter.
71     Integral,
72
73     /// The template argument is a template name that was provided for a
74     /// template template parameter.
75     Template,
76
77     /// The template argument is a pack expansion of a template name that was
78     /// provided for a template template parameter.
79     TemplateExpansion,
80
81     /// The template argument is an expression, and we've not resolved it to one
82     /// of the other forms yet, either because it's dependent or because we're
83     /// representing a non-canonical template argument (for instance, in a
84     /// TemplateSpecializationType). Also used to represent a non-dependent
85     /// __uuidof expression (a Microsoft extension).
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   /// Whether this template argument is dependent on a template
240   /// parameter such that its result can change from one instantiation to
241   /// another.
242   bool isDependent() const;
243
244   /// Whether this template argument is dependent on a template
245   /// parameter.
246   bool isInstantiationDependent() const;
247
248   /// Whether this template argument contains an unexpanded
249   /// parameter pack.
250   bool containsUnexpandedParameterPack() const;
251
252   /// Determine whether this template argument is a pack expansion.
253   bool isPackExpansion() const;
254
255   /// Retrieve the type for a type template argument.
256   QualType getAsType() const {
257     assert(getKind() == Type && "Unexpected kind");
258     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
259   }
260
261   /// Retrieve the declaration for a declaration non-type
262   /// template argument.
263   ValueDecl *getAsDecl() const {
264     assert(getKind() == Declaration && "Unexpected kind");
265     return DeclArg.D;
266   }
267
268   QualType getParamTypeForDecl() const {
269     assert(getKind() == Declaration && "Unexpected kind");
270     return QualType::getFromOpaquePtr(DeclArg.QT);
271   }
272
273   /// Retrieve the type for null non-type template argument.
274   QualType getNullPtrType() const {
275     assert(getKind() == NullPtr && "Unexpected kind");
276     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
277   }
278
279   /// Retrieve the template name for a template name argument.
280   TemplateName getAsTemplate() const {
281     assert(getKind() == Template && "Unexpected kind");
282     return TemplateName::getFromVoidPointer(TemplateArg.Name);
283   }
284
285   /// Retrieve the template argument as a template name; if the argument
286   /// is a pack expansion, return the pattern as a template name.
287   TemplateName getAsTemplateOrTemplatePattern() const {
288     assert((getKind() == Template || getKind() == TemplateExpansion) &&
289            "Unexpected kind");
290
291     return TemplateName::getFromVoidPointer(TemplateArg.Name);
292   }
293
294   /// Retrieve the number of expansions that a template template argument
295   /// expansion will produce, if known.
296   Optional<unsigned> getNumTemplateExpansions() const;
297
298   /// Retrieve the template argument as an integral value.
299   // FIXME: Provide a way to read the integral data without copying the value.
300   llvm::APSInt getAsIntegral() const {
301     assert(getKind() == Integral && "Unexpected kind");
302
303     using namespace llvm;
304
305     if (Integer.BitWidth <= 64)
306       return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
307
308     unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
309     return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
310                   Integer.IsUnsigned);
311   }
312
313   /// Retrieve the type of the integral value.
314   QualType getIntegralType() const {
315     assert(getKind() == Integral && "Unexpected kind");
316     return QualType::getFromOpaquePtr(Integer.Type);
317   }
318
319   void setIntegralType(QualType T) {
320     assert(getKind() == Integral && "Unexpected kind");
321     Integer.Type = T.getAsOpaquePtr();
322   }
323
324   /// If this is a non-type template argument, get its type. Otherwise,
325   /// returns a null QualType.
326   QualType getNonTypeTemplateArgumentType() const;
327
328   /// Retrieve the template argument as an expression.
329   Expr *getAsExpr() const {
330     assert(getKind() == Expression && "Unexpected kind");
331     return reinterpret_cast<Expr *>(TypeOrValue.V);
332   }
333
334   /// Iterator that traverses the elements of a template argument pack.
335   using pack_iterator = const TemplateArgument *;
336
337   /// Iterator referencing the first argument of a template argument
338   /// pack.
339   pack_iterator pack_begin() const {
340     assert(getKind() == Pack);
341     return Args.Args;
342   }
343
344   /// Iterator referencing one past the last argument of a template
345   /// argument pack.
346   pack_iterator pack_end() const {
347     assert(getKind() == Pack);
348     return Args.Args + Args.NumArgs;
349   }
350
351   /// Iterator range referencing all of the elements of a template
352   /// argument pack.
353   ArrayRef<TemplateArgument> pack_elements() const {
354     return llvm::makeArrayRef(pack_begin(), pack_end());
355   }
356
357   /// The number of template arguments in the given template argument
358   /// pack.
359   unsigned pack_size() const {
360     assert(getKind() == Pack);
361     return Args.NumArgs;
362   }
363
364   /// Return the array of arguments in this template argument pack.
365   ArrayRef<TemplateArgument> getPackAsArray() const {
366     assert(getKind() == Pack);
367     return llvm::makeArrayRef(Args.Args, Args.NumArgs);
368   }
369
370   /// Determines whether two template arguments are superficially the
371   /// same.
372   bool structurallyEquals(const TemplateArgument &Other) const;
373
374   /// When the template argument is a pack expansion, returns
375   /// the pattern of the pack expansion.
376   TemplateArgument getPackExpansionPattern() const;
377
378   /// Print this template argument to the given output stream.
379   void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
380
381   /// Debugging aid that dumps the template argument.
382   void dump(raw_ostream &Out) const;
383
384   /// Debugging aid that dumps the template argument to standard error.
385   void dump() const;
386
387   /// Used to insert TemplateArguments into FoldingSets.
388   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
389 };
390
391 /// Location information for a TemplateArgument.
392 struct TemplateArgumentLocInfo {
393 private:
394   struct T {
395     // FIXME: We'd like to just use the qualifier in the TemplateName,
396     // but template arguments get canonicalized too quickly.
397     NestedNameSpecifier *Qualifier;
398     void *QualifierLocData;
399     unsigned TemplateNameLoc;
400     unsigned EllipsisLoc;
401   };
402
403   union {
404     struct T Template;
405     Expr *Expression;
406     TypeSourceInfo *Declarator;
407   };
408
409 public:
410   constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
411
412   TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
413
414   TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
415
416   TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
417                           SourceLocation TemplateNameLoc,
418                           SourceLocation EllipsisLoc) {
419     Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
420     Template.QualifierLocData = QualifierLoc.getOpaqueData();
421     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
422     Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
423   }
424
425   TypeSourceInfo *getAsTypeSourceInfo() const {
426     return Declarator;
427   }
428
429   Expr *getAsExpr() const {
430     return Expression;
431   }
432
433   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
434     return NestedNameSpecifierLoc(Template.Qualifier,
435                                   Template.QualifierLocData);
436   }
437
438   SourceLocation getTemplateNameLoc() const {
439     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
440   }
441
442   SourceLocation getTemplateEllipsisLoc() const {
443     return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
444   }
445 };
446
447 /// Location wrapper for a TemplateArgument.  TemplateArgument is to
448 /// TemplateArgumentLoc as Type is to TypeLoc.
449 class TemplateArgumentLoc {
450   TemplateArgument Argument;
451   TemplateArgumentLocInfo LocInfo;
452
453 public:
454   constexpr TemplateArgumentLoc() {}
455
456   TemplateArgumentLoc(const TemplateArgument &Argument,
457                       TemplateArgumentLocInfo Opaque)
458       : Argument(Argument), LocInfo(Opaque) {}
459
460   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
461       : Argument(Argument), LocInfo(TInfo) {
462     assert(Argument.getKind() == TemplateArgument::Type);
463   }
464
465   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
466       : Argument(Argument), LocInfo(E) {
467
468     // Permit any kind of template argument that can be represented with an
469     // expression.
470     assert(Argument.getKind() == TemplateArgument::NullPtr ||
471            Argument.getKind() == TemplateArgument::Integral ||
472            Argument.getKind() == TemplateArgument::Declaration ||
473            Argument.getKind() == TemplateArgument::Expression);
474   }
475
476   TemplateArgumentLoc(const TemplateArgument &Argument,
477                       NestedNameSpecifierLoc QualifierLoc,
478                       SourceLocation TemplateNameLoc,
479                       SourceLocation EllipsisLoc = SourceLocation())
480       : Argument(Argument),
481         LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
482     assert(Argument.getKind() == TemplateArgument::Template ||
483            Argument.getKind() == TemplateArgument::TemplateExpansion);
484   }
485
486   /// - Fetches the primary location of the argument.
487   SourceLocation getLocation() const {
488     if (Argument.getKind() == TemplateArgument::Template ||
489         Argument.getKind() == TemplateArgument::TemplateExpansion)
490       return getTemplateNameLoc();
491
492     return getSourceRange().getBegin();
493   }
494
495   /// - Fetches the full source range of the argument.
496   SourceRange getSourceRange() const LLVM_READONLY;
497
498   const TemplateArgument &getArgument() const {
499     return Argument;
500   }
501
502   TemplateArgumentLocInfo getLocInfo() const {
503     return LocInfo;
504   }
505
506   TypeSourceInfo *getTypeSourceInfo() const {
507     assert(Argument.getKind() == TemplateArgument::Type);
508     return LocInfo.getAsTypeSourceInfo();
509   }
510
511   Expr *getSourceExpression() const {
512     assert(Argument.getKind() == TemplateArgument::Expression);
513     return LocInfo.getAsExpr();
514   }
515
516   Expr *getSourceDeclExpression() const {
517     assert(Argument.getKind() == TemplateArgument::Declaration);
518     return LocInfo.getAsExpr();
519   }
520
521   Expr *getSourceNullPtrExpression() const {
522     assert(Argument.getKind() == TemplateArgument::NullPtr);
523     return LocInfo.getAsExpr();
524   }
525
526   Expr *getSourceIntegralExpression() const {
527     assert(Argument.getKind() == TemplateArgument::Integral);
528     return LocInfo.getAsExpr();
529   }
530
531   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
532     if (Argument.getKind() != TemplateArgument::Template &&
533         Argument.getKind() != TemplateArgument::TemplateExpansion)
534       return NestedNameSpecifierLoc();
535     return LocInfo.getTemplateQualifierLoc();
536   }
537
538   SourceLocation getTemplateNameLoc() const {
539     if (Argument.getKind() != TemplateArgument::Template &&
540         Argument.getKind() != TemplateArgument::TemplateExpansion)
541       return SourceLocation();
542     return LocInfo.getTemplateNameLoc();
543   }
544
545   SourceLocation getTemplateEllipsisLoc() const {
546     if (Argument.getKind() != TemplateArgument::TemplateExpansion)
547       return SourceLocation();
548     return LocInfo.getTemplateEllipsisLoc();
549   }
550 };
551
552 /// A convenient class for passing around template argument
553 /// information.  Designed to be passed by reference.
554 class TemplateArgumentListInfo {
555   SmallVector<TemplateArgumentLoc, 8> Arguments;
556   SourceLocation LAngleLoc;
557   SourceLocation RAngleLoc;
558
559 public:
560   TemplateArgumentListInfo() = default;
561
562   TemplateArgumentListInfo(SourceLocation LAngleLoc,
563                            SourceLocation RAngleLoc)
564       : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
565
566   // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
567   // instead.
568   void *operator new(size_t bytes, ASTContext &C) = delete;
569
570   SourceLocation getLAngleLoc() const { return LAngleLoc; }
571   SourceLocation getRAngleLoc() const { return RAngleLoc; }
572
573   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
574   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
575
576   unsigned size() const { return Arguments.size(); }
577
578   const TemplateArgumentLoc *getArgumentArray() const {
579     return Arguments.data();
580   }
581
582   llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
583     return Arguments;
584   }
585
586   const TemplateArgumentLoc &operator[](unsigned I) const {
587     return Arguments[I];
588   }
589
590   TemplateArgumentLoc &operator[](unsigned I) {
591     return Arguments[I];
592   }
593
594   void addArgument(const TemplateArgumentLoc &Loc) {
595     Arguments.push_back(Loc);
596   }
597 };
598
599 /// Represents an explicit template argument list in C++, e.g.,
600 /// the "<int>" in "sort<int>".
601 /// This is safe to be used inside an AST node, in contrast with
602 /// TemplateArgumentListInfo.
603 struct ASTTemplateArgumentListInfo final
604     : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
605                                     TemplateArgumentLoc> {
606 private:
607   friend class ASTNodeImporter;
608   friend TrailingObjects;
609
610   ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
611
612 public:
613   /// The source location of the left angle bracket ('<').
614   SourceLocation LAngleLoc;
615
616   /// The source location of the right angle bracket ('>').
617   SourceLocation RAngleLoc;
618
619   /// The number of template arguments in TemplateArgs.
620   unsigned NumTemplateArgs;
621
622   SourceLocation getLAngleLoc() const { return LAngleLoc; }
623   SourceLocation getRAngleLoc() const { return RAngleLoc; }
624
625   /// Retrieve the template arguments
626   const TemplateArgumentLoc *getTemplateArgs() const {
627     return getTrailingObjects<TemplateArgumentLoc>();
628   }
629   unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
630
631   llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
632     return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
633   }
634
635   const TemplateArgumentLoc &operator[](unsigned I) const {
636     return getTemplateArgs()[I];
637   }
638
639   static const ASTTemplateArgumentListInfo *
640   Create(ASTContext &C, const TemplateArgumentListInfo &List);
641 };
642
643 /// Represents an explicit template argument list in C++, e.g.,
644 /// the "<int>" in "sort<int>".
645 ///
646 /// It is intended to be used as a trailing object on AST nodes, and
647 /// as such, doesn't contain the array of TemplateArgumentLoc itself,
648 /// but expects the containing object to also provide storage for
649 /// that.
650 struct alignas(void *) ASTTemplateKWAndArgsInfo {
651   /// The source location of the left angle bracket ('<').
652   SourceLocation LAngleLoc;
653
654   /// The source location of the right angle bracket ('>').
655   SourceLocation RAngleLoc;
656
657   /// The source location of the template keyword; this is used
658   /// as part of the representation of qualified identifiers, such as
659   /// S<T>::template apply<T>.  Will be empty if this expression does
660   /// not have a template keyword.
661   SourceLocation TemplateKWLoc;
662
663   /// The number of template arguments in TemplateArgs.
664   unsigned NumTemplateArgs;
665
666   void initializeFrom(SourceLocation TemplateKWLoc,
667                       const TemplateArgumentListInfo &List,
668                       TemplateArgumentLoc *OutArgArray);
669   void initializeFrom(SourceLocation TemplateKWLoc,
670                       const TemplateArgumentListInfo &List,
671                       TemplateArgumentLoc *OutArgArray, bool &Dependent,
672                       bool &InstantiationDependent,
673                       bool &ContainsUnexpandedParameterPack);
674   void initializeFrom(SourceLocation TemplateKWLoc);
675
676   void copyInto(const TemplateArgumentLoc *ArgArray,
677                 TemplateArgumentListInfo &List) const;
678 };
679
680 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
681                                     const TemplateArgument &Arg);
682
683 inline TemplateSpecializationType::iterator
684     TemplateSpecializationType::end() const {
685   return getArgs() + getNumArgs();
686 }
687
688 inline DependentTemplateSpecializationType::iterator
689     DependentTemplateSpecializationType::end() const {
690   return getArgs() + getNumArgs();
691 }
692
693 inline const TemplateArgument &
694     TemplateSpecializationType::getArg(unsigned Idx) const {
695   assert(Idx < getNumArgs() && "Template argument out of range");
696   return getArgs()[Idx];
697 }
698
699 inline const TemplateArgument &
700     DependentTemplateSpecializationType::getArg(unsigned Idx) const {
701   assert(Idx < getNumArgs() && "Template argument out of range");
702   return getArgs()[Idx];
703 }
704
705 } // namespace clang
706
707 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H