1327952Sdim//===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===//
2198893Srdivacky//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6198893Srdivacky//
7198893Srdivacky//===----------------------------------------------------------------------===//
8198893Srdivacky//
9198893Srdivacky//  This file provides definitions which are common for all kinds of
10198893Srdivacky//  template representation.
11198893Srdivacky//
12198893Srdivacky//===----------------------------------------------------------------------===//
13198893Srdivacky
14198893Srdivacky#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
15198893Srdivacky#define LLVM_CLANG_AST_TEMPLATEBASE_H
16198893Srdivacky
17327952Sdim#include "clang/AST/NestedNameSpecifier.h"
18249423Sdim#include "clang/AST/TemplateName.h"
19234353Sdim#include "clang/AST/Type.h"
20327952Sdim#include "clang/Basic/LLVM.h"
21327952Sdim#include "clang/Basic/SourceLocation.h"
22327952Sdim#include "llvm/ADT/APInt.h"
23198893Srdivacky#include "llvm/ADT/APSInt.h"
24327952Sdim#include "llvm/ADT/ArrayRef.h"
25327952Sdim#include "llvm/ADT/None.h"
26327952Sdim#include "llvm/ADT/Optional.h"
27280031Sdim#include "llvm/ADT/SmallVector.h"
28234353Sdim#include "llvm/Support/Compiler.h"
29296417Sdim#include "llvm/Support/TrailingObjects.h"
30327952Sdim#include <cassert>
31327952Sdim#include <cstddef>
32327952Sdim#include <cstdint>
33198893Srdivacky
34198893Srdivackynamespace llvm {
35198893Srdivacky
36327952Sdimclass FoldingSetNodeID;
37327952Sdim
38327952Sdim} // namespace llvm
39327952Sdim
40198893Srdivackynamespace clang {
41198893Srdivacky
42327952Sdimclass ASTContext;
43208600Srdivackyclass DiagnosticBuilder;
44198893Srdivackyclass Expr;
45218893Sdimstruct PrintingPolicy;
46200583Srdivackyclass TypeSourceInfo;
47243830Sdimclass ValueDecl;
48198893Srdivacky
49341825Sdim/// Represents a template argument.
50198893Srdivackyclass TemplateArgument {
51198893Srdivackypublic:
52341825Sdim  /// The kind of template argument we're storing.
53198893Srdivacky  enum ArgKind {
54341825Sdim    /// Represents an empty template argument, e.g., one that has not
55199482Srdivacky    /// been deduced.
56198893Srdivacky    Null = 0,
57327952Sdim
58243830Sdim    /// The template argument is a type.
59199482Srdivacky    Type,
60327952Sdim
61243830Sdim    /// The template argument is a declaration that was provided for a pointer,
62243830Sdim    /// reference, or pointer to member non-type template parameter.
63199482Srdivacky    Declaration,
64327952Sdim
65243830Sdim    /// The template argument is a null pointer or null pointer to member that
66243830Sdim    /// was provided for a non-type template parameter.
67243830Sdim    NullPtr,
68327952Sdim
69199482Srdivacky    /// The template argument is an integral value stored in an llvm::APSInt
70276479Sdim    /// that was provided for an integral non-type template parameter.
71199482Srdivacky    Integral,
72327952Sdim
73276479Sdim    /// The template argument is a template name that was provided for a
74199482Srdivacky    /// template template parameter.
75199482Srdivacky    Template,
76327952Sdim
77276479Sdim    /// The template argument is a pack expansion of a template name that was
78218893Sdim    /// provided for a template template parameter.
79218893Sdim    TemplateExpansion,
80327952Sdim
81276479Sdim    /// The template argument is an expression, and we've not resolved it to one
82276479Sdim    /// of the other forms yet, either because it's dependent or because we're
83276479Sdim    /// representing a non-canonical template argument (for instance, in a
84276479Sdim    /// TemplateSpecializationType). Also used to represent a non-dependent
85276479Sdim    /// __uuidof expression (a Microsoft extension).
86199482Srdivacky    Expression,
87327952Sdim
88198893Srdivacky    /// The template argument is actually a parameter pack. Arguments are stored
89198893Srdivacky    /// in the Args struct.
90199482Srdivacky    Pack
91218893Sdim  };
92198893Srdivacky
93218893Sdimprivate:
94341825Sdim  /// The kind of template argument we're storing.
95218893Sdim
96249423Sdim  struct DA {
97261991Sdim    unsigned Kind;
98280031Sdim    void *QT;
99249423Sdim    ValueDecl *D;
100249423Sdim  };
101249423Sdim  struct I {
102261991Sdim    unsigned Kind;
103249423Sdim    // We store a decomposed APSInt with the data allocated by ASTContext if
104249423Sdim    // BitWidth > 64. The memory may be shared between multiple
105249423Sdim    // TemplateArgument instances.
106261991Sdim    unsigned BitWidth : 31;
107261991Sdim    unsigned IsUnsigned : 1;
108249423Sdim    union {
109327952Sdim      /// Used to store the <= 64 bits integer value.
110327952Sdim      uint64_t VAL;
111327952Sdim
112327952Sdim      /// Used to store the >64 bits integer value.
113327952Sdim      const uint64_t *pVal;
114249423Sdim    };
115249423Sdim    void *Type;
116249423Sdim  };
117249423Sdim  struct A {
118261991Sdim    unsigned Kind;
119261991Sdim    unsigned NumArgs;
120249423Sdim    const TemplateArgument *Args;
121249423Sdim  };
122249423Sdim  struct TA {
123261991Sdim    unsigned Kind;
124261991Sdim    unsigned NumExpansions;
125249423Sdim    void *Name;
126249423Sdim  };
127261991Sdim  struct TV {
128261991Sdim    unsigned Kind;
129261991Sdim    uintptr_t V;
130261991Sdim  };
131218893Sdim  union {
132249423Sdim    struct DA DeclArg;
133249423Sdim    struct I Integer;
134249423Sdim    struct A Args;
135249423Sdim    struct TA TemplateArg;
136261991Sdim    struct TV TypeOrValue;
137218893Sdim  };
138218893Sdim
139218893Sdimpublic:
140341825Sdim  /// Construct an empty, invalid template argument.
141321369Sdim  constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
142198893Srdivacky
143341825Sdim  /// Construct a template type argument.
144261991Sdim  TemplateArgument(QualType T, bool isNullPtr = false) {
145261991Sdim    TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
146261991Sdim    TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
147198893Srdivacky  }
148198893Srdivacky
149341825Sdim  /// Construct a template argument that refers to a
150198893Srdivacky  /// declaration, which is either an external declaration or a
151198893Srdivacky  /// template declaration.
152280031Sdim  TemplateArgument(ValueDecl *D, QualType QT) {
153243830Sdim    assert(D && "Expected decl");
154261991Sdim    DeclArg.Kind = Declaration;
155280031Sdim    DeclArg.QT = QT.getAsOpaquePtr();
156243830Sdim    DeclArg.D = D;
157198893Srdivacky  }
158198893Srdivacky
159341825Sdim  /// Construct an integral constant template argument. The memory to
160239462Sdim  /// store the value is allocated with Ctx.
161239462Sdim  TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
162239462Sdim
163341825Sdim  /// Construct an integral constant template argument with the same
164239462Sdim  /// value as Other but a different type.
165261991Sdim  TemplateArgument(const TemplateArgument &Other, QualType Type) {
166239462Sdim    Integer = Other.Integer;
167198893Srdivacky    Integer.Type = Type.getAsOpaquePtr();
168198893Srdivacky  }
169198893Srdivacky
170341825Sdim  /// Construct a template argument that is a template.
171199482Srdivacky  ///
172199482Srdivacky  /// This form of template argument is generally used for template template
173199482Srdivacky  /// parameters. However, the template name could be a dependent template
174199482Srdivacky  /// name that ends up being instantiated to a function template whose address
175199482Srdivacky  /// is taken.
176218893Sdim  ///
177218893Sdim  /// \param Name The template name.
178261991Sdim  TemplateArgument(TemplateName Name) {
179261991Sdim    TemplateArg.Kind = Template;
180218893Sdim    TemplateArg.Name = Name.getAsVoidPointer();
181218893Sdim    TemplateArg.NumExpansions = 0;
182199482Srdivacky  }
183218893Sdim
184341825Sdim  /// Construct a template argument that is a template pack expansion.
185218893Sdim  ///
186218893Sdim  /// This form of template argument is generally used for template template
187218893Sdim  /// parameters. However, the template name could be a dependent template
188218893Sdim  /// name that ends up being instantiated to a function template whose address
189218893Sdim  /// is taken.
190218893Sdim  ///
191218893Sdim  /// \param Name The template name.
192218893Sdim  ///
193218893Sdim  /// \param NumExpansions The number of expansions that will be generated by
194218893Sdim  /// instantiating
195261991Sdim  TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
196261991Sdim    TemplateArg.Kind = TemplateExpansion;
197218893Sdim    TemplateArg.Name = Name.getAsVoidPointer();
198218893Sdim    if (NumExpansions)
199218893Sdim      TemplateArg.NumExpansions = *NumExpansions + 1;
200218893Sdim    else
201218893Sdim      TemplateArg.NumExpansions = 0;
202218893Sdim  }
203218893Sdim
204341825Sdim  /// Construct a template argument that is an expression.
205198893Srdivacky  ///
206198893Srdivacky  /// This form of template argument only occurs in template argument
207198893Srdivacky  /// lists used for dependent types and for expression; it will not
208198893Srdivacky  /// occur in a non-dependent, canonical template argument list.
209261991Sdim  TemplateArgument(Expr *E) {
210261991Sdim    TypeOrValue.Kind = Expression;
211261991Sdim    TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
212198893Srdivacky  }
213198893Srdivacky
214341825Sdim  /// Construct a template argument that is a template argument pack.
215218893Sdim  ///
216218893Sdim  /// We assume that storage for the template arguments provided
217218893Sdim  /// outlives the TemplateArgument itself.
218296417Sdim  explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
219261991Sdim    this->Args.Kind = Pack;
220296417Sdim    this->Args.Args = Args.data();
221296417Sdim    this->Args.NumArgs = Args.size();
222218893Sdim  }
223218893Sdim
224327952Sdim  TemplateArgument(TemplateName, bool) = delete;
225327952Sdim
226296417Sdim  static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
227243830Sdim
228341825Sdim  /// Create a new template argument pack by copying the given set of
229218893Sdim  /// template arguments.
230218893Sdim  static TemplateArgument CreatePackCopy(ASTContext &Context,
231296417Sdim                                         ArrayRef<TemplateArgument> Args);
232296417Sdim
233341825Sdim  /// Return the kind of stored template argument.
234261991Sdim  ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
235198893Srdivacky
236341825Sdim  /// Determine whether this template argument has no value.
237261991Sdim  bool isNull() const { return getKind() == Null; }
238198893Srdivacky
239341825Sdim  /// Whether this template argument is dependent on a template
240224145Sdim  /// parameter such that its result can change from one instantiation to
241224145Sdim  /// another.
242218893Sdim  bool isDependent() const;
243218893Sdim
244341825Sdim  /// Whether this template argument is dependent on a template
245224145Sdim  /// parameter.
246224145Sdim  bool isInstantiationDependent() const;
247224145Sdim
248341825Sdim  /// Whether this template argument contains an unexpanded
249218893Sdim  /// parameter pack.
250218893Sdim  bool containsUnexpandedParameterPack() const;
251218893Sdim
252341825Sdim  /// Determine whether this template argument is a pack expansion.
253218893Sdim  bool isPackExpansion() const;
254341825Sdim
255341825Sdim  /// Retrieve the type for a type template argument.
256198893Srdivacky  QualType getAsType() const {
257261991Sdim    assert(getKind() == Type && "Unexpected kind");
258261991Sdim    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
259198893Srdivacky  }
260198893Srdivacky
261341825Sdim  /// Retrieve the declaration for a declaration non-type
262243830Sdim  /// template argument.
263243830Sdim  ValueDecl *getAsDecl() const {
264261991Sdim    assert(getKind() == Declaration && "Unexpected kind");
265243830Sdim    return DeclArg.D;
266198893Srdivacky  }
267198893Srdivacky
268280031Sdim  QualType getParamTypeForDecl() const {
269261991Sdim    assert(getKind() == Declaration && "Unexpected kind");
270280031Sdim    return QualType::getFromOpaquePtr(DeclArg.QT);
271243830Sdim  }
272243830Sdim
273341825Sdim  /// Retrieve the type for null non-type template argument.
274243830Sdim  QualType getNullPtrType() const {
275261991Sdim    assert(getKind() == NullPtr && "Unexpected kind");
276261991Sdim    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
277243830Sdim  }
278243830Sdim
279341825Sdim  /// Retrieve the template name for a template name argument.
280199482Srdivacky  TemplateName getAsTemplate() const {
281261991Sdim    assert(getKind() == Template && "Unexpected kind");
282218893Sdim    return TemplateName::getFromVoidPointer(TemplateArg.Name);
283199482Srdivacky  }
284218893Sdim
285341825Sdim  /// Retrieve the template argument as a template name; if the argument
286218893Sdim  /// is a pack expansion, return the pattern as a template name.
287218893Sdim  TemplateName getAsTemplateOrTemplatePattern() const {
288261991Sdim    assert((getKind() == Template || getKind() == TemplateExpansion) &&
289243830Sdim           "Unexpected kind");
290341825Sdim
291218893Sdim    return TemplateName::getFromVoidPointer(TemplateArg.Name);
292218893Sdim  }
293218893Sdim
294341825Sdim  /// Retrieve the number of expansions that a template template argument
295218893Sdim  /// expansion will produce, if known.
296249423Sdim  Optional<unsigned> getNumTemplateExpansions() const;
297341825Sdim
298341825Sdim  /// Retrieve the template argument as an integral value.
299239462Sdim  // FIXME: Provide a way to read the integral data without copying the value.
300239462Sdim  llvm::APSInt getAsIntegral() const {
301261991Sdim    assert(getKind() == Integral && "Unexpected kind");
302327952Sdim
303239462Sdim    using namespace llvm;
304327952Sdim
305239462Sdim    if (Integer.BitWidth <= 64)
306239462Sdim      return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
307198893Srdivacky
308239462Sdim    unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
309239462Sdim    return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
310239462Sdim                  Integer.IsUnsigned);
311198893Srdivacky  }
312198893Srdivacky
313341825Sdim  /// Retrieve the type of the integral value.
314198893Srdivacky  QualType getIntegralType() const {
315261991Sdim    assert(getKind() == Integral && "Unexpected kind");
316198893Srdivacky    return QualType::getFromOpaquePtr(Integer.Type);
317198893Srdivacky  }
318198893Srdivacky
319198893Srdivacky  void setIntegralType(QualType T) {
320261991Sdim    assert(getKind() == Integral && "Unexpected kind");
321198893Srdivacky    Integer.Type = T.getAsOpaquePtr();
322201361Srdivacky  }
323198893Srdivacky
324341825Sdim  /// If this is a non-type template argument, get its type. Otherwise,
325314564Sdim  /// returns a null QualType.
326314564Sdim  QualType getNonTypeTemplateArgumentType() const;
327314564Sdim
328341825Sdim  /// Retrieve the template argument as an expression.
329198893Srdivacky  Expr *getAsExpr() const {
330261991Sdim    assert(getKind() == Expression && "Unexpected kind");
331261991Sdim    return reinterpret_cast<Expr *>(TypeOrValue.V);
332198893Srdivacky  }
333198893Srdivacky
334341825Sdim  /// Iterator that traverses the elements of a template argument pack.
335327952Sdim  using pack_iterator = const TemplateArgument *;
336198893Srdivacky
337341825Sdim  /// Iterator referencing the first argument of a template argument
338198893Srdivacky  /// pack.
339198893Srdivacky  pack_iterator pack_begin() const {
340261991Sdim    assert(getKind() == Pack);
341198893Srdivacky    return Args.Args;
342198893Srdivacky  }
343198893Srdivacky
344341825Sdim  /// Iterator referencing one past the last argument of a template
345198893Srdivacky  /// argument pack.
346198893Srdivacky  pack_iterator pack_end() const {
347261991Sdim    assert(getKind() == Pack);
348198893Srdivacky    return Args.Args + Args.NumArgs;
349198893Srdivacky  }
350198893Srdivacky
351341825Sdim  /// Iterator range referencing all of the elements of a template
352276479Sdim  /// argument pack.
353314564Sdim  ArrayRef<TemplateArgument> pack_elements() const {
354314564Sdim    return llvm::makeArrayRef(pack_begin(), pack_end());
355276479Sdim  }
356276479Sdim
357341825Sdim  /// The number of template arguments in the given template argument
358198893Srdivacky  /// pack.
359198893Srdivacky  unsigned pack_size() const {
360261991Sdim    assert(getKind() == Pack);
361198893Srdivacky    return Args.NumArgs;
362198893Srdivacky  }
363198893Srdivacky
364341825Sdim  /// Return the array of arguments in this template argument pack.
365276479Sdim  ArrayRef<TemplateArgument> getPackAsArray() const {
366261991Sdim    assert(getKind() == Pack);
367280031Sdim    return llvm::makeArrayRef(Args.Args, Args.NumArgs);
368249423Sdim  }
369249423Sdim
370341825Sdim  /// Determines whether two template arguments are superficially the
371210299Sed  /// same.
372210299Sed  bool structurallyEquals(const TemplateArgument &Other) const;
373210299Sed
374341825Sdim  /// When the template argument is a pack expansion, returns
375218893Sdim  /// the pattern of the pack expansion.
376218893Sdim  TemplateArgument getPackExpansionPattern() const;
377198893Srdivacky
378341825Sdim  /// Print this template argument to the given output stream.
379226633Sdim  void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
380341825Sdim
381341825Sdim  /// Debugging aid that dumps the template argument.
382309124Sdim  void dump(raw_ostream &Out) const;
383309124Sdim
384341825Sdim  /// Debugging aid that dumps the template argument to standard error.
385309124Sdim  void dump() const;
386341825Sdim
387341825Sdim  /// Used to insert TemplateArguments into FoldingSets.
388218893Sdim  void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
389198893Srdivacky};
390198893Srdivacky
391198893Srdivacky/// Location information for a TemplateArgument.
392198893Srdivackystruct TemplateArgumentLocInfo {
393198893Srdivackyprivate:
394249423Sdim  struct T {
395249423Sdim    // FIXME: We'd like to just use the qualifier in the TemplateName,
396249423Sdim    // but template arguments get canonicalized too quickly.
397249423Sdim    NestedNameSpecifier *Qualifier;
398249423Sdim    void *QualifierLocData;
399249423Sdim    unsigned TemplateNameLoc;
400249423Sdim    unsigned EllipsisLoc;
401249423Sdim  };
402249423Sdim
403198893Srdivacky  union {
404249423Sdim    struct T Template;
405198893Srdivacky    Expr *Expression;
406200583Srdivacky    TypeSourceInfo *Declarator;
407198893Srdivacky  };
408198893Srdivacky
409198893Srdivackypublic:
410321369Sdim  constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
411321369Sdim
412218893Sdim  TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
413341825Sdim
414218893Sdim  TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
415341825Sdim
416221345Sdim  TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
417218893Sdim                          SourceLocation TemplateNameLoc,
418327952Sdim                          SourceLocation EllipsisLoc) {
419221345Sdim    Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
420221345Sdim    Template.QualifierLocData = QualifierLoc.getOpaqueData();
421199482Srdivacky    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
422218893Sdim    Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
423199482Srdivacky  }
424198893Srdivacky
425200583Srdivacky  TypeSourceInfo *getAsTypeSourceInfo() const {
426198893Srdivacky    return Declarator;
427198893Srdivacky  }
428198893Srdivacky
429198893Srdivacky  Expr *getAsExpr() const {
430198893Srdivacky    return Expression;
431198893Srdivacky  }
432198893Srdivacky
433221345Sdim  NestedNameSpecifierLoc getTemplateQualifierLoc() const {
434341825Sdim    return NestedNameSpecifierLoc(Template.Qualifier,
435221345Sdim                                  Template.QualifierLocData);
436199482Srdivacky  }
437341825Sdim
438199482Srdivacky  SourceLocation getTemplateNameLoc() const {
439199482Srdivacky    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
440199482Srdivacky  }
441341825Sdim
442218893Sdim  SourceLocation getTemplateEllipsisLoc() const {
443218893Sdim    return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
444198893Srdivacky  }
445198893Srdivacky};
446198893Srdivacky
447198893Srdivacky/// Location wrapper for a TemplateArgument.  TemplateArgument is to
448198893Srdivacky/// TemplateArgumentLoc as Type is to TypeLoc.
449198893Srdivackyclass TemplateArgumentLoc {
450198893Srdivacky  TemplateArgument Argument;
451198893Srdivacky  TemplateArgumentLocInfo LocInfo;
452198893Srdivacky
453198893Srdivackypublic:
454321369Sdim  constexpr TemplateArgumentLoc() {}
455198893Srdivacky
456198893Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument,
457198893Srdivacky                      TemplateArgumentLocInfo Opaque)
458327952Sdim      : Argument(Argument), LocInfo(Opaque) {}
459198893Srdivacky
460200583Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
461327952Sdim      : Argument(Argument), LocInfo(TInfo) {
462198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Type);
463198893Srdivacky  }
464198893Srdivacky
465198893Srdivacky  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
466327952Sdim      : Argument(Argument), LocInfo(E) {
467341825Sdim
468341825Sdim    // Permit any kind of template argument that can be represented with an
469344779Sdim    // expression.
470341825Sdim    assert(Argument.getKind() == TemplateArgument::NullPtr ||
471341825Sdim           Argument.getKind() == TemplateArgument::Integral ||
472341825Sdim           Argument.getKind() == TemplateArgument::Declaration ||
473341825Sdim           Argument.getKind() == TemplateArgument::Expression);
474198893Srdivacky  }
475198893Srdivacky
476341825Sdim  TemplateArgumentLoc(const TemplateArgument &Argument,
477221345Sdim                      NestedNameSpecifierLoc QualifierLoc,
478218893Sdim                      SourceLocation TemplateNameLoc,
479218893Sdim                      SourceLocation EllipsisLoc = SourceLocation())
480327952Sdim      : Argument(Argument),
481327952Sdim        LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
482218893Sdim    assert(Argument.getKind() == TemplateArgument::Template ||
483218893Sdim           Argument.getKind() == TemplateArgument::TemplateExpansion);
484199482Srdivacky  }
485341825Sdim
486341825Sdim  /// - Fetches the primary location of the argument.
487198893Srdivacky  SourceLocation getLocation() const {
488218893Sdim    if (Argument.getKind() == TemplateArgument::Template ||
489218893Sdim        Argument.getKind() == TemplateArgument::TemplateExpansion)
490199482Srdivacky      return getTemplateNameLoc();
491341825Sdim
492198893Srdivacky    return getSourceRange().getBegin();
493198893Srdivacky  }
494198893Srdivacky
495341825Sdim  /// - Fetches the full source range of the argument.
496234353Sdim  SourceRange getSourceRange() const LLVM_READONLY;
497198893Srdivacky
498198893Srdivacky  const TemplateArgument &getArgument() const {
499198893Srdivacky    return Argument;
500198893Srdivacky  }
501198893Srdivacky
502198893Srdivacky  TemplateArgumentLocInfo getLocInfo() const {
503198893Srdivacky    return LocInfo;
504198893Srdivacky  }
505198893Srdivacky
506200583Srdivacky  TypeSourceInfo *getTypeSourceInfo() const {
507198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Type);
508200583Srdivacky    return LocInfo.getAsTypeSourceInfo();
509198893Srdivacky  }
510198893Srdivacky
511198893Srdivacky  Expr *getSourceExpression() const {
512198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Expression);
513198893Srdivacky    return LocInfo.getAsExpr();
514198893Srdivacky  }
515198893Srdivacky
516198893Srdivacky  Expr *getSourceDeclExpression() const {
517198893Srdivacky    assert(Argument.getKind() == TemplateArgument::Declaration);
518198893Srdivacky    return LocInfo.getAsExpr();
519198893Srdivacky  }
520243830Sdim
521243830Sdim  Expr *getSourceNullPtrExpression() const {
522243830Sdim    assert(Argument.getKind() == TemplateArgument::NullPtr);
523243830Sdim    return LocInfo.getAsExpr();
524243830Sdim  }
525243830Sdim
526243830Sdim  Expr *getSourceIntegralExpression() const {
527243830Sdim    assert(Argument.getKind() == TemplateArgument::Integral);
528243830Sdim    return LocInfo.getAsExpr();
529243830Sdim  }
530243830Sdim
531221345Sdim  NestedNameSpecifierLoc getTemplateQualifierLoc() const {
532344779Sdim    if (Argument.getKind() != TemplateArgument::Template &&
533344779Sdim        Argument.getKind() != TemplateArgument::TemplateExpansion)
534344779Sdim      return NestedNameSpecifierLoc();
535221345Sdim    return LocInfo.getTemplateQualifierLoc();
536199482Srdivacky  }
537341825Sdim
538199482Srdivacky  SourceLocation getTemplateNameLoc() const {
539344779Sdim    if (Argument.getKind() != TemplateArgument::Template &&
540344779Sdim        Argument.getKind() != TemplateArgument::TemplateExpansion)
541344779Sdim      return SourceLocation();
542199482Srdivacky    return LocInfo.getTemplateNameLoc();
543341825Sdim  }
544341825Sdim
545218893Sdim  SourceLocation getTemplateEllipsisLoc() const {
546344779Sdim    if (Argument.getKind() != TemplateArgument::TemplateExpansion)
547344779Sdim      return SourceLocation();
548218893Sdim    return LocInfo.getTemplateEllipsisLoc();
549218893Sdim  }
550198893Srdivacky};
551198893Srdivacky
552199990Srdivacky/// A convenient class for passing around template argument
553199990Srdivacky/// information.  Designed to be passed by reference.
554199990Srdivackyclass TemplateArgumentListInfo {
555226633Sdim  SmallVector<TemplateArgumentLoc, 8> Arguments;
556199990Srdivacky  SourceLocation LAngleLoc;
557199990Srdivacky  SourceLocation RAngleLoc;
558199990Srdivacky
559199990Srdivackypublic:
560327952Sdim  TemplateArgumentListInfo() = default;
561199990Srdivacky
562199990Srdivacky  TemplateArgumentListInfo(SourceLocation LAngleLoc,
563199990Srdivacky                           SourceLocation RAngleLoc)
564327952Sdim      : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
565199990Srdivacky
566327952Sdim  // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
567327952Sdim  // instead.
568327952Sdim  void *operator new(size_t bytes, ASTContext &C) = delete;
569327952Sdim
570199990Srdivacky  SourceLocation getLAngleLoc() const { return LAngleLoc; }
571199990Srdivacky  SourceLocation getRAngleLoc() const { return RAngleLoc; }
572199990Srdivacky
573199990Srdivacky  void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
574199990Srdivacky  void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
575199990Srdivacky
576199990Srdivacky  unsigned size() const { return Arguments.size(); }
577199990Srdivacky
578199990Srdivacky  const TemplateArgumentLoc *getArgumentArray() const {
579199990Srdivacky    return Arguments.data();
580199990Srdivacky  }
581199990Srdivacky
582296417Sdim  llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
583296417Sdim    return Arguments;
584296417Sdim  }
585296417Sdim
586199990Srdivacky  const TemplateArgumentLoc &operator[](unsigned I) const {
587199990Srdivacky    return Arguments[I];
588199990Srdivacky  }
589199990Srdivacky
590276479Sdim  TemplateArgumentLoc &operator[](unsigned I) {
591276479Sdim    return Arguments[I];
592276479Sdim  }
593276479Sdim
594199990Srdivacky  void addArgument(const TemplateArgumentLoc &Loc) {
595199990Srdivacky    Arguments.push_back(Loc);
596199990Srdivacky  }
597199990Srdivacky};
598199990Srdivacky
599341825Sdim/// Represents an explicit template argument list in C++, e.g.,
600226633Sdim/// the "<int>" in "sort<int>".
601226633Sdim/// This is safe to be used inside an AST node, in contrast with
602226633Sdim/// TemplateArgumentListInfo.
603296417Sdimstruct ASTTemplateArgumentListInfo final
604296417Sdim    : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
605296417Sdim                                    TemplateArgumentLoc> {
606296417Sdimprivate:
607327952Sdim  friend class ASTNodeImporter;
608296417Sdim  friend TrailingObjects;
609296417Sdim
610296417Sdim  ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
611296417Sdim
612296417Sdimpublic:
613341825Sdim  /// The source location of the left angle bracket ('<').
614226633Sdim  SourceLocation LAngleLoc;
615296417Sdim
616341825Sdim  /// The source location of the right angle bracket ('>').
617226633Sdim  SourceLocation RAngleLoc;
618239462Sdim
619341825Sdim  /// The number of template arguments in TemplateArgs.
620296417Sdim  unsigned NumTemplateArgs;
621239462Sdim
622344779Sdim  SourceLocation getLAngleLoc() const { return LAngleLoc; }
623344779Sdim  SourceLocation getRAngleLoc() const { return RAngleLoc; }
624344779Sdim
625341825Sdim  /// Retrieve the template arguments
626226633Sdim  const TemplateArgumentLoc *getTemplateArgs() const {
627296417Sdim    return getTrailingObjects<TemplateArgumentLoc>();
628226633Sdim  }
629344779Sdim  unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
630226633Sdim
631314564Sdim  llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
632344779Sdim    return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
633314564Sdim  }
634314564Sdim
635226633Sdim  const TemplateArgumentLoc &operator[](unsigned I) const {
636226633Sdim    return getTemplateArgs()[I];
637226633Sdim  }
638226633Sdim
639296417Sdim  static const ASTTemplateArgumentListInfo *
640360784Sdim  Create(const ASTContext &C, const TemplateArgumentListInfo &List);
641226633Sdim};
642226633Sdim
643341825Sdim/// Represents an explicit template argument list in C++, e.g.,
644296417Sdim/// the "<int>" in "sort<int>".
645296417Sdim///
646296417Sdim/// It is intended to be used as a trailing object on AST nodes, and
647296417Sdim/// as such, doesn't contain the array of TemplateArgumentLoc itself,
648296417Sdim/// but expects the containing object to also provide storage for
649296417Sdim/// that.
650314564Sdimstruct alignas(void *) ASTTemplateKWAndArgsInfo {
651341825Sdim  /// The source location of the left angle bracket ('<').
652296417Sdim  SourceLocation LAngleLoc;
653234353Sdim
654341825Sdim  /// The source location of the right angle bracket ('>').
655296417Sdim  SourceLocation RAngleLoc;
656234353Sdim
657341825Sdim  /// The source location of the template keyword; this is used
658296417Sdim  /// as part of the representation of qualified identifiers, such as
659296417Sdim  /// S<T>::template apply<T>.  Will be empty if this expression does
660296417Sdim  /// not have a template keyword.
661296417Sdim  SourceLocation TemplateKWLoc;
662234353Sdim
663341825Sdim  /// The number of template arguments in TemplateArgs.
664296417Sdim  unsigned NumTemplateArgs;
665234353Sdim
666234353Sdim  void initializeFrom(SourceLocation TemplateKWLoc,
667296417Sdim                      const TemplateArgumentListInfo &List,
668296417Sdim                      TemplateArgumentLoc *OutArgArray);
669234353Sdim  void initializeFrom(SourceLocation TemplateKWLoc,
670234353Sdim                      const TemplateArgumentListInfo &List,
671296417Sdim                      TemplateArgumentLoc *OutArgArray, bool &Dependent,
672296417Sdim                      bool &InstantiationDependent,
673234353Sdim                      bool &ContainsUnexpandedParameterPack);
674234353Sdim  void initializeFrom(SourceLocation TemplateKWLoc);
675234353Sdim
676296417Sdim  void copyInto(const TemplateArgumentLoc *ArgArray,
677296417Sdim                TemplateArgumentListInfo &List) const;
678234353Sdim};
679234353Sdim
680208600Srdivackyconst DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
681208600Srdivacky                                    const TemplateArgument &Arg);
682210299Sed
683210299Sedinline TemplateSpecializationType::iterator
684210299Sed    TemplateSpecializationType::end() const {
685210299Sed  return getArgs() + getNumArgs();
686210299Sed}
687210299Sed
688210299Sedinline DependentTemplateSpecializationType::iterator
689210299Sed    DependentTemplateSpecializationType::end() const {
690210299Sed  return getArgs() + getNumArgs();
691210299Sed}
692210299Sed
693210299Sedinline const TemplateArgument &
694210299Sed    TemplateSpecializationType::getArg(unsigned Idx) const {
695210299Sed  assert(Idx < getNumArgs() && "Template argument out of range");
696210299Sed  return getArgs()[Idx];
697210299Sed}
698210299Sed
699210299Sedinline const TemplateArgument &
700210299Sed    DependentTemplateSpecializationType::getArg(unsigned Idx) const {
701210299Sed  assert(Idx < getNumArgs() && "Template argument out of range");
702210299Sed  return getArgs()[Idx];
703210299Sed}
704341825Sdim
705360784Sdiminline const TemplateArgument &AutoType::getArg(unsigned Idx) const {
706360784Sdim  assert(Idx < getNumArgs() && "Template argument out of range");
707360784Sdim  return getArgs()[Idx];
708360784Sdim}
709360784Sdim
710327952Sdim} // namespace clang
711198893Srdivacky
712327952Sdim#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
713