//===------- 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;
  }
  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
  if (!Invalid) {
    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;

    SemaRef.pushCodeSynthesisContext(Inst);

    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) {}

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

  CodeSynthesisContexts.push_back(Ctx);

  if (!Ctx.isInstantiationRecord())
    ++NonInstantiationEntries;

  // 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);
}

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;
}

bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
                                        SourceLocation PointOfInstantiation,
                                           SourceRange InstantiationRange) {
  assert(SemaRef.NonInstantiationEntries <=
         SemaRef.CodeSynthesisContexts.size());
  if ((SemaRef.CodeSynthesisContexts.size() -
          SemaRef.NonInstantiationEntries)
        <= SemaRef.getLangOpts().InstantiationDepth)
    return false;

  SemaRef.Diag(PointOfInstantiation,
               diag::err_template_recursion_depth_exceeded)
    << SemaRef.getLangOpts().InstantiationDepth
    << InstantiationRange;
  SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
    << SemaRef.getLangOpts().InstantiationDepth;
  return true;
}

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;
}

static TemplateArgument
getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
  assert(S.ArgPackSubstIndex);
  assert(*S.ArgPackSubstIndex < Arg.pack_size());
  Arg = Arg.pack_begin()[*S.ArgPackSubstIndex];
  if (Arg.isPackExpansion())
    Arg = Arg.getPackExpansionPattern();
  return Arg;
}

//===----------------------------------------------------------------------===/
// 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);
    }

    UnsignedOrNone getPackIndex(TemplateArgument Pack) {
      UnsignedOrNone Index = getSema().ArgPackSubstIndex;
      if (!Index)
        return std::nullopt;
      return Pack.pack_size() - 1 - *Index;
    }

    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 getPackSubstitutedTemplateArgument(SemaRef, 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);
    ExprResult TransformSubstNonTypeTemplateParmPackExpr(
                                           SubstNonTypeTemplateParmPackExpr *E);
    ExprResult TransformSubstNonTypeTemplateParmExpr(
                                           SubstNonTypeTemplateParmExpr *E);

    /// 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);

  private:
    ExprResult
    transformNonTypeTemplateParmRef(Decl *AssociatedDecl, const NamedDecl *parm,
                                    SourceLocation loc, TemplateArgument arg,
                                    UnsignedOrNone PackIndex, bool Final);
  };
}

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 = getPackSubstitutedTemplateArgument(getSema(), 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 = getPackSubstitutedTemplateArgument(getSema(), 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 (TemplateTemplateParmDecl *TTP
       = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
    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 ? 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 = getPackIndex(Arg);
        Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
      }

      TemplateName Template = Arg.getAsTemplate();
      assert(!Template.isNull() && "Null template template argument");

      if (NestedNameSpecifier Qualifier = Template.getQualifier()) {
        NestedNameSpecifierLocBuilder Builder;
        Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
        QualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
      }

      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 =
        getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
    return getSema().Context.getSubstTemplateTemplateParm(
        Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
        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 = getPackIndex(Arg);
    Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
  }
  return transformNonTypeTemplateParmRef(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::transformNonTypeTemplateParmRef(
    Decl *AssociatedDecl, const NamedDecl *parm, SourceLocation loc,
    TemplateArgument arg, UnsignedOrNone PackIndex, bool Final) {
  ExprResult result;

  // Determine the substituted parameter type. We can usually infer this from
  // the template argument, but not always.
  auto SubstParamType = [&] {
    if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) {
      QualType T;
      if (NTTP->isExpandedParameterPack())
        T = NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex);
      else
        T = NTTP->getType();
      if (parm->isParameterPack() && isa<PackExpansionType>(T))
        T = cast<PackExpansionType>(T)->getPattern();
      return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
    }
    return SemaRef.SubstType(arg.getAsExpr()->getType(), TemplateArgs, loc,
                             parm->getDeclName());
  };

  bool refParam = false;

  // The template argument itself might be an expression, in which case we just
  // return that expression. This happens when substituting into an alias
  // template.
  if (arg.getKind() == TemplateArgument::Expression) {
    Expr *argExpr = arg.getAsExpr();
    result = argExpr;
    if (argExpr->isLValue()) {
      if (argExpr->getType()->isRecordType()) {
        // Check whether the parameter was actually a reference.
        QualType paramType = SubstParamType();
        if (paramType.isNull())
          return ExprError();
        refParam = paramType->isReferenceType();
      } else {
        refParam = true;
      }
    }
  } else if (arg.getKind() == TemplateArgument::Declaration ||
             arg.getKind() == TemplateArgument::NullPtr) {
    if (arg.getKind() == TemplateArgument::Declaration) {
      ValueDecl *VD = arg.getAsDecl();

      // Find the instantiation of the template argument.  This is
      // required for nested templates.
      VD = cast_or_null<ValueDecl>(
             getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
      if (!VD)
        return ExprError();
    }

    QualType paramType = arg.getNonTypeTemplateArgumentType();
    assert(!paramType.isNull() && "type substitution failed for param type");
    assert(!paramType->isDependentType() && "param type still dependent");
    result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
    refParam = paramType->isReferenceType();
  } else {
    QualType paramType = arg.getNonTypeTemplateArgumentType();
    result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
    refParam = paramType->isReferenceType();
    assert(result.isInvalid() ||
           SemaRef.Context.hasSameType(result.get()->getType(),
                                       paramType.getNonReferenceType()));
  }

  if (result.isInvalid())
    return ExprError();

  Expr *resultExpr = result.get();
  return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
      resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
      AssociatedDecl,
      clang::getDepthAndIndex(const_cast<NamedDecl *>(parm)).second, PackIndex,
      refParam, Final);
}

ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
                                          SubstNonTypeTemplateParmPackExpr *E) {
  if (!getSema().ArgPackSubstIndex) {
    // We aren't expanding the parameter pack, so just return ourselves.
    return E;
  }

  TemplateArgument Pack = E->getArgumentPack();
  TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
  return transformNonTypeTemplateParmRef(
      E->getAssociatedDecl(), E->getParameterPack(),
      E->getParameterPackLocation(), Arg, getPackIndex(Pack), E->getFinal());
}

ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
                                          SubstNonTypeTemplateParmExpr *E) {
  ExprResult SubstReplacement = E->getReplacement();
  if (!isa<ConstantExpr>(SubstReplacement.get()))
    SubstReplacement = TransformExpr(E->getReplacement());
  if (SubstReplacement.isInvalid())
    return true;
  QualType SubstType = TransformType(E->getParameterType(getSema().Context));
  if (SubstType.isNull())
    return true;
  // The type may have been previously dependent and not now, which means we
  // might have to implicit cast the argument to the new type, for example:
  // template<auto T, decltype(T) U>
  // concept C = sizeof(U) == 4;
  // void foo() requires C<2, 'a'> { }
  // When normalizing foo(), we first form the normalized constraints of C:
  // AtomicExpr(sizeof(U) == 4,
  //            U=SubstNonTypeTemplateParmExpr(Param=U,
  //                                           Expr=DeclRef(U),
  //                                           Type=decltype(T)))
  // Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
  // produce:
  // AtomicExpr(sizeof(U) == 4,
  //            U=SubstNonTypeTemplateParmExpr(Param=U,
  //                                           Expr=ImpCast(
  //                                               decltype(2),
  //                                               SubstNTTPE(Param=U, Expr='a',
  //                                                          Type=char)),
  //                                           Type=decltype(2)))
  // The call to CheckTemplateArgument here produces the ImpCast.
  TemplateArgument SugaredConverted, CanonicalConverted;
  if (SemaRef
          .CheckTemplateArgument(E->getParameter(), SubstType,
                                 SubstReplacement.get(), SugaredConverted,
                                 CanonicalConverted,
                                 /*StrictCheck=*/false, Sema::CTAK_Specified)
          .isInvalid())
    return true;
  return transformNonTypeTemplateParmRef(
      E->getAssociatedDecl(), E->getParameter(), E->getExprLoc(),
      SugaredConverted, E->getPackIndex(), E->getFinal());
}

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 = getPackIndex(Arg);
      Arg = getPackSubstitutedTemplateArgument(getSema(), 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 = getPackSubstitutedTemplateArgument(getSema(), Pack);
  return BuildSubstTemplateTypeParmType(
      TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
      getPackIndex(Pack), Arg, TL.getNameLoc());
}

QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
    TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
  if (!getSema().ArgPackSubstIndex)
    return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
  auto &Sema = getSema();
  TemplateArgument Result = getPackSubstitutedTemplateArgument(
      Sema, TL.getTypePtr()->getArgumentPack());
  TLB.pushTrivial(Sema.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;
}
