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