1198893Srdivacky//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
2198893Srdivacky//
3198893Srdivacky//                     The LLVM Compiler Infrastructure
4198893Srdivacky//
5198893Srdivacky// This file is distributed under the University of Illinois Open Source
6198893Srdivacky// License. See LICENSE.TXT for details.
7198893Srdivacky//
8198893Srdivacky//===----------------------------------------------------------------------===//
9198893Srdivacky//
10198893Srdivacky//  This file provides definitions which are common for all kinds of
11198893Srdivacky//  template representation.
12198893Srdivacky//
13198893Srdivacky//===----------------------------------------------------------------------===//
14198893Srdivacky
15198893Srdivacky#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
16198893Srdivacky#define LLVM_CLANG_AST_TEMPLATEBASE_H
17198893Srdivacky
18252723Sdim#include "clang/AST/TemplateName.h"
19235633Sdim#include "clang/AST/Type.h"
20198893Srdivacky#include "llvm/ADT/APSInt.h"
21199990Srdivacky#include "llvm/ADT/SmallVector.h"
22235633Sdim#include "llvm/Support/Compiler.h"
23198893Srdivacky#include "llvm/Support/ErrorHandling.h"
24198893Srdivacky
25198893Srdivackynamespace llvm {
26198893Srdivacky  class FoldingSetNodeID;
27198893Srdivacky}
28198893Srdivacky
29198893Srdivackynamespace clang {
30198893Srdivacky
31208600Srdivackyclass DiagnosticBuilder;
32198893Srdivackyclass Expr;
33218893Sdimstruct PrintingPolicy;
34200583Srdivackyclass TypeSourceInfo;
35245431Sdimclass ValueDecl;
36198893Srdivacky
37198893Srdivacky/// \brief Represents a template argument within a class template
38198893Srdivacky/// specialization.
39198893Srdivackyclass TemplateArgument {
40198893Srdivackypublic:
41218893Sdim  /// \brief The kind of template argument we're storing.
42198893Srdivacky  enum ArgKind {
43199482Srdivacky    /// \brief Represents an empty template argument, e.g., one that has not
44199482Srdivacky    /// been deduced.
45198893Srdivacky    Null = 0,
46245431Sdim    /// The template argument is a type.
47199482Srdivacky    Type,
48245431Sdim    /// The template argument is a declaration that was provided for a pointer,
49245431Sdim    /// reference, or pointer to member non-type template parameter.
50199482Srdivacky    Declaration,
51245431Sdim    /// The template argument is a null pointer or null pointer to member that
52245431Sdim    /// was provided for a non-type template parameter.
53245431Sdim    NullPtr,
54199482Srdivacky    /// The template argument is an integral value stored in an llvm::APSInt
55199482Srdivacky    /// that was provided for an integral non-type template parameter.
56199482Srdivacky    Integral,
57199482Srdivacky    /// The template argument is a template name that was provided for a
58199482Srdivacky    /// template template parameter.
59199482Srdivacky    Template,
60218893Sdim    /// The template argument is a pack expansion of a template name that was
61218893Sdim    /// provided for a template template parameter.
62218893Sdim    TemplateExpansion,
63263509Sdim    /// The template argument is a value- or type-dependent expression or a
64263509Sdim    /// non-dependent __uuidof expression stored in an Expr*.
65199482Srdivacky    Expression,
66198893Srdivacky    /// The template argument is actually a parameter pack. Arguments are stored
67198893Srdivacky    /// in the Args struct.
68199482Srdivacky    Pack
69218893Sdim  };
70198893Srdivacky
71218893Sdimprivate:
72218893Sdim  /// \brief The kind of template argument we're storing.
73218893Sdim
74252723Sdim  struct DA {
75263509Sdim    unsigned Kind;
76263509Sdim    bool ForRefParam;
77252723Sdim    ValueDecl *D;
78252723Sdim  };
79252723Sdim  struct I {
80263509Sdim    unsigned Kind;
81252723Sdim    // We store a decomposed APSInt with the data allocated by ASTContext if
82252723Sdim    // BitWidth > 64. The memory may be shared between multiple
83252723Sdim    // TemplateArgument instances.
84263509Sdim    unsigned BitWidth : 31;
85263509Sdim    unsigned IsUnsigned : 1;
86252723Sdim    union {
87252723Sdim      uint64_t VAL;          ///< Used to store the <= 64 bits integer value.
88252723Sdim      const uint64_t *pVal;  ///< Used to store the >64 bits integer value.
89252723Sdim    };
90252723Sdim    void *Type;
91252723Sdim  };
92252723Sdim  struct A {
93263509Sdim    unsigned Kind;
94263509Sdim    unsigned NumArgs;
95252723Sdim    const TemplateArgument *Args;
96252723Sdim  };
97252723Sdim  struct TA {
98263509Sdim    unsigned Kind;
99263509Sdim    unsigned NumExpansions;
100252723Sdim    void *Name;
101252723Sdim  };
102263509Sdim  struct TV {
103263509Sdim    unsigned Kind;
104263509Sdim    uintptr_t V;
105263509Sdim  };
106218893Sdim  union {
107252723Sdim    struct DA DeclArg;
108252723Sdim    struct I Integer;
109252723Sdim    struct A Args;
110252723Sdim    struct TA TemplateArg;
111263509Sdim    struct TV TypeOrValue;
112218893Sdim  };
113218893Sdim
114252723Sdim  TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION;
115218893Sdim
116218893Sdimpublic:
117198893Srdivacky  /// \brief Construct an empty, invalid template argument.
118263509Sdim  TemplateArgument() {
119263509Sdim    TypeOrValue.Kind = Null;
120263509Sdim    TypeOrValue.V = 0;
121263509Sdim  }
122198893Srdivacky
123198893Srdivacky  /// \brief Construct a template type argument.
124263509Sdim  TemplateArgument(QualType T, bool isNullPtr = false) {
125263509Sdim    TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
126263509Sdim    TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
127198893Srdivacky  }
128198893Srdivacky
129198893Srdivacky  /// \brief Construct a template argument that refers to a
130198893Srdivacky  /// declaration, which is either an external declaration or a
131198893Srdivacky  /// template declaration.
132263509Sdim  TemplateArgument(ValueDecl *D, bool ForRefParam) {
133245431Sdim    assert(D && "Expected decl");
134263509Sdim    DeclArg.Kind = Declaration;
135245431Sdim    DeclArg.D = D;
136245431Sdim    DeclArg.ForRefParam = ForRefParam;
137198893Srdivacky  }
138198893Srdivacky
139245431Sdim  /// \brief Construct an integral constant template argument. The memory to
140245431Sdim  /// store the value is allocated with Ctx.
141245431Sdim  TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
142245431Sdim
143245431Sdim  /// \brief Construct an integral constant template argument with the same
144245431Sdim  /// value as Other but a different type.
145263509Sdim  TemplateArgument(const TemplateArgument &Other, QualType Type) {
146245431Sdim    Integer = Other.Integer;
147198893Srdivacky    Integer.Type = Type.getAsOpaquePtr();
148198893Srdivacky  }
149198893Srdivacky
150199482Srdivacky  /// \brief Construct a template argument that is a template.
151199482Srdivacky  ///
152199482Srdivacky  /// This form of template argument is generally used for template template
153199482Srdivacky  /// parameters. However, the template name could be a dependent template
154199482Srdivacky  /// name that ends up being instantiated to a function template whose address
155199482Srdivacky  /// is taken.
156218893Sdim  ///
157218893Sdim  /// \param Name The template name.
158263509Sdim  TemplateArgument(TemplateName Name) {
159263509Sdim    TemplateArg.Kind = Template;
160218893Sdim    TemplateArg.Name = Name.getAsVoidPointer();
161218893Sdim    TemplateArg.NumExpansions = 0;
162199482Srdivacky  }
163218893Sdim
164218893Sdim  /// \brief Construct a template argument that is a template pack expansion.
165218893Sdim  ///
166218893Sdim  /// This form of template argument is generally used for template template
167218893Sdim  /// parameters. However, the template name could be a dependent template
168218893Sdim  /// name that ends up being instantiated to a function template whose address
169218893Sdim  /// is taken.
170218893Sdim  ///
171218893Sdim  /// \param Name The template name.
172218893Sdim  ///
173218893Sdim  /// \param NumExpansions The number of expansions that will be generated by
174218893Sdim  /// instantiating
175263509Sdim  TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
176263509Sdim    TemplateArg.Kind = TemplateExpansion;
177218893Sdim    TemplateArg.Name = Name.getAsVoidPointer();
178218893Sdim    if (NumExpansions)
179218893Sdim      TemplateArg.NumExpansions = *NumExpansions + 1;
180218893Sdim    else
181218893Sdim      TemplateArg.NumExpansions = 0;
182218893Sdim  }
183218893Sdim
184198893Srdivacky  /// \brief Construct a template argument that is an expression.
185198893Srdivacky  ///
186198893Srdivacky  /// This form of template argument only occurs in template argument
187198893Srdivacky  /// lists used for dependent types and for expression; it will not
188198893Srdivacky  /// occur in a non-dependent, canonical template argument list.
189263509Sdim  TemplateArgument(Expr *E) {
190263509Sdim    TypeOrValue.Kind = Expression;
191263509Sdim    TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
192198893Srdivacky  }
193198893Srdivacky
194218893Sdim  /// \brief Construct a template argument that is a template argument pack.
195218893Sdim  ///
196218893Sdim  /// We assume that storage for the template arguments provided
197218893Sdim  /// outlives the TemplateArgument itself.
198263509Sdim  TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
199263509Sdim    this->Args.Kind = Pack;
200218893Sdim    this->Args.Args = Args;
201218893Sdim    this->Args.NumArgs = NumArgs;
202218893Sdim  }
203218893Sdim
204245431Sdim  static TemplateArgument getEmptyPack() {
205245431Sdim    return TemplateArgument((TemplateArgument*)0, 0);
206198893Srdivacky  }
207198893Srdivacky
208218893Sdim  /// \brief Create a new template argument pack by copying the given set of
209218893Sdim  /// template arguments.
210218893Sdim  static TemplateArgument CreatePackCopy(ASTContext &Context,
211218893Sdim                                         const TemplateArgument *Args,
212218893Sdim                                         unsigned NumArgs);
213218893Sdim
214198893Srdivacky  /// \brief Return the kind of stored template argument.
215263509Sdim  ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
216198893Srdivacky
217198893Srdivacky  /// \brief Determine whether this template argument has no value.
218263509Sdim  bool isNull() const { return getKind() == Null; }
219198893Srdivacky
220218893Sdim  /// \brief Whether this template argument is dependent on a template
221224145Sdim  /// parameter such that its result can change from one instantiation to
222224145Sdim  /// another.
223218893Sdim  bool isDependent() const;
224218893Sdim
225224145Sdim  /// \brief Whether this template argument is dependent on a template
226224145Sdim  /// parameter.
227224145Sdim  bool isInstantiationDependent() const;
228224145Sdim
229218893Sdim  /// \brief Whether this template argument contains an unexpanded
230218893Sdim  /// parameter pack.
231218893Sdim  bool containsUnexpandedParameterPack() const;
232218893Sdim
233218893Sdim  /// \brief Determine whether this template argument is a pack expansion.
234218893Sdim  bool isPackExpansion() const;
235218893Sdim
236245431Sdim  /// \brief Retrieve the type for a type template argument.
237198893Srdivacky  QualType getAsType() const {
238263509Sdim    assert(getKind() == Type && "Unexpected kind");
239263509Sdim    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
240198893Srdivacky  }
241198893Srdivacky
242245431Sdim  /// \brief Retrieve the declaration for a declaration non-type
243245431Sdim  /// template argument.
244245431Sdim  ValueDecl *getAsDecl() const {
245263509Sdim    assert(getKind() == Declaration && "Unexpected kind");
246245431Sdim    return DeclArg.D;
247198893Srdivacky  }
248198893Srdivacky
249245431Sdim  /// \brief Retrieve whether a declaration is binding to a
250245431Sdim  /// reference parameter in a declaration non-type template argument.
251245431Sdim  bool isDeclForReferenceParam() const {
252263509Sdim    assert(getKind() == Declaration && "Unexpected kind");
253245431Sdim    return DeclArg.ForRefParam;
254245431Sdim  }
255245431Sdim
256245431Sdim  /// \brief Retrieve the type for null non-type template argument.
257245431Sdim  QualType getNullPtrType() const {
258263509Sdim    assert(getKind() == NullPtr && "Unexpected kind");
259263509Sdim    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
260245431Sdim  }
261245431Sdim
262245431Sdim  /// \brief Retrieve the template name for a template name argument.
263199482Srdivacky  TemplateName getAsTemplate() const {
264263509Sdim    assert(getKind() == Template && "Unexpected kind");
265218893Sdim    return TemplateName::getFromVoidPointer(TemplateArg.Name);
266199482Srdivacky  }
267218893Sdim
268218893Sdim  /// \brief Retrieve the template argument as a template name; if the argument
269218893Sdim  /// is a pack expansion, return the pattern as a template name.
270218893Sdim  TemplateName getAsTemplateOrTemplatePattern() const {
271263509Sdim    assert((getKind() == Template || getKind() == TemplateExpansion) &&
272245431Sdim           "Unexpected kind");
273218893Sdim
274218893Sdim    return TemplateName::getFromVoidPointer(TemplateArg.Name);
275218893Sdim  }
276218893Sdim
277218893Sdim  /// \brief Retrieve the number of expansions that a template template argument
278218893Sdim  /// expansion will produce, if known.
279252723Sdim  Optional<unsigned> getNumTemplateExpansions() const;
280199482Srdivacky
281198893Srdivacky  /// \brief Retrieve the template argument as an integral value.
282245431Sdim  // FIXME: Provide a way to read the integral data without copying the value.
283245431Sdim  llvm::APSInt getAsIntegral() const {
284263509Sdim    assert(getKind() == Integral && "Unexpected kind");
285245431Sdim    using namespace llvm;
286245431Sdim    if (Integer.BitWidth <= 64)
287245431Sdim      return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
288198893Srdivacky
289245431Sdim    unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
290245431Sdim    return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
291245431Sdim                  Integer.IsUnsigned);
292198893Srdivacky  }
293198893Srdivacky
294198893Srdivacky  /// \brief Retrieve the type of the integral value.
295198893Srdivacky  QualType getIntegralType() const {
296263509Sdim    assert(getKind() == Integral && "Unexpected kind");
297198893Srdivacky    return QualType::getFromOpaquePtr(Integer.Type);
298198893Srdivacky  }
299198893Srdivacky
300198893Srdivacky  void setIntegralType(QualType T) {
301263509Sdim    assert(getKind() == Integral && "Unexpected kind");
302198893Srdivacky    Integer.Type = T.getAsOpaquePtr();
303201361Srdivacky  }
304198893Srdivacky
305198893Srdivacky  /// \brief Retrieve the template argument as an expression.
306198893Srdivacky  Expr *getAsExpr() const {
307263509Sdim    assert(getKind() == Expression && "Unexpected kind");
308263509Sdim    return reinterpret_cast<Expr *>(TypeOrValue.V);
309198893Srdivacky  }
310198893Srdivacky
311198893Srdivacky  /// \brief Iterator that traverses the elements of a template argument pack.
312198893Srdivacky  typedef const TemplateArgument * pack_iterator;
313198893Srdivacky
314198893Srdivacky  /// \brief Iterator referencing the first argument of a template argument
315198893Srdivacky  /// pack.
316198893Srdivacky  pack_iterator pack_begin() const {
317263509Sdim    assert(getKind() == Pack);
318198893Srdivacky    return Args.Args;
319198893Srdivacky  }
320198893Srdivacky
321198893Srdivacky  /// \brief Iterator referencing one past the last argument of a template
322198893Srdivacky  /// argument pack.
323198893Srdivacky  pack_iterator pack_end() const {
324263509Sdim    assert(getKind() == Pack);
325198893Srdivacky    return Args.Args + Args.NumArgs;
326198893Srdivacky  }
327198893Srdivacky
328198893Srdivacky  /// \brief The number of template arguments in the given template argument
329198893Srdivacky  /// pack.
330198893Srdivacky  unsigned pack_size() const {
331263509Sdim    assert(getKind() == Pack);
332198893Srdivacky    return Args.NumArgs;
333198893Srdivacky  }
334198893Srdivacky
335252723Sdim  /// \brief Return the array of arguments in this template argument pack.
336252723Sdim  llvm::ArrayRef<TemplateArgument> getPackAsArray() const {
337263509Sdim    assert(getKind() == Pack);
338252723Sdim    return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
339252723Sdim  }
340252723Sdim
341245431Sdim  /// \brief Determines whether two template arguments are superficially the
342210299Sed  /// same.
343210299Sed  bool structurallyEquals(const TemplateArgument &Other) const;
344210299Sed
345245431Sdim  /// \brief When the template argument is a pack expansion, returns
346218893Sdim  /// the pattern of the pack expansion.
347218893Sdim  TemplateArgument getPackExpansionPattern() const;
348198893Srdivacky
349218893Sdim  /// \brief Print this template argument to the given output stream.
350226890Sdim  void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
351218893Sdim
352198893Srdivacky  /// \brief Used to insert TemplateArguments into FoldingSets.
353218893Sdim  void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
354198893Srdivacky};
355198893Srdivacky
356198893Srdivacky/// Location information for a TemplateArgument.
357198893Srdivackystruct TemplateArgumentLocInfo {
358198893Srdivackyprivate:
359252723Sdim
360252723Sdim  struct T {
361252723Sdim    // FIXME: We'd like to just use the qualifier in the TemplateName,
362252723Sdim    // but template arguments get canonicalized too quickly.
363252723Sdim    NestedNameSpecifier *Qualifier;
364252723Sdim    void *QualifierLocData;
365252723Sdim    unsigned TemplateNameLoc;
366252723Sdim    unsigned EllipsisLoc;
367252723Sdim  };
368252723Sdim
369198893Srdivacky  union {
370252723Sdim    struct T Template;
371198893Srdivacky    Expr *Expression;
372200583Srdivacky    TypeSourceInfo *Declarator;
373198893Srdivacky  };
374198893Srdivacky
375198893Srdivackypublic:
376218893Sdim  TemplateArgumentLocInfo();
377198893Srdivacky
378218893Sdim  TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
379198893Srdivacky
380218893Sdim  TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
381199482Srdivacky
382221345Sdim  TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
383218893Sdim                          SourceLocation TemplateNameLoc,
384218893Sdim                          SourceLocation EllipsisLoc)
385199482Srdivacky  {
386221345Sdim    Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
387221345Sdim    Template.QualifierLocData = QualifierLoc.getOpaqueData();
388199482Srdivacky    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
389218893Sdim    Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
390199482Srdivacky  }
391198893Srdivacky
392200583Srdivacky  TypeSourceInfo *getAsTypeSourceInfo() const {
393198893Srdivacky    return Declarator;
394198893Srdivacky  }
395198893Srdivacky
396198893Srdivacky  Expr *getAsExpr() const {
397198893Srdivacky    return Expression;
398198893Srdivacky  }
399198893Srdivacky
400221345Sdim  NestedNameSpecifierLoc getTemplateQualifierLoc() const {
401221345Sdim    return NestedNameSpecifierLoc(Template.Qualifier,
402221345Sdim                                  Template.QualifierLocData);
403199482Srdivacky  }
404199482Srdivacky
405199482Srdivacky  SourceLocation getTemplateNameLoc() const {
406199482Srdivacky    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
407199482Srdivacky  }
408199482Srdivacky
409218893Sdim  SourceLocation getTemplateEllipsisLoc() const {
410218893Sdim    return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
411198893Srdivacky  }
412198893Srdivacky};
413198893Srdivacky
414198893Srdivacky/// Location wrapper for a TemplateArgument.  TemplateArgument is to
415198893Srdivacky/// TemplateArgumentLoc as Type is to TypeLoc.
416198893Srdivackyclass TemplateArgumentLoc {
417198893Srdivacky  TemplateArgument Argument;
418198893Srdivacky  TemplateArgumentLocInfo LocInfo;
419198893Srdivacky
420198893Srdivackypublic:
421198893Srdivacky  TemplateArgumentLoc() {}
422198893Srdivacky
423198893Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument,
424198893Srdivacky                      TemplateArgumentLocInfo Opaque)
425198893Srdivacky    : Argument(Argument), LocInfo(Opaque) {
426198893Srdivacky  }
427198893Srdivacky
428200583Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
429200583Srdivacky    : Argument(Argument), LocInfo(TInfo) {
430198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Type);
431198893Srdivacky  }
432198893Srdivacky
433198893Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
434198893Srdivacky    : Argument(Argument), LocInfo(E) {
435198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Expression);
436198893Srdivacky  }
437198893Srdivacky
438199482Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument,
439221345Sdim                      NestedNameSpecifierLoc QualifierLoc,
440218893Sdim                      SourceLocation TemplateNameLoc,
441218893Sdim                      SourceLocation EllipsisLoc = SourceLocation())
442221345Sdim    : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
443218893Sdim    assert(Argument.getKind() == TemplateArgument::Template ||
444218893Sdim           Argument.getKind() == TemplateArgument::TemplateExpansion);
445199482Srdivacky  }
446199482Srdivacky
447199482Srdivacky  /// \brief - Fetches the primary location of the argument.
448198893Srdivacky  SourceLocation getLocation() const {
449218893Sdim    if (Argument.getKind() == TemplateArgument::Template ||
450218893Sdim        Argument.getKind() == TemplateArgument::TemplateExpansion)
451199482Srdivacky      return getTemplateNameLoc();
452199482Srdivacky
453198893Srdivacky    return getSourceRange().getBegin();
454198893Srdivacky  }
455198893Srdivacky
456198893Srdivacky  /// \brief - Fetches the full source range of the argument.
457235633Sdim  SourceRange getSourceRange() const LLVM_READONLY;
458198893Srdivacky
459198893Srdivacky  const TemplateArgument &getArgument() const {
460198893Srdivacky    return Argument;
461198893Srdivacky  }
462198893Srdivacky
463198893Srdivacky  TemplateArgumentLocInfo getLocInfo() const {
464198893Srdivacky    return LocInfo;
465198893Srdivacky  }
466198893Srdivacky
467200583Srdivacky  TypeSourceInfo *getTypeSourceInfo() const {
468198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Type);
469200583Srdivacky    return LocInfo.getAsTypeSourceInfo();
470198893Srdivacky  }
471198893Srdivacky
472198893Srdivacky  Expr *getSourceExpression() const {
473198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Expression);
474198893Srdivacky    return LocInfo.getAsExpr();
475198893Srdivacky  }
476198893Srdivacky
477198893Srdivacky  Expr *getSourceDeclExpression() const {
478198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Declaration);
479198893Srdivacky    return LocInfo.getAsExpr();
480198893Srdivacky  }
481245431Sdim
482245431Sdim  Expr *getSourceNullPtrExpression() const {
483245431Sdim    assert(Argument.getKind() == TemplateArgument::NullPtr);
484245431Sdim    return LocInfo.getAsExpr();
485245431Sdim  }
486245431Sdim
487245431Sdim  Expr *getSourceIntegralExpression() const {
488245431Sdim    assert(Argument.getKind() == TemplateArgument::Integral);
489245431Sdim    return LocInfo.getAsExpr();
490245431Sdim  }
491245431Sdim
492221345Sdim  NestedNameSpecifierLoc getTemplateQualifierLoc() const {
493218893Sdim    assert(Argument.getKind() == TemplateArgument::Template ||
494218893Sdim           Argument.getKind() == TemplateArgument::TemplateExpansion);
495221345Sdim    return LocInfo.getTemplateQualifierLoc();
496199482Srdivacky  }
497199482Srdivacky
498199482Srdivacky  SourceLocation getTemplateNameLoc() const {
499218893Sdim    assert(Argument.getKind() == TemplateArgument::Template ||
500218893Sdim           Argument.getKind() == TemplateArgument::TemplateExpansion);
501199482Srdivacky    return LocInfo.getTemplateNameLoc();
502199482Srdivacky  }
503218893Sdim
504218893Sdim  SourceLocation getTemplateEllipsisLoc() const {
505218893Sdim    assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
506218893Sdim    return LocInfo.getTemplateEllipsisLoc();
507218893Sdim  }
508198893Srdivacky};
509198893Srdivacky
510199990Srdivacky/// A convenient class for passing around template argument
511199990Srdivacky/// information.  Designed to be passed by reference.
512199990Srdivackyclass TemplateArgumentListInfo {
513226890Sdim  SmallVector<TemplateArgumentLoc, 8> Arguments;
514199990Srdivacky  SourceLocation LAngleLoc;
515199990Srdivacky  SourceLocation RAngleLoc;
516199990Srdivacky
517226890Sdim  // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
518226890Sdim  // instead.
519226890Sdim  void* operator new(size_t bytes, ASTContext& C);
520226890Sdim
521199990Srdivackypublic:
522199990Srdivacky  TemplateArgumentListInfo() {}
523199990Srdivacky
524199990Srdivacky  TemplateArgumentListInfo(SourceLocation LAngleLoc,
525199990Srdivacky                           SourceLocation RAngleLoc)
526199990Srdivacky    : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
527199990Srdivacky
528199990Srdivacky  SourceLocation getLAngleLoc() const { return LAngleLoc; }
529199990Srdivacky  SourceLocation getRAngleLoc() const { return RAngleLoc; }
530199990Srdivacky
531199990Srdivacky  void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
532199990Srdivacky  void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
533199990Srdivacky
534199990Srdivacky  unsigned size() const { return Arguments.size(); }
535199990Srdivacky
536199990Srdivacky  const TemplateArgumentLoc *getArgumentArray() const {
537199990Srdivacky    return Arguments.data();
538199990Srdivacky  }
539199990Srdivacky
540199990Srdivacky  const TemplateArgumentLoc &operator[](unsigned I) const {
541199990Srdivacky    return Arguments[I];
542199990Srdivacky  }
543199990Srdivacky
544199990Srdivacky  void addArgument(const TemplateArgumentLoc &Loc) {
545199990Srdivacky    Arguments.push_back(Loc);
546199990Srdivacky  }
547199990Srdivacky};
548199990Srdivacky
549226890Sdim/// \brief Represents an explicit template argument list in C++, e.g.,
550226890Sdim/// the "<int>" in "sort<int>".
551226890Sdim/// This is safe to be used inside an AST node, in contrast with
552226890Sdim/// TemplateArgumentListInfo.
553226890Sdimstruct ASTTemplateArgumentListInfo {
554245431Sdim  /// \brief The source location of the left angle bracket ('<').
555226890Sdim  SourceLocation LAngleLoc;
556226890Sdim
557245431Sdim  /// \brief The source location of the right angle bracket ('>').
558226890Sdim  SourceLocation RAngleLoc;
559226890Sdim
560245431Sdim  union {
561245431Sdim    /// \brief The number of template arguments in TemplateArgs.
562245431Sdim    /// The actual template arguments (if any) are stored after the
563245431Sdim    /// ExplicitTemplateArgumentList structure.
564245431Sdim    unsigned NumTemplateArgs;
565245431Sdim
566245431Sdim    /// Force ASTTemplateArgumentListInfo to the right alignment
567245431Sdim    /// for the following array of TemplateArgumentLocs.
568245431Sdim    void *Aligner;
569245431Sdim  };
570245431Sdim
571226890Sdim  /// \brief Retrieve the template arguments
572226890Sdim  TemplateArgumentLoc *getTemplateArgs() {
573226890Sdim    return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
574226890Sdim  }
575226890Sdim
576226890Sdim  /// \brief Retrieve the template arguments
577226890Sdim  const TemplateArgumentLoc *getTemplateArgs() const {
578226890Sdim    return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
579226890Sdim  }
580226890Sdim
581226890Sdim  const TemplateArgumentLoc &operator[](unsigned I) const {
582226890Sdim    return getTemplateArgs()[I];
583226890Sdim  }
584226890Sdim
585226890Sdim  static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
586226890Sdim                                          const TemplateArgumentListInfo &List);
587226890Sdim
588226890Sdim  void initializeFrom(const TemplateArgumentListInfo &List);
589226890Sdim  void initializeFrom(const TemplateArgumentListInfo &List,
590226890Sdim                      bool &Dependent, bool &InstantiationDependent,
591226890Sdim                      bool &ContainsUnexpandedParameterPack);
592226890Sdim  void copyInto(TemplateArgumentListInfo &List) const;
593226890Sdim  static std::size_t sizeFor(unsigned NumTemplateArgs);
594226890Sdim};
595226890Sdim
596235633Sdim/// \brief Extends ASTTemplateArgumentListInfo with the source location
597235633Sdim/// information for the template keyword; this is used as part of the
598235633Sdim/// representation of qualified identifiers, such as S<T>::template apply<T>.
599235633Sdimstruct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
600235633Sdim  typedef ASTTemplateArgumentListInfo Base;
601235633Sdim
602235633Sdim  // NOTE: the source location of the (optional) template keyword is
603235633Sdim  // stored after all template arguments.
604235633Sdim
605235633Sdim  /// \brief Get the source location of the template keyword.
606235633Sdim  SourceLocation getTemplateKeywordLoc() const {
607235633Sdim    return *reinterpret_cast<const SourceLocation*>
608235633Sdim      (getTemplateArgs() + NumTemplateArgs);
609235633Sdim  }
610235633Sdim
611235633Sdim  /// \brief Sets the source location of the template keyword.
612235633Sdim  void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
613235633Sdim    *reinterpret_cast<SourceLocation*>
614235633Sdim      (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
615235633Sdim  }
616235633Sdim
617235633Sdim  static const ASTTemplateKWAndArgsInfo*
618235633Sdim  Create(ASTContext &C, SourceLocation TemplateKWLoc,
619235633Sdim         const TemplateArgumentListInfo &List);
620235633Sdim
621235633Sdim  void initializeFrom(SourceLocation TemplateKWLoc,
622235633Sdim                      const TemplateArgumentListInfo &List);
623235633Sdim  void initializeFrom(SourceLocation TemplateKWLoc,
624235633Sdim                      const TemplateArgumentListInfo &List,
625235633Sdim                      bool &Dependent, bool &InstantiationDependent,
626235633Sdim                      bool &ContainsUnexpandedParameterPack);
627235633Sdim  void initializeFrom(SourceLocation TemplateKWLoc);
628235633Sdim
629235633Sdim  static std::size_t sizeFor(unsigned NumTemplateArgs);
630235633Sdim};
631235633Sdim
632208600Srdivackyconst DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
633208600Srdivacky                                    const TemplateArgument &Arg);
634210299Sed
635210299Sedinline TemplateSpecializationType::iterator
636210299Sed    TemplateSpecializationType::end() const {
637210299Sed  return getArgs() + getNumArgs();
638210299Sed}
639210299Sed
640210299Sedinline DependentTemplateSpecializationType::iterator
641210299Sed    DependentTemplateSpecializationType::end() const {
642210299Sed  return getArgs() + getNumArgs();
643210299Sed}
644210299Sed
645210299Sedinline const TemplateArgument &
646210299Sed    TemplateSpecializationType::getArg(unsigned Idx) const {
647210299Sed  assert(Idx < getNumArgs() && "Template argument out of range");
648210299Sed  return getArgs()[Idx];
649210299Sed}
650210299Sed
651210299Sedinline const TemplateArgument &
652210299Sed    DependentTemplateSpecializationType::getArg(unsigned Idx) const {
653210299Sed  assert(Idx < getNumArgs() && "Template argument out of range");
654210299Sed  return getArgs()[Idx];
655210299Sed}
656208600Srdivacky
657208600Srdivacky} // end namespace clang
658198893Srdivacky
659198893Srdivacky#endif
660