106f32e7eSjoerg //===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //===----------------------------------------------------------------------===//
706f32e7eSjoerg //
806f32e7eSjoerg // This file provides types used in the semantic analysis of C++ templates.
906f32e7eSjoerg //
1006f32e7eSjoerg //===----------------------------------------------------------------------===//
1106f32e7eSjoerg 
1206f32e7eSjoerg #ifndef LLVM_CLANG_SEMA_TEMPLATE_H
1306f32e7eSjoerg #define LLVM_CLANG_SEMA_TEMPLATE_H
1406f32e7eSjoerg 
1506f32e7eSjoerg #include "clang/AST/DeclTemplate.h"
1606f32e7eSjoerg #include "clang/AST/DeclVisitor.h"
1706f32e7eSjoerg #include "clang/AST/TemplateBase.h"
1806f32e7eSjoerg #include "clang/AST/Type.h"
1906f32e7eSjoerg #include "clang/Basic/LLVM.h"
2006f32e7eSjoerg #include "clang/Sema/Sema.h"
2106f32e7eSjoerg #include "llvm/ADT/ArrayRef.h"
2206f32e7eSjoerg #include "llvm/ADT/DenseMap.h"
2306f32e7eSjoerg #include "llvm/ADT/PointerUnion.h"
2406f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
2506f32e7eSjoerg #include <cassert>
2606f32e7eSjoerg #include <utility>
2706f32e7eSjoerg 
2806f32e7eSjoerg namespace clang {
2906f32e7eSjoerg 
3006f32e7eSjoerg class ASTContext;
3106f32e7eSjoerg class BindingDecl;
3206f32e7eSjoerg class CXXMethodDecl;
3306f32e7eSjoerg class Decl;
3406f32e7eSjoerg class DeclaratorDecl;
3506f32e7eSjoerg class DeclContext;
3606f32e7eSjoerg class EnumDecl;
3706f32e7eSjoerg class FunctionDecl;
3806f32e7eSjoerg class NamedDecl;
3906f32e7eSjoerg class ParmVarDecl;
4006f32e7eSjoerg class TagDecl;
4106f32e7eSjoerg class TypedefNameDecl;
4206f32e7eSjoerg class TypeSourceInfo;
4306f32e7eSjoerg class VarDecl;
4406f32e7eSjoerg 
45*13fbcb42Sjoerg /// The kind of template substitution being performed.
46*13fbcb42Sjoerg enum class TemplateSubstitutionKind : char {
47*13fbcb42Sjoerg   /// We are substituting template parameters for template arguments in order
48*13fbcb42Sjoerg   /// to form a template specialization.
49*13fbcb42Sjoerg   Specialization,
50*13fbcb42Sjoerg   /// We are substituting template parameters for (typically) other template
51*13fbcb42Sjoerg   /// parameters in order to rewrite a declaration as a different declaration
52*13fbcb42Sjoerg   /// (for example, when forming a deduction guide from a constructor).
53*13fbcb42Sjoerg   Rewrite,
54*13fbcb42Sjoerg };
55*13fbcb42Sjoerg 
5606f32e7eSjoerg   /// Data structure that captures multiple levels of template argument
5706f32e7eSjoerg   /// lists for use in template instantiation.
5806f32e7eSjoerg   ///
5906f32e7eSjoerg   /// Multiple levels of template arguments occur when instantiating the
6006f32e7eSjoerg   /// definitions of member templates. For example:
6106f32e7eSjoerg   ///
6206f32e7eSjoerg   /// \code
6306f32e7eSjoerg   /// template<typename T>
6406f32e7eSjoerg   /// struct X {
6506f32e7eSjoerg   ///   template<T Value>
6606f32e7eSjoerg   ///   struct Y {
6706f32e7eSjoerg   ///     void f();
6806f32e7eSjoerg   ///   };
6906f32e7eSjoerg   /// };
7006f32e7eSjoerg   /// \endcode
7106f32e7eSjoerg   ///
7206f32e7eSjoerg   /// When instantiating X<int>::Y<17>::f, the multi-level template argument
7306f32e7eSjoerg   /// list will contain a template argument list (int) at depth 0 and a
7406f32e7eSjoerg   /// template argument list (17) at depth 1.
7506f32e7eSjoerg   class MultiLevelTemplateArgumentList {
7606f32e7eSjoerg     /// The template argument list at a certain template depth
7706f32e7eSjoerg     using ArgList = ArrayRef<TemplateArgument>;
7806f32e7eSjoerg 
7906f32e7eSjoerg     /// The template argument lists, stored from the innermost template
8006f32e7eSjoerg     /// argument list (first) to the outermost template argument list (last).
8106f32e7eSjoerg     SmallVector<ArgList, 4> TemplateArgumentLists;
8206f32e7eSjoerg 
8306f32e7eSjoerg     /// The number of outer levels of template arguments that are not
8406f32e7eSjoerg     /// being substituted.
8506f32e7eSjoerg     unsigned NumRetainedOuterLevels = 0;
8606f32e7eSjoerg 
87*13fbcb42Sjoerg     /// The kind of substitution described by this argument list.
88*13fbcb42Sjoerg     TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;
89*13fbcb42Sjoerg 
9006f32e7eSjoerg   public:
9106f32e7eSjoerg     /// Construct an empty set of template argument lists.
9206f32e7eSjoerg     MultiLevelTemplateArgumentList() = default;
9306f32e7eSjoerg 
9406f32e7eSjoerg     /// Construct a single-level template argument list.
9506f32e7eSjoerg     explicit
MultiLevelTemplateArgumentList(const TemplateArgumentList & TemplateArgs)9606f32e7eSjoerg     MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
9706f32e7eSjoerg       addOuterTemplateArguments(&TemplateArgs);
9806f32e7eSjoerg     }
9906f32e7eSjoerg 
setKind(TemplateSubstitutionKind K)100*13fbcb42Sjoerg     void setKind(TemplateSubstitutionKind K) { Kind = K; }
101*13fbcb42Sjoerg 
102*13fbcb42Sjoerg     /// Determine the kind of template substitution being performed.
getKind()103*13fbcb42Sjoerg     TemplateSubstitutionKind getKind() const { return Kind; }
104*13fbcb42Sjoerg 
105*13fbcb42Sjoerg     /// Determine whether we are rewriting template parameters rather than
106*13fbcb42Sjoerg     /// substituting for them. If so, we should not leave references to the
107*13fbcb42Sjoerg     /// original template parameters behind.
isRewrite()108*13fbcb42Sjoerg     bool isRewrite() const {
109*13fbcb42Sjoerg       return Kind == TemplateSubstitutionKind::Rewrite;
110*13fbcb42Sjoerg     }
111*13fbcb42Sjoerg 
11206f32e7eSjoerg     /// Determine the number of levels in this template argument
11306f32e7eSjoerg     /// list.
getNumLevels()11406f32e7eSjoerg     unsigned getNumLevels() const {
11506f32e7eSjoerg       return TemplateArgumentLists.size() + NumRetainedOuterLevels;
11606f32e7eSjoerg     }
11706f32e7eSjoerg 
11806f32e7eSjoerg     /// Determine the number of substituted levels in this template
11906f32e7eSjoerg     /// argument list.
getNumSubstitutedLevels()12006f32e7eSjoerg     unsigned getNumSubstitutedLevels() const {
12106f32e7eSjoerg       return TemplateArgumentLists.size();
12206f32e7eSjoerg     }
12306f32e7eSjoerg 
getNumRetainedOuterLevels()124*13fbcb42Sjoerg     unsigned getNumRetainedOuterLevels() const {
125*13fbcb42Sjoerg       return NumRetainedOuterLevels;
126*13fbcb42Sjoerg     }
127*13fbcb42Sjoerg 
128*13fbcb42Sjoerg     /// Determine how many of the \p OldDepth outermost template parameter
129*13fbcb42Sjoerg     /// lists would be removed by substituting these arguments.
getNewDepth(unsigned OldDepth)130*13fbcb42Sjoerg     unsigned getNewDepth(unsigned OldDepth) const {
131*13fbcb42Sjoerg       if (OldDepth < NumRetainedOuterLevels)
132*13fbcb42Sjoerg         return OldDepth;
133*13fbcb42Sjoerg       if (OldDepth < getNumLevels())
134*13fbcb42Sjoerg         return NumRetainedOuterLevels;
135*13fbcb42Sjoerg       return OldDepth - TemplateArgumentLists.size();
136*13fbcb42Sjoerg     }
137*13fbcb42Sjoerg 
13806f32e7eSjoerg     /// Retrieve the template argument at a given depth and index.
operator()13906f32e7eSjoerg     const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
14006f32e7eSjoerg       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
14106f32e7eSjoerg       assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
14206f32e7eSjoerg       return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
14306f32e7eSjoerg     }
14406f32e7eSjoerg 
14506f32e7eSjoerg     /// Determine whether there is a non-NULL template argument at the
14606f32e7eSjoerg     /// given depth and index.
14706f32e7eSjoerg     ///
14806f32e7eSjoerg     /// There must exist a template argument list at the given depth.
hasTemplateArgument(unsigned Depth,unsigned Index)14906f32e7eSjoerg     bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
15006f32e7eSjoerg       assert(Depth < getNumLevels());
15106f32e7eSjoerg 
15206f32e7eSjoerg       if (Depth < NumRetainedOuterLevels)
15306f32e7eSjoerg         return false;
15406f32e7eSjoerg 
15506f32e7eSjoerg       if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size())
15606f32e7eSjoerg         return false;
15706f32e7eSjoerg 
15806f32e7eSjoerg       return !(*this)(Depth, Index).isNull();
15906f32e7eSjoerg     }
16006f32e7eSjoerg 
16106f32e7eSjoerg     /// Clear out a specific template argument.
setArgument(unsigned Depth,unsigned Index,TemplateArgument Arg)16206f32e7eSjoerg     void setArgument(unsigned Depth, unsigned Index,
16306f32e7eSjoerg                      TemplateArgument Arg) {
16406f32e7eSjoerg       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
16506f32e7eSjoerg       assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
16606f32e7eSjoerg       const_cast<TemplateArgument&>(
16706f32e7eSjoerg                 TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
16806f32e7eSjoerg         = Arg;
16906f32e7eSjoerg     }
17006f32e7eSjoerg 
17106f32e7eSjoerg     /// Add a new outermost level to the multi-level template argument
17206f32e7eSjoerg     /// list.
addOuterTemplateArguments(const TemplateArgumentList * TemplateArgs)17306f32e7eSjoerg     void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
17406f32e7eSjoerg       addOuterTemplateArguments(ArgList(TemplateArgs->data(),
17506f32e7eSjoerg                                         TemplateArgs->size()));
17606f32e7eSjoerg     }
17706f32e7eSjoerg 
17806f32e7eSjoerg     /// Add a new outmost level to the multi-level template argument
17906f32e7eSjoerg     /// list.
addOuterTemplateArguments(ArgList Args)18006f32e7eSjoerg     void addOuterTemplateArguments(ArgList Args) {
18106f32e7eSjoerg       assert(!NumRetainedOuterLevels &&
18206f32e7eSjoerg              "substituted args outside retained args?");
18306f32e7eSjoerg       TemplateArgumentLists.push_back(Args);
18406f32e7eSjoerg     }
18506f32e7eSjoerg 
18606f32e7eSjoerg     /// Add an outermost level that we are not substituting. We have no
18706f32e7eSjoerg     /// arguments at this level, and do not remove it from the depth of inner
18806f32e7eSjoerg     /// template parameters that we instantiate.
addOuterRetainedLevel()18906f32e7eSjoerg     void addOuterRetainedLevel() {
19006f32e7eSjoerg       ++NumRetainedOuterLevels;
19106f32e7eSjoerg     }
addOuterRetainedLevels(unsigned Num)192*13fbcb42Sjoerg     void addOuterRetainedLevels(unsigned Num) {
193*13fbcb42Sjoerg       NumRetainedOuterLevels += Num;
194*13fbcb42Sjoerg     }
19506f32e7eSjoerg 
19606f32e7eSjoerg     /// Retrieve the innermost template argument list.
getInnermost()19706f32e7eSjoerg     const ArgList &getInnermost() const {
19806f32e7eSjoerg       return TemplateArgumentLists.front();
19906f32e7eSjoerg     }
20006f32e7eSjoerg   };
20106f32e7eSjoerg 
20206f32e7eSjoerg   /// The context in which partial ordering of function templates occurs.
20306f32e7eSjoerg   enum TPOC {
20406f32e7eSjoerg     /// Partial ordering of function templates for a function call.
20506f32e7eSjoerg     TPOC_Call,
20606f32e7eSjoerg 
20706f32e7eSjoerg     /// Partial ordering of function templates for a call to a
20806f32e7eSjoerg     /// conversion function.
20906f32e7eSjoerg     TPOC_Conversion,
21006f32e7eSjoerg 
21106f32e7eSjoerg     /// Partial ordering of function templates in other contexts, e.g.,
21206f32e7eSjoerg     /// taking the address of a function template or matching a function
21306f32e7eSjoerg     /// template specialization to a function template.
21406f32e7eSjoerg     TPOC_Other
21506f32e7eSjoerg   };
21606f32e7eSjoerg 
21706f32e7eSjoerg   // This is lame but unavoidable in a world without forward
21806f32e7eSjoerg   // declarations of enums.  The alternatives are to either pollute
21906f32e7eSjoerg   // Sema.h (by including this file) or sacrifice type safety (by
22006f32e7eSjoerg   // making Sema.h declare things as enums).
22106f32e7eSjoerg   class TemplatePartialOrderingContext {
22206f32e7eSjoerg     TPOC Value;
22306f32e7eSjoerg 
22406f32e7eSjoerg   public:
TemplatePartialOrderingContext(TPOC Value)22506f32e7eSjoerg     TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
22606f32e7eSjoerg 
TPOC()22706f32e7eSjoerg     operator TPOC() const { return Value; }
22806f32e7eSjoerg   };
22906f32e7eSjoerg 
23006f32e7eSjoerg   /// Captures a template argument whose value has been deduced
23106f32e7eSjoerg   /// via c++ template argument deduction.
23206f32e7eSjoerg   class DeducedTemplateArgument : public TemplateArgument {
23306f32e7eSjoerg     /// For a non-type template argument, whether the value was
23406f32e7eSjoerg     /// deduced from an array bound.
23506f32e7eSjoerg     bool DeducedFromArrayBound = false;
23606f32e7eSjoerg 
23706f32e7eSjoerg   public:
23806f32e7eSjoerg     DeducedTemplateArgument() = default;
23906f32e7eSjoerg 
24006f32e7eSjoerg     DeducedTemplateArgument(const TemplateArgument &Arg,
24106f32e7eSjoerg                             bool DeducedFromArrayBound = false)
TemplateArgument(Arg)24206f32e7eSjoerg         : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}
24306f32e7eSjoerg 
24406f32e7eSjoerg     /// Construct an integral non-type template argument that
24506f32e7eSjoerg     /// has been deduced, possibly from an array bound.
DeducedTemplateArgument(ASTContext & Ctx,const llvm::APSInt & Value,QualType ValueType,bool DeducedFromArrayBound)24606f32e7eSjoerg     DeducedTemplateArgument(ASTContext &Ctx,
24706f32e7eSjoerg                             const llvm::APSInt &Value,
24806f32e7eSjoerg                             QualType ValueType,
24906f32e7eSjoerg                             bool DeducedFromArrayBound)
25006f32e7eSjoerg         : TemplateArgument(Ctx, Value, ValueType),
25106f32e7eSjoerg           DeducedFromArrayBound(DeducedFromArrayBound) {}
25206f32e7eSjoerg 
25306f32e7eSjoerg     /// For a non-type template argument, determine whether the
25406f32e7eSjoerg     /// template argument was deduced from an array bound.
wasDeducedFromArrayBound()25506f32e7eSjoerg     bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
25606f32e7eSjoerg 
25706f32e7eSjoerg     /// Specify whether the given non-type template argument
25806f32e7eSjoerg     /// was deduced from an array bound.
setDeducedFromArrayBound(bool Deduced)25906f32e7eSjoerg     void setDeducedFromArrayBound(bool Deduced) {
26006f32e7eSjoerg       DeducedFromArrayBound = Deduced;
26106f32e7eSjoerg     }
26206f32e7eSjoerg   };
26306f32e7eSjoerg 
26406f32e7eSjoerg   /// A stack-allocated class that identifies which local
26506f32e7eSjoerg   /// variable declaration instantiations are present in this scope.
26606f32e7eSjoerg   ///
26706f32e7eSjoerg   /// A new instance of this class type will be created whenever we
26806f32e7eSjoerg   /// instantiate a new function declaration, which will have its own
26906f32e7eSjoerg   /// set of parameter declarations.
27006f32e7eSjoerg   class LocalInstantiationScope {
27106f32e7eSjoerg   public:
27206f32e7eSjoerg     /// A set of declarations.
27306f32e7eSjoerg     using DeclArgumentPack = SmallVector<VarDecl *, 4>;
27406f32e7eSjoerg 
27506f32e7eSjoerg   private:
27606f32e7eSjoerg     /// Reference to the semantic analysis that is performing
27706f32e7eSjoerg     /// this template instantiation.
27806f32e7eSjoerg     Sema &SemaRef;
27906f32e7eSjoerg 
28006f32e7eSjoerg     using LocalDeclsMap =
28106f32e7eSjoerg         llvm::SmallDenseMap<const Decl *,
28206f32e7eSjoerg                             llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
28306f32e7eSjoerg 
28406f32e7eSjoerg     /// A mapping from local declarations that occur
28506f32e7eSjoerg     /// within a template to their instantiations.
28606f32e7eSjoerg     ///
28706f32e7eSjoerg     /// This mapping is used during instantiation to keep track of,
28806f32e7eSjoerg     /// e.g., function parameter and variable declarations. For example,
28906f32e7eSjoerg     /// given:
29006f32e7eSjoerg     ///
29106f32e7eSjoerg     /// \code
29206f32e7eSjoerg     ///   template<typename T> T add(T x, T y) { return x + y; }
29306f32e7eSjoerg     /// \endcode
29406f32e7eSjoerg     ///
29506f32e7eSjoerg     /// when we instantiate add<int>, we will introduce a mapping from
29606f32e7eSjoerg     /// the ParmVarDecl for 'x' that occurs in the template to the
29706f32e7eSjoerg     /// instantiated ParmVarDecl for 'x'.
29806f32e7eSjoerg     ///
29906f32e7eSjoerg     /// For a parameter pack, the local instantiation scope may contain a
30006f32e7eSjoerg     /// set of instantiated parameters. This is stored as a DeclArgumentPack
30106f32e7eSjoerg     /// pointer.
30206f32e7eSjoerg     LocalDeclsMap LocalDecls;
30306f32e7eSjoerg 
30406f32e7eSjoerg     /// The set of argument packs we've allocated.
30506f32e7eSjoerg     SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
30606f32e7eSjoerg 
30706f32e7eSjoerg     /// The outer scope, which contains local variable
30806f32e7eSjoerg     /// definitions from some other instantiation (that may not be
30906f32e7eSjoerg     /// relevant to this particular scope).
31006f32e7eSjoerg     LocalInstantiationScope *Outer;
31106f32e7eSjoerg 
31206f32e7eSjoerg     /// Whether we have already exited this scope.
31306f32e7eSjoerg     bool Exited = false;
31406f32e7eSjoerg 
31506f32e7eSjoerg     /// Whether to combine this scope with the outer scope, such that
31606f32e7eSjoerg     /// lookup will search our outer scope.
31706f32e7eSjoerg     bool CombineWithOuterScope;
31806f32e7eSjoerg 
31906f32e7eSjoerg     /// If non-NULL, the template parameter pack that has been
32006f32e7eSjoerg     /// partially substituted per C++0x [temp.arg.explicit]p9.
32106f32e7eSjoerg     NamedDecl *PartiallySubstitutedPack = nullptr;
32206f32e7eSjoerg 
32306f32e7eSjoerg     /// If \c PartiallySubstitutedPack is non-null, the set of
32406f32e7eSjoerg     /// explicitly-specified template arguments in that pack.
32506f32e7eSjoerg     const TemplateArgument *ArgsInPartiallySubstitutedPack;
32606f32e7eSjoerg 
32706f32e7eSjoerg     /// If \c PartiallySubstitutedPack, the number of
32806f32e7eSjoerg     /// explicitly-specified template arguments in
32906f32e7eSjoerg     /// ArgsInPartiallySubstitutedPack.
33006f32e7eSjoerg     unsigned NumArgsInPartiallySubstitutedPack;
33106f32e7eSjoerg 
33206f32e7eSjoerg   public:
33306f32e7eSjoerg     LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
SemaRef(SemaRef)33406f32e7eSjoerg         : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
33506f32e7eSjoerg           CombineWithOuterScope(CombineWithOuterScope) {
33606f32e7eSjoerg       SemaRef.CurrentInstantiationScope = this;
33706f32e7eSjoerg     }
33806f32e7eSjoerg 
33906f32e7eSjoerg     LocalInstantiationScope(const LocalInstantiationScope &) = delete;
34006f32e7eSjoerg     LocalInstantiationScope &
34106f32e7eSjoerg     operator=(const LocalInstantiationScope &) = delete;
34206f32e7eSjoerg 
~LocalInstantiationScope()34306f32e7eSjoerg     ~LocalInstantiationScope() {
34406f32e7eSjoerg       Exit();
34506f32e7eSjoerg     }
34606f32e7eSjoerg 
getSema()34706f32e7eSjoerg     const Sema &getSema() const { return SemaRef; }
34806f32e7eSjoerg 
34906f32e7eSjoerg     /// Exit this local instantiation scope early.
Exit()35006f32e7eSjoerg     void Exit() {
35106f32e7eSjoerg       if (Exited)
35206f32e7eSjoerg         return;
35306f32e7eSjoerg 
35406f32e7eSjoerg       for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
35506f32e7eSjoerg         delete ArgumentPacks[I];
35606f32e7eSjoerg 
35706f32e7eSjoerg       SemaRef.CurrentInstantiationScope = Outer;
35806f32e7eSjoerg       Exited = true;
35906f32e7eSjoerg     }
36006f32e7eSjoerg 
36106f32e7eSjoerg     /// Clone this scope, and all outer scopes, down to the given
36206f32e7eSjoerg     /// outermost scope.
cloneScopes(LocalInstantiationScope * Outermost)36306f32e7eSjoerg     LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
36406f32e7eSjoerg       if (this == Outermost) return this;
36506f32e7eSjoerg 
36606f32e7eSjoerg       // Save the current scope from SemaRef since the LocalInstantiationScope
36706f32e7eSjoerg       // will overwrite it on construction
36806f32e7eSjoerg       LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
36906f32e7eSjoerg 
37006f32e7eSjoerg       LocalInstantiationScope *newScope =
37106f32e7eSjoerg         new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
37206f32e7eSjoerg 
37306f32e7eSjoerg       newScope->Outer = nullptr;
37406f32e7eSjoerg       if (Outer)
37506f32e7eSjoerg         newScope->Outer = Outer->cloneScopes(Outermost);
37606f32e7eSjoerg 
37706f32e7eSjoerg       newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
37806f32e7eSjoerg       newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
37906f32e7eSjoerg       newScope->NumArgsInPartiallySubstitutedPack =
38006f32e7eSjoerg         NumArgsInPartiallySubstitutedPack;
38106f32e7eSjoerg 
38206f32e7eSjoerg       for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
38306f32e7eSjoerg            I != E; ++I) {
38406f32e7eSjoerg         const Decl *D = I->first;
38506f32e7eSjoerg         llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
38606f32e7eSjoerg           newScope->LocalDecls[D];
38706f32e7eSjoerg         if (I->second.is<Decl *>()) {
38806f32e7eSjoerg           Stored = I->second.get<Decl *>();
38906f32e7eSjoerg         } else {
39006f32e7eSjoerg           DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
39106f32e7eSjoerg           DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
39206f32e7eSjoerg           Stored = NewPack;
39306f32e7eSjoerg           newScope->ArgumentPacks.push_back(NewPack);
39406f32e7eSjoerg         }
39506f32e7eSjoerg       }
39606f32e7eSjoerg       // Restore the saved scope to SemaRef
39706f32e7eSjoerg       SemaRef.CurrentInstantiationScope = oldScope;
39806f32e7eSjoerg       return newScope;
39906f32e7eSjoerg     }
40006f32e7eSjoerg 
40106f32e7eSjoerg     /// deletes the given scope, and all otuer scopes, down to the
40206f32e7eSjoerg     /// given outermost scope.
deleteScopes(LocalInstantiationScope * Scope,LocalInstantiationScope * Outermost)40306f32e7eSjoerg     static void deleteScopes(LocalInstantiationScope *Scope,
40406f32e7eSjoerg                              LocalInstantiationScope *Outermost) {
40506f32e7eSjoerg       while (Scope && Scope != Outermost) {
40606f32e7eSjoerg         LocalInstantiationScope *Out = Scope->Outer;
40706f32e7eSjoerg         delete Scope;
40806f32e7eSjoerg         Scope = Out;
40906f32e7eSjoerg       }
41006f32e7eSjoerg     }
41106f32e7eSjoerg 
41206f32e7eSjoerg     /// Find the instantiation of the declaration D within the current
41306f32e7eSjoerg     /// instantiation scope.
41406f32e7eSjoerg     ///
41506f32e7eSjoerg     /// \param D The declaration whose instantiation we are searching for.
41606f32e7eSjoerg     ///
41706f32e7eSjoerg     /// \returns A pointer to the declaration or argument pack of declarations
41806f32e7eSjoerg     /// to which the declaration \c D is instantiated, if found. Otherwise,
41906f32e7eSjoerg     /// returns NULL.
42006f32e7eSjoerg     llvm::PointerUnion<Decl *, DeclArgumentPack *> *
42106f32e7eSjoerg     findInstantiationOf(const Decl *D);
42206f32e7eSjoerg 
42306f32e7eSjoerg     void InstantiatedLocal(const Decl *D, Decl *Inst);
42406f32e7eSjoerg     void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
42506f32e7eSjoerg     void MakeInstantiatedLocalArgPack(const Decl *D);
42606f32e7eSjoerg 
42706f32e7eSjoerg     /// Note that the given parameter pack has been partially substituted
42806f32e7eSjoerg     /// via explicit specification of template arguments
42906f32e7eSjoerg     /// (C++0x [temp.arg.explicit]p9).
43006f32e7eSjoerg     ///
43106f32e7eSjoerg     /// \param Pack The parameter pack, which will always be a template
43206f32e7eSjoerg     /// parameter pack.
43306f32e7eSjoerg     ///
43406f32e7eSjoerg     /// \param ExplicitArgs The explicitly-specified template arguments provided
43506f32e7eSjoerg     /// for this parameter pack.
43606f32e7eSjoerg     ///
43706f32e7eSjoerg     /// \param NumExplicitArgs The number of explicitly-specified template
43806f32e7eSjoerg     /// arguments provided for this parameter pack.
43906f32e7eSjoerg     void SetPartiallySubstitutedPack(NamedDecl *Pack,
44006f32e7eSjoerg                                      const TemplateArgument *ExplicitArgs,
44106f32e7eSjoerg                                      unsigned NumExplicitArgs);
44206f32e7eSjoerg 
44306f32e7eSjoerg     /// Reset the partially-substituted pack when it is no longer of
44406f32e7eSjoerg     /// interest.
ResetPartiallySubstitutedPack()44506f32e7eSjoerg     void ResetPartiallySubstitutedPack() {
44606f32e7eSjoerg       assert(PartiallySubstitutedPack && "No partially-substituted pack");
44706f32e7eSjoerg       PartiallySubstitutedPack = nullptr;
44806f32e7eSjoerg       ArgsInPartiallySubstitutedPack = nullptr;
44906f32e7eSjoerg       NumArgsInPartiallySubstitutedPack = 0;
45006f32e7eSjoerg     }
45106f32e7eSjoerg 
45206f32e7eSjoerg     /// Retrieve the partially-substitued template parameter pack.
45306f32e7eSjoerg     ///
45406f32e7eSjoerg     /// If there is no partially-substituted parameter pack, returns NULL.
45506f32e7eSjoerg     NamedDecl *
45606f32e7eSjoerg     getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
45706f32e7eSjoerg                                 unsigned *NumExplicitArgs = nullptr) const;
458*13fbcb42Sjoerg 
459*13fbcb42Sjoerg     /// Determine whether D is a pack expansion created in this scope.
460*13fbcb42Sjoerg     bool isLocalPackExpansion(const Decl *D);
46106f32e7eSjoerg   };
46206f32e7eSjoerg 
46306f32e7eSjoerg   class TemplateDeclInstantiator
46406f32e7eSjoerg     : public DeclVisitor<TemplateDeclInstantiator, Decl *>
46506f32e7eSjoerg   {
46606f32e7eSjoerg     Sema &SemaRef;
46706f32e7eSjoerg     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
46806f32e7eSjoerg     DeclContext *Owner;
46906f32e7eSjoerg     const MultiLevelTemplateArgumentList &TemplateArgs;
47006f32e7eSjoerg     Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
47106f32e7eSjoerg     LocalInstantiationScope *StartingScope = nullptr;
47206f32e7eSjoerg 
47306f32e7eSjoerg     /// A list of out-of-line class template partial
47406f32e7eSjoerg     /// specializations that will need to be instantiated after the
47506f32e7eSjoerg     /// enclosing class's instantiation is complete.
47606f32e7eSjoerg     SmallVector<std::pair<ClassTemplateDecl *,
47706f32e7eSjoerg                                 ClassTemplatePartialSpecializationDecl *>, 4>
47806f32e7eSjoerg       OutOfLinePartialSpecs;
47906f32e7eSjoerg 
48006f32e7eSjoerg     /// A list of out-of-line variable template partial
48106f32e7eSjoerg     /// specializations that will need to be instantiated after the
48206f32e7eSjoerg     /// enclosing variable's instantiation is complete.
48306f32e7eSjoerg     /// FIXME: Verify that this is needed.
48406f32e7eSjoerg     SmallVector<
48506f32e7eSjoerg         std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
48606f32e7eSjoerg     OutOfLineVarPartialSpecs;
48706f32e7eSjoerg 
48806f32e7eSjoerg   public:
TemplateDeclInstantiator(Sema & SemaRef,DeclContext * Owner,const MultiLevelTemplateArgumentList & TemplateArgs)48906f32e7eSjoerg     TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
49006f32e7eSjoerg                              const MultiLevelTemplateArgumentList &TemplateArgs)
49106f32e7eSjoerg         : SemaRef(SemaRef),
49206f32e7eSjoerg           SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
49306f32e7eSjoerg           Owner(Owner), TemplateArgs(TemplateArgs) {}
49406f32e7eSjoerg 
49506f32e7eSjoerg // Define all the decl visitors using DeclNodes.inc
49606f32e7eSjoerg #define DECL(DERIVED, BASE) \
49706f32e7eSjoerg     Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
49806f32e7eSjoerg #define ABSTRACT_DECL(DECL)
49906f32e7eSjoerg 
50006f32e7eSjoerg // Decls which never appear inside a class or function.
50106f32e7eSjoerg #define OBJCCONTAINER(DERIVED, BASE)
50206f32e7eSjoerg #define FILESCOPEASM(DERIVED, BASE)
50306f32e7eSjoerg #define IMPORT(DERIVED, BASE)
50406f32e7eSjoerg #define EXPORT(DERIVED, BASE)
50506f32e7eSjoerg #define LINKAGESPEC(DERIVED, BASE)
50606f32e7eSjoerg #define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
50706f32e7eSjoerg #define OBJCMETHOD(DERIVED, BASE)
50806f32e7eSjoerg #define OBJCTYPEPARAM(DERIVED, BASE)
50906f32e7eSjoerg #define OBJCIVAR(DERIVED, BASE)
51006f32e7eSjoerg #define OBJCPROPERTY(DERIVED, BASE)
51106f32e7eSjoerg #define OBJCPROPERTYIMPL(DERIVED, BASE)
51206f32e7eSjoerg #define EMPTY(DERIVED, BASE)
513*13fbcb42Sjoerg #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
51406f32e7eSjoerg 
51506f32e7eSjoerg     // Decls which use special-case instantiation code.
51606f32e7eSjoerg #define BLOCK(DERIVED, BASE)
51706f32e7eSjoerg #define CAPTURED(DERIVED, BASE)
51806f32e7eSjoerg #define IMPLICITPARAM(DERIVED, BASE)
51906f32e7eSjoerg 
52006f32e7eSjoerg #include "clang/AST/DeclNodes.inc"
52106f32e7eSjoerg 
522*13fbcb42Sjoerg     enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual };
523*13fbcb42Sjoerg 
524*13fbcb42Sjoerg     void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T,
525*13fbcb42Sjoerg                           TypeSourceInfo *&TInfo,
526*13fbcb42Sjoerg                           DeclarationNameInfo &NameInfo);
527*13fbcb42Sjoerg 
52806f32e7eSjoerg     // A few supplemental visitor functions.
52906f32e7eSjoerg     Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
53006f32e7eSjoerg                              TemplateParameterList *TemplateParams,
53106f32e7eSjoerg                              Optional<const ASTTemplateArgumentListInfo *>
532*13fbcb42Sjoerg                                  ClassScopeSpecializationArgs = llvm::None,
533*13fbcb42Sjoerg                              RewriteKind RK = RewriteKind::None);
53406f32e7eSjoerg     Decl *VisitFunctionDecl(FunctionDecl *D,
535*13fbcb42Sjoerg                             TemplateParameterList *TemplateParams,
536*13fbcb42Sjoerg                             RewriteKind RK = RewriteKind::None);
53706f32e7eSjoerg     Decl *VisitDecl(Decl *D);
53806f32e7eSjoerg     Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
53906f32e7eSjoerg                        ArrayRef<BindingDecl *> *Bindings = nullptr);
54006f32e7eSjoerg 
54106f32e7eSjoerg     // Enable late instantiation of attributes.  Late instantiated attributes
54206f32e7eSjoerg     // will be stored in LA.
enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec * LA)54306f32e7eSjoerg     void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
54406f32e7eSjoerg       LateAttrs = LA;
54506f32e7eSjoerg       StartingScope = SemaRef.CurrentInstantiationScope;
54606f32e7eSjoerg     }
54706f32e7eSjoerg 
54806f32e7eSjoerg     // Disable late instantiation of attributes.
disableLateAttributeInstantiation()54906f32e7eSjoerg     void disableLateAttributeInstantiation() {
55006f32e7eSjoerg       LateAttrs = nullptr;
55106f32e7eSjoerg       StartingScope = nullptr;
55206f32e7eSjoerg     }
55306f32e7eSjoerg 
getStartingScope()55406f32e7eSjoerg     LocalInstantiationScope *getStartingScope() const { return StartingScope; }
55506f32e7eSjoerg 
55606f32e7eSjoerg     using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
55706f32e7eSjoerg       ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;
55806f32e7eSjoerg 
55906f32e7eSjoerg     using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
56006f32e7eSjoerg         VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;
56106f32e7eSjoerg 
56206f32e7eSjoerg     /// Return an iterator to the beginning of the set of
56306f32e7eSjoerg     /// "delayed" partial specializations, which must be passed to
56406f32e7eSjoerg     /// InstantiateClassTemplatePartialSpecialization once the class
56506f32e7eSjoerg     /// definition has been completed.
delayed_partial_spec_begin()56606f32e7eSjoerg     delayed_partial_spec_iterator delayed_partial_spec_begin() {
56706f32e7eSjoerg       return OutOfLinePartialSpecs.begin();
56806f32e7eSjoerg     }
56906f32e7eSjoerg 
delayed_var_partial_spec_begin()57006f32e7eSjoerg     delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
57106f32e7eSjoerg       return OutOfLineVarPartialSpecs.begin();
57206f32e7eSjoerg     }
57306f32e7eSjoerg 
57406f32e7eSjoerg     /// Return an iterator to the end of the set of
57506f32e7eSjoerg     /// "delayed" partial specializations, which must be passed to
57606f32e7eSjoerg     /// InstantiateClassTemplatePartialSpecialization once the class
57706f32e7eSjoerg     /// definition has been completed.
delayed_partial_spec_end()57806f32e7eSjoerg     delayed_partial_spec_iterator delayed_partial_spec_end() {
57906f32e7eSjoerg       return OutOfLinePartialSpecs.end();
58006f32e7eSjoerg     }
58106f32e7eSjoerg 
delayed_var_partial_spec_end()58206f32e7eSjoerg     delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
58306f32e7eSjoerg       return OutOfLineVarPartialSpecs.end();
58406f32e7eSjoerg     }
58506f32e7eSjoerg 
58606f32e7eSjoerg     // Helper functions for instantiating methods.
58706f32e7eSjoerg     TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
58806f32e7eSjoerg                              SmallVectorImpl<ParmVarDecl *> &Params);
58906f32e7eSjoerg     bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
59006f32e7eSjoerg     bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
59106f32e7eSjoerg 
592*13fbcb42Sjoerg     bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl);
593*13fbcb42Sjoerg 
59406f32e7eSjoerg     TemplateParameterList *
59506f32e7eSjoerg       SubstTemplateParams(TemplateParameterList *List);
59606f32e7eSjoerg 
59706f32e7eSjoerg     bool SubstQualifier(const DeclaratorDecl *OldDecl,
59806f32e7eSjoerg                         DeclaratorDecl *NewDecl);
59906f32e7eSjoerg     bool SubstQualifier(const TagDecl *OldDecl,
60006f32e7eSjoerg                         TagDecl *NewDecl);
60106f32e7eSjoerg 
60206f32e7eSjoerg     Decl *VisitVarTemplateSpecializationDecl(
603*13fbcb42Sjoerg         VarTemplateDecl *VarTemplate, VarDecl *FromVar,
60406f32e7eSjoerg         const TemplateArgumentListInfo &TemplateArgsInfo,
60506f32e7eSjoerg         ArrayRef<TemplateArgument> Converted,
60606f32e7eSjoerg         VarTemplateSpecializationDecl *PrevDecl = nullptr);
60706f32e7eSjoerg 
60806f32e7eSjoerg     Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
60906f32e7eSjoerg     ClassTemplatePartialSpecializationDecl *
61006f32e7eSjoerg     InstantiateClassTemplatePartialSpecialization(
61106f32e7eSjoerg                                               ClassTemplateDecl *ClassTemplate,
61206f32e7eSjoerg                            ClassTemplatePartialSpecializationDecl *PartialSpec);
61306f32e7eSjoerg     VarTemplatePartialSpecializationDecl *
61406f32e7eSjoerg     InstantiateVarTemplatePartialSpecialization(
61506f32e7eSjoerg         VarTemplateDecl *VarTemplate,
61606f32e7eSjoerg         VarTemplatePartialSpecializationDecl *PartialSpec);
61706f32e7eSjoerg     void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
61806f32e7eSjoerg 
61906f32e7eSjoerg   private:
62006f32e7eSjoerg     template<typename T>
62106f32e7eSjoerg     Decl *instantiateUnresolvedUsingDecl(T *D,
62206f32e7eSjoerg                                          bool InstantiatingPackElement = false);
62306f32e7eSjoerg   };
62406f32e7eSjoerg 
62506f32e7eSjoerg } // namespace clang
62606f32e7eSjoerg 
62706f32e7eSjoerg #endif // LLVM_CLANG_SEMA_TEMPLATE_H
628