//===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//===----------------------------------------------------------------------===//
//
// This file provides types used in the semantic analysis of C++ templates.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
#define LLVM_CLANG_SEMA_TEMPLATE_H

#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <optional>
#include <utility>

namespace clang {

class ASTContext;
class BindingDecl;
class CXXMethodDecl;
class Decl;
class DeclaratorDecl;
class DeclContext;
class EnumDecl;
class FunctionDecl;
class NamedDecl;
class ParmVarDecl;
class TagDecl;
class TypedefNameDecl;
class TypeSourceInfo;
class VarDecl;

/// The kind of template substitution being performed.
enum class TemplateSubstitutionKind : char {
  /// We are substituting template parameters for template arguments in order
  /// to form a template specialization.
  Specialization,
  /// We are substituting template parameters for (typically) other template
  /// parameters in order to rewrite a declaration as a different declaration
  /// (for example, when forming a deduction guide from a constructor).
  Rewrite,
};

  /// Data structure that captures multiple levels of template argument
  /// lists for use in template instantiation.
  ///
  /// Multiple levels of template arguments occur when instantiating the
  /// definitions of member templates. For example:
  ///
  /// \code
  /// template<typename T>
  /// struct X {
  ///   template<T Value>
  ///   struct Y {
  ///     void f();
  ///   };
  /// };
  /// \endcode
  ///
  /// When instantiating X<int>::Y<17>::f, the multi-level template argument
  /// list will contain a template argument list (int) at depth 0 and a
  /// template argument list (17) at depth 1.
  class MultiLevelTemplateArgumentList {
    /// The template argument list at a certain template depth

    using ArgList = ArrayRef<TemplateArgument>;
    struct ArgumentListLevel {
      llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
      ArgList Args;
    };
    using ContainerType = SmallVector<ArgumentListLevel, 4>;

    using ArgListsIterator = ContainerType::iterator;
    using ConstArgListsIterator = ContainerType::const_iterator;

    /// The template argument lists, stored from the innermost template
    /// argument list (first) to the outermost template argument list (last).
    ContainerType TemplateArgumentLists;

    /// The number of outer levels of template arguments that are not
    /// being substituted.
    unsigned NumRetainedOuterLevels = 0;

    /// The kind of substitution described by this argument list.
    TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;

  public:
    /// Construct an empty set of template argument lists.
    MultiLevelTemplateArgumentList() = default;

    /// Construct a single-level template argument list.
    MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
      addOuterTemplateArguments(D, Args, Final);
    }

    void setKind(TemplateSubstitutionKind K) { Kind = K; }

    /// Determine the kind of template substitution being performed.
    TemplateSubstitutionKind getKind() const { return Kind; }

    /// Determine whether we are rewriting template parameters rather than
    /// substituting for them. If so, we should not leave references to the
    /// original template parameters behind.
    bool isRewrite() const {
      return Kind == TemplateSubstitutionKind::Rewrite;
    }

    /// Determine the number of levels in this template argument
    /// list.
    unsigned getNumLevels() const {
      return TemplateArgumentLists.size() + NumRetainedOuterLevels;
    }

    /// Determine the number of substituted levels in this template
    /// argument list.
    unsigned getNumSubstitutedLevels() const {
      return TemplateArgumentLists.size();
    }

    // Determine the number of substituted args at 'Depth'.
    unsigned getNumSubsitutedArgs(unsigned Depth) const {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
    }

    unsigned getNumRetainedOuterLevels() const {
      return NumRetainedOuterLevels;
    }

    /// Determine how many of the \p OldDepth outermost template parameter
    /// lists would be removed by substituting these arguments.
    unsigned getNewDepth(unsigned OldDepth) const {
      if (OldDepth < NumRetainedOuterLevels)
        return OldDepth;
      if (OldDepth < getNumLevels())
        return NumRetainedOuterLevels;
      return OldDepth - TemplateArgumentLists.size();
    }

    /// Retrieve the template argument at a given depth and index.
    const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      assert(Index <
             TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
      return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
    }

    /// A template-like entity which owns the whole pattern being substituted.
    /// This will usually own a set of template parameters, or in some
    /// cases might even be a template parameter itself.
    std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
                    .AssociatedDeclAndFinal;
      return {AD.getPointer(), AD.getInt()};
    }

    /// Determine whether there is a non-NULL template argument at the
    /// given depth and index.
    ///
    /// There must exist a template argument list at the given depth.
    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
      assert(Depth < getNumLevels());

      if (Depth < NumRetainedOuterLevels)
        return false;

      if (Index >=
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
        return false;

      return !(*this)(Depth, Index).isNull();
    }

    bool isAnyArgInstantiationDependent() const {
      for (ArgumentListLevel ListLevel : TemplateArgumentLists)
        for (const TemplateArgument &TA : ListLevel.Args)
          if (TA.isInstantiationDependent())
            return true;
      return false;
    }

    /// Clear out a specific template argument.
    void setArgument(unsigned Depth, unsigned Index,
                     TemplateArgument Arg) {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      assert(Index <
             TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
      const_cast<TemplateArgument &>(
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
    }

    /// Add a new outmost level to the multi-level template argument
    /// list.
    /// A 'Final' substitution means that Subst* nodes won't be built
    /// for the replacements.
    void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
                                   bool Final) {
      assert(!NumRetainedOuterLevels &&
             "substituted args outside retained args?");
      assert(getKind() == TemplateSubstitutionKind::Specialization);
      TemplateArgumentLists.push_back(
          {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
            Final},
           Args});
    }

    void addOuterTemplateArguments(ArgList Args) {
      assert(!NumRetainedOuterLevels &&
             "substituted args outside retained args?");
      assert(getKind() == TemplateSubstitutionKind::Rewrite);
      TemplateArgumentLists.push_back({{}, Args});
    }

    void addOuterTemplateArguments(std::nullopt_t) {
      assert(!NumRetainedOuterLevels &&
             "substituted args outside retained args?");
      TemplateArgumentLists.push_back({});
    }

    /// Replaces the current 'innermost' level with the provided argument list.
    /// This is useful for type deduction cases where we need to get the entire
    /// list from the AST, but then add the deduced innermost list.
    void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
      assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
             "Replacing in an empty list?");

      if (!TemplateArgumentLists.empty()) {
        assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
                TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
                    AssociatedDecl) &&
               "Trying to change incorrect declaration?");
        TemplateArgumentLists[0].Args = Args;
      } else {
        --NumRetainedOuterLevels;
        TemplateArgumentLists.push_back(
            {{AssociatedDecl, /*Final=*/false}, Args});
      }
    }

    /// Add an outermost level that we are not substituting. We have no
    /// arguments at this level, and do not remove it from the depth of inner
    /// template parameters that we instantiate.
    void addOuterRetainedLevel() {
      ++NumRetainedOuterLevels;
    }
    void addOuterRetainedLevels(unsigned Num) {
      NumRetainedOuterLevels += Num;
    }

    /// Retrieve the innermost template argument list.
    const ArgList &getInnermost() const {
      return TemplateArgumentLists.front().Args;
    }
    /// Retrieve the outermost template argument list.
    const ArgList &getOutermost() const {
      return TemplateArgumentLists.back().Args;
    }
    ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
    ConstArgListsIterator begin() const {
      return TemplateArgumentLists.begin();
    }
    ArgListsIterator end() { return TemplateArgumentLists.end(); }
    ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }

    LLVM_DUMP_METHOD void dump() const {
      LangOptions LO;
      LO.CPlusPlus = true;
      LO.Bool = true;
      PrintingPolicy PP(LO);
      llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
                   << "\n";
      for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
           ++Depth) {
        llvm::errs() << Depth << ": ";
        printTemplateArgumentList(
            llvm::errs(),
            TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
        llvm::errs() << "\n";
      }
    }
  };

  /// The context in which partial ordering of function templates occurs.
  enum TPOC {
    /// Partial ordering of function templates for a function call.
    TPOC_Call,

    /// Partial ordering of function templates for a call to a
    /// conversion function.
    TPOC_Conversion,

    /// Partial ordering of function templates in other contexts, e.g.,
    /// taking the address of a function template or matching a function
    /// template specialization to a function template.
    TPOC_Other
  };

  // This is lame but unavoidable in a world without forward
  // declarations of enums.  The alternatives are to either pollute
  // Sema.h (by including this file) or sacrifice type safety (by
  // making Sema.h declare things as enums).
  class TemplatePartialOrderingContext {
    TPOC Value;

  public:
    TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}

    operator TPOC() const { return Value; }
  };

  /// Captures a template argument whose value has been deduced
  /// via c++ template argument deduction.
  class DeducedTemplateArgument : public TemplateArgument {
    /// For a non-type template argument, whether the value was
    /// deduced from an array bound.
    bool DeducedFromArrayBound = false;

  public:
    DeducedTemplateArgument() = default;

    DeducedTemplateArgument(const TemplateArgument &Arg,
                            bool DeducedFromArrayBound = false)
        : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}

    /// Construct an integral non-type template argument that
    /// has been deduced, possibly from an array bound.
    DeducedTemplateArgument(ASTContext &Ctx,
                            const llvm::APSInt &Value,
                            QualType ValueType,
                            bool DeducedFromArrayBound)
        : TemplateArgument(Ctx, Value, ValueType),
          DeducedFromArrayBound(DeducedFromArrayBound) {}

    /// For a non-type template argument, determine whether the
    /// template argument was deduced from an array bound.
    bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }

    /// Specify whether the given non-type template argument
    /// was deduced from an array bound.
    void setDeducedFromArrayBound(bool Deduced) {
      DeducedFromArrayBound = Deduced;
    }
  };

  /// A stack-allocated class that identifies which local
  /// variable declaration instantiations are present in this scope.
  ///
  /// A new instance of this class type will be created whenever we
  /// instantiate a new function declaration, which will have its own
  /// set of parameter declarations.
  class LocalInstantiationScope {
  public:
    /// A set of declarations.
    using DeclArgumentPack = SmallVector<VarDecl *, 4>;

  private:
    /// Reference to the semantic analysis that is performing
    /// this template instantiation.
    Sema &SemaRef;

    using LocalDeclsMap =
        llvm::SmallDenseMap<const Decl *,
                            llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;

    /// A mapping from local declarations that occur
    /// within a template to their instantiations.
    ///
    /// This mapping is used during instantiation to keep track of,
    /// e.g., function parameter and variable declarations. For example,
    /// given:
    ///
    /// \code
    ///   template<typename T> T add(T x, T y) { return x + y; }
    /// \endcode
    ///
    /// when we instantiate add<int>, we will introduce a mapping from
    /// the ParmVarDecl for 'x' that occurs in the template to the
    /// instantiated ParmVarDecl for 'x'.
    ///
    /// For a parameter pack, the local instantiation scope may contain a
    /// set of instantiated parameters. This is stored as a DeclArgumentPack
    /// pointer.
    LocalDeclsMap LocalDecls;

    /// The set of argument packs we've allocated.
    SmallVector<DeclArgumentPack *, 1> ArgumentPacks;

    /// The outer scope, which contains local variable
    /// definitions from some other instantiation (that may not be
    /// relevant to this particular scope).
    LocalInstantiationScope *Outer;

    /// Whether we have already exited this scope.
    bool Exited = false;

    /// Whether to combine this scope with the outer scope, such that
    /// lookup will search our outer scope.
    bool CombineWithOuterScope;

    /// If non-NULL, the template parameter pack that has been
    /// partially substituted per C++0x [temp.arg.explicit]p9.
    NamedDecl *PartiallySubstitutedPack = nullptr;

    /// If \c PartiallySubstitutedPack is non-null, the set of
    /// explicitly-specified template arguments in that pack.
    const TemplateArgument *ArgsInPartiallySubstitutedPack;

    /// If \c PartiallySubstitutedPack, the number of
    /// explicitly-specified template arguments in
    /// ArgsInPartiallySubstitutedPack.
    unsigned NumArgsInPartiallySubstitutedPack;

  public:
    LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
        : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
          CombineWithOuterScope(CombineWithOuterScope) {
      SemaRef.CurrentInstantiationScope = this;
    }

    LocalInstantiationScope(const LocalInstantiationScope &) = delete;
    LocalInstantiationScope &
    operator=(const LocalInstantiationScope &) = delete;

    ~LocalInstantiationScope() {
      Exit();
    }

    const Sema &getSema() const { return SemaRef; }

    /// Exit this local instantiation scope early.
    void Exit() {
      if (Exited)
        return;

      for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
        delete ArgumentPacks[I];

      SemaRef.CurrentInstantiationScope = Outer;
      Exited = true;
    }

    /// Clone this scope, and all outer scopes, down to the given
    /// outermost scope.
    LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
      if (this == Outermost) return this;

      // Save the current scope from SemaRef since the LocalInstantiationScope
      // will overwrite it on construction
      LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;

      LocalInstantiationScope *newScope =
        new LocalInstantiationScope(SemaRef, CombineWithOuterScope);

      newScope->Outer = nullptr;
      if (Outer)
        newScope->Outer = Outer->cloneScopes(Outermost);

      newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
      newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
      newScope->NumArgsInPartiallySubstitutedPack =
        NumArgsInPartiallySubstitutedPack;

      for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
           I != E; ++I) {
        const Decl *D = I->first;
        llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
          newScope->LocalDecls[D];
        if (I->second.is<Decl *>()) {
          Stored = I->second.get<Decl *>();
        } else {
          DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
          DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
          Stored = NewPack;
          newScope->ArgumentPacks.push_back(NewPack);
        }
      }
      // Restore the saved scope to SemaRef
      SemaRef.CurrentInstantiationScope = oldScope;
      return newScope;
    }

    /// deletes the given scope, and all outer scopes, down to the
    /// given outermost scope.
    static void deleteScopes(LocalInstantiationScope *Scope,
                             LocalInstantiationScope *Outermost) {
      while (Scope && Scope != Outermost) {
        LocalInstantiationScope *Out = Scope->Outer;
        delete Scope;
        Scope = Out;
      }
    }

    /// Find the instantiation of the declaration D within the current
    /// instantiation scope.
    ///
    /// \param D The declaration whose instantiation we are searching for.
    ///
    /// \returns A pointer to the declaration or argument pack of declarations
    /// to which the declaration \c D is instantiated, if found. Otherwise,
    /// returns NULL.
    llvm::PointerUnion<Decl *, DeclArgumentPack *> *
    findInstantiationOf(const Decl *D);

    void InstantiatedLocal(const Decl *D, Decl *Inst);
    void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
    void MakeInstantiatedLocalArgPack(const Decl *D);

    /// Note that the given parameter pack has been partially substituted
    /// via explicit specification of template arguments
    /// (C++0x [temp.arg.explicit]p9).
    ///
    /// \param Pack The parameter pack, which will always be a template
    /// parameter pack.
    ///
    /// \param ExplicitArgs The explicitly-specified template arguments provided
    /// for this parameter pack.
    ///
    /// \param NumExplicitArgs The number of explicitly-specified template
    /// arguments provided for this parameter pack.
    void SetPartiallySubstitutedPack(NamedDecl *Pack,
                                     const TemplateArgument *ExplicitArgs,
                                     unsigned NumExplicitArgs);

    /// Reset the partially-substituted pack when it is no longer of
    /// interest.
    void ResetPartiallySubstitutedPack() {
      assert(PartiallySubstitutedPack && "No partially-substituted pack");
      PartiallySubstitutedPack = nullptr;
      ArgsInPartiallySubstitutedPack = nullptr;
      NumArgsInPartiallySubstitutedPack = 0;
    }

    /// Retrieve the partially-substitued template parameter pack.
    ///
    /// If there is no partially-substituted parameter pack, returns NULL.
    NamedDecl *
    getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
                                unsigned *NumExplicitArgs = nullptr) const;

    /// Determine whether D is a pack expansion created in this scope.
    bool isLocalPackExpansion(const Decl *D);
  };

  class TemplateDeclInstantiator
    : public DeclVisitor<TemplateDeclInstantiator, Decl *>
  {
    Sema &SemaRef;
    Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
    DeclContext *Owner;
    const MultiLevelTemplateArgumentList &TemplateArgs;
    Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
    LocalInstantiationScope *StartingScope = nullptr;
    // Whether to evaluate the C++20 constraints or simply substitute into them.
    bool EvaluateConstraints = true;

    /// A list of out-of-line class template partial
    /// specializations that will need to be instantiated after the
    /// enclosing class's instantiation is complete.
    SmallVector<std::pair<ClassTemplateDecl *,
                                ClassTemplatePartialSpecializationDecl *>, 4>
      OutOfLinePartialSpecs;

    /// A list of out-of-line variable template partial
    /// specializations that will need to be instantiated after the
    /// enclosing variable's instantiation is complete.
    /// FIXME: Verify that this is needed.
    SmallVector<
        std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
    OutOfLineVarPartialSpecs;

  public:
    TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
                             const MultiLevelTemplateArgumentList &TemplateArgs)
        : SemaRef(SemaRef),
          SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
          Owner(Owner), TemplateArgs(TemplateArgs) {}

    void setEvaluateConstraints(bool B) {
      EvaluateConstraints = B;
    }
    bool getEvaluateConstraints() {
      return EvaluateConstraints;
    }

// Define all the decl visitors using DeclNodes.inc
#define DECL(DERIVED, BASE) \
    Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
#define ABSTRACT_DECL(DECL)

// Decls which never appear inside a class or function.
#define OBJCCONTAINER(DERIVED, BASE)
#define FILESCOPEASM(DERIVED, BASE)
#define TOPLEVELSTMT(DERIVED, BASE)
#define IMPORT(DERIVED, BASE)
#define EXPORT(DERIVED, BASE)
#define LINKAGESPEC(DERIVED, BASE)
#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
#define OBJCMETHOD(DERIVED, BASE)
#define OBJCTYPEPARAM(DERIVED, BASE)
#define OBJCIVAR(DERIVED, BASE)
#define OBJCPROPERTY(DERIVED, BASE)
#define OBJCPROPERTYIMPL(DERIVED, BASE)
#define EMPTY(DERIVED, BASE)
#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)

    // Decls which use special-case instantiation code.
#define BLOCK(DERIVED, BASE)
#define CAPTURED(DERIVED, BASE)
#define IMPLICITPARAM(DERIVED, BASE)

#include "clang/AST/DeclNodes.inc"

    enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual };

    void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T,
                          TypeSourceInfo *&TInfo,
                          DeclarationNameInfo &NameInfo);

    // A few supplemental visitor functions.
    Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
                             TemplateParameterList *TemplateParams,
                             RewriteKind RK = RewriteKind::None);
    Decl *VisitFunctionDecl(FunctionDecl *D,
                            TemplateParameterList *TemplateParams,
                            RewriteKind RK = RewriteKind::None);
    Decl *VisitDecl(Decl *D);
    Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
                       ArrayRef<BindingDecl *> *Bindings = nullptr);
    Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst,
                              LookupResult *Lookup);

    // Enable late instantiation of attributes.  Late instantiated attributes
    // will be stored in LA.
    void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
      LateAttrs = LA;
      StartingScope = SemaRef.CurrentInstantiationScope;
    }

    // Disable late instantiation of attributes.
    void disableLateAttributeInstantiation() {
      LateAttrs = nullptr;
      StartingScope = nullptr;
    }

    LocalInstantiationScope *getStartingScope() const { return StartingScope; }

    using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
      ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;

    using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
        VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;

    /// Return an iterator to the beginning of the set of
    /// "delayed" partial specializations, which must be passed to
    /// InstantiateClassTemplatePartialSpecialization once the class
    /// definition has been completed.
    delayed_partial_spec_iterator delayed_partial_spec_begin() {
      return OutOfLinePartialSpecs.begin();
    }

    delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
      return OutOfLineVarPartialSpecs.begin();
    }

    /// Return an iterator to the end of the set of
    /// "delayed" partial specializations, which must be passed to
    /// InstantiateClassTemplatePartialSpecialization once the class
    /// definition has been completed.
    delayed_partial_spec_iterator delayed_partial_spec_end() {
      return OutOfLinePartialSpecs.end();
    }

    delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
      return OutOfLineVarPartialSpecs.end();
    }

    // Helper functions for instantiating methods.
    TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
                             SmallVectorImpl<ParmVarDecl *> &Params);
    bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
    bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);

    bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl);

    TemplateParameterList *
      SubstTemplateParams(TemplateParameterList *List);

    bool SubstQualifier(const DeclaratorDecl *OldDecl,
                        DeclaratorDecl *NewDecl);
    bool SubstQualifier(const TagDecl *OldDecl,
                        TagDecl *NewDecl);

    Decl *VisitVarTemplateSpecializationDecl(
        VarTemplateDecl *VarTemplate, VarDecl *FromVar,
        const TemplateArgumentListInfo &TemplateArgsInfo,
        ArrayRef<TemplateArgument> Converted,
        VarTemplateSpecializationDecl *PrevDecl = nullptr);

    Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
    ClassTemplatePartialSpecializationDecl *
    InstantiateClassTemplatePartialSpecialization(
                                              ClassTemplateDecl *ClassTemplate,
                           ClassTemplatePartialSpecializationDecl *PartialSpec);
    VarTemplatePartialSpecializationDecl *
    InstantiateVarTemplatePartialSpecialization(
        VarTemplateDecl *VarTemplate,
        VarTemplatePartialSpecializationDecl *PartialSpec);
    void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);

  private:
    template<typename T>
    Decl *instantiateUnresolvedUsingDecl(T *D,
                                         bool InstantiatingPackElement = false);
  };

} // namespace clang

#endif // LLVM_CLANG_SEMA_TEMPLATE_H
