//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
//
// 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 implements C++ template instantiation.
//
//===----------------------------------------------------------------------===/

#include "TreeTransform.h"
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/TimeProfiler.h"
#include <optional>

using namespace clang;
using namespace sema;

//===----------------------------------------------------------------------===/
// Template Instantiation Support
//===----------------------------------------------------------------------===/

namespace {
namespace TemplateInstArgsHelpers {
struct Response {
  const Decl *NextDecl = nullptr;
  bool IsDone = false;
  bool ClearRelativeToPrimary = true;
  static Response Done() {
    Response R;
    R.IsDone = true;
    return R;
  }
  static Response ChangeDecl(const Decl *ND) {
    Response R;
    R.NextDecl = ND;
    return R;
  }
  static Response ChangeDecl(const DeclContext *Ctx) {
    Response R;
    R.NextDecl = Decl::castFromDeclContext(Ctx);
    return R;
  }

  static Response UseNextDecl(const Decl *CurDecl) {
    return ChangeDecl(CurDecl->getDeclContext());
  }

  static Response DontClearRelativeToPrimaryNextDecl(const Decl *CurDecl) {
    Response R = Response::UseNextDecl(CurDecl);
    R.ClearRelativeToPrimary = false;
    return R;
  }
};

// Retrieve the primary template for a lambda call operator. It's
// unfortunate that we only have the mappings of call operators rather
// than lambda classes.
const FunctionDecl *
getPrimaryTemplateOfGenericLambda(const FunctionDecl *LambdaCallOperator) {
  if (!isLambdaCallOperator(LambdaCallOperator))
    return LambdaCallOperator;
  while (true) {
    if (auto *FTD = dyn_cast_if_present<FunctionTemplateDecl>(
            LambdaCallOperator->getDescribedTemplate());
        FTD && FTD->getInstantiatedFromMemberTemplate()) {
      LambdaCallOperator =
          FTD->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
    } else if (LambdaCallOperator->getPrimaryTemplate()) {
      // Cases where the lambda operator is instantiated in
      // TemplateDeclInstantiator::VisitCXXMethodDecl.
      LambdaCallOperator =
          LambdaCallOperator->getPrimaryTemplate()->getTemplatedDecl();
    } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator)
                                ->getInstantiatedFromMemberFunction())
      LambdaCallOperator = Prev;
    else
      break;
  }
  return LambdaCallOperator;
}

struct EnclosingTypeAliasTemplateDetails {
  TypeAliasTemplateDecl *Template = nullptr;
  TypeAliasTemplateDecl *PrimaryTypeAliasDecl = nullptr;
  ArrayRef<TemplateArgument> AssociatedTemplateArguments;

  explicit operator bool() noexcept { return Template; }
};

// Find the enclosing type alias template Decl from CodeSynthesisContexts, as
// well as its primary template and instantiating template arguments.
EnclosingTypeAliasTemplateDetails
getEnclosingTypeAliasTemplateDecl(Sema &SemaRef) {
  for (auto &CSC : llvm::reverse(SemaRef.CodeSynthesisContexts)) {
    if (CSC.Kind != Sema::CodeSynthesisContext::SynthesisKind::
                        TypeAliasTemplateInstantiation)
      continue;
    EnclosingTypeAliasTemplateDetails Result;
    auto *TATD = cast<TypeAliasTemplateDecl>(CSC.Entity),
         *Next = TATD->getInstantiatedFromMemberTemplate();
    Result = {
        /*Template=*/TATD,
        /*PrimaryTypeAliasDecl=*/TATD,
        /*AssociatedTemplateArguments=*/CSC.template_arguments(),
    };
    while (Next) {
      Result.PrimaryTypeAliasDecl = Next;
      Next = Next->getInstantiatedFromMemberTemplate();
    }
    return Result;
  }
  return {};
}

// Check if we are currently inside of a lambda expression that is
// surrounded by a using alias declaration. e.g.
//   template <class> using type = decltype([](auto) { ^ }());
// We have to do so since a TypeAliasTemplateDecl (or a TypeAliasDecl) is never
// a DeclContext, nor does it have an associated specialization Decl from which
// we could collect these template arguments.
bool isLambdaEnclosedByTypeAliasDecl(
    const FunctionDecl *LambdaCallOperator,
    const TypeAliasTemplateDecl *PrimaryTypeAliasDecl) {
  struct Visitor : DynamicRecursiveASTVisitor {
    Visitor(const FunctionDecl *CallOperator) : CallOperator(CallOperator) {}
    bool VisitLambdaExpr(LambdaExpr *LE) override {
      // Return true to bail out of the traversal, implying the Decl contains
      // the lambda.
      return getPrimaryTemplateOfGenericLambda(LE->getCallOperator()) !=
             CallOperator;
    }
    const FunctionDecl *CallOperator;
  };

  QualType Underlying =
      PrimaryTypeAliasDecl->getTemplatedDecl()->getUnderlyingType();

  return !Visitor(getPrimaryTemplateOfGenericLambda(LambdaCallOperator))
              .TraverseType(Underlying);
}

// Add template arguments from a variable template instantiation.
Response
HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
                      MultiLevelTemplateArgumentList &Result,
                      bool SkipForSpecialization) {
  // For a class-scope explicit specialization, there are no template arguments
  // at this level, but there may be enclosing template arguments.
  if (VarTemplSpec->isClassScopeExplicitSpecialization())
    return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);

  // We're done when we hit an explicit specialization.
  if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
      !isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec))
    return Response::Done();

  // If this variable template specialization was instantiated from a
  // specialized member that is a variable template, we're done.
  assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?");
  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
      Specialized = VarTemplSpec->getSpecializedTemplateOrPartial();
  if (VarTemplatePartialSpecializationDecl *Partial =
          dyn_cast<VarTemplatePartialSpecializationDecl *>(Specialized)) {
    if (!SkipForSpecialization)
      Result.addOuterTemplateArguments(
          Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
          /*Final=*/false);
    if (Partial->isMemberSpecialization())
      return Response::Done();
  } else {
    VarTemplateDecl *Tmpl = cast<VarTemplateDecl *>(Specialized);
    if (!SkipForSpecialization)
      Result.addOuterTemplateArguments(
          Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
          /*Final=*/false);
    if (Tmpl->isMemberSpecialization())
      return Response::Done();
  }
  return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
}

// If we have a template template parameter with translation unit context,
// then we're performing substitution into a default template argument of
// this template template parameter before we've constructed the template
// that will own this template template parameter. In this case, we
// use empty template parameter lists for all of the outer templates
// to avoid performing any substitutions.
Response
HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
                                      MultiLevelTemplateArgumentList &Result) {
  for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
    Result.addOuterTemplateArguments(std::nullopt);
  return Response::Done();
}

Response HandlePartialClassTemplateSpec(
    const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec,
    MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) {
  if (!SkipForSpecialization)
    Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth());
  return Response::Done();
}

// Add template arguments from a class template instantiation.
Response
HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
                        MultiLevelTemplateArgumentList &Result,
                        bool SkipForSpecialization) {
  if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) {
    // We're done when we hit an explicit specialization.
    if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
        !isa<ClassTemplatePartialSpecializationDecl>(ClassTemplSpec))
      return Response::Done();

    if (!SkipForSpecialization)
      Result.addOuterTemplateArguments(
          const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
          ClassTemplSpec->getTemplateInstantiationArgs().asArray(),
          /*Final=*/false);

    // If this class template specialization was instantiated from a
    // specialized member that is a class template, we're done.
    assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?");
    if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization())
      return Response::Done();

    // If this was instantiated from a partial template specialization, we need
    // to get the next level of declaration context from the partial
    // specialization, as the ClassTemplateSpecializationDecl's
    // DeclContext/LexicalDeclContext will be for the primary template.
    if (auto *InstFromPartialTempl =
            ClassTemplSpec->getSpecializedTemplateOrPartial()
                .dyn_cast<ClassTemplatePartialSpecializationDecl *>())
      return Response::ChangeDecl(
          InstFromPartialTempl->getLexicalDeclContext());
  }
  return Response::UseNextDecl(ClassTemplSpec);
}

Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
                        MultiLevelTemplateArgumentList &Result,
                        const FunctionDecl *Pattern, bool RelativeToPrimary,
                        bool ForConstraintInstantiation,
                        bool ForDefaultArgumentSubstitution) {
  // Add template arguments from a function template specialization.
  if (!RelativeToPrimary &&
      Function->getTemplateSpecializationKindForInstantiation() ==
          TSK_ExplicitSpecialization)
    return Response::Done();

  if (!RelativeToPrimary &&
      Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
    // This is an implicit instantiation of an explicit specialization. We
    // don't get any template arguments from this function but might get
    // some from an enclosing template.
    return Response::UseNextDecl(Function);
  } else if (const TemplateArgumentList *TemplateArgs =
                 Function->getTemplateSpecializationArgs()) {
    // Add the template arguments for this specialization.
    Result.addOuterTemplateArguments(const_cast<FunctionDecl *>(Function),
                                     TemplateArgs->asArray(),
                                     /*Final=*/false);

    if (RelativeToPrimary &&
        (Function->getTemplateSpecializationKind() ==
             TSK_ExplicitSpecialization ||
         (Function->getFriendObjectKind() &&
          !Function->getPrimaryTemplate()->getFriendObjectKind())))
      return Response::UseNextDecl(Function);

    // If this function was instantiated from a specialized member that is
    // a function template, we're done.
    assert(Function->getPrimaryTemplate() && "No function template?");
    if (!ForDefaultArgumentSubstitution &&
        Function->getPrimaryTemplate()->isMemberSpecialization())
      return Response::Done();

    // If this function is a generic lambda specialization, we are done.
    if (!ForConstraintInstantiation &&
        isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
      return Response::Done();

  } else if (auto *Template = Function->getDescribedFunctionTemplate()) {
    assert(
        (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
        "Outer template not instantiated?");
    if (ForConstraintInstantiation) {
      for (auto &Inst : llvm::reverse(SemaRef.CodeSynthesisContexts)) {
        if (Inst.Kind == Sema::CodeSynthesisContext::ConstraintsCheck &&
            Inst.Entity == Template) {
          // After CWG2369, the outer templates are not instantiated when
          // checking its associated constraints. So add them back through the
          // synthesis context; this is useful for e.g. nested constraints
          // involving lambdas.
          Result.addOuterTemplateArguments(Template, Inst.template_arguments(),
                                           /*Final=*/false);
          break;
        }
      }
    }
  }
  // If this is a friend or local declaration and it declares an entity at
  // namespace scope, take arguments from its lexical parent
  // instead of its semantic parent, unless of course the pattern we're
  // instantiating actually comes from the file's context!
  if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) &&
      Function->getNonTransparentDeclContext()->isFileContext() &&
      (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
    return Response::ChangeDecl(Function->getLexicalDeclContext());
  }

  if (ForConstraintInstantiation && Function->getFriendObjectKind())
    return Response::ChangeDecl(Function->getLexicalDeclContext());
  return Response::UseNextDecl(Function);
}

Response HandleFunctionTemplateDecl(Sema &SemaRef,
                                    const FunctionTemplateDecl *FTD,
                                    MultiLevelTemplateArgumentList &Result) {
  if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
    Result.addOuterTemplateArguments(
        const_cast<FunctionTemplateDecl *>(FTD),
        const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(
            SemaRef.Context),
        /*Final=*/false);

    NestedNameSpecifier NNS = FTD->getTemplatedDecl()->getQualifier();

    for (const Type *Ty = NNS.getKind() == NestedNameSpecifier::Kind::Type
                              ? NNS.getAsType()
                              : nullptr,
                    *NextTy = nullptr;
         Ty && Ty->isInstantiationDependentType();
         Ty = std::exchange(NextTy, nullptr)) {
      if (NestedNameSpecifier P = Ty->getPrefix();
          P.getKind() == NestedNameSpecifier::Kind::Type)
        NextTy = P.getAsType();
      const auto *TSTy = dyn_cast<TemplateSpecializationType>(Ty);
      if (!TSTy)
        continue;

      ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
      // Prefer template arguments from the injected-class-type if possible.
      // For example,
      // ```cpp
      // template <class... Pack> struct S {
      //   template <class T> void foo();
      // };
      // template <class... Pack> template <class T>
      //           ^^^^^^^^^^^^^ InjectedTemplateArgs
      //           They're of kind TemplateArgument::Pack, not of
      //           TemplateArgument::Type.
      // void S<Pack...>::foo() {}
      //        ^^^^^^^
      //        TSTy->template_arguments() (which are of PackExpansionType)
      // ```
      // This meets the contract in
      // TreeTransform::TryExpandParameterPacks that the template arguments
      // for unexpanded parameters should be of a Pack kind.
      if (TSTy->isCurrentInstantiation()) {
        auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
        if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
          Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
        else if (auto *Specialization =
                     dyn_cast<ClassTemplateSpecializationDecl>(RD))
          Arguments = Specialization->getTemplateInstantiationArgs().asArray();
      }
      Result.addOuterTemplateArguments(
          TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
          /*Final=*/false);
    }
  }

  return Response::ChangeDecl(FTD->getLexicalDeclContext());
}

Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
                          MultiLevelTemplateArgumentList &Result,
                          ASTContext &Context,
                          bool ForConstraintInstantiation) {
  if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
    assert(
        (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
        "Outer template not instantiated?");
    if (ClassTemplate->isMemberSpecialization())
      return Response::Done();
    if (ForConstraintInstantiation)
      Result.addOuterTemplateArguments(
          const_cast<CXXRecordDecl *>(Rec),
          ClassTemplate->getInjectedTemplateArgs(SemaRef.Context),
          /*Final=*/false);
  }

  if (const MemberSpecializationInfo *MSInfo =
          Rec->getMemberSpecializationInfo())
    if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
      return Response::Done();

  bool IsFriend = Rec->getFriendObjectKind() ||
                  (Rec->getDescribedClassTemplate() &&
                   Rec->getDescribedClassTemplate()->getFriendObjectKind());
  if (ForConstraintInstantiation && IsFriend &&
      Rec->getNonTransparentDeclContext()->isFileContext()) {
    return Response::ChangeDecl(Rec->getLexicalDeclContext());
  }

  // This is to make sure we pick up the VarTemplateSpecializationDecl or the
  // TypeAliasTemplateDecl that this lambda is defined inside of.
  if (Rec->isLambda()) {
    if (const Decl *LCD = Rec->getLambdaContextDecl())
      return Response::ChangeDecl(LCD);
    // Retrieve the template arguments for a using alias declaration.
    // This is necessary for constraint checking, since we always keep
    // constraints relative to the primary template.
    if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef);
        ForConstraintInstantiation && TypeAlias) {
      if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(),
                                          TypeAlias.PrimaryTypeAliasDecl)) {
        Result.addOuterTemplateArguments(TypeAlias.Template,
                                         TypeAlias.AssociatedTemplateArguments,
                                         /*Final=*/false);
        // Visit the parent of the current type alias declaration rather than
        // the lambda thereof.
        // E.g., in the following example:
        // struct S {
        //  template <class> using T = decltype([]<Concept> {} ());
        // };
        // void foo() {
        //   S::T var;
        // }
        // The instantiated lambda expression (which we're visiting at 'var')
        // has a function DeclContext 'foo' rather than the Record DeclContext
        // S. This seems to be an oversight to me that we may want to set a
        // Sema Context from the CXXScopeSpec before substituting into T.
        return Response::ChangeDecl(TypeAlias.Template->getDeclContext());
      }
    }
  }

  return Response::UseNextDecl(Rec);
}

Response HandleImplicitConceptSpecializationDecl(
    const ImplicitConceptSpecializationDecl *CSD,
    MultiLevelTemplateArgumentList &Result) {
  Result.addOuterTemplateArguments(
      const_cast<ImplicitConceptSpecializationDecl *>(CSD),
      CSD->getTemplateArguments(),
      /*Final=*/false);
  return Response::UseNextDecl(CSD);
}

Response HandleGenericDeclContext(const Decl *CurDecl) {
  return Response::UseNextDecl(CurDecl);
}
} // namespace TemplateInstArgsHelpers
} // namespace

MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
    const NamedDecl *ND, const DeclContext *DC, bool Final,
    std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
    const FunctionDecl *Pattern, bool ForConstraintInstantiation,
    bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
  assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
  // Accumulate the set of template argument lists in this structure.
  MultiLevelTemplateArgumentList Result;

  using namespace TemplateInstArgsHelpers;
  const Decl *CurDecl = ND;

  if (Innermost) {
    Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
                                     Final);
    // Populate placeholder template arguments for TemplateTemplateParmDecls.
    // This is essential for the case e.g.
    //
    // template <class> concept Concept = false;
    // template <template <Concept C> class T> void foo(T<int>)
    //
    // where parameter C has a depth of 1 but the substituting argument `int`
    // has a depth of 0.
    if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl))
      HandleDefaultTempArgIntoTempTempParam(TTP, Result);
    CurDecl = DC ? Decl::castFromDeclContext(DC)
                 : Response::UseNextDecl(CurDecl).NextDecl;
  } else if (!CurDecl)
    CurDecl = Decl::castFromDeclContext(DC);

  while (!CurDecl->isFileContextDecl()) {
    Response R;
    if (const auto *VarTemplSpec =
            dyn_cast<VarTemplateSpecializationDecl>(CurDecl)) {
      R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization);
    } else if (const auto *PartialClassTemplSpec =
                   dyn_cast<ClassTemplatePartialSpecializationDecl>(CurDecl)) {
      R = HandlePartialClassTemplateSpec(PartialClassTemplSpec, Result,
                                         SkipForSpecialization);
    } else if (const auto *ClassTemplSpec =
                   dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) {
      R = HandleClassTemplateSpec(ClassTemplSpec, Result,
                                  SkipForSpecialization);
    } else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
      R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary,
                         ForConstraintInstantiation,
                         ForDefaultArgumentSubstitution);
    } else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
      R = HandleRecordDecl(*this, Rec, Result, Context,
                           ForConstraintInstantiation);
    } else if (const auto *CSD =
                   dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
      R = HandleImplicitConceptSpecializationDecl(CSD, Result);
    } else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
      R = HandleFunctionTemplateDecl(*this, FTD, Result);
    } else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) {
      R = Response::ChangeDecl(CTD->getLexicalDeclContext());
    } else if (!isa<DeclContext>(CurDecl)) {
      R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
      if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
        R = HandleDefaultTempArgIntoTempTempParam(TTP, Result);
      }
    } else {
      R = HandleGenericDeclContext(CurDecl);
    }

    if (R.IsDone)
      return Result;
    if (R.ClearRelativeToPrimary)
      RelativeToPrimary = false;
    assert(R.NextDecl);
    CurDecl = R.NextDecl;
  }
  return Result;
}

bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
  switch (Kind) {
  case TemplateInstantiation:
  case ExceptionSpecInstantiation:
  case DefaultTemplateArgumentInstantiation:
  case DefaultFunctionArgumentInstantiation:
  case ExplicitTemplateArgumentSubstitution:
  case DeducedTemplateArgumentSubstitution:
  case PriorTemplateArgumentSubstitution:
  case ConstraintsCheck:
  case NestedRequirementConstraintsCheck:
    return true;

  case RequirementInstantiation:
  case RequirementParameterInstantiation:
  case DefaultTemplateArgumentChecking:
  case DeclaringSpecialMember:
  case DeclaringImplicitEqualityComparison:
  case DefiningSynthesizedFunction:
  case ExceptionSpecEvaluation:
  case ConstraintSubstitution:
  case ParameterMappingSubstitution:
  case ConstraintNormalization:
  case RewritingOperatorAsSpaceship:
  case InitializingStructuredBinding:
  case MarkingClassDllexported:
  case BuildingBuiltinDumpStructCall:
  case LambdaExpressionSubstitution:
  case BuildingDeductionGuides:
  case TypeAliasTemplateInstantiation:
  case PartialOrderingTTP:
    return false;

  // This function should never be called when Kind's value is Memoization.
  case Memoization:
    break;
  }

  llvm_unreachable("Invalid SynthesisKind!");
}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
    SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
    Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
    sema::TemplateDeductionInfo *DeductionInfo)
    : SemaRef(SemaRef) {
  // Don't allow further instantiation if a fatal error and an uncompilable
  // error have occurred. Any diagnostics we might have raised will not be
  // visible, and we do not need to construct a correct AST.
  if (SemaRef.Diags.hasFatalErrorOccurred() &&
      SemaRef.hasUncompilableErrorOccurred()) {
    Invalid = true;
    return;
  }

  CodeSynthesisContext Inst;
  Inst.Kind = Kind;
  Inst.PointOfInstantiation = PointOfInstantiation;
  Inst.Entity = Entity;
  Inst.Template = Template;
  Inst.TemplateArgs = TemplateArgs.data();
  Inst.NumTemplateArgs = TemplateArgs.size();
  Inst.DeductionInfo = DeductionInfo;
  Inst.InstantiationRange = InstantiationRange;
  Inst.InConstraintSubstitution =
      Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
  if (!SemaRef.CodeSynthesisContexts.empty())
    Inst.InConstraintSubstitution |=
        SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;

  Invalid = SemaRef.pushCodeSynthesisContext(Inst);
  if (!Invalid) {
    AlreadyInstantiating =
        !Inst.Entity
            ? false
            : !SemaRef.InstantiatingSpecializations
                   .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
                   .second;
    atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
  }
}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(SemaRef,
                            CodeSynthesisContext::TemplateInstantiation,
                            PointOfInstantiation, InstantiationRange, Entity) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity,
    ExceptionSpecification, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::ExceptionSpecInstantiation,
          PointOfInstantiation, InstantiationRange, Entity) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param,
    TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::DefaultTemplateArgumentInstantiation,
          PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param),
          Template, TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    FunctionTemplateDecl *FunctionTemplate,
    ArrayRef<TemplateArgument> TemplateArgs,
    CodeSynthesisContext::SynthesisKind Kind,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
                            InstantiationRange, FunctionTemplate, nullptr,
                            TemplateArgs, &DeductionInfo) {
  assert(Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
         Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution ||
         Kind == CodeSynthesisContext::BuildingDeductionGuides);
}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    TemplateDecl *Template,
    ArrayRef<TemplateArgument> TemplateArgs,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
          PointOfInstantiation, InstantiationRange, Template, nullptr,
          TemplateArgs, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    ClassTemplatePartialSpecializationDecl *PartialSpec,
    ArrayRef<TemplateArgument> TemplateArgs,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
          PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
          TemplateArgs, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    VarTemplatePartialSpecializationDecl *PartialSpec,
    ArrayRef<TemplateArgument> TemplateArgs,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
          PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
          TemplateArgs, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param,
    ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::DefaultFunctionArgumentInstantiation,
          PointOfInstantiation, InstantiationRange, Param, nullptr,
          TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
    NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::PriorTemplateArgumentSubstitution,
          PointOfInstantiation, InstantiationRange, Param, Template,
          TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
    TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef,
          CodeSynthesisContext::PriorTemplateArgumentSubstitution,
          PointOfInstantiation, InstantiationRange, Param, Template,
          TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    TypeAliasTemplateDecl *Entity, ArrayRef<TemplateArgument> TemplateArgs,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::TypeAliasTemplateInstantiation,
          PointOfInstantiation, InstantiationRange, /*Entity=*/Entity,
          /*Template=*/nullptr, TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
    NamedDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::DefaultTemplateArgumentChecking,
          PointOfInstantiation, InstantiationRange, Param, Template,
          TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    concepts::Requirement *Req, sema::TemplateDeductionInfo &DeductionInfo,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::RequirementInstantiation,
          PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
          /*Template=*/nullptr, /*TemplateArgs=*/{}, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    concepts::NestedRequirement *Req, ConstraintsCheck,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::NestedRequirementConstraintsCheck,
          PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
          /*Template=*/nullptr, /*TemplateArgs=*/{}) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, const RequiresExpr *RE,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::RequirementParameterInstantiation,
          PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
          /*Template=*/nullptr, /*TemplateArgs=*/{}, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    ConstraintsCheck, NamedDecl *Template,
    ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::ConstraintsCheck,
          PointOfInstantiation, InstantiationRange, Template, nullptr,
          TemplateArgs) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    ConstraintSubstitution, NamedDecl *Template,
    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::ConstraintSubstitution,
          PointOfInstantiation, InstantiationRange, Template, nullptr,
          {}, &DeductionInfo) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    ConstraintNormalization, NamedDecl *Template,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::ConstraintNormalization,
          PointOfInstantiation, InstantiationRange, Template) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation,
    ParameterMappingSubstitution, NamedDecl *Template,
    SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::ParameterMappingSubstitution,
          PointOfInstantiation, InstantiationRange, Template) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Entity,
    BuildingDeductionGuidesTag, SourceRange InstantiationRange)
    : InstantiatingTemplate(
          SemaRef, CodeSynthesisContext::BuildingDeductionGuides,
          PointOfInstantiation, InstantiationRange, Entity) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
    Sema &SemaRef, SourceLocation ArgLoc, PartialOrderingTTP,
    TemplateDecl *PArg, SourceRange InstantiationRange)
    : InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
                            ArgLoc, InstantiationRange, PArg) {}

bool Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
  Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
  InNonInstantiationSFINAEContext = false;

  if (!Ctx.isInstantiationRecord()) {
    ++NonInstantiationEntries;
  } else {
    assert(SemaRef.NonInstantiationEntries <=
           SemaRef.CodeSynthesisContexts.size());
    if ((SemaRef.CodeSynthesisContexts.size() -
         SemaRef.NonInstantiationEntries) >
        SemaRef.getLangOpts().InstantiationDepth) {
      SemaRef.Diag(Ctx.PointOfInstantiation,
                   diag::err_template_recursion_depth_exceeded)
          << SemaRef.getLangOpts().InstantiationDepth << Ctx.InstantiationRange;
      SemaRef.Diag(Ctx.PointOfInstantiation,
                   diag::note_template_recursion_depth)
          << SemaRef.getLangOpts().InstantiationDepth;
      return true;
    }
  }

  CodeSynthesisContexts.push_back(Ctx);

  // Check to see if we're low on stack space. We can't do anything about this
  // from here, but we can at least warn the user.
  StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
  return false;
}

void Sema::popCodeSynthesisContext() {
  auto &Active = CodeSynthesisContexts.back();
  if (!Active.isInstantiationRecord()) {
    assert(NonInstantiationEntries > 0);
    --NonInstantiationEntries;
  }

  InNonInstantiationSFINAEContext = Active.SavedInNonInstantiationSFINAEContext;

  // Name lookup no longer looks in this template's defining module.
  assert(CodeSynthesisContexts.size() >=
             CodeSynthesisContextLookupModules.size() &&
         "forgot to remove a lookup module for a template instantiation");
  if (CodeSynthesisContexts.size() ==
      CodeSynthesisContextLookupModules.size()) {
    if (Module *M = CodeSynthesisContextLookupModules.back())
      LookupModulesCache.erase(M);
    CodeSynthesisContextLookupModules.pop_back();
  }

  // If we've left the code synthesis context for the current context stack,
  // stop remembering that we've emitted that stack.
  if (CodeSynthesisContexts.size() ==
      LastEmittedCodeSynthesisContextDepth)
    LastEmittedCodeSynthesisContextDepth = 0;

  CodeSynthesisContexts.pop_back();
}

void Sema::InstantiatingTemplate::Clear() {
  if (!Invalid) {
    if (!AlreadyInstantiating) {
      auto &Active = SemaRef.CodeSynthesisContexts.back();
      if (Active.Entity)
        SemaRef.InstantiatingSpecializations.erase(
            {Active.Entity->getCanonicalDecl(), Active.Kind});
    }

    atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
                  SemaRef.CodeSynthesisContexts.back());

    SemaRef.popCodeSynthesisContext();
    Invalid = true;
  }
}

static std::string convertCallArgsToString(Sema &S,
                                           llvm::ArrayRef<const Expr *> Args) {
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  llvm::ListSeparator Comma;
  for (const Expr *Arg : Args) {
    OS << Comma;
    Arg->IgnoreParens()->printPretty(OS, nullptr,
                                     S.Context.getPrintingPolicy());
  }
  return Result;
}

void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
  // Determine which template instantiations to skip, if any.
  unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
  unsigned Limit = Diags.getTemplateBacktraceLimit();
  if (Limit && Limit < CodeSynthesisContexts.size()) {
    SkipStart = Limit / 2 + Limit % 2;
    SkipEnd = CodeSynthesisContexts.size() - Limit / 2;
  }

  // FIXME: In all of these cases, we need to show the template arguments
  unsigned InstantiationIdx = 0;
  for (SmallVectorImpl<CodeSynthesisContext>::reverse_iterator
         Active = CodeSynthesisContexts.rbegin(),
         ActiveEnd = CodeSynthesisContexts.rend();
       Active != ActiveEnd;
       ++Active, ++InstantiationIdx) {
    // Skip this instantiation?
    if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
      if (InstantiationIdx == SkipStart) {
        // Note that we're skipping instantiations.
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_instantiation_contexts_suppressed)
                     << unsigned(CodeSynthesisContexts.size() - Limit));
      }
      continue;
    }

    switch (Active->Kind) {
    case CodeSynthesisContext::TemplateInstantiation: {
      Decl *D = Active->Entity;
      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
        unsigned DiagID = diag::note_template_member_class_here;
        if (isa<ClassTemplateSpecializationDecl>(Record))
          DiagID = diag::note_template_class_instantiation_here;
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(DiagID) << Record << Active->InstantiationRange);
      } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
        unsigned DiagID;
        if (Function->getPrimaryTemplate())
          DiagID = diag::note_function_template_spec_here;
        else
          DiagID = diag::note_template_member_function_here;
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(DiagID) << Function << Active->InstantiationRange);
      } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(VD->isStaticDataMember()
                           ? diag::note_template_static_data_member_def_here
                           : diag::note_template_variable_def_here)
                     << VD << Active->InstantiationRange);
      } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_template_enum_def_here)
                     << ED << Active->InstantiationRange);
      } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_template_nsdmi_here)
                     << FD << Active->InstantiationRange);
      } else if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(D)) {
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_template_class_instantiation_here)
                     << CTD << Active->InstantiationRange);
      }
      break;
    }

    case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: {
      TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
      SmallString<128> TemplateArgsStr;
      llvm::raw_svector_ostream OS(TemplateArgsStr);
      Template->printName(OS, getPrintingPolicy());
      printTemplateArgumentList(OS, Active->template_arguments(),
                                getPrintingPolicy());
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_default_arg_instantiation_here)
                   << OS.str() << Active->InstantiationRange);
      break;
    }

    case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: {
      FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_explicit_template_arg_substitution_here)
                   << FnTmpl
                   << getTemplateArgumentBindingsText(
                          FnTmpl->getTemplateParameters(), Active->TemplateArgs,
                          Active->NumTemplateArgs)
                   << Active->InstantiationRange);
      break;
    }

    case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: {
      if (FunctionTemplateDecl *FnTmpl =
              dyn_cast<FunctionTemplateDecl>(Active->Entity)) {
        DiagFunc(
            Active->PointOfInstantiation,
            PDiag(diag::note_function_template_deduction_instantiation_here)
                << FnTmpl
                << getTemplateArgumentBindingsText(
                       FnTmpl->getTemplateParameters(), Active->TemplateArgs,
                       Active->NumTemplateArgs)
                << Active->InstantiationRange);
      } else {
        bool IsVar = isa<VarTemplateDecl>(Active->Entity) ||
                     isa<VarTemplateSpecializationDecl>(Active->Entity);
        bool IsTemplate = false;
        TemplateParameterList *Params;
        if (auto *D = dyn_cast<TemplateDecl>(Active->Entity)) {
          IsTemplate = true;
          Params = D->getTemplateParameters();
        } else if (auto *D = dyn_cast<ClassTemplatePartialSpecializationDecl>(
                       Active->Entity)) {
          Params = D->getTemplateParameters();
        } else if (auto *D = dyn_cast<VarTemplatePartialSpecializationDecl>(
                       Active->Entity)) {
          Params = D->getTemplateParameters();
        } else {
          llvm_unreachable("unexpected template kind");
        }

        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_deduced_template_arg_substitution_here)
                     << IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
                     << getTemplateArgumentBindingsText(Params,
                                                        Active->TemplateArgs,
                                                        Active->NumTemplateArgs)
                     << Active->InstantiationRange);
      }
      break;
    }

    case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: {
      ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
      FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());

      SmallString<128> TemplateArgsStr;
      llvm::raw_svector_ostream OS(TemplateArgsStr);
      FD->printName(OS, getPrintingPolicy());
      printTemplateArgumentList(OS, Active->template_arguments(),
                                getPrintingPolicy());
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_default_function_arg_instantiation_here)
                   << OS.str() << Active->InstantiationRange);
      break;
    }

    case CodeSynthesisContext::PriorTemplateArgumentSubstitution: {
      NamedDecl *Parm = cast<NamedDecl>(Active->Entity);
      std::string Name;
      if (!Parm->getName().empty())
        Name = std::string(" '") + Parm->getName().str() + "'";

      TemplateParameterList *TemplateParams = nullptr;
      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
        TemplateParams = Template->getTemplateParameters();
      else
        TemplateParams =
          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
                                                      ->getTemplateParameters();
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_prior_template_arg_substitution)
                   << isa<TemplateTemplateParmDecl>(Parm) << Name
                   << getTemplateArgumentBindingsText(TemplateParams,
                                                      Active->TemplateArgs,
                                                      Active->NumTemplateArgs)
                   << Active->InstantiationRange);
      break;
    }

    case CodeSynthesisContext::DefaultTemplateArgumentChecking: {
      TemplateParameterList *TemplateParams = nullptr;
      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
        TemplateParams = Template->getTemplateParameters();
      else
        TemplateParams =
          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
                                                      ->getTemplateParameters();

      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_default_arg_checking)
                   << getTemplateArgumentBindingsText(TemplateParams,
                                                      Active->TemplateArgs,
                                                      Active->NumTemplateArgs)
                   << Active->InstantiationRange);
      break;
    }

    case CodeSynthesisContext::ExceptionSpecEvaluation:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_evaluating_exception_spec_here)
                   << cast<FunctionDecl>(Active->Entity));
      break;

    case CodeSynthesisContext::ExceptionSpecInstantiation:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_exception_spec_instantiation_here)
                   << cast<FunctionDecl>(Active->Entity)
                   << Active->InstantiationRange);
      break;

    case CodeSynthesisContext::RequirementInstantiation:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_requirement_instantiation_here)
                   << Active->InstantiationRange);
      break;
    case CodeSynthesisContext::RequirementParameterInstantiation:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_requirement_params_instantiation_here)
                   << Active->InstantiationRange);
      break;

    case CodeSynthesisContext::NestedRequirementConstraintsCheck:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_nested_requirement_here)
                   << Active->InstantiationRange);
      break;

    case CodeSynthesisContext::DeclaringSpecialMember:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_in_declaration_of_implicit_special_member)
                   << cast<CXXRecordDecl>(Active->Entity)
                   << Active->SpecialMember);
      break;

    case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
      DiagFunc(
          Active->Entity->getLocation(),
          PDiag(diag::note_in_declaration_of_implicit_equality_comparison));
      break;

    case CodeSynthesisContext::DefiningSynthesizedFunction: {
      // FIXME: For synthesized functions that are not defaulted,
      // produce a note.
      auto *FD = dyn_cast<FunctionDecl>(Active->Entity);
      // Note: if FD is nullptr currently setting DFK to DefaultedFunctionKind()
      // will ensure that DFK.isComparison() is false. This is important because
      // we will uncondtionally dereference FD in the else if.
      DefaultedFunctionKind DFK =
          FD ? getDefaultedFunctionKind(FD) : DefaultedFunctionKind();
      if (DFK.isSpecialMember()) {
        auto *MD = cast<CXXMethodDecl>(FD);
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_member_synthesized_at)
                     << MD->isExplicitlyDefaulted() << DFK.asSpecialMember()
                     << Context.getCanonicalTagType(MD->getParent()));
      } else if (DFK.isComparison()) {
        QualType RecordType = FD->getParamDecl(0)
                                  ->getType()
                                  .getNonReferenceType()
                                  .getUnqualifiedType();
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_comparison_synthesized_at)
                     << (int)DFK.asComparison() << RecordType);
      }
      break;
    }

    case CodeSynthesisContext::RewritingOperatorAsSpaceship:
      DiagFunc(Active->Entity->getLocation(),
               PDiag(diag::note_rewriting_operator_as_spaceship));
      break;

    case CodeSynthesisContext::InitializingStructuredBinding:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_in_binding_decl_init)
                   << cast<BindingDecl>(Active->Entity));
      break;

    case CodeSynthesisContext::MarkingClassDllexported:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_due_to_dllexported_class)
                   << cast<CXXRecordDecl>(Active->Entity)
                   << !getLangOpts().CPlusPlus11);
      break;

    case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_building_builtin_dump_struct_call)
                   << convertCallArgsToString(
                          *this, llvm::ArrayRef(Active->CallArgs,
                                                Active->NumCallArgs)));
      break;

    case CodeSynthesisContext::Memoization:
      break;

    case CodeSynthesisContext::LambdaExpressionSubstitution:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_lambda_substitution_here));
      break;
    case CodeSynthesisContext::ConstraintsCheck: {
      unsigned DiagID = 0;
      if (!Active->Entity) {
        DiagFunc(Active->PointOfInstantiation,
                 PDiag(diag::note_nested_requirement_here)
                     << Active->InstantiationRange);
        break;
      }
      if (isa<ConceptDecl>(Active->Entity))
        DiagID = diag::note_concept_specialization_here;
      else if (isa<TemplateDecl>(Active->Entity))
        DiagID = diag::note_checking_constraints_for_template_id_here;
      else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
        DiagID = diag::note_checking_constraints_for_var_spec_id_here;
      else if (isa<ClassTemplatePartialSpecializationDecl>(Active->Entity))
        DiagID = diag::note_checking_constraints_for_class_spec_id_here;
      else {
        assert(isa<FunctionDecl>(Active->Entity));
        DiagID = diag::note_checking_constraints_for_function_here;
      }
      SmallString<128> TemplateArgsStr;
      llvm::raw_svector_ostream OS(TemplateArgsStr);
      cast<NamedDecl>(Active->Entity)->printName(OS, getPrintingPolicy());
      if (!isa<FunctionDecl>(Active->Entity)) {
        printTemplateArgumentList(OS, Active->template_arguments(),
                                  getPrintingPolicy());
      }
      DiagFunc(Active->PointOfInstantiation,
               PDiag(DiagID) << OS.str() << Active->InstantiationRange);
      break;
    }
    case CodeSynthesisContext::ConstraintSubstitution:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_constraint_substitution_here)
                   << Active->InstantiationRange);
      break;
    case CodeSynthesisContext::ConstraintNormalization:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_constraint_normalization_here)
                   << cast<NamedDecl>(Active->Entity)
                   << Active->InstantiationRange);
      break;
    case CodeSynthesisContext::ParameterMappingSubstitution:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_parameter_mapping_substitution_here)
                   << Active->InstantiationRange);
      break;
    case CodeSynthesisContext::BuildingDeductionGuides:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_building_deduction_guide_here));
      break;
    case CodeSynthesisContext::TypeAliasTemplateInstantiation:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_type_alias_instantiation_here)
                   << cast<TypeAliasTemplateDecl>(Active->Entity)
                   << Active->InstantiationRange);
      break;
    case CodeSynthesisContext::PartialOrderingTTP:
      DiagFunc(Active->PointOfInstantiation,
               PDiag(diag::note_template_arg_template_params_mismatch));
      if (SourceLocation ParamLoc = Active->Entity->getLocation();
          ParamLoc.isValid())
        DiagFunc(ParamLoc, PDiag(diag::note_template_prev_declaration)
                               << /*isTemplateTemplateParam=*/true
                               << Active->InstantiationRange);
      break;
    }
  }
}

std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
  if (InNonInstantiationSFINAEContext)
    return std::optional<TemplateDeductionInfo *>(nullptr);

  for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator
         Active = CodeSynthesisContexts.rbegin(),
         ActiveEnd = CodeSynthesisContexts.rend();
       Active != ActiveEnd;
       ++Active)
  {
    switch (Active->Kind) {
    case CodeSynthesisContext::TypeAliasTemplateInstantiation:
      // An instantiation of an alias template may or may not be a SFINAE
      // context, depending on what else is on the stack.
      if (isa<TypeAliasTemplateDecl>(Active->Entity))
        break;
      [[fallthrough]];
    case CodeSynthesisContext::TemplateInstantiation:
    case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
    case CodeSynthesisContext::ExceptionSpecInstantiation:
    case CodeSynthesisContext::ConstraintsCheck:
    case CodeSynthesisContext::ParameterMappingSubstitution:
    case CodeSynthesisContext::ConstraintNormalization:
    case CodeSynthesisContext::NestedRequirementConstraintsCheck:
      // This is a template instantiation, so there is no SFINAE.
      return std::nullopt;
    case CodeSynthesisContext::LambdaExpressionSubstitution:
      // [temp.deduct]p9
      // A lambda-expression appearing in a function type or a template
      // parameter is not considered part of the immediate context for the
      // purposes of template argument deduction.
      // CWG2672: A lambda-expression body is never in the immediate context.
      return std::nullopt;

    case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
    case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
    case CodeSynthesisContext::DefaultTemplateArgumentChecking:
    case CodeSynthesisContext::RewritingOperatorAsSpaceship:
    case CodeSynthesisContext::PartialOrderingTTP:
      // A default template argument instantiation and substitution into
      // template parameters with arguments for prior parameters may or may
      // not be a SFINAE context; look further up the stack.
      break;

    case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
    case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
      // We're either substituting explicitly-specified template arguments,
      // deduced template arguments. SFINAE applies unless we are in a lambda
      // body, see [temp.deduct]p9.
    case CodeSynthesisContext::ConstraintSubstitution:
    case CodeSynthesisContext::RequirementInstantiation:
    case CodeSynthesisContext::RequirementParameterInstantiation:
      // SFINAE always applies in a constraint expression or a requirement
      // in a requires expression.
      assert(Active->DeductionInfo && "Missing deduction info pointer");
      return Active->DeductionInfo;

    case CodeSynthesisContext::DeclaringSpecialMember:
    case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
    case CodeSynthesisContext::DefiningSynthesizedFunction:
    case CodeSynthesisContext::InitializingStructuredBinding:
    case CodeSynthesisContext::MarkingClassDllexported:
    case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
    case CodeSynthesisContext::BuildingDeductionGuides:
      // This happens in a context unrelated to template instantiation, so
      // there is no SFINAE.
      return std::nullopt;

    case CodeSynthesisContext::ExceptionSpecEvaluation:
      // FIXME: This should not be treated as a SFINAE context, because
      // we will cache an incorrect exception specification. However, clang
      // bootstrap relies this! See PR31692.
      break;

    case CodeSynthesisContext::Memoization:
      break;
    }

    // The inner context was transparent for SFINAE. If it occurred within a
    // non-instantiation SFINAE context, then SFINAE applies.
    if (Active->SavedInNonInstantiationSFINAEContext)
      return std::optional<TemplateDeductionInfo *>(nullptr);
  }

  return std::nullopt;
}

//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
namespace {
  class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
    const MultiLevelTemplateArgumentList &TemplateArgs;
    SourceLocation Loc;
    DeclarationName Entity;
    // Whether to evaluate the C++20 constraints or simply substitute into them.
    bool EvaluateConstraints = true;
    // Whether Substitution was Incomplete, that is, we tried to substitute in
    // any user provided template arguments which were null.
    bool IsIncomplete = false;
    // Whether an incomplete substituion should be treated as an error.
    bool BailOutOnIncomplete;

  private:
    // CWG2770: Function parameters should be instantiated when they are
    // needed by a satisfaction check of an atomic constraint or
    // (recursively) by another function parameter.
    bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);

  public:
    typedef TreeTransform<TemplateInstantiator> inherited;

    TemplateInstantiator(Sema &SemaRef,
                         const MultiLevelTemplateArgumentList &TemplateArgs,
                         SourceLocation Loc, DeclarationName Entity,
                         bool BailOutOnIncomplete = false)
        : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
          Entity(Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}

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

    /// Determine whether the given type \p T has already been
    /// transformed.
    ///
    /// For the purposes of template instantiation, a type has already been
    /// transformed if it is NULL or if it is not dependent.
    bool AlreadyTransformed(QualType T);

    /// Returns the location of the entity being instantiated, if known.
    SourceLocation getBaseLocation() { return Loc; }

    /// Returns the name of the entity being instantiated, if any.
    DeclarationName getBaseEntity() { return Entity; }

    /// Returns whether any substitution so far was incomplete.
    bool getIsIncomplete() const { return IsIncomplete; }

    /// Sets the "base" location and entity when that
    /// information is known based on another transformation.
    void setBase(SourceLocation Loc, DeclarationName Entity) {
      this->Loc = Loc;
      this->Entity = Entity;
    }

    unsigned TransformTemplateDepth(unsigned Depth) {
      return TemplateArgs.getNewDepth(Depth);
    }

    bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
                                 SourceRange PatternRange,
                                 ArrayRef<UnexpandedParameterPack> Unexpanded,
                                 bool FailOnPackProducingTemplates,
                                 bool &ShouldExpand, bool &RetainExpansion,
                                 UnsignedOrNone &NumExpansions) {
      if (SemaRef.CurrentInstantiationScope &&
          SemaRef.inConstraintSubstitution()) {
        for (UnexpandedParameterPack ParmPack : Unexpanded) {
          NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
          if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
              PVD && maybeInstantiateFunctionParameterToScope(PVD))
            return true;
        }
      }

      return getSema().CheckParameterPacksForExpansion(
          EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
          FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
          NumExpansions);
    }

    void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
      SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
    }

    TemplateArgument ForgetPartiallySubstitutedPack() {
      TemplateArgument Result;
      if (NamedDecl *PartialPack
            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
        MultiLevelTemplateArgumentList &TemplateArgs
          = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
        unsigned Depth, Index;
        std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
        if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
          Result = TemplateArgs(Depth, Index);
          TemplateArgs.setArgument(Depth, Index, TemplateArgument());
        } else {
          IsIncomplete = true;
          if (BailOutOnIncomplete)
            return TemplateArgument();
        }
      }

      return Result;
    }

    void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
      if (Arg.isNull())
        return;

      if (NamedDecl *PartialPack
            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
        MultiLevelTemplateArgumentList &TemplateArgs
        = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
        unsigned Depth, Index;
        std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
        TemplateArgs.setArgument(Depth, Index, Arg);
      }
    }

    MultiLevelTemplateArgumentList ForgetSubstitution() {
      MultiLevelTemplateArgumentList New;
      New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());

      MultiLevelTemplateArgumentList Old =
          const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
      const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
          std::move(New);
      return Old;
    }
    void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
      const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
          std::move(Old);
    }

    TemplateArgument
    getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
      if (TA.getKind() != TemplateArgument::Pack)
        return TA;
      if (SemaRef.ArgPackSubstIndex)
        return SemaRef.getPackSubstitutedTemplateArgument(TA);
      assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
             "unexpected pack arguments in template rewrite");
      TemplateArgument Arg = *TA.pack_begin();
      if (Arg.isPackExpansion())
        Arg = Arg.getPackExpansionPattern();
      return Arg;
    }

    /// Transform the given declaration by instantiating a reference to
    /// this declaration.
    Decl *TransformDecl(SourceLocation Loc, Decl *D);

    void transformAttrs(Decl *Old, Decl *New) {
      SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
    }

    void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
      if (Old->isParameterPack() &&
          (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
        SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
        for (auto *New : NewDecls)
          SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
              Old, cast<VarDecl>(New));
        return;
      }

      assert(NewDecls.size() == 1 &&
             "should only have multiple expansions for a pack");
      Decl *New = NewDecls.front();

      // If we've instantiated the call operator of a lambda or the call
      // operator template of a generic lambda, update the "instantiation of"
      // information.
      auto *NewMD = dyn_cast<CXXMethodDecl>(New);
      if (NewMD && isLambdaCallOperator(NewMD)) {
        auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
        if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
          NewTD->setInstantiatedFromMemberTemplate(
              OldMD->getDescribedFunctionTemplate());
        else
          NewMD->setInstantiationOfMemberFunction(OldMD,
                                                  TSK_ImplicitInstantiation);
      }

      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);

      // We recreated a local declaration, but not by instantiating it. There
      // may be pending dependent diagnostics to produce.
      if (auto *DC = dyn_cast<DeclContext>(Old);
          DC && DC->isDependentContext() && DC->isFunctionOrMethod())
        SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
    }

    /// Transform the definition of the given declaration by
    /// instantiating it.
    Decl *TransformDefinition(SourceLocation Loc, Decl *D);

    /// Transform the first qualifier within a scope by instantiating the
    /// declaration.
    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);

    bool TransformExceptionSpec(SourceLocation Loc,
                                FunctionProtoType::ExceptionSpecInfo &ESI,
                                SmallVectorImpl<QualType> &Exceptions,
                                bool &Changed);

    /// Rebuild the exception declaration and register the declaration
    /// as an instantiated local.
    VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
                                  TypeSourceInfo *Declarator,
                                  SourceLocation StartLoc,
                                  SourceLocation NameLoc,
                                  IdentifierInfo *Name);

    /// Rebuild the Objective-C exception declaration and register the
    /// declaration as an instantiated local.
    VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
                                      TypeSourceInfo *TSInfo, QualType T);

    TemplateName
    TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
                          SourceLocation TemplateKWLoc, TemplateName Name,
                          SourceLocation NameLoc,
                          QualType ObjectType = QualType(),
                          NamedDecl *FirstQualifierInScope = nullptr,
                          bool AllowInjectedClassName = false);

    const AnnotateAttr *TransformAnnotateAttr(const AnnotateAttr *AA);
    const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
    const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
    const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
                                                  const Stmt *InstS,
                                                  const NoInlineAttr *A);
    const AlwaysInlineAttr *
    TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
                                  const AlwaysInlineAttr *A);
    const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
    const OpenACCRoutineDeclAttr *
    TransformOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A);
    ExprResult TransformPredefinedExpr(PredefinedExpr *E);
    ExprResult TransformDeclRefExpr(DeclRefExpr *E);
    ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);

    ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
                                            NonTypeTemplateParmDecl *D);

    /// Rebuild a DeclRefExpr for a VarDecl reference.
    ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);

    /// Transform a reference to a function or init-capture parameter pack.
    ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, ValueDecl *PD);

    /// Transform a FunctionParmPackExpr which was built when we couldn't
    /// expand a function parameter pack reference which refers to an expanded
    /// pack.
    ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);

    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                        FunctionProtoTypeLoc TL) {
      // Call the base version; it will forward to our overridden version below.
      return inherited::TransformFunctionProtoType(TLB, TL);
    }

    QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
      auto Type = inherited::TransformTagType(TLB, TL);
      if (!Type.isNull())
        return Type;
      // Special case for transforming a deduction guide, we return a
      // transformed TemplateSpecializationType.
      // FIXME: Why is this hack necessary?
      if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
          ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
                      Sema::CodeSynthesisContext::BuildingDeductionGuides) {
        Type = inherited::TransformType(
            ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType(
                SemaRef.Context));
        TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
      }
      return Type;
    }
    // Override the default version to handle a rewrite-template-arg-pack case
    // for building a deduction guide.
    bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
                                   TemplateArgumentLoc &Output,
                                   bool Uneval = false) {
      const TemplateArgument &Arg = Input.getArgument();
      std::vector<TemplateArgument> TArgs;
      switch (Arg.getKind()) {
      case TemplateArgument::Pack:
        assert(SemaRef.CodeSynthesisContexts.empty() ||
               SemaRef.CodeSynthesisContexts.back().Kind ==
                   Sema::CodeSynthesisContext::BuildingDeductionGuides);
        // Literally rewrite the template argument pack, instead of unpacking
        // it.
        for (auto &pack : Arg.getPackAsArray()) {
          TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
              pack, QualType(), SourceLocation{});
          TemplateArgumentLoc Output;
          if (TransformTemplateArgument(Input, Output, Uneval))
            return true; // fails
          TArgs.push_back(Output.getArgument());
        }
        Output = SemaRef.getTrivialTemplateArgumentLoc(
            TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
            QualType(), SourceLocation{});
        return false;
      default:
        break;
      }
      return inherited::TransformTemplateArgument(Input, Output, Uneval);
    }

    using TreeTransform::TransformTemplateSpecializationType;
    QualType
    TransformTemplateSpecializationType(TypeLocBuilder &TLB,
                                        TemplateSpecializationTypeLoc TL) {
      auto *T = TL.getTypePtr();
      if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
          !isPackProducingBuiltinTemplateName(T->getTemplateName()))
        return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
      // Look through sugar to get to the SubstBuiltinTemplatePackType that we
      // need to substitute into.

      // `TransformType` code below will handle picking the element from a pack
      // with the index `ArgPackSubstIndex`.
      // FIXME: add ability to represent sugarred type for N-th element of a
      // builtin pack and produce the sugar here.
      QualType R = TransformType(T->desugar());
      TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
      return R;
    }

    UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
        ArrayRef<TemplateArgument> PackArgs) {
      // Don't do this when rewriting template parameters for CTAD:
      //   1) The heuristic needs the unpacked Subst* nodes to figure out the
      //   expanded size, but this never applies since Subst* nodes are not
      //   created in rewrite scenarios.
      //
      //   2) The heuristic substitutes into the pattern with pack expansion
      //   suppressed, which does not meet the requirements for argument
      //   rewriting when template arguments include a non-pack matching against
      //   a pack, particularly when rewriting an alias CTAD.
      if (TemplateArgs.isRewrite())
        return std::nullopt;

      return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
    }

    template<typename Fn>
    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                        FunctionProtoTypeLoc TL,
                                        CXXRecordDecl *ThisContext,
                                        Qualifiers ThisTypeQuals,
                                        Fn TransformExceptionSpec);

    ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
                                            int indexAdjustment,
                                            UnsignedOrNone NumExpansions,
                                            bool ExpectParameterPack);

    using inherited::TransformTemplateTypeParmType;
    /// Transforms a template type parameter type by performing
    /// substitution of the corresponding template type argument.
    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
                                           TemplateTypeParmTypeLoc TL,
                                           bool SuppressObjCLifetime);

    QualType BuildSubstTemplateTypeParmType(
        TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
        Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex,
        TemplateArgument Arg, SourceLocation NameLoc);

    /// Transforms an already-substituted template type parameter pack
    /// into either itself (if we aren't substituting into its pack expansion)
    /// or the appropriate substituted argument.
    using inherited::TransformSubstTemplateTypeParmPackType;
    QualType
    TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
                                           SubstTemplateTypeParmPackTypeLoc TL,
                                           bool SuppressObjCLifetime);
    QualType
    TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
                                          SubstBuiltinTemplatePackTypeLoc TL);

    CXXRecordDecl::LambdaDependencyKind
    ComputeLambdaDependency(LambdaScopeInfo *LSI) {
      if (auto TypeAlias =
              TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
                  getSema());
          TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
                           LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
        unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
        if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
          return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
        for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments)
          if (TA.isDependent())
            return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
      }
      return inherited::ComputeLambdaDependency(LSI);
    }

    ExprResult TransformLambdaExpr(LambdaExpr *E) {
      // Do not rebuild lambdas to avoid creating a new type.
      // Lambdas have already been processed inside their eval contexts.
      if (SemaRef.RebuildingImmediateInvocation)
        return E;
      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
                                    /*InstantiatingLambdaOrBlock=*/true);
      Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);

      return inherited::TransformLambdaExpr(E);
    }

    ExprResult TransformBlockExpr(BlockExpr *E) {
      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
                                    /*InstantiatingLambdaOrBlock=*/true);
      return inherited::TransformBlockExpr(E);
    }

    ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
                                 LambdaScopeInfo *LSI) {
      CXXMethodDecl *MD = LSI->CallOperator;
      for (ParmVarDecl *PVD : MD->parameters()) {
        assert(PVD && "null in a parameter list");
        if (!PVD->hasDefaultArg())
          continue;
        Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
        // FIXME: Obtain the source location for the '=' token.
        SourceLocation EqualLoc = UninstExpr->getBeginLoc();
        if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
          // If substitution fails, the default argument is set to a
          // RecoveryExpr that wraps the uninstantiated default argument so
          // that downstream diagnostics are omitted.
          ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
              UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
              UninstExpr->getType());
          if (ErrorResult.isUsable())
            PVD->setDefaultArg(ErrorResult.get());
        }
      }
      return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
    }

    StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
      // Currently, we instantiate the body when instantiating the lambda
      // expression. However, `EvaluateConstraints` is disabled during the
      // instantiation of the lambda expression, causing the instantiation
      // failure of the return type requirement in the body. If p0588r1 is fully
      // implemented, the body will be lazily instantiated, and this problem
      // will not occur. Here, `EvaluateConstraints` is temporarily set to
      // `true` to temporarily fix this issue.
      // FIXME: This temporary fix can be removed after fully implementing
      // p0588r1.
      llvm::SaveAndRestore _(EvaluateConstraints, true);
      return inherited::TransformLambdaBody(E, Body);
    }

    ExprResult TransformRequiresExpr(RequiresExpr *E) {
      LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
      ExprResult TransReq = inherited::TransformRequiresExpr(E);
      if (TransReq.isInvalid())
        return TransReq;
      assert(TransReq.get() != E &&
             "Do not change value of isSatisfied for the existing expression. "
             "Create a new expression instead.");
      if (E->getBody()->isDependentContext()) {
        Sema::SFINAETrap Trap(SemaRef);
        // We recreate the RequiresExpr body, but not by instantiating it.
        // Produce pending diagnostics for dependent access check.
        SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
        // FIXME: Store SFINAE diagnostics in RequiresExpr for diagnosis.
        if (Trap.hasErrorOccurred())
          TransReq.getAs<RequiresExpr>()->setSatisfied(false);
      }
      return TransReq;
    }

    bool TransformRequiresExprRequirements(
        ArrayRef<concepts::Requirement *> Reqs,
        SmallVectorImpl<concepts::Requirement *> &Transformed) {
      bool SatisfactionDetermined = false;
      for (concepts::Requirement *Req : Reqs) {
        concepts::Requirement *TransReq = nullptr;
        if (!SatisfactionDetermined) {
          if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
            TransReq = TransformTypeRequirement(TypeReq);
          else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
            TransReq = TransformExprRequirement(ExprReq);
          else
            TransReq = TransformNestedRequirement(
                cast<concepts::NestedRequirement>(Req));
          if (!TransReq)
            return true;
          if (!TransReq->isDependent() && !TransReq->isSatisfied())
            // [expr.prim.req]p6
            //   [...]  The substitution and semantic constraint checking
            //   proceeds in lexical order and stops when a condition that
            //   determines the result of the requires-expression is
            //   encountered. [..]
            SatisfactionDetermined = true;
        } else
          TransReq = Req;
        Transformed.push_back(TransReq);
      }
      return false;
    }

    TemplateParameterList *TransformTemplateParameterList(
                              TemplateParameterList *OrigTPL)  {
      if (!OrigTPL || !OrigTPL->size()) return OrigTPL;

      DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
      TemplateDeclInstantiator  DeclInstantiator(getSema(),
                        /* DeclContext *Owner */ Owner, TemplateArgs);
      DeclInstantiator.setEvaluateConstraints(EvaluateConstraints);
      return DeclInstantiator.SubstTemplateParams(OrigTPL);
    }

    concepts::TypeRequirement *
    TransformTypeRequirement(concepts::TypeRequirement *Req);
    concepts::ExprRequirement *
    TransformExprRequirement(concepts::ExprRequirement *Req);
    concepts::NestedRequirement *
    TransformNestedRequirement(concepts::NestedRequirement *Req);
    ExprResult TransformRequiresTypeParams(
        SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
        RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
        SmallVectorImpl<QualType> &PTypes,
        SmallVectorImpl<ParmVarDecl *> &TransParams,
        Sema::ExtParameterInfoBuilder &PInfos);
  };
}

bool TemplateInstantiator::AlreadyTransformed(QualType T) {
  if (T.isNull())
    return true;

  if (T->isInstantiationDependentType() || T->isVariablyModifiedType() ||
      T->containsUnexpandedParameterPack())
    return false;

  getSema().MarkDeclarationsReferencedInType(Loc, T);
  return true;
}

Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
  if (!D)
    return nullptr;

  if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
      // If the corresponding template argument is NULL or non-existent, it's
      // because we are performing instantiation from explicitly-specified
      // template arguments in a function template, but there were some
      // arguments left unspecified.
      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
                                            TTP->getPosition())) {
        IsIncomplete = true;
        return BailOutOnIncomplete ? nullptr : D;
      }

      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());

      if (TTP->isParameterPack()) {
        assert(Arg.getKind() == TemplateArgument::Pack &&
               "Missing argument pack");
        Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
      }

      TemplateName Template = Arg.getAsTemplate();
      assert(!Template.isNull() && Template.getAsTemplateDecl() &&
             "Wrong kind of template template argument");
      return Template.getAsTemplateDecl();
    }

    // Fall through to find the instantiated declaration for this template
    // template parameter.
  }

  if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D);
      PVD && SemaRef.CurrentInstantiationScope &&
      SemaRef.inConstraintSubstitution() &&
      maybeInstantiateFunctionParameterToScope(PVD))
    return nullptr;

  return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
}

bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope(
    ParmVarDecl *OldParm) {
  if (SemaRef.CurrentInstantiationScope->getInstantiationOfIfExists(OldParm))
    return false;

  if (!OldParm->isParameterPack())
    return !TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
                                       /*NumExpansions=*/std::nullopt,
                                       /*ExpectParameterPack=*/false);

  SmallVector<UnexpandedParameterPack, 2> Unexpanded;

  // Find the parameter packs that could be expanded.
  TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
  PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>();
  TypeLoc Pattern = ExpansionTL.getPatternLoc();
  SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
  assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");

  bool ShouldExpand = false;
  bool RetainExpansion = false;
  UnsignedOrNone OrigNumExpansions =
      ExpansionTL.getTypePtr()->getNumExpansions();
  UnsignedOrNone NumExpansions = OrigNumExpansions;
  if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
                              Pattern.getSourceRange(), Unexpanded,
                              /*FailOnPackProducingTemplates=*/true,
                              ShouldExpand, RetainExpansion, NumExpansions))
    return true;

  assert(ShouldExpand && !RetainExpansion &&
         "Shouldn't preserve pack expansion when evaluating constraints");
  ExpandingFunctionParameterPack(OldParm);
  for (unsigned I = 0; I != *NumExpansions; ++I) {
    Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), I);
    if (!TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
                                    /*NumExpansions=*/OrigNumExpansions,
                                    /*ExpectParameterPack=*/false))
      return true;
  }
  return false;
}

Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
  Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
  if (!Inst)
    return nullptr;

  getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
  return Inst;
}

bool TemplateInstantiator::TransformExceptionSpec(
    SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI,
    SmallVectorImpl<QualType> &Exceptions, bool &Changed) {
  if (ESI.Type == EST_Uninstantiated) {
    ESI.instantiate();
    Changed = true;
  }
  return inherited::TransformExceptionSpec(Loc, ESI, Exceptions, Changed);
}

NamedDecl *
TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
                                                     SourceLocation Loc) {
  // If the first part of the nested-name-specifier was a template type
  // parameter, instantiate that type parameter down to a tag type.
  if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
    const TemplateTypeParmType *TTP
      = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));

    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
      // FIXME: This needs testing w/ member access expressions.
      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());

      if (TTP->isParameterPack()) {
        assert(Arg.getKind() == TemplateArgument::Pack &&
               "Missing argument pack");

        if (!getSema().ArgPackSubstIndex)
          return nullptr;

        Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
      }

      QualType T = Arg.getAsType();
      if (T.isNull())
        return cast_or_null<NamedDecl>(TransformDecl(Loc, D));

      if (const TagType *Tag = T->getAs<TagType>())
        return Tag->getOriginalDecl();

      // The resulting type is not a tag; complain.
      getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
      return nullptr;
    }
  }

  return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
}

VarDecl *
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
                                           TypeSourceInfo *Declarator,
                                           SourceLocation StartLoc,
                                           SourceLocation NameLoc,
                                           IdentifierInfo *Name) {
  VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
                                                 StartLoc, NameLoc, Name);
  if (Var)
    getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
  return Var;
}

VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
                                                        TypeSourceInfo *TSInfo,
                                                        QualType T) {
  VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
  if (Var)
    getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
  return Var;
}

TemplateName TemplateInstantiator::TransformTemplateName(
    NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
    TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
    NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
  if (Name.getKind() == TemplateName::Template) {
    assert(!QualifierLoc && "Unexpected qualifier");
    if (auto *TTP =
            dyn_cast<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
        TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
      // If the corresponding template argument is NULL or non-existent, it's
      // because we are performing instantiation from explicitly-specified
      // template arguments in a function template, but there were some
      // arguments left unspecified.
      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
                                            TTP->getPosition())) {
        IsIncomplete = true;
        return BailOutOnIncomplete ? TemplateName() : Name;
      }

      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());

      if (TemplateArgs.isRewrite()) {
        // We're rewriting the template parameter as a reference to another
        // template parameter.
        Arg = getTemplateArgumentPackPatternForRewrite(Arg);
        assert(Arg.getKind() == TemplateArgument::Template &&
               "unexpected nontype template argument kind in template rewrite");
        return Arg.getAsTemplate();
      }

      auto [AssociatedDecl, Final] =
          TemplateArgs.getAssociatedDecl(TTP->getDepth());
      UnsignedOrNone PackIndex = std::nullopt;
      if (TTP->isParameterPack()) {
        assert(Arg.getKind() == TemplateArgument::Pack &&
               "Missing argument pack");

        if (!getSema().ArgPackSubstIndex) {
          // We have the template argument pack to substitute, but we're not
          // actually expanding the enclosing pack expansion yet. So, just
          // keep the entire argument pack.
          return getSema().Context.getSubstTemplateTemplateParmPack(
              Arg, AssociatedDecl, TTP->getIndex(), Final);
        }

        PackIndex = SemaRef.getPackIndex(Arg);
        Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
      }

      TemplateName Template = Arg.getAsTemplate();
      assert(!Template.isNull() && "Null template template argument");
      return getSema().Context.getSubstTemplateTemplateParm(
          Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
    }
  }

  if (SubstTemplateTemplateParmPackStorage *SubstPack
      = Name.getAsSubstTemplateTemplateParmPack()) {
    if (!getSema().ArgPackSubstIndex)
      return Name;

    TemplateArgument Pack = SubstPack->getArgumentPack();
    TemplateName Template =
        SemaRef.getPackSubstitutedTemplateArgument(Pack).getAsTemplate();
    return getSema().Context.getSubstTemplateTemplateParm(
        Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
        SemaRef.getPackIndex(Pack), SubstPack->getFinal());
  }

  return inherited::TransformTemplateName(
      QualifierLoc, TemplateKWLoc, Name, NameLoc, ObjectType,
      FirstQualifierInScope, AllowInjectedClassName);
}

ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
  if (!E->isTypeDependent())
    return E;

  return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
}

ExprResult
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
                                               NonTypeTemplateParmDecl *NTTP) {
  // If the corresponding template argument is NULL or non-existent, it's
  // because we are performing instantiation from explicitly-specified
  // template arguments in a function template, but there were some
  // arguments left unspecified.
  if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
                                        NTTP->getPosition())) {
    IsIncomplete = true;
    return BailOutOnIncomplete ? ExprError() : E;
  }

  TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());

  if (TemplateArgs.isRewrite()) {
    // We're rewriting the template parameter as a reference to another
    // template parameter.
    Arg = getTemplateArgumentPackPatternForRewrite(Arg);
    assert(Arg.getKind() == TemplateArgument::Expression &&
           "unexpected nontype template argument kind in template rewrite");
    // FIXME: This can lead to the same subexpression appearing multiple times
    // in a complete expression.
    return Arg.getAsExpr();
  }

  auto [AssociatedDecl, Final] =
      TemplateArgs.getAssociatedDecl(NTTP->getDepth());
  UnsignedOrNone PackIndex = std::nullopt;
  if (NTTP->isParameterPack()) {
    assert(Arg.getKind() == TemplateArgument::Pack &&
           "Missing argument pack");

    if (!getSema().ArgPackSubstIndex) {
      // We have an argument pack, but we can't select a particular argument
      // out of it yet. Therefore, we'll build an expression to hold on to that
      // argument pack.
      QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
                                              E->getLocation(),
                                              NTTP->getDeclName());
      if (TargetType.isNull())
        return ExprError();

      QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context);
      if (TargetType->isRecordType())
        ExprType.addConst();
      return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
          ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
          E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition(), Final);
    }
    PackIndex = SemaRef.getPackIndex(Arg);
    Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
  }
  return SemaRef.BuildSubstNonTypeTemplateParmExpr(
      AssociatedDecl, NTTP, E->getLocation(), Arg, PackIndex, Final);
}

const AnnotateAttr *
TemplateInstantiator::TransformAnnotateAttr(const AnnotateAttr *AA) {
  SmallVector<Expr *> Args;
  for (Expr *Arg : AA->args()) {
    ExprResult Res = getDerived().TransformExpr(Arg);
    if (Res.isUsable())
      Args.push_back(Res.get());
  }
  return AnnotateAttr::CreateImplicit(getSema().Context, AA->getAnnotation(),
                                      Args.data(), Args.size(), AA->getRange());
}

const CXXAssumeAttr *
TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) {
  ExprResult Res = getDerived().TransformExpr(AA->getAssumption());
  if (!Res.isUsable())
    return AA;

  if (!(Res.get()->getDependence() & ExprDependence::TypeValueInstantiation)) {
    Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
                                       AA->getRange());
    if (!Res.isUsable())
      return AA;
  }

  return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(),
                                       AA->getRange());
}

const LoopHintAttr *
TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
  Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();

  if (TransformedExpr == LH->getValue())
    return LH;

  // Generate error if there is a problem with the value.
  if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation(),
                                  LH->getSemanticSpelling() ==
                                      LoopHintAttr::Pragma_unroll))
    return LH;

  LoopHintAttr::OptionType Option = LH->getOption();
  LoopHintAttr::LoopHintState State = LH->getState();

  llvm::APSInt ValueAPS =
      TransformedExpr->EvaluateKnownConstInt(getSema().getASTContext());
  // The values of 0 and 1 block any unrolling of the loop.
  if (ValueAPS.isZero() || ValueAPS.isOne()) {
    Option = LoopHintAttr::Unroll;
    State = LoopHintAttr::Disable;
  }

  // Create new LoopHintValueAttr with integral expression in place of the
  // non-type template parameter.
  return LoopHintAttr::CreateImplicit(getSema().Context, Option, State,
                                      TransformedExpr, *LH);
}
const NoInlineAttr *TemplateInstantiator::TransformStmtNoInlineAttr(
    const Stmt *OrigS, const Stmt *InstS, const NoInlineAttr *A) {
  if (!A || getSema().CheckNoInlineAttr(OrigS, InstS, *A))
    return nullptr;

  return A;
}
const AlwaysInlineAttr *TemplateInstantiator::TransformStmtAlwaysInlineAttr(
    const Stmt *OrigS, const Stmt *InstS, const AlwaysInlineAttr *A) {
  if (!A || getSema().CheckAlwaysInlineAttr(OrigS, InstS, *A))
    return nullptr;

  return A;
}

const CodeAlignAttr *
TemplateInstantiator::TransformCodeAlignAttr(const CodeAlignAttr *CA) {
  Expr *TransformedExpr = getDerived().TransformExpr(CA->getAlignment()).get();
  return getSema().BuildCodeAlignAttr(*CA, TransformedExpr);
}
const OpenACCRoutineDeclAttr *
TemplateInstantiator::TransformOpenACCRoutineDeclAttr(
    const OpenACCRoutineDeclAttr *A) {
  llvm_unreachable("RoutineDecl should only be a declaration attribute, as it "
                   "applies to a Function Decl (and a few places for VarDecl)");
}

ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(ValueDecl *PD,
                                                       SourceLocation Loc) {
  DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
  return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
}

ExprResult
TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
  if (getSema().ArgPackSubstIndex) {
    // We can expand this parameter pack now.
    ValueDecl *D = E->getExpansion(*getSema().ArgPackSubstIndex);
    ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D));
    if (!VD)
      return ExprError();
    return RebuildVarDeclRefExpr(VD, E->getExprLoc());
  }

  QualType T = TransformType(E->getType());
  if (T.isNull())
    return ExprError();

  // Transform each of the parameter expansions into the corresponding
  // parameters in the instantiation of the function decl.
  SmallVector<ValueDecl *, 8> Vars;
  Vars.reserve(E->getNumExpansions());
  for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
       I != End; ++I) {
    ValueDecl *D = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), *I));
    if (!D)
      return ExprError();
    Vars.push_back(D);
  }

  auto *PackExpr =
      FunctionParmPackExpr::Create(getSema().Context, T, E->getParameterPack(),
                                   E->getParameterPackLocation(), Vars);
  getSema().MarkFunctionParmPackReferenced(PackExpr);
  return PackExpr;
}

ExprResult
TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
                                                       ValueDecl *PD) {
  typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
    = getSema().CurrentInstantiationScope->findInstantiationOf(PD);
  assert(Found && "no instantiation for parameter pack");

  Decl *TransformedDecl;
  if (DeclArgumentPack *Pack = dyn_cast<DeclArgumentPack *>(*Found)) {
    // If this is a reference to a function parameter pack which we can
    // substitute but can't yet expand, build a FunctionParmPackExpr for it.
    if (!getSema().ArgPackSubstIndex) {
      QualType T = TransformType(E->getType());
      if (T.isNull())
        return ExprError();
      auto *PackExpr = FunctionParmPackExpr::Create(getSema().Context, T, PD,
                                                    E->getExprLoc(), *Pack);
      getSema().MarkFunctionParmPackReferenced(PackExpr);
      return PackExpr;
    }

    TransformedDecl = (*Pack)[*getSema().ArgPackSubstIndex];
  } else {
    TransformedDecl = cast<Decl *>(*Found);
  }

  // We have either an unexpanded pack or a specific expansion.
  return RebuildVarDeclRefExpr(cast<ValueDecl>(TransformedDecl),
                               E->getExprLoc());
}

ExprResult
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
  NamedDecl *D = E->getDecl();

  // Handle references to non-type template parameters and non-type template
  // parameter packs.
  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
    if (NTTP->getDepth() < TemplateArgs.getNumLevels())
      return TransformTemplateParmRefExpr(E, NTTP);

    // We have a non-type template parameter that isn't fully substituted;
    // FindInstantiatedDecl will find it in the local instantiation scope.
  }

  // Handle references to function parameter packs.
  if (VarDecl *PD = dyn_cast<VarDecl>(D))
    if (PD->isParameterPack())
      return TransformFunctionParmPackRefExpr(E, PD);

  return inherited::TransformDeclRefExpr(E);
}

ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
    CXXDefaultArgExpr *E) {
  assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
             getDescribedFunctionTemplate() &&
         "Default arg expressions are never formed in dependent cases.");
  return SemaRef.BuildCXXDefaultArgExpr(
      E->getUsedLocation(), cast<FunctionDecl>(E->getParam()->getDeclContext()),
      E->getParam());
}

template<typename Fn>
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
                                 FunctionProtoTypeLoc TL,
                                 CXXRecordDecl *ThisContext,
                                 Qualifiers ThisTypeQuals,
                                 Fn TransformExceptionSpec) {
  // If this is a lambda or block, the transformation MUST be done in the
  // CurrentInstantiationScope since it introduces a mapping of
  // the original to the newly created transformed parameters.
  //
  // In that case, TemplateInstantiator::TransformLambdaExpr will
  // have already pushed a scope for this prototype, so don't create
  // a second one.
  LocalInstantiationScope *Current = getSema().CurrentInstantiationScope;
  std::optional<LocalInstantiationScope> Scope;
  if (!Current || !Current->isLambdaOrBlock())
    Scope.emplace(SemaRef, /*CombineWithOuterScope=*/true);

  return inherited::TransformFunctionProtoType(
      TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
}

ParmVarDecl *TemplateInstantiator::TransformFunctionTypeParam(
    ParmVarDecl *OldParm, int indexAdjustment, UnsignedOrNone NumExpansions,
    bool ExpectParameterPack) {
  auto NewParm = SemaRef.SubstParmVarDecl(
      OldParm, TemplateArgs, indexAdjustment, NumExpansions,
      ExpectParameterPack, EvaluateConstraints);
  if (NewParm && SemaRef.getLangOpts().OpenCL)
    SemaRef.deduceOpenCLAddressSpace(NewParm);
  return NewParm;
}

QualType TemplateInstantiator::BuildSubstTemplateTypeParmType(
    TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
    Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex,
    TemplateArgument Arg, SourceLocation NameLoc) {
  QualType Replacement = Arg.getAsType();

  // If the template parameter had ObjC lifetime qualifiers,
  // then any such qualifiers on the replacement type are ignored.
  if (SuppressObjCLifetime) {
    Qualifiers RQs;
    RQs = Replacement.getQualifiers();
    RQs.removeObjCLifetime();
    Replacement =
        SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(), RQs);
  }

  // TODO: only do this uniquing once, at the start of instantiation.
  QualType Result = getSema().Context.getSubstTemplateTypeParmType(
      Replacement, AssociatedDecl, Index, PackIndex, Final);
  SubstTemplateTypeParmTypeLoc NewTL =
      TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
  NewTL.setNameLoc(NameLoc);
  return Result;
}

QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
                                                    TemplateTypeParmTypeLoc TL,
                                                    bool SuppressObjCLifetime) {
  const TemplateTypeParmType *T = TL.getTypePtr();
  if (T->getDepth() < TemplateArgs.getNumLevels()) {
    // Replace the template type parameter with its corresponding
    // template argument.

    // If the corresponding template argument is NULL or doesn't exist, it's
    // because we are performing instantiation from explicitly-specified
    // template arguments in a function template class, but there were some
    // arguments left unspecified.
    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
      IsIncomplete = true;
      if (BailOutOnIncomplete)
        return QualType();

      TemplateTypeParmTypeLoc NewTL
        = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
      NewTL.setNameLoc(TL.getNameLoc());
      return TL.getType();
    }

    TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());

    if (TemplateArgs.isRewrite()) {
      // We're rewriting the template parameter as a reference to another
      // template parameter.
      Arg = getTemplateArgumentPackPatternForRewrite(Arg);
      assert(Arg.getKind() == TemplateArgument::Type &&
             "unexpected nontype template argument kind in template rewrite");
      QualType NewT = Arg.getAsType();
      TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc());
      return NewT;
    }

    auto [AssociatedDecl, Final] =
        TemplateArgs.getAssociatedDecl(T->getDepth());
    UnsignedOrNone PackIndex = std::nullopt;
    if (T->isParameterPack()) {
      assert(Arg.getKind() == TemplateArgument::Pack &&
             "Missing argument pack");

      if (!getSema().ArgPackSubstIndex) {
        // We have the template argument pack, but we're not expanding the
        // enclosing pack expansion yet. Just save the template argument
        // pack for later substitution.
        QualType Result = getSema().Context.getSubstTemplateTypeParmPackType(
            AssociatedDecl, T->getIndex(), Final, Arg);
        SubstTemplateTypeParmPackTypeLoc NewTL
          = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
        NewTL.setNameLoc(TL.getNameLoc());
        return Result;
      }

      // PackIndex starts from last element.
      PackIndex = SemaRef.getPackIndex(Arg);
      Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
    }

    assert(Arg.getKind() == TemplateArgument::Type &&
           "Template argument kind mismatch");

    return BuildSubstTemplateTypeParmType(TLB, SuppressObjCLifetime, Final,
                                          AssociatedDecl, T->getIndex(),
                                          PackIndex, Arg, TL.getNameLoc());
  }

  // The template type parameter comes from an inner template (e.g.,
  // the template parameter list of a member template inside the
  // template we are instantiating). Create a new template type
  // parameter with the template "level" reduced by one.
  TemplateTypeParmDecl *NewTTPDecl = nullptr;
  if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
    NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
        TransformDecl(TL.getNameLoc(), OldTTPDecl));
  QualType Result = getSema().Context.getTemplateTypeParmType(
      T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
      T->isParameterPack(), NewTTPDecl);
  TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
  NewTL.setNameLoc(TL.getNameLoc());
  return Result;
}

QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
    TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL,
    bool SuppressObjCLifetime) {
  const SubstTemplateTypeParmPackType *T = TL.getTypePtr();

  Decl *NewReplaced = TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());

  if (!getSema().ArgPackSubstIndex) {
    // We aren't expanding the parameter pack, so just return ourselves.
    QualType Result = TL.getType();
    if (NewReplaced != T->getAssociatedDecl())
      Result = getSema().Context.getSubstTemplateTypeParmPackType(
          NewReplaced, T->getIndex(), T->getFinal(), T->getArgumentPack());
    SubstTemplateTypeParmPackTypeLoc NewTL =
        TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
    NewTL.setNameLoc(TL.getNameLoc());
    return Result;
  }

  TemplateArgument Pack = T->getArgumentPack();
  TemplateArgument Arg = SemaRef.getPackSubstitutedTemplateArgument(Pack);
  return BuildSubstTemplateTypeParmType(
      TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
      SemaRef.getPackIndex(Pack), Arg, TL.getNameLoc());
}

QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
    TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
  if (!getSema().ArgPackSubstIndex)
    return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
  TemplateArgument Result = SemaRef.getPackSubstitutedTemplateArgument(
      TL.getTypePtr()->getArgumentPack());
  TLB.pushTrivial(SemaRef.getASTContext(), Result.getAsType(),
                  TL.getBeginLoc());
  return Result.getAsType();
}

static concepts::Requirement::SubstitutionDiagnostic *
createSubstDiag(Sema &S, TemplateDeductionInfo &Info,
                Sema::EntityPrinter Printer) {
  SmallString<128> Message;
  SourceLocation ErrorLoc;
  if (Info.hasSFINAEDiagnostic()) {
    PartialDiagnosticAt PDA(SourceLocation(),
                            PartialDiagnostic::NullDiagnostic{});
    Info.takeSFINAEDiagnostic(PDA);
    PDA.second.EmitToString(S.getDiagnostics(), Message);
    ErrorLoc = PDA.first;
  } else {
    ErrorLoc = Info.getLocation();
  }
  SmallString<128> Entity;
  llvm::raw_svector_ostream OS(Entity);
  Printer(OS);
  const ASTContext &C = S.Context;
  return new (C) concepts::Requirement::SubstitutionDiagnostic{
      C.backupStr(Entity), ErrorLoc, C.backupStr(Message)};
}

concepts::Requirement::SubstitutionDiagnostic *
Sema::createSubstDiagAt(SourceLocation Location, EntityPrinter Printer) {
  SmallString<128> Entity;
  llvm::raw_svector_ostream OS(Entity);
  Printer(OS);
  const ASTContext &C = Context;
  return new (C) concepts::Requirement::SubstitutionDiagnostic{
      /*SubstitutedEntity=*/C.backupStr(Entity),
      /*DiagLoc=*/Location, /*DiagMessage=*/StringRef()};
}

ExprResult TemplateInstantiator::TransformRequiresTypeParams(
    SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
    RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
    SmallVectorImpl<QualType> &PTypes,
    SmallVectorImpl<ParmVarDecl *> &TransParams,
    Sema::ExtParameterInfoBuilder &PInfos) {

  TemplateDeductionInfo Info(KWLoc);
  Sema::InstantiatingTemplate TypeInst(SemaRef, KWLoc,
                                       RE, Info,
                                       SourceRange{KWLoc, RBraceLoc});
  Sema::SFINAETrap Trap(SemaRef);

  unsigned ErrorIdx;
  if (getDerived().TransformFunctionTypeParams(
          KWLoc, Params, /*ParamTypes=*/nullptr, /*ParamInfos=*/nullptr, PTypes,
          &TransParams, PInfos, &ErrorIdx) ||
      Trap.hasErrorOccurred()) {
    SmallVector<concepts::Requirement *, 4> TransReqs;
    ParmVarDecl *FailedDecl = Params[ErrorIdx];
    // Add a 'failed' Requirement to contain the error that caused the failure
    // here.
    TransReqs.push_back(RebuildTypeRequirement(createSubstDiag(
        SemaRef, Info, [&](llvm::raw_ostream &OS) { OS << *FailedDecl; })));
    return getDerived().RebuildRequiresExpr(KWLoc, Body, RE->getLParenLoc(),
                                            TransParams, RE->getRParenLoc(),
                                            TransReqs, RBraceLoc);
  }

  return ExprResult{};
}

concepts::TypeRequirement *
TemplateInstantiator::TransformTypeRequirement(concepts::TypeRequirement *Req) {
  if (!Req->isDependent() && !AlwaysRebuild())
    return Req;
  if (Req->isSubstitutionFailure()) {
    if (AlwaysRebuild())
      return RebuildTypeRequirement(
              Req->getSubstitutionDiagnostic());
    return Req;
  }

  Sema::SFINAETrap Trap(SemaRef);
  TemplateDeductionInfo Info(Req->getType()->getTypeLoc().getBeginLoc());
  Sema::InstantiatingTemplate TypeInst(SemaRef,
      Req->getType()->getTypeLoc().getBeginLoc(), Req, Info,
      Req->getType()->getTypeLoc().getSourceRange());
  if (TypeInst.isInvalid())
    return nullptr;
  TypeSourceInfo *TransType = TransformType(Req->getType());
  if (!TransType || Trap.hasErrorOccurred())
    return RebuildTypeRequirement(createSubstDiag(SemaRef, Info,
        [&] (llvm::raw_ostream& OS) {
            Req->getType()->getType().print(OS, SemaRef.getPrintingPolicy());
        }));
  return RebuildTypeRequirement(TransType);
}

concepts::ExprRequirement *
TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
  if (!Req->isDependent() && !AlwaysRebuild())
    return Req;

  Sema::SFINAETrap Trap(SemaRef);

  llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *>
      TransExpr;
  if (Req->isExprSubstitutionFailure())
    TransExpr = Req->getExprSubstitutionDiagnostic();
  else {
    Expr *E = Req->getExpr();
    TemplateDeductionInfo Info(E->getBeginLoc());
    Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info,
                                         E->getSourceRange());
    if (ExprInst.isInvalid())
      return nullptr;
    ExprResult TransExprRes = TransformExpr(E);
    if (!TransExprRes.isInvalid() && !Trap.hasErrorOccurred() &&
        TransExprRes.get()->hasPlaceholderType())
      TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
    if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
      TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream &OS) {
        E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
      });
    else
      TransExpr = TransExprRes.get();
  }

  std::optional<concepts::ExprRequirement::ReturnTypeRequirement> TransRetReq;
  const auto &RetReq = Req->getReturnTypeRequirement();
  if (RetReq.isEmpty())
    TransRetReq.emplace();
  else if (RetReq.isSubstitutionFailure())
    TransRetReq.emplace(RetReq.getSubstitutionDiagnostic());
  else if (RetReq.isTypeConstraint()) {
    TemplateParameterList *OrigTPL =
        RetReq.getTypeConstraintTemplateParameterList();
    TemplateDeductionInfo Info(OrigTPL->getTemplateLoc());
    Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(),
                                        Req, Info, OrigTPL->getSourceRange());
    if (TPLInst.isInvalid())
      return nullptr;
    TemplateParameterList *TPL = TransformTemplateParameterList(OrigTPL);
    if (!TPL || Trap.hasErrorOccurred())
      TransRetReq.emplace(createSubstDiag(SemaRef, Info,
          [&] (llvm::raw_ostream& OS) {
              RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()
                  ->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
          }));
    else {
      TPLInst.Clear();
      TransRetReq.emplace(TPL);
    }
  }
  assert(TransRetReq && "All code paths leading here must set TransRetReq");
  if (Expr *E = TransExpr.dyn_cast<Expr *>())
    return RebuildExprRequirement(E, Req->isSimple(), Req->getNoexceptLoc(),
                                  std::move(*TransRetReq));
  return RebuildExprRequirement(
      cast<concepts::Requirement::SubstitutionDiagnostic *>(TransExpr),
      Req->isSimple(), Req->getNoexceptLoc(), std::move(*TransRetReq));
}

concepts::NestedRequirement *
TemplateInstantiator::TransformNestedRequirement(
    concepts::NestedRequirement *Req) {
  if (!Req->isDependent() && !AlwaysRebuild())
    return Req;
  if (Req->hasInvalidConstraint()) {
    if (AlwaysRebuild())
      return RebuildNestedRequirement(Req->getInvalidConstraintEntity(),
                                      Req->getConstraintSatisfaction());
    return Req;
  }
  Sema::InstantiatingTemplate ReqInst(SemaRef,
      Req->getConstraintExpr()->getBeginLoc(), Req,
      Sema::InstantiatingTemplate::ConstraintsCheck{},
      Req->getConstraintExpr()->getSourceRange());
  if (!getEvaluateConstraints()) {
    ExprResult TransConstraint = TransformExpr(Req->getConstraintExpr());
    if (TransConstraint.isInvalid() || !TransConstraint.get())
      return nullptr;
    if (TransConstraint.get()->isInstantiationDependent())
      return new (SemaRef.Context)
          concepts::NestedRequirement(TransConstraint.get());
    ConstraintSatisfaction Satisfaction;
    return new (SemaRef.Context) concepts::NestedRequirement(
        SemaRef.Context, TransConstraint.get(), Satisfaction);
  }

  ExprResult TransConstraint;
  ConstraintSatisfaction Satisfaction;
  TemplateDeductionInfo Info(Req->getConstraintExpr()->getBeginLoc());
  {
    EnterExpressionEvaluationContext ContextRAII(
        SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
    Sema::SFINAETrap Trap(SemaRef);
    Sema::InstantiatingTemplate ConstrInst(SemaRef,
        Req->getConstraintExpr()->getBeginLoc(), Req, Info,
        Req->getConstraintExpr()->getSourceRange());
    if (ConstrInst.isInvalid())
      return nullptr;
    llvm::SmallVector<Expr *> Result;
    if (!SemaRef.CheckConstraintSatisfaction(
            nullptr,
            AssociatedConstraint(Req->getConstraintExpr(),
                                 SemaRef.ArgPackSubstIndex),
            Result, TemplateArgs, Req->getConstraintExpr()->getSourceRange(),
            Satisfaction) &&
        !Result.empty())
      TransConstraint = Result[0];
    assert(!Trap.hasErrorOccurred() && "Substitution failures must be handled "
                                       "by CheckConstraintSatisfaction.");
  }
  ASTContext &C = SemaRef.Context;
  if (TransConstraint.isUsable() &&
      TransConstraint.get()->isInstantiationDependent())
    return new (C) concepts::NestedRequirement(TransConstraint.get());
  if (TransConstraint.isInvalid() || !TransConstraint.get() ||
      Satisfaction.HasSubstitutionFailure()) {
    SmallString<128> Entity;
    llvm::raw_svector_ostream OS(Entity);
    Req->getConstraintExpr()->printPretty(OS, nullptr,
                                          SemaRef.getPrintingPolicy());
    return new (C) concepts::NestedRequirement(
        SemaRef.Context, C.backupStr(Entity), Satisfaction);
  }
  return new (C)
      concepts::NestedRequirement(C, TransConstraint.get(), Satisfaction);
}

TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
                                const MultiLevelTemplateArgumentList &Args,
                                SourceLocation Loc,
                                DeclarationName Entity,
                                bool AllowDeducedTST) {
  assert(!CodeSynthesisContexts.empty() &&
         "Cannot perform an instantiation without some context on the "
         "instantiation stack");

  if (!T->getType()->isInstantiationDependentType() &&
      !T->getType()->isVariablyModifiedType())
    return T;

  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
  return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T)
                         : Instantiator.TransformType(T);
}

TypeSourceInfo *Sema::SubstType(TypeLoc TL,
                                const MultiLevelTemplateArgumentList &Args,
                                SourceLocation Loc,
                                DeclarationName Entity) {
  assert(!CodeSynthesisContexts.empty() &&
         "Cannot perform an instantiation without some context on the "
         "instantiation stack");

  if (TL.getType().isNull())
    return nullptr;

  if (!TL.getType()->isInstantiationDependentType() &&
      !TL.getType()->isVariablyModifiedType()) {
    // FIXME: Make a copy of the TypeLoc data here, so that we can
    // return a new TypeSourceInfo. Inefficient!
    TypeLocBuilder TLB;
    TLB.pushFullCopy(TL);
    return TLB.getTypeSourceInfo(Context, TL.getType());
  }

  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
  TypeLocBuilder TLB;
  TLB.reserve(TL.getFullDataSize());
  QualType Result = Instantiator.TransformType(TLB, TL);
  if (Result.isNull())
    return nullptr;

  return TLB.getTypeSourceInfo(Context, Result);
}

/// Deprecated form of the above.
QualType Sema::SubstType(QualType T,
                         const MultiLevelTemplateArgumentList &TemplateArgs,
                         SourceLocation Loc, DeclarationName Entity,
                         bool *IsIncompleteSubstitution) {
  assert(!CodeSynthesisContexts.empty() &&
         "Cannot perform an instantiation without some context on the "
         "instantiation stack");

  // If T is not a dependent type or a variably-modified type, there
  // is nothing to do.
  if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType())
    return T;

  TemplateInstantiator Instantiator(
      *this, TemplateArgs, Loc, Entity,
      /*BailOutOnIncomplete=*/IsIncompleteSubstitution != nullptr);
  QualType QT = Instantiator.TransformType(T);
  if (IsIncompleteSubstitution && Instantiator.getIsIncomplete())
    *IsIncompleteSubstitution = true;
  return QT;
}

static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
  if (T->getType()->isInstantiationDependentType() ||
      T->getType()->isVariablyModifiedType())
    return true;

  TypeLoc TL = T->getTypeLoc().IgnoreParens();
  if (!TL.getAs<FunctionProtoTypeLoc>())
    return false;

  FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
  for (ParmVarDecl *P : FP.getParams()) {
    // This must be synthesized from a typedef.
    if (!P) continue;

    // If there are any parameters, a new TypeSourceInfo that refers to the
    // instantiated parameters must be built.
    return true;
  }

  return false;
}

TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
                                const MultiLevelTemplateArgumentList &Args,
                                SourceLocation Loc,
                                DeclarationName Entity,
                                CXXRecordDecl *ThisContext,
                                Qualifiers ThisTypeQuals,
                                bool EvaluateConstraints) {
  assert(!CodeSynthesisContexts.empty() &&
         "Cannot perform an instantiation without some context on the "
         "instantiation stack");

  if (!NeedsInstantiationAsFunctionType(T))
    return T;

  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
  Instantiator.setEvaluateConstraints(EvaluateConstraints);

  TypeLocBuilder TLB;

  TypeLoc TL = T->getTypeLoc();
  TLB.reserve(TL.getFullDataSize());

  QualType Result;

  if (FunctionProtoTypeLoc Proto =
          TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
    // Instantiate the type, other than its exception specification. The
    // exception specification is instantiated in InitFunctionInstantiation
    // once we've built the FunctionDecl.
    // FIXME: Set the exception specification to EST_Uninstantiated here,
    // instead of rebuilding the function type again later.
    Result = Instantiator.TransformFunctionProtoType(
        TLB, Proto, ThisContext, ThisTypeQuals,
        [](FunctionProtoType::ExceptionSpecInfo &ESI,
           bool &Changed) { return false; });
  } else {
    Result = Instantiator.TransformType(TLB, TL);
  }
  // When there are errors resolving types, clang may use IntTy as a fallback,
  // breaking our assumption that function declarations have function types.
  if (Result.isNull() || !Result->isFunctionType())
    return nullptr;

  return TLB.getTypeSourceInfo(Context, Result);
}

bool Sema::SubstExceptionSpec(SourceLocation Loc,
                              FunctionProtoType::ExceptionSpecInfo &ESI,
                              SmallVectorImpl<QualType> &ExceptionStorage,
                              const MultiLevelTemplateArgumentList &Args) {
  bool Changed = false;
  TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName());
  return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage,
                                             Changed);
}

void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
                              const MultiLevelTemplateArgumentList &Args) {
  FunctionProtoType::ExceptionSpecInfo ESI =
      Proto->getExtProtoInfo().ExceptionSpec;

  SmallVector<QualType, 4> ExceptionStorage;
  if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(),
                         ESI, ExceptionStorage, Args))
    // On error, recover by dropping the exception specification.
    ESI.Type = EST_None;

  UpdateExceptionSpec(New, ESI);
}

namespace {

  struct GetContainedInventedTypeParmVisitor :
    public TypeVisitor<GetContainedInventedTypeParmVisitor,
                       TemplateTypeParmDecl *> {
    using TypeVisitor<GetContainedInventedTypeParmVisitor,
                      TemplateTypeParmDecl *>::Visit;

    TemplateTypeParmDecl *Visit(QualType T) {
      if (T.isNull())
        return nullptr;
      return Visit(T.getTypePtr());
    }
    // The deduced type itself.
    TemplateTypeParmDecl *VisitTemplateTypeParmType(
        const TemplateTypeParmType *T) {
      if (!T->getDecl() || !T->getDecl()->isImplicit())
        return nullptr;
      return T->getDecl();
    }

    // Only these types can contain 'auto' types, and subsequently be replaced
    // by references to invented parameters.

    TemplateTypeParmDecl *VisitPointerType(const PointerType *T) {
      return Visit(T->getPointeeType());
    }

    TemplateTypeParmDecl *VisitBlockPointerType(const BlockPointerType *T) {
      return Visit(T->getPointeeType());
    }

    TemplateTypeParmDecl *VisitReferenceType(const ReferenceType *T) {
      return Visit(T->getPointeeTypeAsWritten());
    }

    TemplateTypeParmDecl *VisitMemberPointerType(const MemberPointerType *T) {
      return Visit(T->getPointeeType());
    }

    TemplateTypeParmDecl *VisitArrayType(const ArrayType *T) {
      return Visit(T->getElementType());
    }

    TemplateTypeParmDecl *VisitDependentSizedExtVectorType(
      const DependentSizedExtVectorType *T) {
      return Visit(T->getElementType());
    }

    TemplateTypeParmDecl *VisitVectorType(const VectorType *T) {
      return Visit(T->getElementType());
    }

    TemplateTypeParmDecl *VisitFunctionProtoType(const FunctionProtoType *T) {
      return VisitFunctionType(T);
    }

    TemplateTypeParmDecl *VisitFunctionType(const FunctionType *T) {
      return Visit(T->getReturnType());
    }

    TemplateTypeParmDecl *VisitParenType(const ParenType *T) {
      return Visit(T->getInnerType());
    }

    TemplateTypeParmDecl *VisitAttributedType(const AttributedType *T) {
      return Visit(T->getModifiedType());
    }

    TemplateTypeParmDecl *VisitMacroQualifiedType(const MacroQualifiedType *T) {
      return Visit(T->getUnderlyingType());
    }

    TemplateTypeParmDecl *VisitAdjustedType(const AdjustedType *T) {
      return Visit(T->getOriginalType());
    }

    TemplateTypeParmDecl *VisitPackExpansionType(const PackExpansionType *T) {
      return Visit(T->getPattern());
    }
  };

} // namespace

bool Sema::SubstTypeConstraint(
    TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
    const MultiLevelTemplateArgumentList &TemplateArgs,
    bool EvaluateConstraints) {
  const ASTTemplateArgumentListInfo *TemplArgInfo =
      TC->getTemplateArgsAsWritten();

  if (!EvaluateConstraints) {
    UnsignedOrNone Index = TC->getArgPackSubstIndex();
    if (!Index)
      Index = SemaRef.ArgPackSubstIndex;
    Inst->setTypeConstraint(TC->getConceptReference(),
                            TC->getImmediatelyDeclaredConstraint(), Index);
    return false;
  }

  TemplateArgumentListInfo InstArgs;

  if (TemplArgInfo) {
    InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
    InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
    if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs,
                               InstArgs))
      return true;
  }
  return AttachTypeConstraint(
      TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
      TC->getNamedConcept(),
      /*FoundDecl=*/TC->getConceptReference()->getFoundDecl(), &InstArgs, Inst,
      Inst->isParameterPack()
          ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
                ->getEllipsisLoc()
          : SourceLocation());
}

ParmVarDecl *
Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
                       const MultiLevelTemplateArgumentList &TemplateArgs,
                       int indexAdjustment, UnsignedOrNone NumExpansions,
                       bool ExpectParameterPack, bool EvaluateConstraint) {
  TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
  TypeSourceInfo *NewDI = nullptr;

  TypeLoc OldTL = OldDI->getTypeLoc();
  if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {

    // We have a function parameter pack. Substitute into the pattern of the
    // expansion.
    NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
                      OldParm->getLocation(), OldParm->getDeclName());
    if (!NewDI)
      return nullptr;

    if (NewDI->getType()->containsUnexpandedParameterPack()) {
      // We still have unexpanded parameter packs, which means that
      // our function parameter is still a function parameter pack.
      // Therefore, make its type a pack expansion type.
      NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
                                 NumExpansions);
    } else if (ExpectParameterPack) {
      // We expected to get a parameter pack but didn't (because the type
      // itself is not a pack expansion type), so complain. This can occur when
      // the substitution goes through an alias template that "loses" the
      // pack expansion.
      Diag(OldParm->getLocation(),
           diag::err_function_parameter_pack_without_parameter_packs)
        << NewDI->getType();
      return nullptr;
    }
  } else {
    NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
                      OldParm->getDeclName());
  }

  if (!NewDI)
    return nullptr;

  if (NewDI->getType()->isVoidType()) {
    Diag(OldParm->getLocation(), diag::err_param_with_void_type);
    return nullptr;
  }

  // In abbreviated templates, TemplateTypeParmDecls with possible
  // TypeConstraints are created when the parameter list is originally parsed.
  // The TypeConstraints can therefore reference other functions parameters in
  // the abbreviated function template, which is why we must instantiate them
  // here, when the instantiated versions of those referenced parameters are in
  // scope.
  if (TemplateTypeParmDecl *TTP =
          GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
    if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
      auto *Inst = cast_or_null<TemplateTypeParmDecl>(
          FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
      // We will first get here when instantiating the abbreviated function
      // template's described function, but we might also get here later.
      // Make sure we do not instantiate the TypeConstraint more than once.
      if (Inst && !Inst->getTypeConstraint()) {
        if (SubstTypeConstraint(Inst, TC, TemplateArgs, EvaluateConstraint))
          return nullptr;
      }
    }
  }

  ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
                                        OldParm->getInnerLocStart(),
                                        OldParm->getLocation(),
                                        OldParm->getIdentifier(),
                                        NewDI->getType(), NewDI,
                                        OldParm->getStorageClass());
  if (!NewParm)
    return nullptr;

  // Mark the (new) default argument as uninstantiated (if any).
  if (OldParm->hasUninstantiatedDefaultArg()) {
    Expr *Arg = OldParm->getUninstantiatedDefaultArg();
    NewParm->setUninstantiatedDefaultArg(Arg);
  } else if (OldParm->hasUnparsedDefaultArg()) {
    NewParm->setUnparsedDefaultArg();
    UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
  } else if (Expr *Arg = OldParm->getDefaultArg()) {
    // Default arguments cannot be substituted until the declaration context
    // for the associated function or lambda capture class is available.
    // This is necessary for cases like the following where construction of
    // the lambda capture class for the outer lambda is dependent on the
    // parameter types but where the default argument is dependent on the
    // outer lambda's declaration context.
    //   template <typename T>
    //   auto f() {
    //     return [](T = []{ return T{}; }()) { return 0; };
    //   }
    NewParm->setUninstantiatedDefaultArg(Arg);
  }

  NewParm->setExplicitObjectParameterLoc(
      OldParm->getExplicitObjectParamThisLoc());
  NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());

  if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
    // Add the new parameter to the instantiated parameter pack.
    CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
  } else {
    // Introduce an Old -> New mapping
    CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
  }

  // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
  // can be anything, is this right ?
  NewParm->setDeclContext(CurContext);

  NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
                        OldParm->getFunctionScopeIndex() + indexAdjustment);

  InstantiateAttrs(TemplateArgs, OldParm, NewParm);

  return NewParm;
}

bool Sema::SubstParmTypes(
    SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
    const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
    const MultiLevelTemplateArgumentList &TemplateArgs,
    SmallVectorImpl<QualType> &ParamTypes,
    SmallVectorImpl<ParmVarDecl *> *OutParams,
    ExtParameterInfoBuilder &ParamInfos) {
  assert(!CodeSynthesisContexts.empty() &&
         "Cannot perform an instantiation without some context on the "
         "instantiation stack");

  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
                                    DeclarationName());
  return Instantiator.TransformFunctionTypeParams(
      Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}

bool Sema::SubstDefaultArgument(
    SourceLocation Loc,
    ParmVarDecl *Param,
    const MultiLevelTemplateArgumentList &TemplateArgs,
    bool ForCallExpr) {
  FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
  Expr *PatternExpr = Param->getUninstantiatedDefaultArg();

  EnterExpressionEvaluationContext EvalContext(
      *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);

  InstantiatingTemplate Inst(*this, Loc, Param, TemplateArgs.getInnermost());
  if (Inst.isInvalid())
    return true;
  if (Inst.isAlreadyInstantiating()) {
    Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
    Param->setInvalidDecl();
    return true;
  }

  ExprResult Result;
  // C++ [dcl.fct.default]p5:
  //   The names in the [default argument] expression are bound, and
  //   the semantic constraints are checked, at the point where the
  //   default argument expression appears.
  ContextRAII SavedContext(*this, FD);
  {
    std::optional<LocalInstantiationScope> LIS;

    if (ForCallExpr) {
      // When instantiating a default argument due to use in a call expression,
      // an instantiation scope that includes the parameters of the callee is
      // required to satisfy references from the default argument. For example:
      //   template<typename T> void f(T a, int = decltype(a)());
      //   void g() { f(0); }
      LIS.emplace(*this);
      FunctionDecl *PatternFD = FD->getTemplateInstantiationPattern(
          /*ForDefinition*/ false);
      if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
        return true;
    }

    runWithSufficientStackSpace(Loc, [&] {
      Result = SubstInitializer(PatternExpr, TemplateArgs,
                                /*DirectInit*/ false);
    });
  }
  if (Result.isInvalid())
    return true;

  if (ForCallExpr) {
    // Check the expression as an initializer for the parameter.
    InitializedEntity Entity
      = InitializedEntity::InitializeParameter(Context, Param);
    InitializationKind Kind = InitializationKind::CreateCopy(
        Param->getLocation(),
        /*FIXME:EqualLoc*/ PatternExpr->getBeginLoc());
    Expr *ResultE = Result.getAs<Expr>();

    InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
    Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
    if (Result.isInvalid())
      return true;

    Result =
        ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
                            /*DiscardedValue*/ false);
  } else {
    // FIXME: Obtain the source location for the '=' token.
    SourceLocation EqualLoc = PatternExpr->getBeginLoc();
    Result = ConvertParamDefaultArgument(Param, Result.getAs<Expr>(), EqualLoc);
  }
  if (Result.isInvalid())
      return true;

  // Remember the instantiated default argument.
  Param->setDefaultArg(Result.getAs<Expr>());

  return false;
}

// See TreeTransform::PreparePackForExpansion for the relevant comment.
// This function implements the same concept for base specifiers.
static bool
PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base,
                        const MultiLevelTemplateArgumentList &TemplateArgs,
                        TypeSourceInfo *&Out, UnexpandedInfo &Info) {
  SourceRange BaseSourceRange = Base.getSourceRange();
  SourceLocation BaseEllipsisLoc = Base.getEllipsisLoc();
  Info.Ellipsis = Base.getEllipsisLoc();
  auto ComputeInfo = [&S, &TemplateArgs, BaseSourceRange, BaseEllipsisLoc](
                         TypeSourceInfo *BaseTypeInfo,
                         bool IsLateExpansionAttempt, UnexpandedInfo &Info) {
    // This is a pack expansion. See whether we should expand it now, or
    // wait until later.
    SmallVector<UnexpandedParameterPack, 2> Unexpanded;
    S.collectUnexpandedParameterPacks(BaseTypeInfo->getTypeLoc(), Unexpanded);
    if (IsLateExpansionAttempt) {
      // Request expansion only when there is an opportunity to expand a pack
      // that required a substituion first.
      bool SawPackTypes =
          llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) {
            return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>();
          });
      if (!SawPackTypes) {
        Info.Expand = false;
        return false;
      }
    }

    // Determine whether the set of unexpanded parameter packs can and should be
    // expanded.
    Info.Expand = false;
    Info.RetainExpansion = false;
    Info.NumExpansions = std::nullopt;
    return S.CheckParameterPacksForExpansion(
        BaseEllipsisLoc, BaseSourceRange, Unexpanded, TemplateArgs,
        /*FailOnPackProducingTemplates=*/false, Info.Expand,
        Info.RetainExpansion, Info.NumExpansions);
  };

  if (ComputeInfo(Base.getTypeSourceInfo(), false, Info))
    return true;

  if (Info.Expand) {
    Out = Base.getTypeSourceInfo();
    return false;
  }

  // The resulting base specifier will (still) be a pack expansion.
  {
    Sema::ArgPackSubstIndexRAII SubstIndex(S, std::nullopt);
    Out = S.SubstType(Base.getTypeSourceInfo(), TemplateArgs,
                      BaseSourceRange.getBegin(), DeclarationName());
  }
  if (!Out->getType()->containsUnexpandedParameterPack())
    return false;

  // Some packs will learn their length after substitution.
  // We may need to request their expansion.
  if (ComputeInfo(Out, /*IsLateExpansionAttempt=*/true, Info))
    return true;
  if (Info.Expand)
    Info.ExpandUnderForgetSubstitions = true;
  return false;
}

bool
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
                          CXXRecordDecl *Pattern,
                          const MultiLevelTemplateArgumentList &TemplateArgs) {
  bool Invalid = false;
  SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
  for (const auto &Base : Pattern->bases()) {
    if (!Base.getType()->isDependentType()) {
      if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
        if (RD->isInvalidDecl())
          Instantiation->setInvalidDecl();
      }
      InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(Base));
      continue;
    }

    SourceLocation EllipsisLoc;
    TypeSourceInfo *BaseTypeLoc = nullptr;
    if (Base.isPackExpansion()) {
      UnexpandedInfo Info;
      if (PreparePackForExpansion(*this, Base, TemplateArgs, BaseTypeLoc,
                                  Info)) {
        Invalid = true;
        continue;
      }

      // If we should expand this pack expansion now, do so.
      MultiLevelTemplateArgumentList EmptyList;
      const MultiLevelTemplateArgumentList *ArgsForSubst = &TemplateArgs;
      if (Info.ExpandUnderForgetSubstitions)
        ArgsForSubst = &EmptyList;

      if (Info.Expand) {
        for (unsigned I = 0; I != *Info.NumExpansions; ++I) {
          Sema::ArgPackSubstIndexRAII SubstIndex(*this, I);

          TypeSourceInfo *Expanded =
              SubstType(BaseTypeLoc, *ArgsForSubst,
                        Base.getSourceRange().getBegin(), DeclarationName());
          if (!Expanded) {
            Invalid = true;
            continue;
          }

          if (CXXBaseSpecifier *InstantiatedBase = CheckBaseSpecifier(
                  Instantiation, Base.getSourceRange(), Base.isVirtual(),
                  Base.getAccessSpecifierAsWritten(), Expanded,
                  SourceLocation()))
            InstantiatedBases.push_back(InstantiatedBase);
          else
            Invalid = true;
        }

        continue;
      }

      // The resulting base specifier will (still) be a pack expansion.
      EllipsisLoc = Base.getEllipsisLoc();
      Sema::ArgPackSubstIndexRAII SubstIndex(*this, std::nullopt);
      BaseTypeLoc =
          SubstType(BaseTypeLoc, *ArgsForSubst,
                    Base.getSourceRange().getBegin(), DeclarationName());
    } else {
      BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
                              TemplateArgs,
                              Base.getSourceRange().getBegin(),
                              DeclarationName());
    }

    if (!BaseTypeLoc) {
      Invalid = true;
      continue;
    }

    if (CXXBaseSpecifier *InstantiatedBase
          = CheckBaseSpecifier(Instantiation,
                               Base.getSourceRange(),
                               Base.isVirtual(),
                               Base.getAccessSpecifierAsWritten(),
                               BaseTypeLoc,
                               EllipsisLoc))
      InstantiatedBases.push_back(InstantiatedBase);
    else
      Invalid = true;
  }

  if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases))
    Invalid = true;

  return Invalid;
}

// Defined via #include from SemaTemplateInstantiateDecl.cpp
namespace clang {
  namespace sema {
    Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
                            const MultiLevelTemplateArgumentList &TemplateArgs);
    Attr *instantiateTemplateAttributeForDecl(
        const Attr *At, ASTContext &C, Sema &S,
        const MultiLevelTemplateArgumentList &TemplateArgs);
  }
}

bool
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
                       CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
                       const MultiLevelTemplateArgumentList &TemplateArgs,
                       TemplateSpecializationKind TSK,
                       bool Complain) {
  CXXRecordDecl *PatternDef
    = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
  if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
                                Instantiation->getInstantiatedFromMemberClass(),
                                     Pattern, PatternDef, TSK, Complain))
    return true;

  llvm::TimeTraceScope TimeScope("InstantiateClass", [&]() {
    llvm::TimeTraceMetadata M;
    llvm::raw_string_ostream OS(M.Detail);
    Instantiation->getNameForDiagnostic(OS, getPrintingPolicy(),
                                        /*Qualified=*/true);
    if (llvm::isTimeTraceVerbose()) {
      auto Loc = SourceMgr.getExpansionLoc(Instantiation->getLocation());
      M.File = SourceMgr.getFilename(Loc);
      M.Line = SourceMgr.getExpansionLineNumber(Loc);
    }
    return M;
  });

  Pattern = PatternDef;

  // Record the point of instantiation.
  if (MemberSpecializationInfo *MSInfo
        = Instantiation->getMemberSpecializationInfo()) {
    MSInfo->setTemplateSpecializationKind(TSK);
    MSInfo->setPointOfInstantiation(PointOfInstantiation);
  } else if (ClassTemplateSpecializationDecl *Spec
        = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
    Spec->setTemplateSpecializationKind(TSK);
    Spec->setPointOfInstantiation(PointOfInstantiation);
  }

  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
  if (Inst.isInvalid())
    return true;
  assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
  PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
                                      "instantiating class definition");

  // Enter the scope of this instantiation. We don't use
  // PushDeclContext because we don't have a scope.
  ContextRAII SavedContext(*this, Instantiation);
  EnterExpressionEvaluationContext EvalContext(
      *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

  // If this is an instantiation of a local class, merge this local
  // instantiation scope with the enclosing scope. Otherwise, every
  // instantiation of a class has its own local instantiation scope.
  bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
  LocalInstantiationScope Scope(*this, MergeWithParentScope);

  // Some class state isn't processed immediately but delayed till class
  // instantiation completes. We may not be ready to handle any delayed state
  // already on the stack as it might correspond to a different class, so save
  // it now and put it back later.
  SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);

  // Pull attributes from the pattern onto the instantiation.
  InstantiateAttrs(TemplateArgs, Pattern, Instantiation);

  // Start the definition of this instantiation.
  Instantiation->startDefinition();

  // The instantiation is visible here, even if it was first declared in an
  // unimported module.
  Instantiation->setVisibleDespiteOwningModule();

  // FIXME: This loses the as-written tag kind for an explicit instantiation.
  Instantiation->setTagKind(Pattern->getTagKind());

  // Do substitution on the base class specifiers.
  if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
    Instantiation->setInvalidDecl();

  TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
  Instantiator.setEvaluateConstraints(false);
  SmallVector<Decl*, 4> Fields;
  // Delay instantiation of late parsed attributes.
  LateInstantiatedAttrVec LateAttrs;
  Instantiator.enableLateAttributeInstantiation(&LateAttrs);

  bool MightHaveConstexprVirtualFunctions = false;
  for (auto *Member : Pattern->decls()) {
    // Don't instantiate members not belonging in this semantic context.
    // e.g. for:
    // @code
    //    template <int i> class A {
    //      class B *g;
    //    };
    // @endcode
    // 'class B' has the template as lexical context but semantically it is
    // introduced in namespace scope.
    if (Member->getDeclContext() != Pattern)
      continue;

    // BlockDecls can appear in a default-member-initializer. They must be the
    // child of a BlockExpr, so we only know how to instantiate them from there.
    // Similarly, lambda closure types are recreated when instantiating the
    // corresponding LambdaExpr.
    if (isa<BlockDecl>(Member) ||
        (isa<CXXRecordDecl>(Member) && cast<CXXRecordDecl>(Member)->isLambda()))
      continue;

    if (Member->isInvalidDecl()) {
      Instantiation->setInvalidDecl();
      continue;
    }

    Decl *NewMember = Instantiator.Visit(Member);
    if (NewMember) {
      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
        Fields.push_back(Field);
      } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
        // C++11 [temp.inst]p1: The implicit instantiation of a class template
        // specialization causes the implicit instantiation of the definitions
        // of unscoped member enumerations.
        // Record a point of instantiation for this implicit instantiation.
        if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
            Enum->isCompleteDefinition()) {
          MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
          assert(MSInfo && "no spec info for member enum specialization");
          MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
          MSInfo->setPointOfInstantiation(PointOfInstantiation);
        }
      } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(NewMember)) {
        if (SA->isFailed()) {
          // A static_assert failed. Bail out; instantiating this
          // class is probably not meaningful.
          Instantiation->setInvalidDecl();
          break;
        }
      } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
        if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
            (MD->isVirtualAsWritten() || Instantiation->getNumBases()))
          MightHaveConstexprVirtualFunctions = true;
      }

      if (NewMember->isInvalidDecl())
        Instantiation->setInvalidDecl();
    } else {
      // FIXME: Eventually, a NULL return will mean that one of the
      // instantiations was a semantic disaster, and we'll want to mark the
      // declaration invalid.
      // For now, we expect to skip some members that we can't yet handle.
    }
  }

  // Finish checking fields.
  ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
              SourceLocation(), SourceLocation(), ParsedAttributesView());
  CheckCompletedCXXClass(nullptr, Instantiation);

  // Default arguments are parsed, if not instantiated. We can go instantiate
  // default arg exprs for default constructors if necessary now. Unless we're
  // parsing a class, in which case wait until that's finished.
  if (ParsingClassDepth == 0)
    ActOnFinishCXXNonNestedClass();

  // Instantiate late parsed attributes, and attach them to their decls.
  // See Sema::InstantiateAttrs
  for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
       E = LateAttrs.end(); I != E; ++I) {
    assert(CurrentInstantiationScope == Instantiator.getStartingScope());
    CurrentInstantiationScope = I->Scope;

    // Allow 'this' within late-parsed attributes.
    auto *ND = cast<NamedDecl>(I->NewDecl);
    auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
    CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
                               ND->isCXXInstanceMember());

    Attr *NewAttr =
      instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
    if (NewAttr)
      I->NewDecl->addAttr(NewAttr);
    LocalInstantiationScope::deleteScopes(I->Scope,
                                          Instantiator.getStartingScope());
  }
  Instantiator.disableLateAttributeInstantiation();
  LateAttrs.clear();

  ActOnFinishDelayedMemberInitializers(Instantiation);

  // FIXME: We should do something similar for explicit instantiations so they
  // end up in the right module.
  if (TSK == TSK_ImplicitInstantiation) {
    Instantiation->setLocation(Pattern->getLocation());
    Instantiation->setLocStart(Pattern->getInnerLocStart());
    Instantiation->setBraceRange(Pattern->getBraceRange());
  }

  if (!Instantiation->isInvalidDecl()) {
    // Perform any dependent diagnostics from the pattern.
    if (Pattern->isDependentContext())
      PerformDependentDiagnostics(Pattern, TemplateArgs);

    // Instantiate any out-of-line class template partial
    // specializations now.
    for (TemplateDeclInstantiator::delayed_partial_spec_iterator
              P = Instantiator.delayed_partial_spec_begin(),
           PEnd = Instantiator.delayed_partial_spec_end();
         P != PEnd; ++P) {
      if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
              P->first, P->second)) {
        Instantiation->setInvalidDecl();
        break;
      }
    }

    // Instantiate any out-of-line variable template partial
    // specializations now.
    for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
              P = Instantiator.delayed_var_partial_spec_begin(),
           PEnd = Instantiator.delayed_var_partial_spec_end();
         P != PEnd; ++P) {
      if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
              P->first, P->second)) {
        Instantiation->setInvalidDecl();
        break;
      }
    }
  }

  // Exit the scope of this instantiation.
  SavedContext.pop();

  if (!Instantiation->isInvalidDecl()) {
    // Always emit the vtable for an explicit instantiation definition
    // of a polymorphic class template specialization. Otherwise, eagerly
    // instantiate only constexpr virtual functions in preparation for their use
    // in constant evaluation.
    if (TSK == TSK_ExplicitInstantiationDefinition)
      MarkVTableUsed(PointOfInstantiation, Instantiation, true);
    else if (MightHaveConstexprVirtualFunctions)
      MarkVirtualMembersReferenced(PointOfInstantiation, Instantiation,
                                   /*ConstexprOnly*/ true);
  }

  Consumer.HandleTagDeclDefinition(Instantiation);

  return Instantiation->isInvalidDecl();
}

bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
                           EnumDecl *Instantiation, EnumDecl *Pattern,
                           const MultiLevelTemplateArgumentList &TemplateArgs,
                           TemplateSpecializationKind TSK) {
  EnumDecl *PatternDef = Pattern->getDefinition();
  if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
                                 Instantiation->getInstantiatedFromMemberEnum(),
                                     Pattern, PatternDef, TSK,/*Complain*/true))
    return true;
  Pattern = PatternDef;

  // Record the point of instantiation.
  if (MemberSpecializationInfo *MSInfo
        = Instantiation->getMemberSpecializationInfo()) {
    MSInfo->setTemplateSpecializationKind(TSK);
    MSInfo->setPointOfInstantiation(PointOfInstantiation);
  }

  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
  if (Inst.isInvalid())
    return true;
  if (Inst.isAlreadyInstantiating())
    return false;
  PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
                                      "instantiating enum definition");

  // The instantiation is visible here, even if it was first declared in an
  // unimported module.
  Instantiation->setVisibleDespiteOwningModule();

  // Enter the scope of this instantiation. We don't use
  // PushDeclContext because we don't have a scope.
  ContextRAII SavedContext(*this, Instantiation);
  EnterExpressionEvaluationContext EvalContext(
      *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

  LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true);

  // Pull attributes from the pattern onto the instantiation.
  InstantiateAttrs(TemplateArgs, Pattern, Instantiation);

  TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
  Instantiator.InstantiateEnumDefinition(Instantiation, Pattern);

  // Exit the scope of this instantiation.
  SavedContext.pop();

  return Instantiation->isInvalidDecl();
}

bool Sema::InstantiateInClassInitializer(
    SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
    FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) {
  // If there is no initializer, we don't need to do anything.
  if (!Pattern->hasInClassInitializer())
    return false;

  assert(Instantiation->getInClassInitStyle() ==
             Pattern->getInClassInitStyle() &&
         "pattern and instantiation disagree about init style");

  // Error out if we haven't parsed the initializer of the pattern yet because
  // we are waiting for the closing brace of the outer class.
  Expr *OldInit = Pattern->getInClassInitializer();
  if (!OldInit) {
    RecordDecl *PatternRD = Pattern->getParent();
    RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
    Diag(PointOfInstantiation,
         diag::err_default_member_initializer_not_yet_parsed)
        << OutermostClass << Pattern;
    Diag(Pattern->getEndLoc(),
         diag::note_default_member_initializer_not_yet_parsed);
    Instantiation->setInvalidDecl();
    return true;
  }

  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
  if (Inst.isInvalid())
    return true;
  if (Inst.isAlreadyInstantiating()) {
    // Error out if we hit an instantiation cycle for this initializer.
    Diag(PointOfInstantiation, diag::err_default_member_initializer_cycle)
      << Instantiation;
    return true;
  }
  PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
                                      "instantiating default member init");

  // Enter the scope of this instantiation. We don't use PushDeclContext because
  // we don't have a scope.
  ContextRAII SavedContext(*this, Instantiation->getParent());
  EnterExpressionEvaluationContext EvalContext(
      *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
  ExprEvalContexts.back().DelayedDefaultInitializationContext = {
      PointOfInstantiation, Instantiation, CurContext};

  LocalInstantiationScope Scope(*this, true);

  // Instantiate the initializer.
  ActOnStartCXXInClassMemberInitializer();
  CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers());

  ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
                                        /*CXXDirectInit=*/false);
  Expr *Init = NewInit.get();
  assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class");
  ActOnFinishCXXInClassMemberInitializer(
      Instantiation, Init ? Init->getBeginLoc() : SourceLocation(), Init);

  if (auto *L = getASTMutationListener())
    L->DefaultMemberInitializerInstantiated(Instantiation);

  // Return true if the in-class initializer is still missing.
  return !Instantiation->getInClassInitializer();
}

namespace {
  /// A partial specialization whose template arguments have matched
  /// a given template-id.
  struct PartialSpecMatchResult {
    ClassTemplatePartialSpecializationDecl *Partial;
    TemplateArgumentList *Args;
  };
}

bool Sema::usesPartialOrExplicitSpecialization(
    SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) {
  if (ClassTemplateSpec->getTemplateSpecializationKind() ==
      TSK_ExplicitSpecialization)
    return true;

  SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
  ClassTemplateDecl *CTD = ClassTemplateSpec->getSpecializedTemplate();
  CTD->getPartialSpecializations(PartialSpecs);
  for (ClassTemplatePartialSpecializationDecl *CTPSD : PartialSpecs) {
    // C++ [temp.spec.partial.member]p2:
    //   If the primary member template is explicitly specialized for a given
    //   (implicit) specialization of the enclosing class template, the partial
    //   specializations of the member template are ignored for this
    //   specialization of the enclosing class template. If a partial
    //   specialization of the member template is explicitly specialized for a
    //   given (implicit) specialization of the enclosing class template, the
    //   primary member template and its other partial specializations are still
    //   considered for this specialization of the enclosing class template.
    if (CTD->getMostRecentDecl()->isMemberSpecialization() &&
        !CTPSD->getMostRecentDecl()->isMemberSpecialization())
      continue;

    TemplateDeductionInfo Info(Loc);
    if (DeduceTemplateArguments(CTPSD,
                                ClassTemplateSpec->getTemplateArgs().asArray(),
                                Info) == TemplateDeductionResult::Success)
      return true;
  }

  return false;
}

/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
    Sema &S, SourceLocation PointOfInstantiation,
    ClassTemplateSpecializationDecl *ClassTemplateSpec,
    TemplateSpecializationKind TSK, bool PrimaryStrictPackMatch) {
  Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
  if (Inst.isInvalid())
    return {/*Invalid=*/true};
  if (Inst.isAlreadyInstantiating())
    return {/*Invalid=*/false};

  llvm::PointerUnion<ClassTemplateDecl *,
                     ClassTemplatePartialSpecializationDecl *>
      Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
  if (!isa<ClassTemplatePartialSpecializationDecl *>(Specialized)) {
    // Find best matching specialization.
    ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();

    // C++ [temp.class.spec.match]p1:
    //   When a class template is used in a context that requires an
    //   instantiation of the class, it is necessary to determine
    //   whether the instantiation is to be generated using the primary
    //   template or one of the partial specializations. This is done by
    //   matching the template arguments of the class template
    //   specialization with the template argument lists of the partial
    //   specializations.
    typedef PartialSpecMatchResult MatchResult;
    SmallVector<MatchResult, 4> Matched, ExtraMatched;
    SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
    Template->getPartialSpecializations(PartialSpecs);
    TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
    for (ClassTemplatePartialSpecializationDecl *Partial : PartialSpecs) {
      // C++ [temp.spec.partial.member]p2:
      //   If the primary member template is explicitly specialized for a given
      //   (implicit) specialization of the enclosing class template, the
      //   partial specializations of the member template are ignored for this
      //   specialization of the enclosing class template. If a partial
      //   specialization of the member template is explicitly specialized for a
      //   given (implicit) specialization of the enclosing class template, the
      //   primary member template and its other partial specializations are
      //   still considered for this specialization of the enclosing class
      //   template.
      if (Template->getMostRecentDecl()->isMemberSpecialization() &&
          !Partial->getMostRecentDecl()->isMemberSpecialization())
        continue;

      TemplateDeductionInfo Info(FailedCandidates.getLocation());
      if (TemplateDeductionResult Result = S.DeduceTemplateArguments(
              Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info);
          Result != TemplateDeductionResult::Success) {
        // Store the failed-deduction information for use in diagnostics, later.
        // TODO: Actually use the failed-deduction info?
        FailedCandidates.addCandidate().set(
            DeclAccessPair::make(Template, AS_public), Partial,
            MakeDeductionFailureInfo(S.Context, Result, Info));
        (void)Result;
      } else {
        auto &List = Info.hasStrictPackMatch() ? ExtraMatched : Matched;
        List.push_back(MatchResult{Partial, Info.takeCanonical()});
      }
    }
    if (Matched.empty() && PrimaryStrictPackMatch)
      Matched = std::move(ExtraMatched);

    // If we're dealing with a member template where the template parameters
    // have been instantiated, this provides the original template parameters
    // from which the member template's parameters were instantiated.

    if (Matched.size() >= 1) {
      SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
      if (Matched.size() == 1) {
        //   -- If exactly one matching specialization is found, the
        //      instantiation is generated from that specialization.
        // We don't need to do anything for this.
      } else {
        //   -- If more than one matching specialization is found, the
        //      partial order rules (14.5.4.2) are used to determine
        //      whether one of the specializations is more specialized
        //      than the others. If none of the specializations is more
        //      specialized than all of the other matching
        //      specializations, then the use of the class template is
        //      ambiguous and the program is ill-formed.
        for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
                                                 PEnd = Matched.end();
             P != PEnd; ++P) {
          if (S.getMoreSpecializedPartialSpecialization(
                  P->Partial, Best->Partial, PointOfInstantiation) ==
              P->Partial)
            Best = P;
        }

        // Determine if the best partial specialization is more specialized than
        // the others.
        bool Ambiguous = false;
        for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
                                                 PEnd = Matched.end();
             P != PEnd; ++P) {
          if (P != Best && S.getMoreSpecializedPartialSpecialization(
                               P->Partial, Best->Partial,
                               PointOfInstantiation) != Best->Partial) {
            Ambiguous = true;
            break;
          }
        }

        if (Ambiguous) {
          // Partial ordering did not produce a clear winner. Complain.
          Inst.Clear();
          S.Diag(PointOfInstantiation,
                 diag::err_partial_spec_ordering_ambiguous)
              << ClassTemplateSpec;

          // Print the matching partial specializations.
          for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
                                                   PEnd = Matched.end();
               P != PEnd; ++P)
            S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
                << S.getTemplateArgumentBindingsText(
                       P->Partial->getTemplateParameters(), *P->Args);

          return {/*Invalid=*/true};
        }
      }

      ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
    } else {
      //   -- If no matches are found, the instantiation is generated
      //      from the primary template.
    }
  }

  CXXRecordDecl *Pattern = nullptr;
  Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
  if (auto *PartialSpec =
          Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
    // Instantiate using the best class template partial specialization.
    while (PartialSpec->getInstantiatedFromMember()) {
      // If we've found an explicit specialization of this class template,
      // stop here and use that as the pattern.
      if (PartialSpec->isMemberSpecialization())
        break;

      PartialSpec = PartialSpec->getInstantiatedFromMember();
    }
    Pattern = PartialSpec;
  } else {
    ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
    while (Template->getInstantiatedFromMemberTemplate()) {
      // If we've found an explicit specialization of this class template,
      // stop here and use that as the pattern.
      if (Template->isMemberSpecialization())
        break;

      Template = Template->getInstantiatedFromMemberTemplate();
    }
    Pattern = Template->getTemplatedDecl();
  }

  return Pattern;
}

bool Sema::InstantiateClassTemplateSpecialization(
    SourceLocation PointOfInstantiation,
    ClassTemplateSpecializationDecl *ClassTemplateSpec,
    TemplateSpecializationKind TSK, bool Complain,
    bool PrimaryStrictPackMatch) {
  // Perform the actual instantiation on the canonical declaration.
  ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
      ClassTemplateSpec->getCanonicalDecl());
  if (ClassTemplateSpec->isInvalidDecl())
    return true;

  bool HadAvaibilityWarning =
      ShouldDiagnoseAvailabilityOfDecl(ClassTemplateSpec, nullptr, nullptr)
          .first != AR_Available;

  ActionResult<CXXRecordDecl *> Pattern =
      getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
                                               ClassTemplateSpec, TSK,
                                               PrimaryStrictPackMatch);

  if (!Pattern.isUsable())
    return Pattern.isInvalid();

  bool Err = InstantiateClass(
      PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
      getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);

  // If we haven't already warn on avaibility, consider the avaibility
  // attributes of the partial specialization.
  // Note that - because we need to have deduced the partial specialization -
  // We can only emit these warnings when the specialization is instantiated.
  if (!Err && !HadAvaibilityWarning) {
    assert(ClassTemplateSpec->getTemplateSpecializationKind() !=
           TSK_Undeclared);
    DiagnoseAvailabilityOfDecl(ClassTemplateSpec, PointOfInstantiation);
  }
  return Err;
}

void
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
                              CXXRecordDecl *Instantiation,
                        const MultiLevelTemplateArgumentList &TemplateArgs,
                              TemplateSpecializationKind TSK) {
  // FIXME: We need to notify the ASTMutationListener that we did all of these
  // things, in case we have an explicit instantiation definition in a PCM, a
  // module, or preamble, and the declaration is in an imported AST.
  assert(
      (TSK == TSK_ExplicitInstantiationDefinition ||
       TSK == TSK_ExplicitInstantiationDeclaration ||
       (TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) &&
      "Unexpected template specialization kind!");
  for (auto *D : Instantiation->decls()) {
    bool SuppressNew = false;
    if (auto *Function = dyn_cast<FunctionDecl>(D)) {
      if (FunctionDecl *Pattern =
              Function->getInstantiatedFromMemberFunction()) {

        if (Function->getTrailingRequiresClause()) {
          ConstraintSatisfaction Satisfaction;
          if (CheckFunctionConstraints(Function, Satisfaction) ||
              !Satisfaction.IsSatisfied) {
            continue;
          }
        }

        if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
          continue;

        TemplateSpecializationKind PrevTSK =
            Function->getTemplateSpecializationKind();
        if (PrevTSK == TSK_ExplicitSpecialization)
          continue;

        if (CheckSpecializationInstantiationRedecl(
                PointOfInstantiation, TSK, Function, PrevTSK,
                Function->getPointOfInstantiation(), SuppressNew) ||
            SuppressNew)
          continue;

        // C++11 [temp.explicit]p8:
        //   An explicit instantiation definition that names a class template
        //   specialization explicitly instantiates the class template
        //   specialization and is only an explicit instantiation definition
        //   of members whose definition is visible at the point of
        //   instantiation.
        if (TSK == TSK_ExplicitInstantiationDefinition && !Pattern->isDefined())
          continue;

        Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);

        if (Function->isDefined()) {
          // Let the ASTConsumer know that this function has been explicitly
          // instantiated now, and its linkage might have changed.
          Consumer.HandleTopLevelDecl(DeclGroupRef(Function));
        } else if (TSK == TSK_ExplicitInstantiationDefinition) {
          InstantiateFunctionDefinition(PointOfInstantiation, Function);
        } else if (TSK == TSK_ImplicitInstantiation) {
          PendingLocalImplicitInstantiations.push_back(
              std::make_pair(Function, PointOfInstantiation));
        }
      }
    } else if (auto *Var = dyn_cast<VarDecl>(D)) {
      if (isa<VarTemplateSpecializationDecl>(Var))
        continue;

      if (Var->isStaticDataMember()) {
        if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
          continue;

        MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
        assert(MSInfo && "No member specialization information?");
        if (MSInfo->getTemplateSpecializationKind()
                                                 == TSK_ExplicitSpecialization)
          continue;

        if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
                                                   Var,
                                        MSInfo->getTemplateSpecializationKind(),
                                              MSInfo->getPointOfInstantiation(),
                                                   SuppressNew) ||
            SuppressNew)
          continue;

        if (TSK == TSK_ExplicitInstantiationDefinition) {
          // C++0x [temp.explicit]p8:
          //   An explicit instantiation definition that names a class template
          //   specialization explicitly instantiates the class template
          //   specialization and is only an explicit instantiation definition
          //   of members whose definition is visible at the point of
          //   instantiation.
          if (!Var->getInstantiatedFromStaticDataMember()->getDefinition())
            continue;

          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
          InstantiateVariableDefinition(PointOfInstantiation, Var);
        } else {
          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
        }
      }
    } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
      if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
        continue;

      // Always skip the injected-class-name, along with any
      // redeclarations of nested classes, since both would cause us
      // to try to instantiate the members of a class twice.
      // Skip closure types; they'll get instantiated when we instantiate
      // the corresponding lambda-expression.
      if (Record->isInjectedClassName() || Record->getPreviousDecl() ||
          Record->isLambda())
        continue;

      MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
      assert(MSInfo && "No member specialization information?");

      if (MSInfo->getTemplateSpecializationKind()
                                                == TSK_ExplicitSpecialization)
        continue;

      if (Context.getTargetInfo().getTriple().isOSWindows() &&
          TSK == TSK_ExplicitInstantiationDeclaration) {
        // On Windows, explicit instantiation decl of the outer class doesn't
        // affect the inner class. Typically extern template declarations are
        // used in combination with dll import/export annotations, but those
        // are not propagated from the outer class templates to inner classes.
        // Therefore, do not instantiate inner classes on this platform, so
        // that users don't end up with undefined symbols during linking.
        continue;
      }

      if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
                                                 Record,
                                        MSInfo->getTemplateSpecializationKind(),
                                              MSInfo->getPointOfInstantiation(),
                                                 SuppressNew) ||
          SuppressNew)
        continue;

      CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
      assert(Pattern && "Missing instantiated-from-template information");

      if (!Record->getDefinition()) {
        if (!Pattern->getDefinition()) {
          // C++0x [temp.explicit]p8:
          //   An explicit instantiation definition that names a class template
          //   specialization explicitly instantiates the class template
          //   specialization and is only an explicit instantiation definition
          //   of members whose definition is visible at the point of
          //   instantiation.
          if (TSK == TSK_ExplicitInstantiationDeclaration) {
            MSInfo->setTemplateSpecializationKind(TSK);
            MSInfo->setPointOfInstantiation(PointOfInstantiation);
          }

          continue;
        }

        InstantiateClass(PointOfInstantiation, Record, Pattern,
                         TemplateArgs,
                         TSK);
      } else {
        if (TSK == TSK_ExplicitInstantiationDefinition &&
            Record->getTemplateSpecializationKind() ==
                TSK_ExplicitInstantiationDeclaration) {
          Record->setTemplateSpecializationKind(TSK);
          MarkVTableUsed(PointOfInstantiation, Record, true);
        }
      }

      Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
      if (Pattern)
        InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
                                TSK);
    } else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
      MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
      assert(MSInfo && "No member specialization information?");

      if (MSInfo->getTemplateSpecializationKind()
            == TSK_ExplicitSpecialization)
        continue;

      if (CheckSpecializationInstantiationRedecl(
            PointOfInstantiation, TSK, Enum,
            MSInfo->getTemplateSpecializationKind(),
            MSInfo->getPointOfInstantiation(), SuppressNew) ||
          SuppressNew)
        continue;

      if (Enum->getDefinition())
        continue;

      EnumDecl *Pattern = Enum->getTemplateInstantiationPattern();
      assert(Pattern && "Missing instantiated-from-template information");

      if (TSK == TSK_ExplicitInstantiationDefinition) {
        if (!Pattern->getDefinition())
          continue;

        InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK);
      } else {
        MSInfo->setTemplateSpecializationKind(TSK);
        MSInfo->setPointOfInstantiation(PointOfInstantiation);
      }
    } else if (auto *Field = dyn_cast<FieldDecl>(D)) {
      // No need to instantiate in-class initializers during explicit
      // instantiation.
      if (Field->hasInClassInitializer() && TSK == TSK_ImplicitInstantiation) {
        // Handle local classes which could have substituted template params.
        CXXRecordDecl *ClassPattern =
            Instantiation->isLocalClass()
                ? Instantiation->getInstantiatedFromMemberClass()
                : Instantiation->getTemplateInstantiationPattern();

        DeclContext::lookup_result Lookup =
            ClassPattern->lookup(Field->getDeclName());
        FieldDecl *Pattern = Lookup.find_first<FieldDecl>();
        assert(Pattern);
        InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
                                      TemplateArgs);
      }
    }
  }
}

void
Sema::InstantiateClassTemplateSpecializationMembers(
                                           SourceLocation PointOfInstantiation,
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
                                               TemplateSpecializationKind TSK) {
  // C++0x [temp.explicit]p7:
  //   An explicit instantiation that names a class template
  //   specialization is an explicit instantion of the same kind
  //   (declaration or definition) of each of its members (not
  //   including members inherited from base classes) that has not
  //   been previously explicitly specialized in the translation unit
  //   containing the explicit instantiation, except as described
  //   below.
  InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
                          getTemplateInstantiationArgs(ClassTemplateSpec),
                          TSK);
}

StmtResult
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
  if (!S)
    return S;

  TemplateInstantiator Instantiator(*this, TemplateArgs,
                                    SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformStmt(S);
}

bool Sema::SubstTemplateArgument(
    const TemplateArgumentLoc &Input,
    const MultiLevelTemplateArgumentList &TemplateArgs,
    TemplateArgumentLoc &Output, SourceLocation Loc,
    const DeclarationName &Entity) {
  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
  return Instantiator.TransformTemplateArgument(Input, Output);
}

bool Sema::SubstTemplateArguments(
    ArrayRef<TemplateArgumentLoc> Args,
    const MultiLevelTemplateArgumentList &TemplateArgs,
    TemplateArgumentListInfo &Out) {
  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(), Out);
}

ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
  if (!E)
    return E;

  TemplateInstantiator Instantiator(*this, TemplateArgs,
                                    SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformExpr(E);
}

ExprResult
Sema::SubstCXXIdExpr(Expr *E,
                     const MultiLevelTemplateArgumentList &TemplateArgs) {
  if (!E)
    return E;

  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformAddressOfOperand(E);
}

ExprResult
Sema::SubstConstraintExpr(Expr *E,
                          const MultiLevelTemplateArgumentList &TemplateArgs) {
  // FIXME: should call SubstExpr directly if this function is equivalent or
  //        should it be different?
  return SubstExpr(E, TemplateArgs);
}

ExprResult Sema::SubstConstraintExprWithoutSatisfaction(
    Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
  if (!E)
    return E;

  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                    DeclarationName());
  Instantiator.setEvaluateConstraints(false);
  return Instantiator.TransformExpr(E);
}

ExprResult Sema::SubstInitializer(Expr *Init,
                          const MultiLevelTemplateArgumentList &TemplateArgs,
                          bool CXXDirectInit) {
  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformInitializer(Init, CXXDirectInit);
}

bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
                      const MultiLevelTemplateArgumentList &TemplateArgs,
                      SmallVectorImpl<Expr *> &Outputs) {
  if (Exprs.empty())
    return false;

  TemplateInstantiator Instantiator(*this, TemplateArgs,
                                    SourceLocation(),
                                    DeclarationName());
  return Instantiator.TransformExprs(Exprs.data(), Exprs.size(),
                                     IsCall, Outputs);
}

NestedNameSpecifierLoc
Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
                        const MultiLevelTemplateArgumentList &TemplateArgs) {
  if (!NNS)
    return NestedNameSpecifierLoc();

  TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
                                    DeclarationName());
  return Instantiator.TransformNestedNameSpecifierLoc(NNS);
}

DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
                         const MultiLevelTemplateArgumentList &TemplateArgs) {
  TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
                                    NameInfo.getName());
  return Instantiator.TransformDeclarationNameInfo(NameInfo);
}

TemplateName
Sema::SubstTemplateName(SourceLocation TemplateKWLoc,
                        NestedNameSpecifierLoc &QualifierLoc, TemplateName Name,
                        SourceLocation NameLoc,
                        const MultiLevelTemplateArgumentList &TemplateArgs) {
  TemplateInstantiator Instantiator(*this, TemplateArgs, NameLoc,
                                    DeclarationName());
  return Instantiator.TransformTemplateName(QualifierLoc, TemplateKWLoc, Name,
                                            NameLoc);
}

static const Decl *getCanonicalParmVarDecl(const Decl *D) {
  // When storing ParmVarDecls in the local instantiation scope, we always
  // want to use the ParmVarDecl from the canonical function declaration,
  // since the map is then valid for any redeclaration or definition of that
  // function.
  if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) {
    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
      unsigned i = PV->getFunctionScopeIndex();
      // This parameter might be from a freestanding function type within the
      // function and isn't necessarily referring to one of FD's parameters.
      if (i < FD->getNumParams() && FD->getParamDecl(i) == PV)
        return FD->getCanonicalDecl()->getParamDecl(i);
    }
  }
  return D;
}

llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
LocalInstantiationScope::getInstantiationOfIfExists(const Decl *D) {
  D = getCanonicalParmVarDecl(D);
  for (LocalInstantiationScope *Current = this; Current;
       Current = Current->Outer) {

    // Check if we found something within this scope.
    const Decl *CheckD = D;
    do {
      LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
      if (Found != Current->LocalDecls.end())
        return &Found->second;

      // If this is a tag declaration, it's possible that we need to look for
      // a previous declaration.
      if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
        CheckD = Tag->getPreviousDecl();
      else
        CheckD = nullptr;
    } while (CheckD);

    // If we aren't combined with our outer scope, we're done.
    if (!Current->CombineWithOuterScope)
      break;
  }

  return nullptr;
}

llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
LocalInstantiationScope::findInstantiationOf(const Decl *D) {
  auto *Result = getInstantiationOfIfExists(D);
  if (Result)
    return Result;
  // If we're performing a partial substitution during template argument
  // deduction, we may not have values for template parameters yet.
  if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
      isa<TemplateTemplateParmDecl>(D))
    return nullptr;

  // Local types referenced prior to definition may require instantiation.
  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
    if (RD->isLocalClass())
      return nullptr;

  // Enumeration types referenced prior to definition may appear as a result of
  // error recovery.
  if (isa<EnumDecl>(D))
    return nullptr;

  // Materialized typedefs/type alias for implicit deduction guides may require
  // instantiation.
  if (isa<TypedefNameDecl>(D) &&
      isa<CXXDeductionGuideDecl>(D->getDeclContext()))
    return nullptr;

  // If we didn't find the decl, then we either have a sema bug, or we have a
  // forward reference to a label declaration.  Return null to indicate that
  // we have an uninstantiated label.
  assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
  return nullptr;
}

void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
  D = getCanonicalParmVarDecl(D);
  llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
  if (Stored.isNull()) {
#ifndef NDEBUG
    // It should not be present in any surrounding scope either.
    LocalInstantiationScope *Current = this;
    while (Current->CombineWithOuterScope && Current->Outer) {
      Current = Current->Outer;
      assert(!Current->LocalDecls.contains(D) &&
             "Instantiated local in inner and outer scopes");
    }
#endif
    Stored = Inst;
  } else if (DeclArgumentPack *Pack = dyn_cast<DeclArgumentPack *>(Stored)) {
    Pack->push_back(cast<ValueDecl>(Inst));
  } else {
    assert(cast<Decl *>(Stored) == Inst && "Already instantiated this local");
  }
}

void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
                                                       VarDecl *Inst) {
  D = getCanonicalParmVarDecl(D);
  DeclArgumentPack *Pack = cast<DeclArgumentPack *>(LocalDecls[D]);
  Pack->push_back(Inst);
}

void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
#ifndef NDEBUG
  // This should be the first time we've been told about this decl.
  for (LocalInstantiationScope *Current = this;
       Current && Current->CombineWithOuterScope; Current = Current->Outer)
    assert(!Current->LocalDecls.contains(D) &&
           "Creating local pack after instantiation of local");
#endif

  D = getCanonicalParmVarDecl(D);
  llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
  DeclArgumentPack *Pack = new DeclArgumentPack;
  Stored = Pack;
  ArgumentPacks.push_back(Pack);
}

bool LocalInstantiationScope::isLocalPackExpansion(const Decl *D) {
  for (DeclArgumentPack *Pack : ArgumentPacks)
    if (llvm::is_contained(*Pack, D))
      return true;
  return false;
}

void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
                                          const TemplateArgument *ExplicitArgs,
                                                    unsigned NumExplicitArgs) {
  assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
         "Already have a partially-substituted pack");
  assert((!PartiallySubstitutedPack
          || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
         "Wrong number of arguments in partially-substituted pack");
  PartiallySubstitutedPack = Pack;
  ArgsInPartiallySubstitutedPack = ExplicitArgs;
  NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
}

NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
                                         const TemplateArgument **ExplicitArgs,
                                              unsigned *NumExplicitArgs) const {
  if (ExplicitArgs)
    *ExplicitArgs = nullptr;
  if (NumExplicitArgs)
    *NumExplicitArgs = 0;

  for (const LocalInstantiationScope *Current = this; Current;
       Current = Current->Outer) {
    if (Current->PartiallySubstitutedPack) {
      if (ExplicitArgs)
        *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
      if (NumExplicitArgs)
        *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;

      return Current->PartiallySubstitutedPack;
    }

    if (!Current->CombineWithOuterScope)
      break;
  }

  return nullptr;
}
