//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===//
//
// 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 semantic analysis for C++ templates.
//===----------------------------------------------------------------------===//

#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SaveAndRestore.h"

#include <optional>
using namespace clang;
using namespace sema;

// Exported for use by Parser.
SourceRange
clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
                              unsigned N) {
  if (!N) return SourceRange();
  return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}

unsigned Sema::getTemplateDepth(Scope *S) const {
  unsigned Depth = 0;

  // Each template parameter scope represents one level of template parameter
  // depth.
  for (Scope *TempParamScope = S->getTemplateParamParent(); TempParamScope;
       TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) {
    ++Depth;
  }

  // Note that there are template parameters with the given depth.
  auto ParamsAtDepth = [&](unsigned D) { Depth = std::max(Depth, D + 1); };

  // Look for parameters of an enclosing generic lambda. We don't create a
  // template parameter scope for these.
  for (FunctionScopeInfo *FSI : getFunctionScopes()) {
    if (auto *LSI = dyn_cast<LambdaScopeInfo>(FSI)) {
      if (!LSI->TemplateParams.empty()) {
        ParamsAtDepth(LSI->AutoTemplateParameterDepth);
        break;
      }
      if (LSI->GLTemplateParameterList) {
        ParamsAtDepth(LSI->GLTemplateParameterList->getDepth());
        break;
      }
    }
  }

  // Look for parameters of an enclosing terse function template. We don't
  // create a template parameter scope for these either.
  for (const InventedTemplateParameterInfo &Info :
       getInventedParameterInfos()) {
    if (!Info.TemplateParams.empty()) {
      ParamsAtDepth(Info.AutoTemplateParameterDepth);
      break;
    }
  }

  return Depth;
}

/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns null.
///
/// Note that this may return an UnresolvedUsingValueDecl if AllowDependent
/// is true. In all other cases it will return a TemplateDecl (or null).
NamedDecl *Sema::getAsTemplateNameDecl(NamedDecl *D,
                                       bool AllowFunctionTemplates,
                                       bool AllowDependent) {
  D = D->getUnderlyingDecl();

  if (isa<TemplateDecl>(D)) {
    if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
      return nullptr;

    return D;
  }

  if (const auto *Record = dyn_cast<CXXRecordDecl>(D)) {
    // C++ [temp.local]p1:
    //   Like normal (non-template) classes, class templates have an
    //   injected-class-name (Clause 9). The injected-class-name
    //   can be used with or without a template-argument-list. When
    //   it is used without a template-argument-list, it is
    //   equivalent to the injected-class-name followed by the
    //   template-parameters of the class template enclosed in
    //   <>. When it is used with a template-argument-list, it
    //   refers to the specified class template specialization,
    //   which could be the current specialization or another
    //   specialization.
    if (Record->isInjectedClassName()) {
      Record = cast<CXXRecordDecl>(Record->getDeclContext());
      if (Record->getDescribedClassTemplate())
        return Record->getDescribedClassTemplate();

      if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record))
        return Spec->getSpecializedTemplate();
    }

    return nullptr;
  }

  // 'using Dependent::foo;' can resolve to a template name.
  // 'using typename Dependent::foo;' cannot (not even if 'foo' is an
  // injected-class-name).
  if (AllowDependent && isa<UnresolvedUsingValueDecl>(D))
    return D;

  return nullptr;
}

void Sema::FilterAcceptableTemplateNames(LookupResult &R,
                                         bool AllowFunctionTemplates,
                                         bool AllowDependent) {
  LookupResult::Filter filter = R.makeFilter();
  while (filter.hasNext()) {
    NamedDecl *Orig = filter.next();
    if (!getAsTemplateNameDecl(Orig, AllowFunctionTemplates, AllowDependent))
      filter.erase();
  }
  filter.done();
}

bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
                                         bool AllowFunctionTemplates,
                                         bool AllowDependent,
                                         bool AllowNonTemplateFunctions) {
  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {
    if (getAsTemplateNameDecl(*I, AllowFunctionTemplates, AllowDependent))
      return true;
    if (AllowNonTemplateFunctions &&
        isa<FunctionDecl>((*I)->getUnderlyingDecl()))
      return true;
  }

  return false;
}

TemplateNameKind Sema::isTemplateName(Scope *S,
                                      CXXScopeSpec &SS,
                                      bool hasTemplateKeyword,
                                      const UnqualifiedId &Name,
                                      ParsedType ObjectTypePtr,
                                      bool EnteringContext,
                                      TemplateTy &TemplateResult,
                                      bool &MemberOfUnknownSpecialization,
                                      bool Disambiguation) {
  assert(getLangOpts().CPlusPlus && "No template names in C!");

  DeclarationName TName;
  MemberOfUnknownSpecialization = false;

  switch (Name.getKind()) {
  case UnqualifiedIdKind::IK_Identifier:
    TName = DeclarationName(Name.Identifier);
    break;

  case UnqualifiedIdKind::IK_OperatorFunctionId:
    TName = Context.DeclarationNames.getCXXOperatorName(
                                              Name.OperatorFunctionId.Operator);
    break;

  case UnqualifiedIdKind::IK_LiteralOperatorId:
    TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
    break;

  default:
    return TNK_Non_template;
  }

  QualType ObjectType = ObjectTypePtr.get();

  AssumedTemplateKind AssumedTemplate;
  LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);
  if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
                         /*RequiredTemplate=*/SourceLocation(),
                         &AssumedTemplate,
                         /*AllowTypoCorrection=*/!Disambiguation))
    return TNK_Non_template;
  MemberOfUnknownSpecialization = R.wasNotFoundInCurrentInstantiation();

  if (AssumedTemplate != AssumedTemplateKind::None) {
    TemplateResult = TemplateTy::make(Context.getAssumedTemplateName(TName));
    // Let the parser know whether we found nothing or found functions; if we
    // found nothing, we want to more carefully check whether this is actually
    // a function template name versus some other kind of undeclared identifier.
    return AssumedTemplate == AssumedTemplateKind::FoundNothing
               ? TNK_Undeclared_template
               : TNK_Function_template;
  }

  if (R.empty())
    return TNK_Non_template;

  NamedDecl *D = nullptr;
  UsingShadowDecl *FoundUsingShadow = dyn_cast<UsingShadowDecl>(*R.begin());
  if (R.isAmbiguous()) {
    // If we got an ambiguity involving a non-function template, treat this
    // as a template name, and pick an arbitrary template for error recovery.
    bool AnyFunctionTemplates = false;
    for (NamedDecl *FoundD : R) {
      if (NamedDecl *FoundTemplate = getAsTemplateNameDecl(FoundD)) {
        if (isa<FunctionTemplateDecl>(FoundTemplate))
          AnyFunctionTemplates = true;
        else {
          D = FoundTemplate;
          FoundUsingShadow = dyn_cast<UsingShadowDecl>(FoundD);
          break;
        }
      }
    }

    // If we didn't find any templates at all, this isn't a template name.
    // Leave the ambiguity for a later lookup to diagnose.
    if (!D && !AnyFunctionTemplates) {
      R.suppressDiagnostics();
      return TNK_Non_template;
    }

    // If the only templates were function templates, filter out the rest.
    // We'll diagnose the ambiguity later.
    if (!D)
      FilterAcceptableTemplateNames(R);
  }

  // At this point, we have either picked a single template name declaration D
  // or we have a non-empty set of results R containing either one template name
  // declaration or a set of function templates.

  TemplateName Template;
  TemplateNameKind TemplateKind;

  unsigned ResultCount = R.end() - R.begin();
  if (!D && ResultCount > 1) {
    // We assume that we'll preserve the qualifier from a function
    // template name in other ways.
    Template = Context.getOverloadedTemplateName(R.begin(), R.end());
    TemplateKind = TNK_Function_template;

    // We'll do this lookup again later.
    R.suppressDiagnostics();
  } else {
    if (!D) {
      D = getAsTemplateNameDecl(*R.begin());
      assert(D && "unambiguous result is not a template name");
    }

    if (isa<UnresolvedUsingValueDecl>(D)) {
      // We don't yet know whether this is a template-name or not.
      MemberOfUnknownSpecialization = true;
      return TNK_Non_template;
    }

    TemplateDecl *TD = cast<TemplateDecl>(D);
    Template =
        FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
    assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
    if (!SS.isInvalid()) {
      NestedNameSpecifier *Qualifier = SS.getScopeRep();
      Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword,
                                                  Template);
    }

    if (isa<FunctionTemplateDecl>(TD)) {
      TemplateKind = TNK_Function_template;

      // We'll do this lookup again later.
      R.suppressDiagnostics();
    } else {
      assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
             isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
             isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));
      TemplateKind =
          isa<VarTemplateDecl>(TD) ? TNK_Var_template :
          isa<ConceptDecl>(TD) ? TNK_Concept_template :
          TNK_Type_template;
    }
  }

  TemplateResult = TemplateTy::make(Template);
  return TemplateKind;
}

bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
                                SourceLocation NameLoc, CXXScopeSpec &SS,
                                ParsedTemplateTy *Template /*=nullptr*/) {
  // We could use redeclaration lookup here, but we don't need to: the
  // syntactic form of a deduction guide is enough to identify it even
  // if we can't look up the template name at all.
  LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName);
  if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(),
                         /*EnteringContext*/ false))
    return false;

  if (R.empty()) return false;
  if (R.isAmbiguous()) {
    // FIXME: Diagnose an ambiguity if we find at least one template.
    R.suppressDiagnostics();
    return false;
  }

  // We only treat template-names that name type templates as valid deduction
  // guide names.
  TemplateDecl *TD = R.getAsSingle<TemplateDecl>();
  if (!TD || !getAsTypeTemplateDecl(TD))
    return false;

  if (Template) {
    TemplateName Name = Context.getQualifiedTemplateName(
        SS.getScopeRep(), /*TemplateKeyword=*/false, TemplateName(TD));
    *Template = TemplateTy::make(Name);
  }
  return true;
}

bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
                                       SourceLocation IILoc,
                                       Scope *S,
                                       const CXXScopeSpec *SS,
                                       TemplateTy &SuggestedTemplate,
                                       TemplateNameKind &SuggestedKind) {
  // We can't recover unless there's a dependent scope specifier preceding the
  // template name.
  // FIXME: Typo correction?
  if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
      computeDeclContext(*SS))
    return false;

  // The code is missing a 'template' keyword prior to the dependent template
  // name.
  NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep();
  SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName(
      {Qualifier, &II, /*HasTemplateKeyword=*/false}));
  Diag(IILoc, diag::err_template_kw_missing)
      << SuggestedTemplate.get()
      << FixItHint::CreateInsertion(IILoc, "template ");
  SuggestedKind = TNK_Dependent_template_name;
  return true;
}

bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
                              QualType ObjectType, bool EnteringContext,
                              RequiredTemplateKind RequiredTemplate,
                              AssumedTemplateKind *ATK,
                              bool AllowTypoCorrection) {
  if (ATK)
    *ATK = AssumedTemplateKind::None;

  if (SS.isInvalid())
    return true;

  Found.setTemplateNameLookup(true);

  // Determine where to perform name lookup
  DeclContext *LookupCtx = nullptr;
  bool IsDependent = false;
  if (!ObjectType.isNull()) {
    // This nested-name-specifier occurs in a member access expression, e.g.,
    // x->B::f, and we are looking into the type of the object.
    assert(SS.isEmpty() && "ObjectType and scope specifier cannot coexist");
    LookupCtx = computeDeclContext(ObjectType);
    IsDependent = !LookupCtx && ObjectType->isDependentType();
    assert((IsDependent || !ObjectType->isIncompleteType() ||
            !ObjectType->getAs<TagType>() ||
            ObjectType->castAs<TagType>()->isBeingDefined()) &&
           "Caller should have completed object type");

    // Template names cannot appear inside an Objective-C class or object type
    // or a vector type.
    //
    // FIXME: This is wrong. For example:
    //
    //   template<typename T> using Vec = T __attribute__((ext_vector_type(4)));
    //   Vec<int> vi;
    //   vi.Vec<int>::~Vec<int>();
    //
    // ... should be accepted but we will not treat 'Vec' as a template name
    // here. The right thing to do would be to check if the name is a valid
    // vector component name, and look up a template name if not. And similarly
    // for lookups into Objective-C class and object types, where the same
    // problem can arise.
    if (ObjectType->isObjCObjectOrInterfaceType() ||
        ObjectType->isVectorType()) {
      Found.clear();
      return false;
    }
  } else if (SS.isNotEmpty()) {
    // This nested-name-specifier occurs after another nested-name-specifier,
    // so long into the context associated with the prior nested-name-specifier.
    LookupCtx = computeDeclContext(SS, EnteringContext);
    IsDependent = !LookupCtx && isDependentScopeSpecifier(SS);

    // The declaration context must be complete.
    if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
      return true;
  }

  bool ObjectTypeSearchedInScope = false;
  bool AllowFunctionTemplatesInLookup = true;
  if (LookupCtx) {
    // Perform "qualified" name lookup into the declaration context we
    // computed, which is either the type of the base of a member access
    // expression or the declaration context associated with a prior
    // nested-name-specifier.
    LookupQualifiedName(Found, LookupCtx);

    // FIXME: The C++ standard does not clearly specify what happens in the
    // case where the object type is dependent, and implementations vary. In
    // Clang, we treat a name after a . or -> as a template-name if lookup
    // finds a non-dependent member or member of the current instantiation that
    // is a type template, or finds no such members and lookup in the context
    // of the postfix-expression finds a type template. In the latter case, the
    // name is nonetheless dependent, and we may resolve it to a member of an
    // unknown specialization when we come to instantiate the template.
    IsDependent |= Found.wasNotFoundInCurrentInstantiation();
  }

  if (SS.isEmpty() && (ObjectType.isNull() || Found.empty())) {
    // C++ [basic.lookup.classref]p1:
    //   In a class member access expression (5.2.5), if the . or -> token is
    //   immediately followed by an identifier followed by a <, the
    //   identifier must be looked up to determine whether the < is the
    //   beginning of a template argument list (14.2) or a less-than operator.
    //   The identifier is first looked up in the class of the object
    //   expression. If the identifier is not found, it is then looked up in
    //   the context of the entire postfix-expression and shall name a class
    //   template.
    if (S)
      LookupName(Found, S);

    if (!ObjectType.isNull()) {
      //  FIXME: We should filter out all non-type templates here, particularly
      //  variable templates and concepts. But the exclusion of alias templates
      //  and template template parameters is a wording defect.
      AllowFunctionTemplatesInLookup = false;
      ObjectTypeSearchedInScope = true;
    }

    IsDependent |= Found.wasNotFoundInCurrentInstantiation();
  }

  if (Found.isAmbiguous())
    return false;

  if (ATK && SS.isEmpty() && ObjectType.isNull() &&
      !RequiredTemplate.hasTemplateKeyword()) {
    // C++2a [temp.names]p2:
    //   A name is also considered to refer to a template if it is an
    //   unqualified-id followed by a < and name lookup finds either one or more
    //   functions or finds nothing.
    //
    // To keep our behavior consistent, we apply the "finds nothing" part in
    // all language modes, and diagnose the empty lookup in ActOnCallExpr if we
    // successfully form a call to an undeclared template-id.
    bool AllFunctions =
        getLangOpts().CPlusPlus20 && llvm::all_of(Found, [](NamedDecl *ND) {
          return isa<FunctionDecl>(ND->getUnderlyingDecl());
        });
    if (AllFunctions || (Found.empty() && !IsDependent)) {
      // If lookup found any functions, or if this is a name that can only be
      // used for a function, then strongly assume this is a function
      // template-id.
      *ATK = (Found.empty() && Found.getLookupName().isIdentifier())
                 ? AssumedTemplateKind::FoundNothing
                 : AssumedTemplateKind::FoundFunctions;
      Found.clear();
      return false;
    }
  }

  if (Found.empty() && !IsDependent && AllowTypoCorrection) {
    // If we did not find any names, and this is not a disambiguation, attempt
    // to correct any typos.
    DeclarationName Name = Found.getLookupName();
    Found.clear();
    // Simple filter callback that, for keywords, only accepts the C++ *_cast
    DefaultFilterCCC FilterCCC{};
    FilterCCC.WantTypeSpecifiers = false;
    FilterCCC.WantExpressionKeywords = false;
    FilterCCC.WantRemainingKeywords = false;
    FilterCCC.WantCXXNamedCasts = true;
    if (TypoCorrection Corrected = CorrectTypo(
            Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, FilterCCC,
            CorrectTypoKind::ErrorRecovery, LookupCtx)) {
      if (auto *ND = Corrected.getFoundDecl())
        Found.addDecl(ND);
      FilterAcceptableTemplateNames(Found);
      if (Found.isAmbiguous()) {
        Found.clear();
      } else if (!Found.empty()) {
        Found.setLookupName(Corrected.getCorrection());
        if (LookupCtx) {
          std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
          bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
                                  Name.getAsString() == CorrectedStr;
          diagnoseTypo(Corrected, PDiag(diag::err_no_member_template_suggest)
                                    << Name << LookupCtx << DroppedSpecifier
                                    << SS.getRange());
        } else {
          diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name);
        }
      }
    }
  }

  NamedDecl *ExampleLookupResult =
      Found.empty() ? nullptr : Found.getRepresentativeDecl();
  FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
  if (Found.empty()) {
    if (IsDependent) {
      Found.setNotFoundInCurrentInstantiation();
      return false;
    }

    // If a 'template' keyword was used, a lookup that finds only non-template
    // names is an error.
    if (ExampleLookupResult && RequiredTemplate) {
      Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
          << Found.getLookupName() << SS.getRange()
          << RequiredTemplate.hasTemplateKeyword()
          << RequiredTemplate.getTemplateKeywordLoc();
      Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
           diag::note_template_kw_refers_to_non_template)
          << Found.getLookupName();
      return true;
    }

    return false;
  }

  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
      !getLangOpts().CPlusPlus11) {
    // C++03 [basic.lookup.classref]p1:
    //   [...] If the lookup in the class of the object expression finds a
    //   template, the name is also looked up in the context of the entire
    //   postfix-expression and [...]
    //
    // Note: C++11 does not perform this second lookup.
    LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
                            LookupOrdinaryName);
    FoundOuter.setTemplateNameLookup(true);
    LookupName(FoundOuter, S);
    // FIXME: We silently accept an ambiguous lookup here, in violation of
    // [basic.lookup]/1.
    FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false);

    NamedDecl *OuterTemplate;
    if (FoundOuter.empty()) {
      //   - if the name is not found, the name found in the class of the
      //     object expression is used, otherwise
    } else if (FoundOuter.isAmbiguous() || !FoundOuter.isSingleResult() ||
               !(OuterTemplate =
                     getAsTemplateNameDecl(FoundOuter.getFoundDecl()))) {
      //   - if the name is found in the context of the entire
      //     postfix-expression and does not name a class template, the name
      //     found in the class of the object expression is used, otherwise
      FoundOuter.clear();
    } else if (!Found.isSuppressingAmbiguousDiagnostics()) {
      //   - if the name found is a class template, it must refer to the same
      //     entity as the one found in the class of the object expression,
      //     otherwise the program is ill-formed.
      if (!Found.isSingleResult() ||
          getAsTemplateNameDecl(Found.getFoundDecl())->getCanonicalDecl() !=
              OuterTemplate->getCanonicalDecl()) {
        Diag(Found.getNameLoc(),
             diag::ext_nested_name_member_ref_lookup_ambiguous)
          << Found.getLookupName()
          << ObjectType;
        Diag(Found.getRepresentativeDecl()->getLocation(),
             diag::note_ambig_member_ref_object_type)
          << ObjectType;
        Diag(FoundOuter.getFoundDecl()->getLocation(),
             diag::note_ambig_member_ref_scope);

        // Recover by taking the template that we found in the object
        // expression's type.
      }
    }
  }

  return false;
}

void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
                                              SourceLocation Less,
                                              SourceLocation Greater) {
  if (TemplateName.isInvalid())
    return;

  DeclarationNameInfo NameInfo;
  CXXScopeSpec SS;
  LookupNameKind LookupKind;

  DeclContext *LookupCtx = nullptr;
  NamedDecl *Found = nullptr;
  bool MissingTemplateKeyword = false;

  // Figure out what name we looked up.
  if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) {
    NameInfo = DRE->getNameInfo();
    SS.Adopt(DRE->getQualifierLoc());
    LookupKind = LookupOrdinaryName;
    Found = DRE->getFoundDecl();
  } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
    NameInfo = ME->getMemberNameInfo();
    SS.Adopt(ME->getQualifierLoc());
    LookupKind = LookupMemberName;
    LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl();
    Found = ME->getMemberDecl();
  } else if (auto *DSDRE =
                 dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) {
    NameInfo = DSDRE->getNameInfo();
    SS.Adopt(DSDRE->getQualifierLoc());
    MissingTemplateKeyword = true;
  } else if (auto *DSME =
                 dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) {
    NameInfo = DSME->getMemberNameInfo();
    SS.Adopt(DSME->getQualifierLoc());
    MissingTemplateKeyword = true;
  } else {
    llvm_unreachable("unexpected kind of potential template name");
  }

  // If this is a dependent-scope lookup, diagnose that the 'template' keyword
  // was missing.
  if (MissingTemplateKeyword) {
    Diag(NameInfo.getBeginLoc(), diag::err_template_kw_missing)
        << NameInfo.getName() << SourceRange(Less, Greater);
    return;
  }

  // Try to correct the name by looking for templates and C++ named casts.
  struct TemplateCandidateFilter : CorrectionCandidateCallback {
    Sema &S;
    TemplateCandidateFilter(Sema &S) : S(S) {
      WantTypeSpecifiers = false;
      WantExpressionKeywords = false;
      WantRemainingKeywords = false;
      WantCXXNamedCasts = true;
    };
    bool ValidateCandidate(const TypoCorrection &Candidate) override {
      if (auto *ND = Candidate.getCorrectionDecl())
        return S.getAsTemplateNameDecl(ND);
      return Candidate.isKeyword();
    }

    std::unique_ptr<CorrectionCandidateCallback> clone() override {
      return std::make_unique<TemplateCandidateFilter>(*this);
    }
  };

  DeclarationName Name = NameInfo.getName();
  TemplateCandidateFilter CCC(*this);
  if (TypoCorrection Corrected =
          CorrectTypo(NameInfo, LookupKind, S, &SS, CCC,
                      CorrectTypoKind::ErrorRecovery, LookupCtx)) {
    auto *ND = Corrected.getFoundDecl();
    if (ND)
      ND = getAsTemplateNameDecl(ND);
    if (ND || Corrected.isKeyword()) {
      if (LookupCtx) {
        std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
        bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
                                Name.getAsString() == CorrectedStr;
        diagnoseTypo(Corrected,
                     PDiag(diag::err_non_template_in_member_template_id_suggest)
                         << Name << LookupCtx << DroppedSpecifier
                         << SS.getRange(), false);
      } else {
        diagnoseTypo(Corrected,
                     PDiag(diag::err_non_template_in_template_id_suggest)
                         << Name, false);
      }
      if (Found)
        Diag(Found->getLocation(),
             diag::note_non_template_in_template_id_found);
      return;
    }
  }

  Diag(NameInfo.getLoc(), diag::err_non_template_in_template_id)
    << Name << SourceRange(Less, Greater);
  if (Found)
    Diag(Found->getLocation(), diag::note_non_template_in_template_id_found);
}

ExprResult
Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
                                 SourceLocation TemplateKWLoc,
                                 const DeclarationNameInfo &NameInfo,
                                 bool isAddressOfOperand,
                           const TemplateArgumentListInfo *TemplateArgs) {
  if (SS.isEmpty()) {
    // FIXME: This codepath is only used by dependent unqualified names
    // (e.g. a dependent conversion-function-id, or operator= once we support
    // it). It doesn't quite do the right thing, and it will silently fail if
    // getCurrentThisType() returns null.
    QualType ThisType = getCurrentThisType();
    if (ThisType.isNull())
      return ExprError();

    return CXXDependentScopeMemberExpr::Create(
        Context, /*Base=*/nullptr, ThisType,
        /*IsArrow=*/!Context.getLangOpts().HLSL,
        /*OperatorLoc=*/SourceLocation(),
        /*QualifierLoc=*/NestedNameSpecifierLoc(), TemplateKWLoc,
        /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs);
  }
  return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
}

ExprResult
Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
                                SourceLocation TemplateKWLoc,
                                const DeclarationNameInfo &NameInfo,
                                const TemplateArgumentListInfo *TemplateArgs) {
  // DependentScopeDeclRefExpr::Create requires a valid NestedNameSpecifierLoc
  if (!SS.isValid())
    return CreateRecoveryExpr(
        SS.getBeginLoc(),
        TemplateArgs ? TemplateArgs->getRAngleLoc() : NameInfo.getEndLoc(), {});

  return DependentScopeDeclRefExpr::Create(
      Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
      TemplateArgs);
}

bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
                                          NamedDecl *Instantiation,
                                          bool InstantiatedFromMember,
                                          const NamedDecl *Pattern,
                                          const NamedDecl *PatternDef,
                                          TemplateSpecializationKind TSK,
                                          bool Complain, bool *Unreachable) {
  assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) ||
         isa<VarDecl>(Instantiation));

  bool IsEntityBeingDefined = false;
  if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(PatternDef))
    IsEntityBeingDefined = TD->isBeingDefined();

  if (PatternDef && !IsEntityBeingDefined) {
    NamedDecl *SuggestedDef = nullptr;
    if (!hasReachableDefinition(const_cast<NamedDecl *>(PatternDef),
                                &SuggestedDef,
                                /*OnlyNeedComplete*/ false)) {
      if (Unreachable)
        *Unreachable = true;
      // If we're allowed to diagnose this and recover, do so.
      bool Recover = Complain && !isSFINAEContext();
      if (Complain)
        diagnoseMissingImport(PointOfInstantiation, SuggestedDef,
                              Sema::MissingImportKind::Definition, Recover);
      return !Recover;
    }
    return false;
  }

  if (!Complain || (PatternDef && PatternDef->isInvalidDecl()))
    return true;

  QualType InstantiationTy;
  if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation))
    InstantiationTy = Context.getTypeDeclType(TD);
  if (PatternDef) {
    Diag(PointOfInstantiation,
         diag::err_template_instantiate_within_definition)
      << /*implicit|explicit*/(TSK != TSK_ImplicitInstantiation)
      << InstantiationTy;
    // Not much point in noting the template declaration here, since
    // we're lexically inside it.
    Instantiation->setInvalidDecl();
  } else if (InstantiatedFromMember) {
    if (isa<FunctionDecl>(Instantiation)) {
      Diag(PointOfInstantiation,
           diag::err_explicit_instantiation_undefined_member)
        << /*member function*/ 1 << Instantiation->getDeclName()
        << Instantiation->getDeclContext();
      Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here);
    } else {
      assert(isa<TagDecl>(Instantiation) && "Must be a TagDecl!");
      Diag(PointOfInstantiation,
           diag::err_implicit_instantiate_member_undefined)
        << InstantiationTy;
      Diag(Pattern->getLocation(), diag::note_member_declared_at);
    }
  } else {
    if (isa<FunctionDecl>(Instantiation)) {
      Diag(PointOfInstantiation,
           diag::err_explicit_instantiation_undefined_func_template)
        << Pattern;
      Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here);
    } else if (isa<TagDecl>(Instantiation)) {
      Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
        << (TSK != TSK_ImplicitInstantiation)
        << InstantiationTy;
      NoteTemplateLocation(*Pattern);
    } else {
      assert(isa<VarDecl>(Instantiation) && "Must be a VarDecl!");
      if (isa<VarTemplateSpecializationDecl>(Instantiation)) {
        Diag(PointOfInstantiation,
             diag::err_explicit_instantiation_undefined_var_template)
          << Instantiation;
        Instantiation->setInvalidDecl();
      } else
        Diag(PointOfInstantiation,
             diag::err_explicit_instantiation_undefined_member)
          << /*static data member*/ 2 << Instantiation->getDeclName()
          << Instantiation->getDeclContext();
      Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here);
    }
  }

  // In general, Instantiation isn't marked invalid to get more than one
  // error for multiple undefined instantiations. But the code that does
  // explicit declaration -> explicit definition conversion can't handle
  // invalid declarations, so mark as invalid in that case.
  if (TSK == TSK_ExplicitInstantiationDeclaration)
    Instantiation->setInvalidDecl();
  return true;
}

void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
                                           bool SupportedForCompatibility) {
  assert(PrevDecl->isTemplateParameter() && "Not a template parameter");

  // C++23 [temp.local]p6:
  //   The name of a template-parameter shall not be bound to any following.
  //   declaration whose locus is contained by the scope to which the
  //   template-parameter belongs.
  //
  // When MSVC compatibility is enabled, the diagnostic is always a warning
  // by default. Otherwise, it an error unless SupportedForCompatibility is
  // true, in which case it is a default-to-error warning.
  unsigned DiagId =
      getLangOpts().MSVCCompat
          ? diag::ext_template_param_shadow
          : (SupportedForCompatibility ? diag::ext_compat_template_param_shadow
                                       : diag::err_template_param_shadow);
  const auto *ND = cast<NamedDecl>(PrevDecl);
  Diag(Loc, DiagId) << ND->getDeclName();
  NoteTemplateParameterLocation(*ND);
}

TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
  if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) {
    D = Temp->getTemplatedDecl();
    return Temp;
  }
  return nullptr;
}

ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
                                             SourceLocation EllipsisLoc) const {
  assert(Kind == Template &&
         "Only template template arguments can be pack expansions here");
  assert(getAsTemplate().get().containsUnexpandedParameterPack() &&
         "Template template argument pack expansion without packs");
  ParsedTemplateArgument Result(*this);
  Result.EllipsisLoc = EllipsisLoc;
  return Result;
}

static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
                                            const ParsedTemplateArgument &Arg) {

  switch (Arg.getKind()) {
  case ParsedTemplateArgument::Type: {
    TypeSourceInfo *DI;
    QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
    if (!DI)
      DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
    return TemplateArgumentLoc(TemplateArgument(T), DI);
  }

  case ParsedTemplateArgument::NonType: {
    Expr *E = static_cast<Expr *>(Arg.getAsExpr());
    return TemplateArgumentLoc(TemplateArgument(E, /*IsCanonical=*/false), E);
  }

  case ParsedTemplateArgument::Template: {
    TemplateName Template = Arg.getAsTemplate().get();
    TemplateArgument TArg;
    if (Arg.getEllipsisLoc().isValid())
      TArg = TemplateArgument(Template, /*NumExpansions=*/std::nullopt);
    else
      TArg = Template;
    return TemplateArgumentLoc(
        SemaRef.Context, TArg,
        Arg.getScopeSpec().getWithLocInContext(SemaRef.Context),
        Arg.getLocation(), Arg.getEllipsisLoc());
  }
  }

  llvm_unreachable("Unhandled parsed template argument");
}

void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
                                      TemplateArgumentListInfo &TemplateArgs) {
 for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
   TemplateArgs.addArgument(translateTemplateArgument(*this,
                                                      TemplateArgsIn[I]));
}

static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
                                                 SourceLocation Loc,
                                                 const IdentifierInfo *Name) {
  NamedDecl *PrevDecl =
      SemaRef.LookupSingleName(S, Name, Loc, Sema::LookupOrdinaryName,
                               RedeclarationKind::ForVisibleRedeclaration);
  if (PrevDecl && PrevDecl->isTemplateParameter())
    SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}

ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
  TypeSourceInfo *TInfo;
  QualType T = GetTypeFromParser(ParsedType.get(), &TInfo);
  if (T.isNull())
    return ParsedTemplateArgument();
  assert(TInfo && "template argument with no location");

  // If we might have formed a deduced template specialization type, convert
  // it to a template template argument.
  if (getLangOpts().CPlusPlus17) {
    TypeLoc TL = TInfo->getTypeLoc();
    SourceLocation EllipsisLoc;
    if (auto PET = TL.getAs<PackExpansionTypeLoc>()) {
      EllipsisLoc = PET.getEllipsisLoc();
      TL = PET.getPatternLoc();
    }

    CXXScopeSpec SS;
    if (auto ET = TL.getAs<ElaboratedTypeLoc>()) {
      SS.Adopt(ET.getQualifierLoc());
      TL = ET.getNamedTypeLoc();
    }

    if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
      TemplateName Name = DTST.getTypePtr()->getTemplateName();
      ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
                                    DTST.getTemplateNameLoc());
      if (EllipsisLoc.isValid())
        Result = Result.getTemplatePackExpansion(EllipsisLoc);
      return Result;
    }
  }

  // This is a normal type template argument. Note, if the type template
  // argument is an injected-class-name for a template, it has a dual nature
  // and can be used as either a type or a template. We handle that in
  // convertTypeTemplateArgumentToTemplate.
  return ParsedTemplateArgument(ParsedTemplateArgument::Type,
                                ParsedType.get().getAsOpaquePtr(),
                                TInfo->getTypeLoc().getBeginLoc());
}

NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
                                    SourceLocation EllipsisLoc,
                                    SourceLocation KeyLoc,
                                    IdentifierInfo *ParamName,
                                    SourceLocation ParamNameLoc,
                                    unsigned Depth, unsigned Position,
                                    SourceLocation EqualLoc,
                                    ParsedType DefaultArg,
                                    bool HasTypeConstraint) {
  assert(S->isTemplateParamScope() &&
         "Template type parameter not in template parameter scope!");

  bool IsParameterPack = EllipsisLoc.isValid();
  TemplateTypeParmDecl *Param
    = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                   KeyLoc, ParamNameLoc, Depth, Position,
                                   ParamName, Typename, IsParameterPack,
                                   HasTypeConstraint);
  Param->setAccess(AS_public);

  if (Param->isParameterPack())
    if (auto *CSI = getEnclosingLambdaOrBlock())
      CSI->LocalPacks.push_back(Param);

  if (ParamName) {
    maybeDiagnoseTemplateParameterShadow(*this, S, ParamNameLoc, ParamName);

    // Add the template parameter into the current scope.
    S->AddDecl(Param);
    IdResolver.AddDecl(Param);
  }

  // C++0x [temp.param]p9:
  //   A default template-argument may be specified for any kind of
  //   template-parameter that is not a template parameter pack.
  if (DefaultArg && IsParameterPack) {
    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
    DefaultArg = nullptr;
  }

  // Handle the default argument, if provided.
  if (DefaultArg) {
    TypeSourceInfo *DefaultTInfo;
    GetTypeFromParser(DefaultArg, &DefaultTInfo);

    assert(DefaultTInfo && "expected source information for type");

    // Check for unexpanded parameter packs.
    if (DiagnoseUnexpandedParameterPack(ParamNameLoc, DefaultTInfo,
                                        UPPC_DefaultArgument))
      return Param;

    // Check the template argument itself.
    if (CheckTemplateArgument(DefaultTInfo)) {
      Param->setInvalidDecl();
      return Param;
    }

    Param->setDefaultArgument(
        Context, TemplateArgumentLoc(DefaultTInfo->getType(), DefaultTInfo));
  }

  return Param;
}

/// Convert the parser's template argument list representation into our form.
static TemplateArgumentListInfo
makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
  TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
                                        TemplateId.RAngleLoc);
  ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
                                     TemplateId.NumArgs);
  S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
  return TemplateArgs;
}

bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {

  TemplateName TN = TypeConstr->Template.get();
  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());

  // C++2a [temp.param]p4:
  //     [...] The concept designated by a type-constraint shall be a type
  //     concept ([temp.concept]).
  if (!CD->isTypeConcept()) {
    Diag(TypeConstr->TemplateNameLoc,
         diag::err_type_constraint_non_type_concept);
    return true;
  }

  if (CheckConceptUseInDefinition(CD, TypeConstr->TemplateNameLoc))
    return true;

  bool WereArgsSpecified = TypeConstr->LAngleLoc.isValid();

  if (!WereArgsSpecified &&
      CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
    Diag(TypeConstr->TemplateNameLoc,
         diag::err_type_constraint_missing_arguments)
        << CD;
    return true;
  }
  return false;
}

bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
                               TemplateIdAnnotation *TypeConstr,
                               TemplateTypeParmDecl *ConstrainedParameter,
                               SourceLocation EllipsisLoc) {
  return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
                             false);
}

bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
                               TemplateIdAnnotation *TypeConstr,
                               TemplateTypeParmDecl *ConstrainedParameter,
                               SourceLocation EllipsisLoc,
                               bool AllowUnexpandedPack) {

  if (CheckTypeConstraint(TypeConstr))
    return true;

  TemplateName TN = TypeConstr->Template.get();
  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
  UsingShadowDecl *USD = TN.getAsUsingShadowDecl();

  DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
                                  TypeConstr->TemplateNameLoc);

  TemplateArgumentListInfo TemplateArgs;
  if (TypeConstr->LAngleLoc.isValid()) {
    TemplateArgs =
        makeTemplateArgumentListInfo(*this, *TypeConstr);

    if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
      for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
        if (DiagnoseUnexpandedParameterPack(Arg, UPPC_TypeConstraint))
          return true;
      }
    }
  }
  return AttachTypeConstraint(
      SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(),
      ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
      TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
      ConstrainedParameter, EllipsisLoc);
}

template <typename ArgumentLocAppender>
static ExprResult formImmediatelyDeclaredConstraint(
    Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
    ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc,
    SourceLocation RAngleLoc, QualType ConstrainedType,
    SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
    SourceLocation EllipsisLoc) {

  TemplateArgumentListInfo ConstraintArgs;
  ConstraintArgs.addArgument(
    S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
                                    /*NTTPType=*/QualType(), ParamNameLoc));

  ConstraintArgs.setRAngleLoc(RAngleLoc);
  ConstraintArgs.setLAngleLoc(LAngleLoc);
  Appender(ConstraintArgs);

  // C++2a [temp.param]p4:
  //     [...] This constraint-expression E is called the immediately-declared
  //     constraint of T. [...]
  CXXScopeSpec SS;
  SS.Adopt(NS);
  ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId(
      SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
      /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept,
      &ConstraintArgs);
  if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
    return ImmediatelyDeclaredConstraint;

  // C++2a [temp.param]p4:
  //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
  //
  // We have the following case:
  //
  // template<typename T> concept C1 = true;
  // template<C1... T> struct s1;
  //
  // The constraint: (C1<T> && ...)
  //
  // Note that the type of C1<T> is known to be 'bool', so we don't need to do
  // any unqualified lookups for 'operator&&' here.
  return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
                            /*LParenLoc=*/SourceLocation(),
                            ImmediatelyDeclaredConstraint.get(), BO_LAnd,
                            EllipsisLoc, /*RHS=*/nullptr,
                            /*RParenLoc=*/SourceLocation(),
                            /*NumExpansions=*/std::nullopt);
}

bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
                                DeclarationNameInfo NameInfo,
                                ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
                                const TemplateArgumentListInfo *TemplateArgs,
                                TemplateTypeParmDecl *ConstrainedParameter,
                                SourceLocation EllipsisLoc) {
  // C++2a [temp.param]p4:
  //     [...] If Q is of the form C<A1, ..., An>, then let E' be
  //     C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
  const ASTTemplateArgumentListInfo *ArgsAsWritten =
    TemplateArgs ? ASTTemplateArgumentListInfo::Create(Context,
                                                       *TemplateArgs) : nullptr;

  QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);

  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
      *this, NS, NameInfo, NamedConcept, FoundDecl,
      TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
      TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
      ParamAsArgument, ConstrainedParameter->getLocation(),
      [&](TemplateArgumentListInfo &ConstraintArgs) {
        if (TemplateArgs)
          for (const auto &ArgLoc : TemplateArgs->arguments())
            ConstraintArgs.addArgument(ArgLoc);
      },
      EllipsisLoc);
  if (ImmediatelyDeclaredConstraint.isInvalid())
    return true;

  auto *CL = ConceptReference::Create(Context, /*NNS=*/NS,
                                      /*TemplateKWLoc=*/SourceLocation{},
                                      /*ConceptNameInfo=*/NameInfo,
                                      /*FoundDecl=*/FoundDecl,
                                      /*NamedConcept=*/NamedConcept,
                                      /*ArgsWritten=*/ArgsAsWritten);
  ConstrainedParameter->setTypeConstraint(
      CL, ImmediatelyDeclaredConstraint.get(), std::nullopt);
  return false;
}

bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
                                NonTypeTemplateParmDecl *NewConstrainedParm,
                                NonTypeTemplateParmDecl *OrigConstrainedParm,
                                SourceLocation EllipsisLoc) {
  if (NewConstrainedParm->getType().getNonPackExpansionType() != TL.getType() ||
      TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
    Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
         diag::err_unsupported_placeholder_constraint)
        << NewConstrainedParm->getTypeSourceInfo()
               ->getTypeLoc()
               .getSourceRange();
    return true;
  }
  // FIXME: Concepts: This should be the type of the placeholder, but this is
  // unclear in the wording right now.
  DeclRefExpr *Ref =
      BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
                       VK_PRValue, OrigConstrainedParm->getLocation());
  if (!Ref)
    return true;
  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
      *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
      TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(),
      TL.getRAngleLoc(), BuildDecltypeType(Ref),
      OrigConstrainedParm->getLocation(),
      [&](TemplateArgumentListInfo &ConstraintArgs) {
        for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
          ConstraintArgs.addArgument(TL.getArgLoc(I));
      },
      EllipsisLoc);
  if (ImmediatelyDeclaredConstraint.isInvalid() ||
      !ImmediatelyDeclaredConstraint.isUsable())
    return true;

  NewConstrainedParm->setPlaceholderTypeConstraint(
      ImmediatelyDeclaredConstraint.get());
  return false;
}

QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
                                                 SourceLocation Loc) {
  if (TSI->getType()->isUndeducedType()) {
    // C++17 [temp.dep.expr]p3:
    //   An id-expression is type-dependent if it contains
    //    - an identifier associated by name lookup with a non-type
    //      template-parameter declared with a type that contains a
    //      placeholder type (7.1.7.4),
    TSI = SubstAutoTypeSourceInfoDependent(TSI);
  }

  return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
}

bool Sema::RequireStructuralType(QualType T, SourceLocation Loc) {
  if (T->isDependentType())
    return false;

  if (RequireCompleteType(Loc, T, diag::err_template_nontype_parm_incomplete))
    return true;

  if (T->isStructuralType())
    return false;

  // Structural types are required to be object types or lvalue references.
  if (T->isRValueReferenceType()) {
    Diag(Loc, diag::err_template_nontype_parm_rvalue_ref) << T;
    return true;
  }

  // Don't mention structural types in our diagnostic prior to C++20. Also,
  // there's not much more we can say about non-scalar non-class types --
  // because we can't see functions or arrays here, those can only be language
  // extensions.
  if (!getLangOpts().CPlusPlus20 ||
      (!T->isScalarType() && !T->isRecordType())) {
    Diag(Loc, diag::err_template_nontype_parm_bad_type) << T;
    return true;
  }

  // Structural types are required to be literal types.
  if (RequireLiteralType(Loc, T, diag::err_template_nontype_parm_not_literal))
    return true;

  Diag(Loc, diag::err_template_nontype_parm_not_structural) << T;

  // Drill down into the reason why the class is non-structural.
  while (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
    // All members are required to be public and non-mutable, and can't be of
    // rvalue reference type. Check these conditions first to prefer a "local"
    // reason over a more distant one.
    for (const FieldDecl *FD : RD->fields()) {
      if (FD->getAccess() != AS_public) {
        Diag(FD->getLocation(), diag::note_not_structural_non_public) << T << 0;
        return true;
      }
      if (FD->isMutable()) {
        Diag(FD->getLocation(), diag::note_not_structural_mutable_field) << T;
        return true;
      }
      if (FD->getType()->isRValueReferenceType()) {
        Diag(FD->getLocation(), diag::note_not_structural_rvalue_ref_field)
            << T;
        return true;
      }
    }

    // All bases are required to be public.
    for (const auto &BaseSpec : RD->bases()) {
      if (BaseSpec.getAccessSpecifier() != AS_public) {
        Diag(BaseSpec.getBaseTypeLoc(), diag::note_not_structural_non_public)
            << T << 1;
        return true;
      }
    }

    // All subobjects are required to be of structural types.
    SourceLocation SubLoc;
    QualType SubType;
    int Kind = -1;

    for (const FieldDecl *FD : RD->fields()) {
      QualType T = Context.getBaseElementType(FD->getType());
      if (!T->isStructuralType()) {
        SubLoc = FD->getLocation();
        SubType = T;
        Kind = 0;
        break;
      }
    }

    if (Kind == -1) {
      for (const auto &BaseSpec : RD->bases()) {
        QualType T = BaseSpec.getType();
        if (!T->isStructuralType()) {
          SubLoc = BaseSpec.getBaseTypeLoc();
          SubType = T;
          Kind = 1;
          break;
        }
      }
    }

    assert(Kind != -1 && "couldn't find reason why type is not structural");
    Diag(SubLoc, diag::note_not_structural_subobject)
        << T << Kind << SubType;
    T = SubType;
    RD = T->getAsCXXRecordDecl();
  }

  return true;
}

QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
                                                 SourceLocation Loc) {
  // We don't allow variably-modified types as the type of non-type template
  // parameters.
  if (T->isVariablyModifiedType()) {
    Diag(Loc, diag::err_variably_modified_nontype_template_param)
      << T;
    return QualType();
  }

  // C++ [temp.param]p4:
  //
  // A non-type template-parameter shall have one of the following
  // (optionally cv-qualified) types:
  //
  //       -- integral or enumeration type,
  if (T->isIntegralOrEnumerationType() ||
      //   -- pointer to object or pointer to function,
      T->isPointerType() ||
      //   -- lvalue reference to object or lvalue reference to function,
      T->isLValueReferenceType() ||
      //   -- pointer to member,
      T->isMemberPointerType() ||
      //   -- std::nullptr_t, or
      T->isNullPtrType() ||
      //   -- a type that contains a placeholder type.
      T->isUndeducedType()) {
    // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
    // are ignored when determining its type.
    return T.getUnqualifiedType();
  }

  // C++ [temp.param]p8:
  //
  //   A non-type template-parameter of type "array of T" or
  //   "function returning T" is adjusted to be of type "pointer to
  //   T" or "pointer to function returning T", respectively.
  if (T->isArrayType() || T->isFunctionType())
    return Context.getDecayedType(T);

  // If T is a dependent type, we can't do the check now, so we
  // assume that it is well-formed. Note that stripping off the
  // qualifiers here is not really correct if T turns out to be
  // an array type, but we'll recompute the type everywhere it's
  // used during instantiation, so that should be OK. (Using the
  // qualified type is equally wrong.)
  if (T->isDependentType())
    return T.getUnqualifiedType();

  // C++20 [temp.param]p6:
  //   -- a structural type
  if (RequireStructuralType(T, Loc))
    return QualType();

  if (!getLangOpts().CPlusPlus20) {
    // FIXME: Consider allowing structural types as an extension in C++17. (In
    // earlier language modes, the template argument evaluation rules are too
    // inflexible.)
    Diag(Loc, diag::err_template_nontype_parm_bad_structural_type) << T;
    return QualType();
  }

  Diag(Loc, diag::warn_cxx17_compat_template_nontype_parm_type) << T;
  return T.getUnqualifiedType();
}

NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
                                          unsigned Depth,
                                          unsigned Position,
                                          SourceLocation EqualLoc,
                                          Expr *Default) {
  TypeSourceInfo *TInfo = GetTypeForDeclarator(D);

  // Check that we have valid decl-specifiers specified.
  auto CheckValidDeclSpecifiers = [this, &D] {
    // C++ [temp.param]
    // p1
    //   template-parameter:
    //     ...
    //     parameter-declaration
    // p2
    //   ... A storage class shall not be specified in a template-parameter
    //   declaration.
    // [dcl.typedef]p1:
    //   The typedef specifier [...] shall not be used in the decl-specifier-seq
    //   of a parameter-declaration
    const DeclSpec &DS = D.getDeclSpec();
    auto EmitDiag = [this](SourceLocation Loc) {
      Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm)
          << FixItHint::CreateRemoval(Loc);
    };
    if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
      EmitDiag(DS.getStorageClassSpecLoc());

    if (DS.getThreadStorageClassSpec() != TSCS_unspecified)
      EmitDiag(DS.getThreadStorageClassSpecLoc());

    // [dcl.inline]p1:
    //   The inline specifier can be applied only to the declaration or
    //   definition of a variable or function.

    if (DS.isInlineSpecified())
      EmitDiag(DS.getInlineSpecLoc());

    // [dcl.constexpr]p1:
    //   The constexpr specifier shall be applied only to the definition of a
    //   variable or variable template or the declaration of a function or
    //   function template.

    if (DS.hasConstexprSpecifier())
      EmitDiag(DS.getConstexprSpecLoc());

    // [dcl.fct.spec]p1:
    //   Function-specifiers can be used only in function declarations.

    if (DS.isVirtualSpecified())
      EmitDiag(DS.getVirtualSpecLoc());

    if (DS.hasExplicitSpecifier())
      EmitDiag(DS.getExplicitSpecLoc());

    if (DS.isNoreturnSpecified())
      EmitDiag(DS.getNoreturnSpecLoc());
  };

  CheckValidDeclSpecifiers();

  if (const auto *T = TInfo->getType()->getContainedDeducedType())
    if (isa<AutoType>(T))
      Diag(D.getIdentifierLoc(),
           diag::warn_cxx14_compat_template_nontype_parm_auto_type)
          << QualType(TInfo->getType()->getContainedAutoType(), 0);

  assert(S->isTemplateParamScope() &&
         "Non-type template parameter not in template parameter scope!");
  bool Invalid = false;

  QualType T = CheckNonTypeTemplateParameterType(TInfo, D.getIdentifierLoc());
  if (T.isNull()) {
    T = Context.IntTy; // Recover with an 'int' type.
    Invalid = true;
  }

  CheckFunctionOrTemplateParamDeclarator(S, D);

  const IdentifierInfo *ParamName = D.getIdentifier();
  bool IsParameterPack = D.hasEllipsis();
  NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(
      Context, Context.getTranslationUnitDecl(), D.getBeginLoc(),
      D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack,
      TInfo);
  Param->setAccess(AS_public);

  if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc())
    if (TL.isConstrained()) {
      if (D.getEllipsisLoc().isInvalid() &&
          T->containsUnexpandedParameterPack()) {
        assert(TL.getConceptReference()->getTemplateArgsAsWritten());
        for (auto &Loc :
             TL.getConceptReference()->getTemplateArgsAsWritten()->arguments())
          Invalid |= DiagnoseUnexpandedParameterPack(
              Loc, UnexpandedParameterPackContext::UPPC_TypeConstraint);
      }
      if (!Invalid &&
          AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
        Invalid = true;
    }

  if (Invalid)
    Param->setInvalidDecl();

  if (Param->isParameterPack())
    if (auto *CSI = getEnclosingLambdaOrBlock())
      CSI->LocalPacks.push_back(Param);

  if (ParamName) {
    maybeDiagnoseTemplateParameterShadow(*this, S, D.getIdentifierLoc(),
                                         ParamName);

    // Add the template parameter into the current scope.
    S->AddDecl(Param);
    IdResolver.AddDecl(Param);
  }

  // C++0x [temp.param]p9:
  //   A default template-argument may be specified for any kind of
  //   template-parameter that is not a template parameter pack.
  if (Default && IsParameterPack) {
    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
    Default = nullptr;
  }

  // Check the well-formedness of the default template argument, if provided.
  if (Default) {
    // Check for unexpanded parameter packs.
    if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
      return Param;

    Param->setDefaultArgument(
        Context, getTrivialTemplateArgumentLoc(
                     TemplateArgument(Default, /*IsCanonical=*/false),
                     QualType(), SourceLocation()));
  }

  return Param;
}

NamedDecl *Sema::ActOnTemplateTemplateParameter(
    Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params,
    bool Typename, SourceLocation EllipsisLoc, IdentifierInfo *Name,
    SourceLocation NameLoc, unsigned Depth, unsigned Position,
    SourceLocation EqualLoc, ParsedTemplateArgument Default) {
  assert(S->isTemplateParamScope() &&
         "Template template parameter not in template parameter scope!");

  bool IsParameterPack = EllipsisLoc.isValid();

  bool Invalid = false;
  if (CheckTemplateParameterList(
          Params,
          /*OldParams=*/nullptr,
          IsParameterPack ? TPC_TemplateTemplateParameterPack : TPC_Other))
    Invalid = true;

  // Construct the parameter object.
  TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(
      Context, Context.getTranslationUnitDecl(),
      NameLoc.isInvalid() ? TmpLoc : NameLoc, Depth, Position, IsParameterPack,
      Name, Typename, Params);
  Param->setAccess(AS_public);

  if (Param->isParameterPack())
    if (auto *LSI = getEnclosingLambdaOrBlock())
      LSI->LocalPacks.push_back(Param);

  // If the template template parameter has a name, then link the identifier
  // into the scope and lookup mechanisms.
  if (Name) {
    maybeDiagnoseTemplateParameterShadow(*this, S, NameLoc, Name);

    S->AddDecl(Param);
    IdResolver.AddDecl(Param);
  }

  if (Params->size() == 0) {
    Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
    << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
    Invalid = true;
  }

  if (Invalid)
    Param->setInvalidDecl();

  // C++0x [temp.param]p9:
  //   A default template-argument may be specified for any kind of
  //   template-parameter that is not a template parameter pack.
  if (IsParameterPack && !Default.isInvalid()) {
    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
    Default = ParsedTemplateArgument();
  }

  if (!Default.isInvalid()) {
    // Check only that we have a template template argument. We don't want to
    // try to check well-formedness now, because our template template parameter
    // might have dependent types in its template parameters, which we wouldn't
    // be able to match now.
    //
    // If none of the template template parameter's template arguments mention
    // other template parameters, we could actually perform more checking here.
    // However, it isn't worth doing.
    TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
    if (DefaultArg.getArgument().getAsTemplate().isNull()) {
      Diag(DefaultArg.getLocation(), diag::err_template_arg_not_valid_template)
        << DefaultArg.getSourceRange();
      return Param;
    }

    // Check for unexpanded parameter packs.
    if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(),
                                        DefaultArg.getArgument().getAsTemplate(),
                                        UPPC_DefaultArgument))
      return Param;

    Param->setDefaultArgument(Context, DefaultArg);
  }

  return Param;
}

namespace {
class ConstraintRefersToContainingTemplateChecker
    : public TreeTransform<ConstraintRefersToContainingTemplateChecker> {
  bool Result = false;
  const FunctionDecl *Friend = nullptr;
  unsigned TemplateDepth = 0;

  // Check a record-decl that we've seen to see if it is a lexical parent of the
  // Friend, likely because it was referred to without its template arguments.
  void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) {
    CheckingRD = CheckingRD->getMostRecentDecl();
    if (!CheckingRD->isTemplated())
      return;

    for (const DeclContext *DC = Friend->getLexicalDeclContext();
         DC && !DC->isFileContext(); DC = DC->getParent())
      if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
        if (CheckingRD == RD->getMostRecentDecl())
          Result = true;
  }

  void CheckNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
    if (D->getDepth() < TemplateDepth)
      Result = true;

    // Necessary because the type of the NTTP might be what refers to the parent
    // constriant.
    TransformType(D->getType());
  }

public:
  using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;

  ConstraintRefersToContainingTemplateChecker(Sema &SemaRef,
                                              const FunctionDecl *Friend,
                                              unsigned TemplateDepth)
      : inherited(SemaRef), Friend(Friend), TemplateDepth(TemplateDepth) {}
  bool getResult() const { return Result; }

  // This should be the only template parm type that we have to deal with.
  // SubstTempalteTypeParmPack, SubstNonTypeTemplateParmPack, and
  // FunctionParmPackExpr are all partially substituted, which cannot happen
  // with concepts at this point in translation.
  using inherited::TransformTemplateTypeParmType;
  QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
                                         TemplateTypeParmTypeLoc TL, bool) {
    if (TL.getDecl()->getDepth() < TemplateDepth)
      Result = true;
    return inherited::TransformTemplateTypeParmType(
        TLB, TL,
        /*SuppressObjCLifetime=*/false);
  }

  Decl *TransformDecl(SourceLocation Loc, Decl *D) {
    if (!D)
      return D;
    // FIXME : This is possibly an incomplete list, but it is unclear what other
    // Decl kinds could be used to refer to the template parameters.  This is a
    // best guess so far based on examples currently available, but the
    // unreachable should catch future instances/cases.
    if (auto *TD = dyn_cast<TypedefNameDecl>(D))
      TransformType(TD->getUnderlyingType());
    else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D))
      CheckNonTypeTemplateParmDecl(NTTPD);
    else if (auto *VD = dyn_cast<ValueDecl>(D))
      TransformType(VD->getType());
    else if (auto *TD = dyn_cast<TemplateDecl>(D))
      TransformTemplateParameterList(TD->getTemplateParameters());
    else if (auto *RD = dyn_cast<CXXRecordDecl>(D))
      CheckIfContainingRecord(RD);
    else if (isa<NamedDecl>(D)) {
      // No direct types to visit here I believe.
    } else
      llvm_unreachable("Don't know how to handle this declaration type yet");
    return D;
  }
};
} // namespace

bool Sema::ConstraintExpressionDependsOnEnclosingTemplate(
    const FunctionDecl *Friend, unsigned TemplateDepth,
    const Expr *Constraint) {
  assert(Friend->getFriendObjectKind() && "Only works on a friend");
  ConstraintRefersToContainingTemplateChecker Checker(*this, Friend,
                                                      TemplateDepth);
  Checker.TransformExpr(const_cast<Expr *>(Constraint));
  return Checker.getResult();
}

TemplateParameterList *
Sema::ActOnTemplateParameterList(unsigned Depth,
                                 SourceLocation ExportLoc,
                                 SourceLocation TemplateLoc,
                                 SourceLocation LAngleLoc,
                                 ArrayRef<NamedDecl *> Params,
                                 SourceLocation RAngleLoc,
                                 Expr *RequiresClause) {
  if (ExportLoc.isValid())
    Diag(ExportLoc, diag::warn_template_export_unsupported);

  for (NamedDecl *P : Params)
    warnOnReservedIdentifier(P);

  return TemplateParameterList::Create(
      Context, TemplateLoc, LAngleLoc,
      llvm::ArrayRef(Params.data(), Params.size()), RAngleLoc, RequiresClause);
}

static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
                                   const CXXScopeSpec &SS) {
  if (SS.isSet())
    T->setQualifierInfo(SS.getWithLocInContext(S.Context));
}

// Returns the template parameter list with all default template argument
// information.
TemplateParameterList *Sema::GetTemplateParameterList(TemplateDecl *TD) {
  // Make sure we get the template parameter list from the most
  // recent declaration, since that is the only one that is guaranteed to
  // have all the default template argument information.
  Decl *D = TD->getMostRecentDecl();
  // C++11 N3337 [temp.param]p12:
  // A default template argument shall not be specified in a friend class
  // template declaration.
  //
  // Skip past friend *declarations* because they are not supposed to contain
  // default template arguments. Moreover, these declarations may introduce
  // template parameters living in different template depths than the
  // corresponding template parameters in TD, causing unmatched constraint
  // substitution.
  //
  // FIXME: Diagnose such cases within a class template:
  //  template <class T>
  //  struct S {
  //    template <class = void> friend struct C;
  //  };
  //  template struct S<int>;
  while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None &&
         D->getPreviousDecl())
    D = D->getPreviousDecl();
  return cast<TemplateDecl>(D)->getTemplateParameters();
}

DeclResult Sema::CheckClassTemplate(
    Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
    CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
    const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
    AccessSpecifier AS, SourceLocation ModulePrivateLoc,
    SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
    TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
  assert(TemplateParams && TemplateParams->size() > 0 &&
         "No template parameters");
  assert(TUK != TagUseKind::Reference &&
         "Can only declare or define class templates");
  bool Invalid = false;

  // Check that we can declare a template here.
  if (CheckTemplateDeclScope(S, TemplateParams))
    return true;

  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
  assert(Kind != TagTypeKind::Enum &&
         "can't build template of enumerated type");

  // There is no such thing as an unnamed class template.
  if (!Name) {
    Diag(KWLoc, diag::err_template_unnamed_class);
    return true;
  }

  // Find any previous declaration with this name. For a friend with no
  // scope explicitly specified, we only look for tag declarations (per
  // C++11 [basic.lookup.elab]p2).
  DeclContext *SemanticContext;
  LookupResult Previous(*this, Name, NameLoc,
                        (SS.isEmpty() && TUK == TagUseKind::Friend)
                            ? LookupTagName
                            : LookupOrdinaryName,
                        forRedeclarationInCurContext());
  if (SS.isNotEmpty() && !SS.isInvalid()) {
    SemanticContext = computeDeclContext(SS, true);
    if (!SemanticContext) {
      // FIXME: Horrible, horrible hack! We can't currently represent this
      // in the AST, and historically we have just ignored such friend
      // class templates, so don't complain here.
      Diag(NameLoc, TUK == TagUseKind::Friend
                        ? diag::warn_template_qualified_friend_ignored
                        : diag::err_template_qualified_declarator_no_match)
          << SS.getScopeRep() << SS.getRange();
      return TUK != TagUseKind::Friend;
    }

    if (RequireCompleteDeclContext(SS, SemanticContext))
      return true;

    // If we're adding a template to a dependent context, we may need to
    // rebuilding some of the types used within the template parameter list,
    // now that we know what the current instantiation is.
    if (SemanticContext->isDependentContext()) {
      ContextRAII SavedContext(*this, SemanticContext);
      if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
        Invalid = true;
    }

    if (TUK != TagUseKind::Friend && TUK != TagUseKind::Reference)
      diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc,
                                   /*TemplateId-*/ nullptr,
                                   /*IsMemberSpecialization*/ false);

    LookupQualifiedName(Previous, SemanticContext);
  } else {
    SemanticContext = CurContext;

    // C++14 [class.mem]p14:
    //   If T is the name of a class, then each of the following shall have a
    //   name different from T:
    //    -- every member template of class T
    if (TUK != TagUseKind::Friend &&
        DiagnoseClassNameShadow(SemanticContext,
                                DeclarationNameInfo(Name, NameLoc)))
      return true;

    LookupName(Previous, S);
  }

  if (Previous.isAmbiguous())
    return true;

  // Let the template parameter scope enter the lookup chain of the current
  // class template. For example, given
  //
  //  namespace ns {
  //    template <class> bool Param = false;
  //    template <class T> struct N;
  //  }
  //
  //  template <class Param> struct ns::N { void foo(Param); };
  //
  // When we reference Param inside the function parameter list, our name lookup
  // chain for it should be like:
  //  FunctionScope foo
  //  -> RecordScope N
  //  -> TemplateParamScope (where we will find Param)
  //  -> NamespaceScope ns
  //
  // See also CppLookupName().
  if (S->isTemplateParamScope())
    EnterTemplatedContext(S, SemanticContext);

  NamedDecl *PrevDecl = nullptr;
  if (Previous.begin() != Previous.end())
    PrevDecl = (*Previous.begin())->getUnderlyingDecl();

  if (PrevDecl && PrevDecl->isTemplateParameter()) {
    // Maybe we will complain about the shadowed template parameter.
    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = nullptr;
  }

  // If there is a previous declaration with the same name, check
  // whether this is a valid redeclaration.
  ClassTemplateDecl *PrevClassTemplate =
      dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);

  // We may have found the injected-class-name of a class template,
  // class template partial specialization, or class template specialization.
  // In these cases, grab the template that is being defined or specialized.
  if (!PrevClassTemplate && isa_and_nonnull<CXXRecordDecl>(PrevDecl) &&
      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
    PrevClassTemplate
      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
      PrevClassTemplate
        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
            ->getSpecializedTemplate();
    }
  }

  if (TUK == TagUseKind::Friend) {
    // C++ [namespace.memdef]p3:
    //   [...] When looking for a prior declaration of a class or a function
    //   declared as a friend, and when the name of the friend class or
    //   function is neither a qualified name nor a template-id, scopes outside
    //   the innermost enclosing namespace scope are not considered.
    if (!SS.isSet()) {
      DeclContext *OutermostContext = CurContext;
      while (!OutermostContext->isFileContext())
        OutermostContext = OutermostContext->getLookupParent();

      if (PrevDecl &&
          (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
           OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
        SemanticContext = PrevDecl->getDeclContext();
      } else {
        // Declarations in outer scopes don't matter. However, the outermost
        // context we computed is the semantic context for our new
        // declaration.
        PrevDecl = PrevClassTemplate = nullptr;
        SemanticContext = OutermostContext;

        // Check that the chosen semantic context doesn't already contain a
        // declaration of this name as a non-tag type.
        Previous.clear(LookupOrdinaryName);
        DeclContext *LookupContext = SemanticContext;
        while (LookupContext->isTransparentContext())
          LookupContext = LookupContext->getLookupParent();
        LookupQualifiedName(Previous, LookupContext);

        if (Previous.isAmbiguous())
          return true;

        if (Previous.begin() != Previous.end())
          PrevDecl = (*Previous.begin())->getUnderlyingDecl();
      }
    }
  } else if (PrevDecl && !isDeclInScope(Previous.getRepresentativeDecl(),
                                        SemanticContext, S, SS.isValid()))
    PrevDecl = PrevClassTemplate = nullptr;

  if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>(
          PrevDecl ? Previous.getRepresentativeDecl() : nullptr)) {
    if (SS.isEmpty() &&
        !(PrevClassTemplate &&
          PrevClassTemplate->getDeclContext()->getRedeclContext()->Equals(
              SemanticContext->getRedeclContext()))) {
      Diag(KWLoc, diag::err_using_decl_conflict_reverse);
      Diag(Shadow->getTargetDecl()->getLocation(),
           diag::note_using_decl_target);
      Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl) << 0;
      // Recover by ignoring the old declaration.
      PrevDecl = PrevClassTemplate = nullptr;
    }
  }

  if (PrevClassTemplate) {
    // Ensure that the template parameter lists are compatible. Skip this check
    // for a friend in a dependent context: the template parameter list itself
    // could be dependent.
    if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
        !TemplateParameterListsAreEqual(
            TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext
                                                       : CurContext,
                                       CurContext, KWLoc),
            TemplateParams, PrevClassTemplate,
            PrevClassTemplate->getTemplateParameters(), /*Complain=*/true,
            TPL_TemplateMatch))
      return true;

    // C++ [temp.class]p4:
    //   In a redeclaration, partial specialization, explicit
    //   specialization or explicit instantiation of a class template,
    //   the class-key shall agree in kind with the original class
    //   template declaration (7.1.5.3).
    RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
    if (!isAcceptableTagRedeclaration(
            PrevRecordDecl, Kind, TUK == TagUseKind::Definition, KWLoc, Name)) {
      Diag(KWLoc, diag::err_use_with_wrong_tag)
        << Name
        << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
      Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
      Kind = PrevRecordDecl->getTagKind();
    }

    // Check for redefinition of this class template.
    if (TUK == TagUseKind::Definition) {
      if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
        // If we have a prior definition that is not visible, treat this as
        // simply making that previous definition visible.
        NamedDecl *Hidden = nullptr;
        if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
          SkipBody->ShouldSkip = true;
          SkipBody->Previous = Def;
          auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
          assert(Tmpl && "original definition of a class template is not a "
                         "class template?");
          makeMergedDefinitionVisible(Hidden);
          makeMergedDefinitionVisible(Tmpl);
        } else {
          Diag(NameLoc, diag::err_redefinition) << Name;
          Diag(Def->getLocation(), diag::note_previous_definition);
          // FIXME: Would it make sense to try to "forget" the previous
          // definition, as part of error recovery?
          return true;
        }
      }
    }
  } else if (PrevDecl) {
    // C++ [temp]p5:
    //   A class template shall not have the same name as any other
    //   template, class, function, object, enumeration, enumerator,
    //   namespace, or type in the same scope (3.3), except as specified
    //   in (14.5.4).
    Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
    return true;
  }

  // Check the template parameter list of this declaration, possibly
  // merging in the template parameter list from the previous class
  // template declaration. Skip this check for a friend in a dependent
  // context, because the template parameter list might be dependent.
  if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
      CheckTemplateParameterList(
          TemplateParams,
          PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate)
                            : nullptr,
          (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
           SemanticContext->isDependentContext())
              ? TPC_ClassTemplateMember
          : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
                                      : TPC_Other,
          SkipBody))
    Invalid = true;

  if (SS.isSet()) {
    // If the name of the template was qualified, we must be defining the
    // template out-of-line.
    if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) {
      Diag(NameLoc, TUK == TagUseKind::Friend
                        ? diag::err_friend_decl_does_not_match
                        : diag::err_member_decl_does_not_match)
          << Name << SemanticContext << /*IsDefinition*/ true << SS.getRange();
      Invalid = true;
    }
  }

  // If this is a templated friend in a dependent context we should not put it
  // on the redecl chain. In some cases, the templated friend can be the most
  // recent declaration tricking the template instantiator to make substitutions
  // there.
  // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
  bool ShouldAddRedecl =
      !(TUK == TagUseKind::Friend && CurContext->isDependentContext());

  CXXRecordDecl *NewClass =
    CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
                          PrevClassTemplate && ShouldAddRedecl ?
                            PrevClassTemplate->getTemplatedDecl() : nullptr,
                          /*DelayTypeCreation=*/true);
  SetNestedNameSpecifier(*this, NewClass, SS);
  if (NumOuterTemplateParamLists > 0)
    NewClass->setTemplateParameterListsInfo(
        Context,
        llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists));

  // Add alignment attributes if necessary; these attributes are checked when
  // the ASTContext lays out the structure.
  if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
    if (LangOpts.HLSL)
      NewClass->addAttr(PackedAttr::CreateImplicit(Context));
    AddAlignmentAttributesForRecord(NewClass);
    AddMsStructLayoutForRecord(NewClass);
  }

  ClassTemplateDecl *NewTemplate
    = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
                                DeclarationName(Name), TemplateParams,
                                NewClass);

  if (ShouldAddRedecl)
    NewTemplate->setPreviousDecl(PrevClassTemplate);

  NewClass->setDescribedClassTemplate(NewTemplate);

  if (ModulePrivateLoc.isValid())
    NewTemplate->setModulePrivate();

  // Build the type for the class template declaration now.
  QualType T = NewTemplate->getInjectedClassNameSpecialization();
  T = Context.getInjectedClassNameType(NewClass, T);
  assert(T->isDependentType() && "Class template type is not dependent?");
  (void)T;

  // If we are providing an explicit specialization of a member that is a
  // class template, make a note of that.
  if (PrevClassTemplate &&
      PrevClassTemplate->getInstantiatedFromMemberTemplate())
    PrevClassTemplate->setMemberSpecialization();

  // Set the access specifier.
  if (!Invalid && TUK != TagUseKind::Friend &&
      NewTemplate->getDeclContext()->isRecord())
    SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);

  // Set the lexical context of these templates
  NewClass->setLexicalDeclContext(CurContext);
  NewTemplate->setLexicalDeclContext(CurContext);

  if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
    NewClass->startDefinition();

  ProcessDeclAttributeList(S, NewClass, Attr);

  if (PrevClassTemplate)
    mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());

  AddPushedVisibilityAttribute(NewClass);
  inferGslOwnerPointerAttribute(NewClass);
  inferNullableClassAttribute(NewClass);

  if (TUK != TagUseKind::Friend) {
    // Per C++ [basic.scope.temp]p2, skip the template parameter scopes.
    Scope *Outer = S;
    while ((Outer->getFlags() & Scope::TemplateParamScope) != 0)
      Outer = Outer->getParent();
    PushOnScopeChains(NewTemplate, Outer);
  } else {
    if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
      NewTemplate->setAccess(PrevClassTemplate->getAccess());
      NewClass->setAccess(PrevClassTemplate->getAccess());
    }

    NewTemplate->setObjectOfFriendDecl();

    // Friend templates are visible in fairly strange ways.
    if (!CurContext->isDependentContext()) {
      DeclContext *DC = SemanticContext->getRedeclContext();
      DC->makeDeclVisibleInContext(NewTemplate);
      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
        PushOnScopeChains(NewTemplate, EnclosingScope,
                          /* AddToContext = */ false);
    }

    FriendDecl *Friend = FriendDecl::Create(
        Context, CurContext, NewClass->getLocation(), NewTemplate, FriendLoc);
    Friend->setAccess(AS_public);
    CurContext->addDecl(Friend);
  }

  if (PrevClassTemplate)
    CheckRedeclarationInModule(NewTemplate, PrevClassTemplate);

  if (Invalid) {
    NewTemplate->setInvalidDecl();
    NewClass->setInvalidDecl();
  }

  ActOnDocumentableDecl(NewTemplate);

  if (SkipBody && SkipBody->ShouldSkip)
    return SkipBody->Previous;

  return NewTemplate;
}

/// Diagnose the presence of a default template argument on a
/// template parameter, which is ill-formed in certain contexts.
///
/// \returns true if the default template argument should be dropped.
static bool DiagnoseDefaultTemplateArgument(Sema &S,
                                            Sema::TemplateParamListContext TPC,
                                            SourceLocation ParamLoc,
                                            SourceRange DefArgRange) {
  switch (TPC) {
  case Sema::TPC_Other:
  case Sema::TPC_TemplateTemplateParameterPack:
    return false;

  case Sema::TPC_FunctionTemplate:
  case Sema::TPC_FriendFunctionTemplateDefinition:
    // C++ [temp.param]p9:
    //   A default template-argument shall not be specified in a
    //   function template declaration or a function template
    //   definition [...]
    //   If a friend function template declaration specifies a default
    //   template-argument, that declaration shall be a definition and shall be
    //   the only declaration of the function template in the translation unit.
    // (C++98/03 doesn't have this wording; see DR226).
    S.DiagCompat(ParamLoc, diag_compat::templ_default_in_function_templ)
        << DefArgRange;
    return false;

  case Sema::TPC_ClassTemplateMember:
    // C++0x [temp.param]p9:
    //   A default template-argument shall not be specified in the
    //   template-parameter-lists of the definition of a member of a
    //   class template that appears outside of the member's class.
    S.Diag(ParamLoc, diag::err_template_parameter_default_template_member)
      << DefArgRange;
    return true;

  case Sema::TPC_FriendClassTemplate:
  case Sema::TPC_FriendFunctionTemplate:
    // C++ [temp.param]p9:
    //   A default template-argument shall not be specified in a
    //   friend template declaration.
    S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template)
      << DefArgRange;
    return true;

    // FIXME: C++0x [temp.param]p9 allows default template-arguments
    // for friend function templates if there is only a single
    // declaration (and it is a definition). Strange!
  }

  llvm_unreachable("Invalid TemplateParamListContext!");
}

/// Check for unexpanded parameter packs within the template parameters
/// of a template template parameter, recursively.
static bool DiagnoseUnexpandedParameterPacks(Sema &S,
                                             TemplateTemplateParmDecl *TTP) {
  // A template template parameter which is a parameter pack is also a pack
  // expansion.
  if (TTP->isParameterPack())
    return false;

  TemplateParameterList *Params = TTP->getTemplateParameters();
  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
    NamedDecl *P = Params->getParam(I);
    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
      if (!TTP->isParameterPack())
        if (const TypeConstraint *TC = TTP->getTypeConstraint())
          if (TC->hasExplicitTemplateArgs())
            for (auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments())
              if (S.DiagnoseUnexpandedParameterPack(ArgLoc,
                                                    Sema::UPPC_TypeConstraint))
                return true;
      continue;
    }

    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
      if (!NTTP->isParameterPack() &&
          S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(),
                                            NTTP->getTypeSourceInfo(),
                                      Sema::UPPC_NonTypeTemplateParameterType))
        return true;

      continue;
    }

    if (TemplateTemplateParmDecl *InnerTTP
                                        = dyn_cast<TemplateTemplateParmDecl>(P))
      if (DiagnoseUnexpandedParameterPacks(S, InnerTTP))
        return true;
  }

  return false;
}

bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
                                      TemplateParameterList *OldParams,
                                      TemplateParamListContext TPC,
                                      SkipBodyInfo *SkipBody) {
  bool Invalid = false;

  // C++ [temp.param]p10:
  //   The set of default template-arguments available for use with a
  //   template declaration or definition is obtained by merging the
  //   default arguments from the definition (if in scope) and all
  //   declarations in scope in the same way default function
  //   arguments are (8.3.6).
  bool SawDefaultArgument = false;
  SourceLocation PreviousDefaultArgLoc;

  // Dummy initialization to avoid warnings.
  TemplateParameterList::iterator OldParam = NewParams->end();
  if (OldParams)
    OldParam = OldParams->begin();

  bool RemoveDefaultArguments = false;
  for (TemplateParameterList::iterator NewParam = NewParams->begin(),
                                    NewParamEnd = NewParams->end();
       NewParam != NewParamEnd; ++NewParam) {
    // Whether we've seen a duplicate default argument in the same translation
    // unit.
    bool RedundantDefaultArg = false;
    // Whether we've found inconsis inconsitent default arguments in different
    // translation unit.
    bool InconsistentDefaultArg = false;
    // The name of the module which contains the inconsistent default argument.
    std::string PrevModuleName;

    SourceLocation OldDefaultLoc;
    SourceLocation NewDefaultLoc;

    // Variable used to diagnose missing default arguments
    bool MissingDefaultArg = false;

    // Variable used to diagnose non-final parameter packs
    bool SawParameterPack = false;

    if (TemplateTypeParmDecl *NewTypeParm
          = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
      // Check the presence of a default argument here.
      if (NewTypeParm->hasDefaultArgument() &&
          DiagnoseDefaultTemplateArgument(
              *this, TPC, NewTypeParm->getLocation(),
              NewTypeParm->getDefaultArgument().getSourceRange()))
        NewTypeParm->removeDefaultArgument();

      // Merge default arguments for template type parameters.
      TemplateTypeParmDecl *OldTypeParm
          = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
      if (NewTypeParm->isParameterPack()) {
        assert(!NewTypeParm->hasDefaultArgument() &&
               "Parameter packs can't have a default argument!");
        SawParameterPack = true;
      } else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) &&
                 NewTypeParm->hasDefaultArgument() &&
                 (!SkipBody || !SkipBody->ShouldSkip)) {
        OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
        NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
        SawDefaultArgument = true;

        if (!OldTypeParm->getOwningModule())
          RedundantDefaultArg = true;
        else if (!getASTContext().isSameDefaultTemplateArgument(OldTypeParm,
                                                                NewTypeParm)) {
          InconsistentDefaultArg = true;
          PrevModuleName =
              OldTypeParm->getImportedOwningModule()->getFullModuleName();
        }
        PreviousDefaultArgLoc = NewDefaultLoc;
      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
        // Merge the default argument from the old declaration to the
        // new declaration.
        NewTypeParm->setInheritedDefaultArgument(Context, OldTypeParm);
        PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
      } else if (NewTypeParm->hasDefaultArgument()) {
        SawDefaultArgument = true;
        PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc();
      } else if (SawDefaultArgument)
        MissingDefaultArg = true;
    } else if (NonTypeTemplateParmDecl *NewNonTypeParm
               = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) {
      // Check for unexpanded parameter packs, except in a template template
      // parameter pack, as in those any unexpanded packs should be expanded
      // along with the parameter itself.
      if (TPC != TPC_TemplateTemplateParameterPack &&
          !NewNonTypeParm->isParameterPack() &&
          DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(),
                                          NewNonTypeParm->getTypeSourceInfo(),
                                          UPPC_NonTypeTemplateParameterType)) {
        Invalid = true;
        continue;
      }

      // Check the presence of a default argument here.
      if (NewNonTypeParm->hasDefaultArgument() &&
          DiagnoseDefaultTemplateArgument(
              *this, TPC, NewNonTypeParm->getLocation(),
              NewNonTypeParm->getDefaultArgument().getSourceRange())) {
        NewNonTypeParm->removeDefaultArgument();
      }

      // Merge default arguments for non-type template parameters
      NonTypeTemplateParmDecl *OldNonTypeParm
        = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr;
      if (NewNonTypeParm->isParameterPack()) {
        assert(!NewNonTypeParm->hasDefaultArgument() &&
               "Parameter packs can't have a default argument!");
        if (!NewNonTypeParm->isPackExpansion())
          SawParameterPack = true;
      } else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) &&
                 NewNonTypeParm->hasDefaultArgument() &&
                 (!SkipBody || !SkipBody->ShouldSkip)) {
        OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
        NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
        SawDefaultArgument = true;
        if (!OldNonTypeParm->getOwningModule())
          RedundantDefaultArg = true;
        else if (!getASTContext().isSameDefaultTemplateArgument(
                     OldNonTypeParm, NewNonTypeParm)) {
          InconsistentDefaultArg = true;
          PrevModuleName =
              OldNonTypeParm->getImportedOwningModule()->getFullModuleName();
        }
        PreviousDefaultArgLoc = NewDefaultLoc;
      } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
        // Merge the default argument from the old declaration to the
        // new declaration.
        NewNonTypeParm->setInheritedDefaultArgument(Context, OldNonTypeParm);
        PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
      } else if (NewNonTypeParm->hasDefaultArgument()) {
        SawDefaultArgument = true;
        PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc();
      } else if (SawDefaultArgument)
        MissingDefaultArg = true;
    } else {
      TemplateTemplateParmDecl *NewTemplateParm
        = cast<TemplateTemplateParmDecl>(*NewParam);

      // Check for unexpanded parameter packs, recursively.
      if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
        Invalid = true;
        continue;
      }

      // Check the presence of a default argument here.
      if (NewTemplateParm->hasDefaultArgument() &&
          DiagnoseDefaultTemplateArgument(*this, TPC,
                                          NewTemplateParm->getLocation(),
                     NewTemplateParm->getDefaultArgument().getSourceRange()))
        NewTemplateParm->removeDefaultArgument();

      // Merge default arguments for template template parameters
      TemplateTemplateParmDecl *OldTemplateParm
        = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr;
      if (NewTemplateParm->isParameterPack()) {
        assert(!NewTemplateParm->hasDefaultArgument() &&
               "Parameter packs can't have a default argument!");
        if (!NewTemplateParm->isPackExpansion())
          SawParameterPack = true;
      } else if (OldTemplateParm &&
                 hasVisibleDefaultArgument(OldTemplateParm) &&
                 NewTemplateParm->hasDefaultArgument() &&
                 (!SkipBody || !SkipBody->ShouldSkip)) {
        OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
        NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
        SawDefaultArgument = true;
        if (!OldTemplateParm->getOwningModule())
          RedundantDefaultArg = true;
        else if (!getASTContext().isSameDefaultTemplateArgument(
                     OldTemplateParm, NewTemplateParm)) {
          InconsistentDefaultArg = true;
          PrevModuleName =
              OldTemplateParm->getImportedOwningModule()->getFullModuleName();
        }
        PreviousDefaultArgLoc = NewDefaultLoc;
      } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
        // Merge the default argument from the old declaration to the
        // new declaration.
        NewTemplateParm->setInheritedDefaultArgument(Context, OldTemplateParm);
        PreviousDefaultArgLoc
          = OldTemplateParm->getDefaultArgument().getLocation();
      } else if (NewTemplateParm->hasDefaultArgument()) {
        SawDefaultArgument = true;
        PreviousDefaultArgLoc
          = NewTemplateParm->getDefaultArgument().getLocation();
      } else if (SawDefaultArgument)
        MissingDefaultArg = true;
    }

    // C++11 [temp.param]p11:
    //   If a template parameter of a primary class template or alias template
    //   is a template parameter pack, it shall be the last template parameter.
    if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
        (TPC == TPC_Other || TPC == TPC_TemplateTemplateParameterPack)) {
      Diag((*NewParam)->getLocation(),
           diag::err_template_param_pack_must_be_last_template_parameter);
      Invalid = true;
    }

    // [basic.def.odr]/13:
    //     There can be more than one definition of a
    //     ...
    //     default template argument
    //     ...
    //     in a program provided that each definition appears in a different
    //     translation unit and the definitions satisfy the [same-meaning
    //     criteria of the ODR].
    //
    // Simply, the design of modules allows the definition of template default
    // argument to be repeated across translation unit. Note that the ODR is
    // checked elsewhere. But it is still not allowed to repeat template default
    // argument in the same translation unit.
    if (RedundantDefaultArg) {
      Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition);
      Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg);
      Invalid = true;
    } else if (InconsistentDefaultArg) {
      // We could only diagnose about the case that the OldParam is imported.
      // The case NewParam is imported should be handled in ASTReader.
      Diag(NewDefaultLoc,
           diag::err_template_param_default_arg_inconsistent_redefinition);
      Diag(OldDefaultLoc,
           diag::note_template_param_prev_default_arg_in_other_module)
          << PrevModuleName;
      Invalid = true;
    } else if (MissingDefaultArg &&
               (TPC == TPC_Other || TPC == TPC_TemplateTemplateParameterPack ||
                TPC == TPC_FriendClassTemplate)) {
      // C++ 23[temp.param]p14:
      // If a template-parameter of a class template, variable template, or
      // alias template has a default template argument, each subsequent
      // template-parameter shall either have a default template argument
      // supplied or be a template parameter pack.
      Diag((*NewParam)->getLocation(),
           diag::err_template_param_default_arg_missing);
      Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
      Invalid = true;
      RemoveDefaultArguments = true;
    }

    // If we have an old template parameter list that we're merging
    // in, move on to the next parameter.
    if (OldParams)
      ++OldParam;
  }

  // We were missing some default arguments at the end of the list, so remove
  // all of the default arguments.
  if (RemoveDefaultArguments) {
    for (TemplateParameterList::iterator NewParam = NewParams->begin(),
                                      NewParamEnd = NewParams->end();
         NewParam != NewParamEnd; ++NewParam) {
      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
        TTP->removeDefaultArgument();
      else if (NonTypeTemplateParmDecl *NTTP
                                = dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
        NTTP->removeDefaultArgument();
      else
        cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
    }
  }

  return Invalid;
}

namespace {

/// A class which looks for a use of a certain level of template
/// parameter.
struct DependencyChecker : DynamicRecursiveASTVisitor {
  unsigned Depth;

  // Whether we're looking for a use of a template parameter that makes the
  // overall construct type-dependent / a dependent type. This is strictly
  // best-effort for now; we may fail to match at all for a dependent type
  // in some cases if this is set.
  bool IgnoreNonTypeDependent;

  bool Match;
  SourceLocation MatchLoc;

  DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent)
      : Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent),
        Match(false) {}

  DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent)
      : IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {
    NamedDecl *ND = Params->getParam(0);
    if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
      Depth = PD->getDepth();
    } else if (NonTypeTemplateParmDecl *PD =
                 dyn_cast<NonTypeTemplateParmDecl>(ND)) {
      Depth = PD->getDepth();
    } else {
      Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth();
    }
  }

  bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) {
    if (ParmDepth >= Depth) {
      Match = true;
      MatchLoc = Loc;
      return true;
    }
    return false;
  }

  bool TraverseStmt(Stmt *S) override {
    // Prune out non-type-dependent expressions if requested. This can
    // sometimes result in us failing to find a template parameter reference
    // (if a value-dependent expression creates a dependent type), but this
    // mode is best-effort only.
    if (auto *E = dyn_cast_or_null<Expr>(S))
      if (IgnoreNonTypeDependent && !E->isTypeDependent())
        return true;
    return DynamicRecursiveASTVisitor::TraverseStmt(S);
  }

  bool TraverseTypeLoc(TypeLoc TL) override {
    if (IgnoreNonTypeDependent && !TL.isNull() &&
        !TL.getType()->isDependentType())
      return true;
    return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
  }

  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
    return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
  }

  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
    // For a best-effort search, keep looking until we find a location.
    return IgnoreNonTypeDependent || !Matches(T->getDepth());
  }

  bool TraverseTemplateName(TemplateName N) override {
    if (TemplateTemplateParmDecl *PD =
          dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
      if (Matches(PD->getDepth()))
        return false;
    return DynamicRecursiveASTVisitor::TraverseTemplateName(N);
  }

  bool VisitDeclRefExpr(DeclRefExpr *E) override {
    if (NonTypeTemplateParmDecl *PD =
          dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
      if (Matches(PD->getDepth(), E->getExprLoc()))
        return false;
    return DynamicRecursiveASTVisitor::VisitDeclRefExpr(E);
  }

  bool VisitSubstTemplateTypeParmType(SubstTemplateTypeParmType *T) override {
    return TraverseType(T->getReplacementType());
  }

  bool VisitSubstTemplateTypeParmPackType(
      SubstTemplateTypeParmPackType *T) override {
    return TraverseTemplateArgument(T->getArgumentPack());
  }

  bool TraverseInjectedClassNameType(InjectedClassNameType *T) override {
    return TraverseType(T->getInjectedSpecializationType());
  }
};
} // end anonymous namespace

/// Determines whether a given type depends on the given parameter
/// list.
static bool
DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) {
  if (!Params->size())
    return false;

  DependencyChecker Checker(Params, /*IgnoreNonTypeDependent*/false);
  Checker.TraverseType(T);
  return Checker.Match;
}

// Find the source range corresponding to the named type in the given
// nested-name-specifier, if any.
static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
                                                       QualType T,
                                                       const CXXScopeSpec &SS) {
  NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data());
  while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) {
    if (const Type *CurType = NNS->getAsType()) {
      if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0)))
        return NNSLoc.getTypeLoc().getSourceRange();
    } else
      break;

    NNSLoc = NNSLoc.getPrefix();
  }

  return SourceRange();
}

TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
    SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
    TemplateIdAnnotation *TemplateId,
    ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
    bool &IsMemberSpecialization, bool &Invalid, bool SuppressDiagnostic) {
  IsMemberSpecialization = false;
  Invalid = false;

  // The sequence of nested types to which we will match up the template
  // parameter lists. We first build this list by starting with the type named
  // by the nested-name-specifier and walking out until we run out of types.
  SmallVector<QualType, 4> NestedTypes;
  QualType T;
  if (SS.getScopeRep()) {
    if (CXXRecordDecl *Record
              = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
      T = Context.getTypeDeclType(Record);
    else
      T = QualType(SS.getScopeRep()->getAsType(), 0);
  }

  // If we found an explicit specialization that prevents us from needing
  // 'template<>' headers, this will be set to the location of that
  // explicit specialization.
  SourceLocation ExplicitSpecLoc;

  while (!T.isNull()) {
    NestedTypes.push_back(T);

    // Retrieve the parent of a record type.
    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
      // If this type is an explicit specialization, we're done.
      if (ClassTemplateSpecializationDecl *Spec
          = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
        if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&
            Spec->getSpecializationKind() == TSK_ExplicitSpecialization) {
          ExplicitSpecLoc = Spec->getLocation();
          break;
        }
      } else if (Record->getTemplateSpecializationKind()
                                                == TSK_ExplicitSpecialization) {
        ExplicitSpecLoc = Record->getLocation();
        break;
      }

      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent()))
        T = Context.getTypeDeclType(Parent);
      else
        T = QualType();
      continue;
    }

    if (const TemplateSpecializationType *TST
                                     = T->getAs<TemplateSpecializationType>()) {
      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
        if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext()))
          T = Context.getTypeDeclType(Parent);
        else
          T = QualType();
        continue;
      }
    }

    // Look one step prior in a dependent template specialization type.
    if (const DependentTemplateSpecializationType *DependentTST
                          = T->getAs<DependentTemplateSpecializationType>()) {
      if (NestedNameSpecifier *NNS =
              DependentTST->getDependentTemplateName().getQualifier())
        T = QualType(NNS->getAsType(), 0);
      else
        T = QualType();
      continue;
    }

    // Look one step prior in a dependent name type.
    if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
      if (NestedNameSpecifier *NNS = DependentName->getQualifier())
        T = QualType(NNS->getAsType(), 0);
      else
        T = QualType();
      continue;
    }

    // Retrieve the parent of an enumeration type.
    if (const EnumType *EnumT = T->getAs<EnumType>()) {
      // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
      // check here.
      EnumDecl *Enum = EnumT->getDecl();

      // Get to the parent type.
      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
        T = Context.getTypeDeclType(Parent);
      else
        T = QualType();
      continue;
    }

    T = QualType();
  }
  // Reverse the nested types list, since we want to traverse from the outermost
  // to the innermost while checking template-parameter-lists.
  std::reverse(NestedTypes.begin(), NestedTypes.end());

  // C++0x [temp.expl.spec]p17:
  //   A member or a member template may be nested within many
  //   enclosing class templates. In an explicit specialization for
  //   such a member, the member declaration shall be preceded by a
  //   template<> for each enclosing class template that is
  //   explicitly specialized.
  bool SawNonEmptyTemplateParameterList = false;

  auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) {
    if (SawNonEmptyTemplateParameterList) {
      if (!SuppressDiagnostic)
        Diag(DeclLoc, diag::err_specialize_member_of_template)
          << !Recovery << Range;
      Invalid = true;
      IsMemberSpecialization = false;
      return true;
    }

    return false;
  };

  auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
    // Check that we can have an explicit specialization here.
    if (CheckExplicitSpecialization(Range, true))
      return true;

    // We don't have a template header, but we should.
    SourceLocation ExpectedTemplateLoc;
    if (!ParamLists.empty())
      ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
    else
      ExpectedTemplateLoc = DeclStartLoc;

    if (!SuppressDiagnostic)
      Diag(DeclLoc, diag::err_template_spec_needs_header)
        << Range
        << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
    return false;
  };

  unsigned ParamIdx = 0;
  for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
       ++TypeIdx) {
    T = NestedTypes[TypeIdx];

    // Whether we expect a 'template<>' header.
    bool NeedEmptyTemplateHeader = false;

    // Whether we expect a template header with parameters.
    bool NeedNonemptyTemplateHeader = false;

    // For a dependent type, the set of template parameters that we
    // expect to see.
    TemplateParameterList *ExpectedTemplateParams = nullptr;

    // C++0x [temp.expl.spec]p15:
    //   A member or a member template may be nested within many enclosing
    //   class templates. In an explicit specialization for such a member, the
    //   member declaration shall be preceded by a template<> for each
    //   enclosing class template that is explicitly specialized.
    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
      if (ClassTemplatePartialSpecializationDecl *Partial
            = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
        ExpectedTemplateParams = Partial->getTemplateParameters();
        NeedNonemptyTemplateHeader = true;
      } else if (Record->isDependentType()) {
        if (Record->getDescribedClassTemplate()) {
          ExpectedTemplateParams = Record->getDescribedClassTemplate()
                                                      ->getTemplateParameters();
          NeedNonemptyTemplateHeader = true;
        }
      } else if (ClassTemplateSpecializationDecl *Spec
                     = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
        // C++0x [temp.expl.spec]p4:
        //   Members of an explicitly specialized class template are defined
        //   in the same manner as members of normal classes, and not using
        //   the template<> syntax.
        if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization)
          NeedEmptyTemplateHeader = true;
        else
          continue;
      } else if (Record->getTemplateSpecializationKind()) {
        if (Record->getTemplateSpecializationKind()
                                                != TSK_ExplicitSpecialization &&
            TypeIdx == NumTypes - 1)
          IsMemberSpecialization = true;

        continue;
      }
    } else if (const TemplateSpecializationType *TST
                                     = T->getAs<TemplateSpecializationType>()) {
      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
        ExpectedTemplateParams = Template->getTemplateParameters();
        NeedNonemptyTemplateHeader = true;
      }
    } else if (T->getAs<DependentTemplateSpecializationType>()) {
      // FIXME:  We actually could/should check the template arguments here
      // against the corresponding template parameter list.
      NeedNonemptyTemplateHeader = false;
    }

    // C++ [temp.expl.spec]p16:
    //   In an explicit specialization declaration for a member of a class
    //   template or a member template that appears in namespace scope, the
    //   member template and some of its enclosing class templates may remain
    //   unspecialized, except that the declaration shall not explicitly
    //   specialize a class member template if its enclosing class templates
    //   are not explicitly specialized as well.
    if (ParamIdx < ParamLists.size()) {
      if (ParamLists[ParamIdx]->size() == 0) {
        if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
                                        false))
          return nullptr;
      } else
        SawNonEmptyTemplateParameterList = true;
    }

    if (NeedEmptyTemplateHeader) {
      // If we're on the last of the types, and we need a 'template<>' header
      // here, then it's a member specialization.
      if (TypeIdx == NumTypes - 1)
        IsMemberSpecialization = true;

      if (ParamIdx < ParamLists.size()) {
        if (ParamLists[ParamIdx]->size() > 0) {
          // The header has template parameters when it shouldn't. Complain.
          if (!SuppressDiagnostic)
            Diag(ParamLists[ParamIdx]->getTemplateLoc(),
                 diag::err_template_param_list_matches_nontemplate)
              << T
              << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
                             ParamLists[ParamIdx]->getRAngleLoc())
              << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
          Invalid = true;
          return nullptr;
        }

        // Consume this template header.
        ++ParamIdx;
        continue;
      }

      if (!IsFriend)
        if (DiagnoseMissingExplicitSpecialization(
                getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
          return nullptr;

      continue;
    }

    if (NeedNonemptyTemplateHeader) {
      // In friend declarations we can have template-ids which don't
      // depend on the corresponding template parameter lists.  But
      // assume that empty parameter lists are supposed to match this
      // template-id.
      if (IsFriend && T->isDependentType()) {
        if (ParamIdx < ParamLists.size() &&
            DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
          ExpectedTemplateParams = nullptr;
        else
          continue;
      }

      if (ParamIdx < ParamLists.size()) {
        // Check the template parameter list, if we can.
        if (ExpectedTemplateParams &&
            !TemplateParameterListsAreEqual(ParamLists[ParamIdx],
                                            ExpectedTemplateParams,
                                            !SuppressDiagnostic, TPL_TemplateMatch))
          Invalid = true;

        if (!Invalid &&
            CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
                                       TPC_ClassTemplateMember))
          Invalid = true;

        ++ParamIdx;
        continue;
      }

      if (!SuppressDiagnostic)
        Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
          << T
          << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
      Invalid = true;
      continue;
    }
  }

  // If there were at least as many template-ids as there were template
  // parameter lists, then there are no template parameter lists remaining for
  // the declaration itself.
  if (ParamIdx >= ParamLists.size()) {
    if (TemplateId && !IsFriend) {
      // We don't have a template header for the declaration itself, but we
      // should.
      DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
                                                        TemplateId->RAngleLoc));

      // Fabricate an empty template parameter list for the invented header.
      return TemplateParameterList::Create(Context, SourceLocation(),
                                           SourceLocation(), {},
                                           SourceLocation(), nullptr);
    }

    return nullptr;
  }

  // If there were too many template parameter lists, complain about that now.
  if (ParamIdx < ParamLists.size() - 1) {
    bool HasAnyExplicitSpecHeader = false;
    bool AllExplicitSpecHeaders = true;
    for (unsigned I = ParamIdx, E = ParamLists.size() - 1; I != E; ++I) {
      if (ParamLists[I]->size() == 0)
        HasAnyExplicitSpecHeader = true;
      else
        AllExplicitSpecHeaders = false;
    }

    if (!SuppressDiagnostic)
      Diag(ParamLists[ParamIdx]->getTemplateLoc(),
           AllExplicitSpecHeaders ? diag::ext_template_spec_extra_headers
                                  : diag::err_template_spec_extra_headers)
          << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
                         ParamLists[ParamLists.size() - 2]->getRAngleLoc());

    // If there was a specialization somewhere, such that 'template<>' is
    // not required, and there were any 'template<>' headers, note where the
    // specialization occurred.
    if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader &&
        !SuppressDiagnostic)
      Diag(ExplicitSpecLoc,
           diag::note_explicit_template_spec_does_not_need_header)
        << NestedTypes.back();

    // We have a template parameter list with no corresponding scope, which
    // means that the resulting template declaration can't be instantiated
    // properly (we'll end up with dependent nodes when we shouldn't).
    if (!AllExplicitSpecHeaders)
      Invalid = true;
  }

  // C++ [temp.expl.spec]p16:
  //   In an explicit specialization declaration for a member of a class
  //   template or a member template that ap- pears in namespace scope, the
  //   member template and some of its enclosing class templates may remain
  //   unspecialized, except that the declaration shall not explicitly
  //   specialize a class member template if its en- closing class templates
  //   are not explicitly specialized as well.
  if (ParamLists.back()->size() == 0 &&
      CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
                                  false))
    return nullptr;

  // Return the last template parameter list, which corresponds to the
  // entity being declared.
  return ParamLists.back();
}

void Sema::NoteAllFoundTemplates(TemplateName Name) {
  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
    Diag(Template->getLocation(), diag::note_template_declared_here)
        << (isa<FunctionTemplateDecl>(Template)
                ? 0
                : isa<ClassTemplateDecl>(Template)
                      ? 1
                      : isa<VarTemplateDecl>(Template)
                            ? 2
                            : isa<TypeAliasTemplateDecl>(Template) ? 3 : 4)
        << Template->getDeclName();
    return;
  }

  if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
    for (OverloadedTemplateStorage::iterator I = OST->begin(),
                                          IEnd = OST->end();
         I != IEnd; ++I)
      Diag((*I)->getLocation(), diag::note_template_declared_here)
        << 0 << (*I)->getDeclName();

    return;
  }
}

static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
                                      SourceLocation TemplateLoc,
                                      ArrayRef<TemplateArgument> Ts) {
  auto lookUpCommonType = [&](TemplateArgument T1,
                              TemplateArgument T2) -> QualType {
    // Don't bother looking for other specializations if both types are
    // builtins - users aren't allowed to specialize for them
    if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType())
      return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2});

    TemplateArgumentListInfo Args;
    Args.addArgument(TemplateArgumentLoc(
        T1, S.Context.getTrivialTypeSourceInfo(T1.getAsType())));
    Args.addArgument(TemplateArgumentLoc(
        T2, S.Context.getTrivialTypeSourceInfo(T2.getAsType())));

    EnterExpressionEvaluationContext UnevaluatedContext(
        S, Sema::ExpressionEvaluationContext::Unevaluated);
    Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
    Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());

    QualType BaseTemplateInst =
        S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);

    if (SFINAE.hasErrorOccurred())
      return QualType();

    return BaseTemplateInst;
  };

  // Note A: For the common_type trait applied to a template parameter pack T of
  // types, the member type shall be either defined or not present as follows:
  switch (Ts.size()) {

  // If sizeof...(T) is zero, there shall be no member type.
  case 0:
    return QualType();

  // If sizeof...(T) is one, let T0 denote the sole type constituting the
  // pack T. The member typedef-name type shall denote the same type, if any, as
  // common_type_t<T0, T0>; otherwise there shall be no member type.
  case 1:
    return lookUpCommonType(Ts[0], Ts[0]);

  // If sizeof...(T) is two, let the first and second types constituting T be
  // denoted by T1 and T2, respectively, and let D1 and D2 denote the same types
  // as decay_t<T1> and decay_t<T2>, respectively.
  case 2: {
    QualType T1 = Ts[0].getAsType();
    QualType T2 = Ts[1].getAsType();
    QualType D1 = S.BuiltinDecay(T1, {});
    QualType D2 = S.BuiltinDecay(T2, {});

    // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C denote
    // the same type, if any, as common_type_t<D1, D2>.
    if (!S.Context.hasSameType(T1, D1) || !S.Context.hasSameType(T2, D2))
      return lookUpCommonType(D1, D2);

    // Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
    // denotes a valid type, let C denote that type.
    {
      auto CheckConditionalOperands = [&](bool ConstRefQual) -> QualType {
        EnterExpressionEvaluationContext UnevaluatedContext(
            S, Sema::ExpressionEvaluationContext::Unevaluated);
        Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
        Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());

        // false
        OpaqueValueExpr CondExpr(SourceLocation(), S.Context.BoolTy,
                                 VK_PRValue);
        ExprResult Cond = &CondExpr;

        auto EVK = ConstRefQual ? VK_LValue : VK_PRValue;
        if (ConstRefQual) {
          D1.addConst();
          D2.addConst();
        }

        // declval<D1>()
        OpaqueValueExpr LHSExpr(TemplateLoc, D1, EVK);
        ExprResult LHS = &LHSExpr;

        // declval<D2>()
        OpaqueValueExpr RHSExpr(TemplateLoc, D2, EVK);
        ExprResult RHS = &RHSExpr;

        ExprValueKind VK = VK_PRValue;
        ExprObjectKind OK = OK_Ordinary;

        // decltype(false ? declval<D1>() : declval<D2>())
        QualType Result =
            S.CheckConditionalOperands(Cond, LHS, RHS, VK, OK, TemplateLoc);

        if (Result.isNull() || SFINAE.hasErrorOccurred())
          return QualType();

        // decay_t<decltype(false ? declval<D1>() : declval<D2>())>
        return S.BuiltinDecay(Result, TemplateLoc);
      };

      if (auto Res = CheckConditionalOperands(false); !Res.isNull())
        return Res;

      // Let:
      // CREF(A) be add_lvalue_reference_t<const remove_reference_t<A>>,
      // COND-RES(X, Y) be
      //   decltype(false ? declval<X(&)()>()() : declval<Y(&)()>()()).

      // C++20 only
      // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, let C denote
      // the type decay_t<COND-RES(CREF(D1), CREF(D2))>.
      if (!S.Context.getLangOpts().CPlusPlus20)
        return QualType();
      return CheckConditionalOperands(true);
    }
  }

  // If sizeof...(T) is greater than two, let T1, T2, and R, respectively,
  // denote the first, second, and (pack of) remaining types constituting T. Let
  // C denote the same type, if any, as common_type_t<T1, T2>. If there is such
  // a type C, the member typedef-name type shall denote the same type, if any,
  // as common_type_t<C, R...>. Otherwise, there shall be no member type.
  default: {
    QualType Result = Ts.front().getAsType();
    for (auto T : llvm::drop_begin(Ts)) {
      Result = lookUpCommonType(Result, T.getAsType());
      if (Result.isNull())
        return QualType();
    }
    return Result;
  }
  }
}

static QualType
checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
                           ArrayRef<TemplateArgument> Converted,
                           SourceLocation TemplateLoc,
                           TemplateArgumentListInfo &TemplateArgs) {
  ASTContext &Context = SemaRef.getASTContext();

  switch (BTD->getBuiltinTemplateKind()) {
  case BTK__make_integer_seq: {
    // Specializations of __make_integer_seq<S, T, N> are treated like
    // S<T, 0, ..., N-1>.

    QualType OrigType = Converted[1].getAsType();
    // C++14 [inteseq.intseq]p1:
    //   T shall be an integer type.
    if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) {
      SemaRef.Diag(TemplateArgs[1].getLocation(),
                   diag::err_integer_sequence_integral_element_type);
      return QualType();
    }

    TemplateArgument NumArgsArg = Converted[2];
    if (NumArgsArg.isDependent())
      return QualType();

    TemplateArgumentListInfo SyntheticTemplateArgs;
    // The type argument, wrapped in substitution sugar, gets reused as the
    // first template argument in the synthetic template argument list.
    SyntheticTemplateArgs.addArgument(
        TemplateArgumentLoc(TemplateArgument(OrigType),
                            SemaRef.Context.getTrivialTypeSourceInfo(
                                OrigType, TemplateArgs[1].getLocation())));

    if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) {
      // Expand N into 0 ... N-1.
      for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
           I < NumArgs; ++I) {
        TemplateArgument TA(Context, I, OrigType);
        SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
            TA, OrigType, TemplateArgs[2].getLocation()));
      }
    } else {
      // C++14 [inteseq.make]p1:
      //   If N is negative the program is ill-formed.
      SemaRef.Diag(TemplateArgs[2].getLocation(),
                   diag::err_integer_sequence_negative_length);
      return QualType();
    }

    // The first template argument will be reused as the template decl that
    // our synthetic template arguments will be applied to.
    return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
                                       TemplateLoc, SyntheticTemplateArgs);
  }

  case BTK__type_pack_element: {
    // Specializations of
    //    __type_pack_element<Index, T_1, ..., T_N>
    // are treated like T_Index.
    assert(Converted.size() == 2 &&
           "__type_pack_element should be given an index and a parameter pack");

    TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
    if (IndexArg.isDependent() || Ts.isDependent())
      return QualType();

    llvm::APSInt Index = IndexArg.getAsIntegral();
    assert(Index >= 0 && "the index used with __type_pack_element should be of "
                         "type std::size_t, and hence be non-negative");
    // If the Index is out of bounds, the program is ill-formed.
    if (Index >= Ts.pack_size()) {
      SemaRef.Diag(TemplateArgs[0].getLocation(),
                   diag::err_type_pack_element_out_of_bounds);
      return QualType();
    }

    // We simply return the type at index `Index`.
    int64_t N = Index.getExtValue();
    return Ts.getPackAsArray()[N].getAsType();
  }

  case BTK__builtin_common_type: {
    assert(Converted.size() == 4);
    if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); }))
      return QualType();

    TemplateName BaseTemplate = Converted[0].getAsTemplate();
    ArrayRef<TemplateArgument> Ts = Converted[3].getPackAsArray();
    if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
        !CT.isNull()) {
      TemplateArgumentListInfo TAs;
      TAs.addArgument(TemplateArgumentLoc(
          TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
                                    CT, TemplateArgs[1].getLocation())));
      TemplateName HasTypeMember = Converted[1].getAsTemplate();
      return SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
    }
    QualType HasNoTypeMember = Converted[2].getAsType();
    return HasNoTypeMember;
  }
  }
  llvm_unreachable("unexpected BuiltinTemplateDecl!");
}

/// Determine whether this alias template is "enable_if_t".
/// libc++ >=14 uses "__enable_if_t" in C++11 mode.
static bool isEnableIfAliasTemplate(TypeAliasTemplateDecl *AliasTemplate) {
  return AliasTemplate->getName() == "enable_if_t" ||
         AliasTemplate->getName() == "__enable_if_t";
}

/// Collect all of the separable terms in the given condition, which
/// might be a conjunction.
///
/// FIXME: The right answer is to convert the logical expression into
/// disjunctive normal form, so we can find the first failed term
/// within each possible clause.
static void collectConjunctionTerms(Expr *Clause,
                                    SmallVectorImpl<Expr *> &Terms) {
  if (auto BinOp = dyn_cast<BinaryOperator>(Clause->IgnoreParenImpCasts())) {
    if (BinOp->getOpcode() == BO_LAnd) {
      collectConjunctionTerms(BinOp->getLHS(), Terms);
      collectConjunctionTerms(BinOp->getRHS(), Terms);
      return;
    }
  }

  Terms.push_back(Clause);
}

// The ranges-v3 library uses an odd pattern of a top-level "||" with
// a left-hand side that is value-dependent but never true. Identify
// the idiom and ignore that term.
static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
  // Top-level '||'.
  auto *BinOp = dyn_cast<BinaryOperator>(Cond->IgnoreParenImpCasts());
  if (!BinOp) return Cond;

  if (BinOp->getOpcode() != BO_LOr) return Cond;

  // With an inner '==' that has a literal on the right-hand side.
  Expr *LHS = BinOp->getLHS();
  auto *InnerBinOp = dyn_cast<BinaryOperator>(LHS->IgnoreParenImpCasts());
  if (!InnerBinOp) return Cond;

  if (InnerBinOp->getOpcode() != BO_EQ ||
      !isa<IntegerLiteral>(InnerBinOp->getRHS()))
    return Cond;

  // If the inner binary operation came from a macro expansion named
  // CONCEPT_REQUIRES or CONCEPT_REQUIRES_, return the right-hand side
  // of the '||', which is the real, user-provided condition.
  SourceLocation Loc = InnerBinOp->getExprLoc();
  if (!Loc.isMacroID()) return Cond;

  StringRef MacroName = PP.getImmediateMacroName(Loc);
  if (MacroName == "CONCEPT_REQUIRES" || MacroName == "CONCEPT_REQUIRES_")
    return BinOp->getRHS();

  return Cond;
}

namespace {

// A PrinterHelper that prints more helpful diagnostics for some sub-expressions
// within failing boolean expression, such as substituting template parameters
// for actual types.
class FailedBooleanConditionPrinterHelper : public PrinterHelper {
public:
  explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P)
      : Policy(P) {}

  bool handledStmt(Stmt *E, raw_ostream &OS) override {
    const auto *DR = dyn_cast<DeclRefExpr>(E);
    if (DR && DR->getQualifier()) {
      // If this is a qualified name, expand the template arguments in nested
      // qualifiers.
      DR->getQualifier()->print(OS, Policy, true);
      // Then print the decl itself.
      const ValueDecl *VD = DR->getDecl();
      OS << VD->getName();
      if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
        // This is a template variable, print the expanded template arguments.
        printTemplateArgumentList(
            OS, IV->getTemplateArgs().asArray(), Policy,
            IV->getSpecializedTemplate()->getTemplateParameters());
      }
      return true;
    }
    return false;
  }

private:
  const PrintingPolicy Policy;
};

} // end anonymous namespace

std::pair<Expr *, std::string>
Sema::findFailedBooleanCondition(Expr *Cond) {
  Cond = lookThroughRangesV3Condition(PP, Cond);

  // Separate out all of the terms in a conjunction.
  SmallVector<Expr *, 4> Terms;
  collectConjunctionTerms(Cond, Terms);

  // Determine which term failed.
  Expr *FailedCond = nullptr;
  for (Expr *Term : Terms) {
    Expr *TermAsWritten = Term->IgnoreParenImpCasts();

    // Literals are uninteresting.
    if (isa<CXXBoolLiteralExpr>(TermAsWritten) ||
        isa<IntegerLiteral>(TermAsWritten))
      continue;

    // The initialization of the parameter from the argument is
    // a constant-evaluated context.
    EnterExpressionEvaluationContext ConstantEvaluated(
      *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);

    bool Succeeded;
    if (Term->EvaluateAsBooleanCondition(Succeeded, Context) &&
        !Succeeded) {
      FailedCond = TermAsWritten;
      break;
    }
  }
  if (!FailedCond)
    FailedCond = Cond->IgnoreParenImpCasts();

  std::string Description;
  {
    llvm::raw_string_ostream Out(Description);
    PrintingPolicy Policy = getPrintingPolicy();
    Policy.PrintAsCanonical = true;
    FailedBooleanConditionPrinterHelper Helper(Policy);
    FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
  }
  return { FailedCond, Description };
}

QualType Sema::CheckTemplateIdType(TemplateName Name,
                                   SourceLocation TemplateLoc,
                                   TemplateArgumentListInfo &TemplateArgs) {
  // FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias
  // template substitutions.
  if (DependentTemplateName *DTN =
          Name.getUnderlying().getAsDependentTemplateName();
      DTN && DTN->getName().getIdentifier())
    // When building a template-id where the template-name is dependent,
    // assume the template is a type template. Either our assumption is
    // correct, or the code is ill-formed and will be diagnosed when the
    // dependent name is substituted.
    return Context.getDependentTemplateSpecializationType(
        ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments());

  if (Name.getAsAssumedTemplateName() &&
      resolveAssumedTemplateNameAsType(/*Scope=*/nullptr, Name, TemplateLoc))
    return QualType();

  TemplateDecl *Template;
  DefaultArguments DefaultArgs;
  if (const SubstTemplateTemplateParmPackStorage *S =
          Name.getAsSubstTemplateTemplateParmPack()) {
    Template = S->getParameterPack();
  } else {
    std::tie(Template, DefaultArgs) = Name.getTemplateDeclAndDefaultArgs();
    if (!Template || isa<FunctionTemplateDecl>(Template) ||
        isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
      Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name;
      NoteAllFoundTemplates(Name);
      return QualType();
    }
  }

  // Check that the template argument list is well-formed for this
  // template.
  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
                                DefaultArgs, /*PartialTemplateArgs=*/false,
                                CTAI,
                                /*UpdateArgsWithConversions=*/true))
    return QualType();

  QualType CanonType;

  if (isa<TemplateTemplateParmDecl>(Template)) {
    // We might have a substituted template template parameter pack. If so,
    // build a template specialization type for it.
  } else if (TypeAliasTemplateDecl *AliasTemplate =
                 dyn_cast<TypeAliasTemplateDecl>(Template)) {

    // Find the canonical type for this type alias template specialization.
    TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
    if (Pattern->isInvalidDecl())
      return QualType();

    // Only substitute for the innermost template argument list.
    MultiLevelTemplateArgumentList TemplateArgLists;
    TemplateArgLists.addOuterTemplateArguments(Template, CTAI.SugaredConverted,
                                               /*Final=*/true);
    TemplateArgLists.addOuterRetainedLevels(
        AliasTemplate->getTemplateParameters()->getDepth());

    LocalInstantiationScope Scope(*this);
    InstantiatingTemplate Inst(
        *this, /*PointOfInstantiation=*/TemplateLoc,
        /*Entity=*/AliasTemplate,
        /*TemplateArgs=*/TemplateArgLists.getInnermost());

    // Diagnose uses of this alias.
    (void)DiagnoseUseOfDecl(AliasTemplate, TemplateLoc);

    if (Inst.isInvalid())
      return QualType();

    std::optional<ContextRAII> SavedContext;
    if (!AliasTemplate->getDeclContext()->isFileContext())
      SavedContext.emplace(*this, AliasTemplate->getDeclContext());

    CanonType =
        SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
                  AliasTemplate->getLocation(), AliasTemplate->getDeclName());
    if (CanonType.isNull()) {
      // If this was enable_if and we failed to find the nested type
      // within enable_if in a SFINAE context, dig out the specific
      // enable_if condition that failed and present that instead.
      if (isEnableIfAliasTemplate(AliasTemplate)) {
        if (auto DeductionInfo = isSFINAEContext()) {
          if (*DeductionInfo &&
              (*DeductionInfo)->hasSFINAEDiagnostic() &&
              (*DeductionInfo)->peekSFINAEDiagnostic().second.getDiagID() ==
                diag::err_typename_nested_not_found_enable_if &&
              TemplateArgs[0].getArgument().getKind()
                == TemplateArgument::Expression) {
            Expr *FailedCond;
            std::string FailedDescription;
            std::tie(FailedCond, FailedDescription) =
              findFailedBooleanCondition(TemplateArgs[0].getSourceExpression());

            // Remove the old SFINAE diagnostic.
            PartialDiagnosticAt OldDiag =
              {SourceLocation(), PartialDiagnostic::NullDiagnostic()};
            (*DeductionInfo)->takeSFINAEDiagnostic(OldDiag);

            // Add a new SFINAE diagnostic specifying which condition
            // failed.
            (*DeductionInfo)->addSFINAEDiagnostic(
              OldDiag.first,
              PDiag(diag::err_typename_nested_not_found_requirement)
                << FailedDescription
                << FailedCond->getSourceRange());
          }
        }
      }

      return QualType();
    }
  } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
    CanonType = checkBuiltinTemplateIdType(*this, BTD, CTAI.SugaredConverted,
                                           TemplateLoc, TemplateArgs);
  } else if (Name.isDependent() ||
             TemplateSpecializationType::anyDependentTemplateArguments(
                 TemplateArgs, CTAI.CanonicalConverted)) {
    // This class template specialization is a dependent
    // type. Therefore, its canonical type is another class template
    // specialization type that contains all of the converted
    // arguments in canonical form. This ensures that, e.g., A<T> and
    // A<T, T> have identical types when A is declared as:
    //
    //   template<typename T, typename U = T> struct A;
    CanonType = Context.getCanonicalTemplateSpecializationType(
        Context.getCanonicalTemplateName(Name, /*IgnoreDeduced=*/true),
        CTAI.CanonicalConverted);
    assert(CanonType->isCanonicalUnqualified());

    // This might work out to be a current instantiation, in which
    // case the canonical type needs to be the InjectedClassNameType.
    //
    // TODO: in theory this could be a simple hashtable lookup; most
    // changes to CurContext don't change the set of current
    // instantiations.
    if (isa<ClassTemplateDecl>(Template)) {
      for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
        // If we get out to a namespace, we're done.
        if (Ctx->isFileContext()) break;

        // If this isn't a record, keep looking.
        CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
        if (!Record) continue;

        // Look for one of the two cases with InjectedClassNameTypes
        // and check whether it's the same template.
        if (!isa<ClassTemplatePartialSpecializationDecl>(Record) &&
            !Record->getDescribedClassTemplate())
          continue;

        // Fetch the injected class name type and check whether its
        // injected type is equal to the type we just built.
        QualType ICNT = Context.getTypeDeclType(Record);
        QualType Injected = cast<InjectedClassNameType>(ICNT)
          ->getInjectedSpecializationType();

        if (CanonType != Injected->getCanonicalTypeInternal())
          continue;

        // If so, the canonical type of this TST is the injected
        // class name type of the record we just found.
        assert(ICNT.isCanonical());
        CanonType = ICNT;
        break;
      }
    }
  } else if (ClassTemplateDecl *ClassTemplate =
                 dyn_cast<ClassTemplateDecl>(Template)) {
    // Find the class template specialization declaration that
    // corresponds to these arguments.
    void *InsertPos = nullptr;
    ClassTemplateSpecializationDecl *Decl =
        ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos);
    if (!Decl) {
      // This is the first time we have referenced this class template
      // specialization. Create the canonical declaration and add it to
      // the set of specializations.
      Decl = ClassTemplateSpecializationDecl::Create(
          Context, ClassTemplate->getTemplatedDecl()->getTagKind(),
          ClassTemplate->getDeclContext(),
          ClassTemplate->getTemplatedDecl()->getBeginLoc(),
          ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted,
          CTAI.StrictPackMatch, nullptr);
      ClassTemplate->AddSpecialization(Decl, InsertPos);
      if (ClassTemplate->isOutOfLine())
        Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
    }

    if (Decl->getSpecializationKind() == TSK_Undeclared &&
        ClassTemplate->getTemplatedDecl()->hasAttrs()) {
      InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
      if (!Inst.isInvalid()) {
        MultiLevelTemplateArgumentList TemplateArgLists(Template,
                                                        CTAI.CanonicalConverted,
                                                        /*Final=*/false);
        InstantiateAttrsForDecl(TemplateArgLists,
                                ClassTemplate->getTemplatedDecl(), Decl);
      }
    }

    // Diagnose uses of this specialization.
    (void)DiagnoseUseOfDecl(Decl, TemplateLoc);

    CanonType = Context.getTypeDeclType(Decl);
    assert(isa<RecordType>(CanonType) &&
           "type of non-dependent specialization is not a RecordType");
  } else {
    llvm_unreachable("Unhandled template kind");
  }

  // Build the fully-sugared type for this class template
  // specialization, which refers back to the class template
  // specialization we created or found.
  return Context.getTemplateSpecializationType(
      Name, TemplateArgs.arguments(), CTAI.CanonicalConverted, CanonType);
}

void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
                                           TemplateNameKind &TNK,
                                           SourceLocation NameLoc,
                                           IdentifierInfo *&II) {
  assert(TNK == TNK_Undeclared_template && "not an undeclared template name");

  TemplateName Name = ParsedName.get();
  auto *ATN = Name.getAsAssumedTemplateName();
  assert(ATN && "not an assumed template name");
  II = ATN->getDeclName().getAsIdentifierInfo();

  if (!resolveAssumedTemplateNameAsType(S, Name, NameLoc, /*Diagnose*/false)) {
    // Resolved to a type template name.
    ParsedName = TemplateTy::make(Name);
    TNK = TNK_Type_template;
  }
}

bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
                                            SourceLocation NameLoc,
                                            bool Diagnose) {
  // We assumed this undeclared identifier to be an (ADL-only) function
  // template name, but it was used in a context where a type was required.
  // Try to typo-correct it now.
  AssumedTemplateStorage *ATN = Name.getAsAssumedTemplateName();
  assert(ATN && "not an assumed template name");

  LookupResult R(*this, ATN->getDeclName(), NameLoc, LookupOrdinaryName);
  struct CandidateCallback : CorrectionCandidateCallback {
    bool ValidateCandidate(const TypoCorrection &TC) override {
      return TC.getCorrectionDecl() &&
             getAsTypeTemplateDecl(TC.getCorrectionDecl());
    }
    std::unique_ptr<CorrectionCandidateCallback> clone() override {
      return std::make_unique<CandidateCallback>(*this);
    }
  } FilterCCC;

  TypoCorrection Corrected =
      CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,
                  FilterCCC, CorrectTypoKind::ErrorRecovery);
  if (Corrected && Corrected.getFoundDecl()) {
    diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest)
                                << ATN->getDeclName());
    Name = Context.getQualifiedTemplateName(
        /*NNS=*/nullptr, /*TemplateKeyword=*/false,
        TemplateName(Corrected.getCorrectionDeclAs<TemplateDecl>()));
    return false;
  }

  if (Diagnose)
    Diag(R.getNameLoc(), diag::err_no_template) << R.getLookupName();
  return true;
}

TypeResult Sema::ActOnTemplateIdType(
    Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
    TemplateTy TemplateD, const IdentifierInfo *TemplateII,
    SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
    ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc,
    bool IsCtorOrDtorName, bool IsClassName,
    ImplicitTypenameContext AllowImplicitTypename) {
  if (SS.isInvalid())
    return true;

  if (!IsCtorOrDtorName && !IsClassName && SS.isSet()) {
    DeclContext *LookupCtx = computeDeclContext(SS, /*EnteringContext*/false);

    // C++ [temp.res]p3:
    //   A qualified-id that refers to a type and in which the
    //   nested-name-specifier depends on a template-parameter (14.6.2)
    //   shall be prefixed by the keyword typename to indicate that the
    //   qualified-id denotes a type, forming an
    //   elaborated-type-specifier (7.1.5.3).
    if (!LookupCtx && isDependentScopeSpecifier(SS)) {
      // C++2a relaxes some of those restrictions in [temp.res]p5.
      NestedNameSpecifier *NNS =
          NestedNameSpecifier::Create(Context, SS.getScopeRep(), TemplateII);
      if (AllowImplicitTypename == ImplicitTypenameContext::Yes) {
        auto DB = DiagCompat(SS.getBeginLoc(), diag_compat::implicit_typename)
                  << NNS;
        if (!getLangOpts().CPlusPlus20)
          DB << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename ");
      } else
        Diag(SS.getBeginLoc(), diag::err_typename_missing_template) << NNS;

      // FIXME: This is not quite correct recovery as we don't transform SS
      // into the corresponding dependent form (and we don't diagnose missing
      // 'template' keywords within SS as a result).
      return ActOnTypenameType(nullptr, SourceLocation(), SS, TemplateKWLoc,
                               TemplateD, TemplateII, TemplateIILoc, LAngleLoc,
                               TemplateArgsIn, RAngleLoc);
    }

    // Per C++ [class.qual]p2, if the template-id was an injected-class-name,
    // it's not actually allowed to be used as a type in most cases. Because
    // we annotate it before we know whether it's valid, we have to check for
    // this case here.
    auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
    if (LookupRD && LookupRD->getIdentifier() == TemplateII) {
      Diag(TemplateIILoc,
           TemplateKWLoc.isInvalid()
               ? diag::err_out_of_line_qualified_id_type_names_constructor
               : diag::ext_out_of_line_qualified_id_type_names_constructor)
        << TemplateII << 0 /*injected-class-name used as template name*/
        << 1 /*if any keyword was present, it was 'template'*/;
    }
  }

  TemplateName Template = TemplateD.get();
  if (Template.getAsAssumedTemplateName() &&
      resolveAssumedTemplateNameAsType(S, Template, TemplateIILoc))
    return true;

  // Translate the parser's template argument list in our AST format.
  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
  translateTemplateArguments(TemplateArgsIn, TemplateArgs);

  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
    assert(SS.getScopeRep() == DTN->getQualifier());
    QualType T = Context.getDependentTemplateSpecializationType(
        ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments());
    // Build type-source information.
    TypeLocBuilder TLB;
    DependentTemplateSpecializationTypeLoc SpecTL
      = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
    SpecTL.setElaboratedKeywordLoc(SourceLocation());
    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
    SpecTL.setTemplateNameLoc(TemplateIILoc);
    SpecTL.setLAngleLoc(LAngleLoc);
    SpecTL.setRAngleLoc(RAngleLoc);
    for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
    return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
  }

  QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
  if (SpecTy.isNull())
    return true;

  // Build type-source information.
  TypeLocBuilder TLB;
  TemplateSpecializationTypeLoc SpecTL =
      TLB.push<TemplateSpecializationTypeLoc>(SpecTy);
  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
  SpecTL.setTemplateNameLoc(TemplateIILoc);
  SpecTL.setLAngleLoc(LAngleLoc);
  SpecTL.setRAngleLoc(RAngleLoc);
  for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
    SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());

  // Create an elaborated-type-specifier containing the nested-name-specifier.
  QualType ElTy =
      getElaboratedType(ElaboratedTypeKeyword::None,
                        !IsCtorOrDtorName ? SS : CXXScopeSpec(), SpecTy);
  ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(ElTy);
  ElabTL.setElaboratedKeywordLoc(SourceLocation());
  if (!ElabTL.isEmpty())
    ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
  return CreateParsedType(ElTy, TLB.getTypeSourceInfo(Context, ElTy));
}

TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
                                        TypeSpecifierType TagSpec,
                                        SourceLocation TagLoc,
                                        CXXScopeSpec &SS,
                                        SourceLocation TemplateKWLoc,
                                        TemplateTy TemplateD,
                                        SourceLocation TemplateLoc,
                                        SourceLocation LAngleLoc,
                                        ASTTemplateArgsPtr TemplateArgsIn,
                                        SourceLocation RAngleLoc) {
  if (SS.isInvalid())
    return TypeResult(true);

  TemplateName Template = TemplateD.get();

  // Translate the parser's template argument list in our AST format.
  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
  translateTemplateArguments(TemplateArgsIn, TemplateArgs);

  // Determine the tag kind
  TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
  ElaboratedTypeKeyword Keyword
    = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);

  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
    assert(SS.getScopeRep() == DTN->getQualifier());
    QualType T = Context.getDependentTemplateSpecializationType(
        Keyword, *DTN, TemplateArgs.arguments());

    // Build type-source information.
    TypeLocBuilder TLB;
    DependentTemplateSpecializationTypeLoc SpecTL
      = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
    SpecTL.setElaboratedKeywordLoc(TagLoc);
    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
    SpecTL.setTemplateNameLoc(TemplateLoc);
    SpecTL.setLAngleLoc(LAngleLoc);
    SpecTL.setRAngleLoc(RAngleLoc);
    for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
    return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
  }

  if (TypeAliasTemplateDecl *TAT =
        dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
    // C++0x [dcl.type.elab]p2:
    //   If the identifier resolves to a typedef-name or the simple-template-id
    //   resolves to an alias template specialization, the
    //   elaborated-type-specifier is ill-formed.
    Diag(TemplateLoc, diag::err_tag_reference_non_tag)
        << TAT << NonTagKind::TypeAliasTemplate << TagKind;
    Diag(TAT->getLocation(), diag::note_declared_at);
  }

  QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
  if (Result.isNull())
    return TypeResult(true);

  // Check the tag kind
  if (const RecordType *RT = Result->getAs<RecordType>()) {
    RecordDecl *D = RT->getDecl();

    IdentifierInfo *Id = D->getIdentifier();
    assert(Id && "templated class must have an identifier");

    if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TagUseKind::Definition,
                                      TagLoc, Id)) {
      Diag(TagLoc, diag::err_use_with_wrong_tag)
        << Result
        << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
      Diag(D->getLocation(), diag::note_previous_use);
    }
  }

  // Provide source-location information for the template specialization.
  TypeLocBuilder TLB;
  TemplateSpecializationTypeLoc SpecTL
    = TLB.push<TemplateSpecializationTypeLoc>(Result);
  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
  SpecTL.setTemplateNameLoc(TemplateLoc);
  SpecTL.setLAngleLoc(LAngleLoc);
  SpecTL.setRAngleLoc(RAngleLoc);
  for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
    SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());

  // Construct an elaborated type containing the nested-name-specifier (if any)
  // and tag keyword.
  Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
  ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
  ElabTL.setElaboratedKeywordLoc(TagLoc);
  ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
  return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}

static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
                                             NamedDecl *PrevDecl,
                                             SourceLocation Loc,
                                             bool IsPartialSpecialization);

static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);

static bool isTemplateArgumentTemplateParameter(
    const TemplateArgument &Arg, unsigned Depth, unsigned Index) {
  switch (Arg.getKind()) {
  case TemplateArgument::Null:
  case TemplateArgument::NullPtr:
  case TemplateArgument::Integral:
  case TemplateArgument::Declaration:
  case TemplateArgument::StructuralValue:
  case TemplateArgument::Pack:
  case TemplateArgument::TemplateExpansion:
    return false;

  case TemplateArgument::Type: {
    QualType Type = Arg.getAsType();
    const TemplateTypeParmType *TPT =
        Arg.getAsType()->getAs<TemplateTypeParmType>();
    return TPT && !Type.hasQualifiers() &&
           TPT->getDepth() == Depth && TPT->getIndex() == Index;
  }

  case TemplateArgument::Expression: {
    DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg.getAsExpr());
    if (!DRE || !DRE->getDecl())
      return false;
    const NonTypeTemplateParmDecl *NTTP =
        dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
    return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index;
  }

  case TemplateArgument::Template:
    const TemplateTemplateParmDecl *TTP =
        dyn_cast_or_null<TemplateTemplateParmDecl>(
            Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl());
    return TTP && TTP->getDepth() == Depth && TTP->getIndex() == Index;
  }
  llvm_unreachable("unexpected kind of template argument");
}

static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
                                    ArrayRef<TemplateArgument> Args) {
  if (Params->size() != Args.size())
    return false;

  unsigned Depth = Params->getDepth();

  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
    TemplateArgument Arg = Args[I];

    // If the parameter is a pack expansion, the argument must be a pack
    // whose only element is a pack expansion.
    if (Params->getParam(I)->isParameterPack()) {
      if (Arg.getKind() != TemplateArgument::Pack || Arg.pack_size() != 1 ||
          !Arg.pack_begin()->isPackExpansion())
        return false;
      Arg = Arg.pack_begin()->getPackExpansionPattern();
    }

    if (!isTemplateArgumentTemplateParameter(Arg, Depth, I))
      return false;
  }

  return true;
}

template<typename PartialSpecDecl>
static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
  if (Partial->getDeclContext()->isDependentContext())
    return;

  // FIXME: Get the TDK from deduction in order to provide better diagnostics
  // for non-substitution-failure issues?
  TemplateDeductionInfo Info(Partial->getLocation());
  if (S.isMoreSpecializedThanPrimary(Partial, Info))
    return;

  auto *Template = Partial->getSpecializedTemplate();
  S.Diag(Partial->getLocation(),
         diag::ext_partial_spec_not_more_specialized_than_primary)
      << isa<VarTemplateDecl>(Template);

  if (Info.hasSFINAEDiagnostic()) {
    PartialDiagnosticAt Diag = {SourceLocation(),
                                PartialDiagnostic::NullDiagnostic()};
    Info.takeSFINAEDiagnostic(Diag);
    SmallString<128> SFINAEArgString;
    Diag.second.EmitToString(S.getDiagnostics(), SFINAEArgString);
    S.Diag(Diag.first,
           diag::note_partial_spec_not_more_specialized_than_primary)
      << SFINAEArgString;
  }

  S.NoteTemplateLocation(*Template);
  SmallVector<AssociatedConstraint, 3> PartialAC, TemplateAC;
  Template->getAssociatedConstraints(TemplateAC);
  Partial->getAssociatedConstraints(PartialAC);
  S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
                                                  TemplateAC);
}

static void
noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams,
                           const llvm::SmallBitVector &DeducibleParams) {
  for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
    if (!DeducibleParams[I]) {
      NamedDecl *Param = TemplateParams->getParam(I);
      if (Param->getDeclName())
        S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
            << Param->getDeclName();
      else
        S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
            << "(anonymous)";
    }
  }
}


template<typename PartialSpecDecl>
static void checkTemplatePartialSpecialization(Sema &S,
                                               PartialSpecDecl *Partial) {
  // C++1z [temp.class.spec]p8: (DR1495)
  //   - The specialization shall be more specialized than the primary
  //     template (14.5.5.2).
  checkMoreSpecializedThanPrimary(S, Partial);

  // C++ [temp.class.spec]p8: (DR1315)
  //   - Each template-parameter shall appear at least once in the
  //     template-id outside a non-deduced context.
  // C++1z [temp.class.spec.match]p3 (P0127R2)
  //   If the template arguments of a partial specialization cannot be
  //   deduced because of the structure of its template-parameter-list
  //   and the template-id, the program is ill-formed.
  auto *TemplateParams = Partial->getTemplateParameters();
  llvm::SmallBitVector DeducibleParams(TemplateParams->size());
  S.MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
                               TemplateParams->getDepth(), DeducibleParams);

  if (!DeducibleParams.all()) {
    unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
    S.Diag(Partial->getLocation(), diag::ext_partial_specs_not_deducible)
      << isa<VarTemplatePartialSpecializationDecl>(Partial)
      << (NumNonDeducible > 1)
      << SourceRange(Partial->getLocation(),
                     Partial->getTemplateArgsAsWritten()->RAngleLoc);
    noteNonDeducibleParameters(S, TemplateParams, DeducibleParams);
  }
}

void Sema::CheckTemplatePartialSpecialization(
    ClassTemplatePartialSpecializationDecl *Partial) {
  checkTemplatePartialSpecialization(*this, Partial);
}

void Sema::CheckTemplatePartialSpecialization(
    VarTemplatePartialSpecializationDecl *Partial) {
  checkTemplatePartialSpecialization(*this, Partial);
}

void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
  // C++1z [temp.param]p11:
  //   A template parameter of a deduction guide template that does not have a
  //   default-argument shall be deducible from the parameter-type-list of the
  //   deduction guide template.
  auto *TemplateParams = TD->getTemplateParameters();
  llvm::SmallBitVector DeducibleParams(TemplateParams->size());
  MarkDeducedTemplateParameters(TD, DeducibleParams);
  for (unsigned I = 0; I != TemplateParams->size(); ++I) {
    // A parameter pack is deducible (to an empty pack).
    auto *Param = TemplateParams->getParam(I);
    if (Param->isParameterPack() || hasVisibleDefaultArgument(Param))
      DeducibleParams[I] = true;
  }

  if (!DeducibleParams.all()) {
    unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
    Diag(TD->getLocation(), diag::err_deduction_guide_template_not_deducible)
      << (NumNonDeducible > 1);
    noteNonDeducibleParameters(*this, TemplateParams, DeducibleParams);
  }
}

DeclResult Sema::ActOnVarTemplateSpecialization(
    Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
    SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
    StorageClass SC, bool IsPartialSpecialization) {
  // D must be variable template id.
  assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
         "Variable template specialization is declared with a template id.");

  TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
  TemplateArgumentListInfo TemplateArgs =
      makeTemplateArgumentListInfo(*this, *TemplateId);
  SourceLocation TemplateNameLoc = D.getIdentifierLoc();
  SourceLocation LAngleLoc = TemplateId->LAngleLoc;
  SourceLocation RAngleLoc = TemplateId->RAngleLoc;

  TemplateName Name = TemplateId->Template.get();

  // The template-id must name a variable template.
  VarTemplateDecl *VarTemplate =
      dyn_cast_or_null<VarTemplateDecl>(Name.getAsTemplateDecl());
  if (!VarTemplate) {
    NamedDecl *FnTemplate;
    if (auto *OTS = Name.getAsOverloadedTemplate())
      FnTemplate = *OTS->begin();
    else
      FnTemplate = dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
    if (FnTemplate)
      return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template_but_method)
               << FnTemplate->getDeclName();
    return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
             << IsPartialSpecialization;
  }

  if (const auto *DSA = VarTemplate->getAttr<NoSpecializationsAttr>()) {
    auto Message = DSA->getMessage();
    Diag(TemplateNameLoc, diag::warn_invalid_specialization)
        << VarTemplate << !Message.empty() << Message;
    Diag(DSA->getLoc(), diag::note_marked_here) << DSA;
  }

  // Check for unexpanded parameter packs in any of the template arguments.
  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
    if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
                                        IsPartialSpecialization
                                            ? UPPC_PartialSpecialization
                                            : UPPC_ExplicitSpecialization))
      return true;

  // Check that the template argument list is well-formed for this
  // template.
  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
                                /*DefaultArgs=*/{},
                                /*PartialTemplateArgs=*/false, CTAI,
                                /*UpdateArgsWithConversions=*/true))
    return true;

  // Find the variable template (partial) specialization declaration that
  // corresponds to these arguments.
  if (IsPartialSpecialization) {
    if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate,
                                               TemplateArgs.size(),
                                               CTAI.CanonicalConverted))
      return true;

    // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so
    // we also do them during instantiation.
    if (!Name.isDependent() &&
        !TemplateSpecializationType::anyDependentTemplateArguments(
            TemplateArgs, CTAI.CanonicalConverted)) {
      Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
          << VarTemplate->getDeclName();
      IsPartialSpecialization = false;
    }

    if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
                                CTAI.CanonicalConverted) &&
        (!Context.getLangOpts().CPlusPlus20 ||
         !TemplateParams->hasAssociatedConstraints())) {
      // C++ [temp.class.spec]p9b3:
      //
      //   -- The argument list of the specialization shall not be identical
      //      to the implicit argument list of the primary template.
      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
          << /*variable template*/ 1
          << /*is definition*/ (SC != SC_Extern && !CurContext->isRecord())
          << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
      // FIXME: Recover from this by treating the declaration as a
      // redeclaration of the primary template.
      return true;
    }
  }

  void *InsertPos = nullptr;
  VarTemplateSpecializationDecl *PrevDecl = nullptr;

  if (IsPartialSpecialization)
    PrevDecl = VarTemplate->findPartialSpecialization(
        CTAI.CanonicalConverted, TemplateParams, InsertPos);
  else
    PrevDecl =
        VarTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos);

  VarTemplateSpecializationDecl *Specialization = nullptr;

  // Check whether we can declare a variable template specialization in
  // the current scope.
  if (CheckTemplateSpecializationScope(*this, VarTemplate, PrevDecl,
                                       TemplateNameLoc,
                                       IsPartialSpecialization))
    return true;

  if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
    // Since the only prior variable template specialization with these
    // arguments was referenced but not declared,  reuse that
    // declaration node as our own, updating its source location and
    // the list of outer template parameters to reflect our new declaration.
    Specialization = PrevDecl;
    Specialization->setLocation(TemplateNameLoc);
    PrevDecl = nullptr;
  } else if (IsPartialSpecialization) {
    // Create a new class template partial specialization declaration node.
    VarTemplatePartialSpecializationDecl *PrevPartial =
        cast_or_null<VarTemplatePartialSpecializationDecl>(PrevDecl);
    VarTemplatePartialSpecializationDecl *Partial =
        VarTemplatePartialSpecializationDecl::Create(
            Context, VarTemplate->getDeclContext(), TemplateKWLoc,
            TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
            CTAI.CanonicalConverted);
    Partial->setTemplateArgsAsWritten(TemplateArgs);

    if (!PrevPartial)
      VarTemplate->AddPartialSpecialization(Partial, InsertPos);
    Specialization = Partial;

    // If we are providing an explicit specialization of a member variable
    // template specialization, make a note of that.
    if (PrevPartial && PrevPartial->getInstantiatedFromMember())
      PrevPartial->setMemberSpecialization();

    CheckTemplatePartialSpecialization(Partial);
  } else {
    // Create a new class template specialization declaration node for
    // this explicit specialization or friend declaration.
    Specialization = VarTemplateSpecializationDecl::Create(
        Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
        VarTemplate, DI->getType(), DI, SC, CTAI.CanonicalConverted);
    Specialization->setTemplateArgsAsWritten(TemplateArgs);

    if (!PrevDecl)
      VarTemplate->AddSpecialization(Specialization, InsertPos);
  }

  // C++ [temp.expl.spec]p6:
  //   If a template, a member template or the member of a class template is
  //   explicitly specialized then that specialization shall be declared
  //   before the first use of that specialization that would cause an implicit
  //   instantiation to take place, in every translation unit in which such a
  //   use occurs; no diagnostic is required.
  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
    bool Okay = false;
    for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
      // Is there any previous explicit specialization declaration?
      if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
        Okay = true;
        break;
      }
    }

    if (!Okay) {
      SourceRange Range(TemplateNameLoc, RAngleLoc);
      Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
          << Name << Range;

      Diag(PrevDecl->getPointOfInstantiation(),
           diag::note_instantiation_required_here)
          << (PrevDecl->getTemplateSpecializationKind() !=
              TSK_ImplicitInstantiation);
      return true;
    }
  }

  Specialization->setLexicalDeclContext(CurContext);

  // Add the specialization into its lexical context, so that it can
  // be seen when iterating through the list of declarations in that
  // context. However, specializations are not found by name lookup.
  CurContext->addDecl(Specialization);

  // Note that this is an explicit specialization.
  Specialization->setSpecializationKind(TSK_ExplicitSpecialization);

  Previous.clear();
  if (PrevDecl)
    Previous.addDecl(PrevDecl);
  else if (Specialization->isStaticDataMember() &&
           Specialization->isOutOfLine())
    Specialization->setAccess(VarTemplate->getAccess());

  return Specialization;
}

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

DeclResult
Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
                         SourceLocation TemplateNameLoc,
                         const TemplateArgumentListInfo &TemplateArgs) {
  assert(Template && "A variable template id without template?");

  // Check that the template argument list is well-formed for this template.
  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(
          Template, TemplateNameLoc,
          const_cast<TemplateArgumentListInfo &>(TemplateArgs),
          /*DefaultArgs=*/{}, /*PartialTemplateArgs=*/false, CTAI,
          /*UpdateArgsWithConversions=*/true))
    return true;

  // Produce a placeholder value if the specialization is dependent.
  if (Template->getDeclContext()->isDependentContext() ||
      TemplateSpecializationType::anyDependentTemplateArguments(
          TemplateArgs, CTAI.CanonicalConverted)) {
    if (ParsingInitForAutoVars.empty())
      return DeclResult();

    auto IsSameTemplateArg = [&](const TemplateArgument &Arg1,
                                 const TemplateArgument &Arg2) {
      return Context.isSameTemplateArgument(Arg1, Arg2);
    };

    if (VarDecl *Var = Template->getTemplatedDecl();
        ParsingInitForAutoVars.count(Var) &&
        llvm::equal(
            CTAI.CanonicalConverted,
            Template->getTemplateParameters()->getInjectedTemplateArgs(Context),
            IsSameTemplateArg)) {
      Diag(TemplateNameLoc,
           diag::err_auto_variable_cannot_appear_in_own_initializer)
          << diag::ParsingInitFor::VarTemplate << Var << Var->getType();
      return true;
    }

    SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
    Template->getPartialSpecializations(PartialSpecs);
    for (VarTemplatePartialSpecializationDecl *Partial : PartialSpecs)
      if (ParsingInitForAutoVars.count(Partial) &&
          llvm::equal(CTAI.CanonicalConverted,
                      Partial->getTemplateArgs().asArray(),
                      IsSameTemplateArg)) {
        Diag(TemplateNameLoc,
             diag::err_auto_variable_cannot_appear_in_own_initializer)
            << diag::ParsingInitFor::VarTemplatePartialSpec << Partial
            << Partial->getType();
        return true;
      }

    return DeclResult();
  }

  // Find the variable template specialization declaration that
  // corresponds to these arguments.
  void *InsertPos = nullptr;
  if (VarTemplateSpecializationDecl *Spec =
          Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) {
    checkSpecializationReachability(TemplateNameLoc, Spec);
    if (Spec->getType()->isUndeducedType()) {
      if (ParsingInitForAutoVars.count(Spec))
        Diag(TemplateNameLoc,
             diag::err_auto_variable_cannot_appear_in_own_initializer)
            << diag::ParsingInitFor::VarTemplateExplicitSpec << Spec
            << Spec->getType();
      else
        // We are substituting the initializer of this variable template
        // specialization.
        Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self)
            << Spec << Spec->getType();

      return true;
    }
    // If we already have a variable template specialization, return it.
    return Spec;
  }

  // This is the first time we have referenced this variable template
  // specialization. Create the canonical declaration and add it to
  // the set of specializations, based on the closest partial specialization
  // that it represents. That is,
  VarDecl *InstantiationPattern = Template->getTemplatedDecl();
  const TemplateArgumentList *PartialSpecArgs = nullptr;
  bool AmbiguousPartialSpec = false;
  typedef PartialSpecMatchResult MatchResult;
  SmallVector<MatchResult, 4> Matched;
  SourceLocation PointOfInstantiation = TemplateNameLoc;
  TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation,
                                            /*ForTakingAddress=*/false);

  // 1. Attempt to find the closest partial specialization that this
  // specializes, if any.
  // TODO: Unify with InstantiateClassTemplateSpecialization()?
  //       Perhaps better after unification of DeduceTemplateArguments() and
  //       getMoreSpecializedPartialSpecialization().
  SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
  Template->getPartialSpecializations(PartialSpecs);

  for (VarTemplatePartialSpecializationDecl *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 =
            DeduceTemplateArguments(Partial, CTAI.SugaredConverted, 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(Context, Result, Info));
      (void)Result;
    } else {
      Matched.push_back(PartialSpecMatchResult());
      Matched.back().Partial = Partial;
      Matched.back().Args = Info.takeSugared();
    }
  }

  if (Matched.size() >= 1) {
    SmallVector<MatchResult, 4>::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 variable template is
      //      ambiguous and the program is ill-formed.
      for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
                                                 PEnd = Matched.end();
           P != PEnd; ++P) {
        if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
                                                    PointOfInstantiation) ==
            P->Partial)
          Best = P;
      }

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

    // Instantiate using the best variable template partial specialization.
    InstantiationPattern = Best->Partial;
    PartialSpecArgs = Best->Args;
  } else {
    //   -- If no match is found, the instantiation is generated
    //      from the primary template.
    // InstantiationPattern = Template->getTemplatedDecl();
  }

  // 2. Create the canonical declaration.
  // Note that we do not instantiate a definition until we see an odr-use
  // in DoMarkVarDeclReferenced().
  // FIXME: LateAttrs et al.?
  VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
      Template, InstantiationPattern, PartialSpecArgs, TemplateArgs,
      CTAI.CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
  if (!Decl)
    return true;

  if (AmbiguousPartialSpec) {
    // Partial ordering did not produce a clear winner. Complain.
    Decl->setInvalidDecl();
    Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
        << Decl;

    // Print the matching partial specializations.
    for (MatchResult P : Matched)
      Diag(P.Partial->getLocation(), diag::note_partial_spec_match)
          << getTemplateArgumentBindingsText(P.Partial->getTemplateParameters(),
                                             *P.Args);
    return true;
  }

  if (VarTemplatePartialSpecializationDecl *D =
          dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
    Decl->setInstantiationOf(D, PartialSpecArgs);

  checkSpecializationReachability(TemplateNameLoc, Decl);

  assert(Decl && "No variable template specialization?");
  return Decl;
}

ExprResult Sema::CheckVarTemplateId(
    const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
    VarTemplateDecl *Template, NamedDecl *FoundD, SourceLocation TemplateLoc,
    const TemplateArgumentListInfo *TemplateArgs) {

  DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
                                       *TemplateArgs);
  if (Decl.isInvalid())
    return ExprError();

  if (!Decl.get())
    return ExprResult();

  VarDecl *Var = cast<VarDecl>(Decl.get());
  if (!Var->getTemplateSpecializationKind())
    Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
                                       NameInfo.getLoc());

  // Build an ordinary singleton decl ref.
  return BuildDeclarationNameExpr(SS, NameInfo, Var, FoundD, TemplateArgs);
}

void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
                                            SourceLocation Loc) {
  Diag(Loc, diag::err_template_missing_args)
    << (int)getTemplateNameKindForDiagnostics(Name) << Name;
  if (TemplateDecl *TD = Name.getAsTemplateDecl()) {
    NoteTemplateLocation(*TD, TD->getTemplateParameters()->getSourceRange());
  }
}

void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
                                            bool TemplateKeyword,
                                            TemplateDecl *TD,
                                            SourceLocation Loc) {
  TemplateName Name = Context.getQualifiedTemplateName(
      SS.getScopeRep(), TemplateKeyword, TemplateName(TD));
  diagnoseMissingTemplateArguments(Name, Loc);
}

ExprResult
Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
                             SourceLocation TemplateKWLoc,
                             const DeclarationNameInfo &ConceptNameInfo,
                             NamedDecl *FoundDecl,
                             ConceptDecl *NamedConcept,
                             const TemplateArgumentListInfo *TemplateArgs) {
  assert(NamedConcept && "A concept template id without a template?");

  if (NamedConcept->isInvalidDecl())
    return ExprError();

  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(
          NamedConcept, ConceptNameInfo.getLoc(),
          const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
          /*DefaultArgs=*/{},
          /*PartialTemplateArgs=*/false, CTAI,
          /*UpdateArgsWithConversions=*/false))
    return ExprError();

  DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());

  auto *CSD = ImplicitConceptSpecializationDecl::Create(
      Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
      CTAI.CanonicalConverted);
  ConstraintSatisfaction Satisfaction;
  bool AreArgsDependent =
      TemplateSpecializationType::anyDependentTemplateArguments(
          *TemplateArgs, CTAI.CanonicalConverted);
  MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.CanonicalConverted,
                                       /*Final=*/false);
  LocalInstantiationScope Scope(*this);

  EnterExpressionEvaluationContext EECtx{
      *this, ExpressionEvaluationContext::Unevaluated, CSD};

  if (!AreArgsDependent &&
      CheckConstraintSatisfaction(
          NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()),
          MLTAL,
          SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
                      TemplateArgs->getRAngleLoc()),
          Satisfaction))
    return ExprError();
  auto *CL = ConceptReference::Create(
      Context,
      SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
      TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
      ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
  return ConceptSpecializationExpr::Create(
      Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
}

ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
                                     SourceLocation TemplateKWLoc,
                                     LookupResult &R,
                                     bool RequiresADL,
                                 const TemplateArgumentListInfo *TemplateArgs) {
  // FIXME: Can we do any checking at this point? I guess we could check the
  // template arguments that we have against the template name, if the template
  // name refers to a single template. That's not a terribly common case,
  // though.
  // foo<int> could identify a single function unambiguously
  // This approach does NOT work, since f<int>(1);
  // gets resolved prior to resorting to overload resolution
  // i.e., template<class T> void f(double);
  //       vs template<class T, class U> void f(U);

  // These should be filtered out by our callers.
  assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");

  // Non-function templates require a template argument list.
  if (auto *TD = R.getAsSingle<TemplateDecl>()) {
    if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) {
      diagnoseMissingTemplateArguments(
          SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), TD, R.getNameLoc());
      return ExprError();
    }
  }
  bool KnownDependent = false;
  // In C++1y, check variable template ids.
  if (R.getAsSingle<VarTemplateDecl>()) {
    ExprResult Res = CheckVarTemplateId(
        SS, R.getLookupNameInfo(), R.getAsSingle<VarTemplateDecl>(),
        R.getRepresentativeDecl(), TemplateKWLoc, TemplateArgs);
    if (Res.isInvalid() || Res.isUsable())
      return Res;
    // Result is dependent. Carry on to build an UnresolvedLookupExpr.
    KnownDependent = true;
  }

  if (R.getAsSingle<ConceptDecl>()) {
    return CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
                                  R.getRepresentativeDecl(),
                                  R.getAsSingle<ConceptDecl>(), TemplateArgs);
  }

  // We don't want lookup warnings at this point.
  R.suppressDiagnostics();

  UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
      Context, R.getNamingClass(), SS.getWithLocInContext(Context),
      TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs,
      R.begin(), R.end(), KnownDependent,
      /*KnownInstantiationDependent=*/false);

  // Model the templates with UnresolvedTemplateTy. The expression should then
  // either be transformed in an instantiation or be diagnosed in
  // CheckPlaceholderExpr.
  if (ULE->getType() == Context.OverloadTy && R.isSingleResult() &&
      !R.getFoundDecl()->getAsFunction())
    ULE->setType(Context.UnresolvedTemplateTy);

  return ULE;
}

ExprResult Sema::BuildQualifiedTemplateIdExpr(
    CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
    const DeclarationNameInfo &NameInfo,
    const TemplateArgumentListInfo *TemplateArgs, bool IsAddressOfOperand) {
  assert(TemplateArgs || TemplateKWLoc.isValid());

  LookupResult R(*this, NameInfo, LookupOrdinaryName);
  if (LookupTemplateName(R, /*S=*/nullptr, SS, /*ObjectType=*/QualType(),
                         /*EnteringContext=*/false, TemplateKWLoc))
    return ExprError();

  if (R.isAmbiguous())
    return ExprError();

  if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid())
    return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);

  if (R.empty()) {
    DeclContext *DC = computeDeclContext(SS);
    Diag(NameInfo.getLoc(), diag::err_no_member)
      << NameInfo.getName() << DC << SS.getRange();
    return ExprError();
  }

  // If necessary, build an implicit class member access.
  if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand))
    return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs,
                                           /*S=*/nullptr);

  return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL=*/false, TemplateArgs);
}

TemplateNameKind Sema::ActOnTemplateName(Scope *S,
                                         CXXScopeSpec &SS,
                                         SourceLocation TemplateKWLoc,
                                         const UnqualifiedId &Name,
                                         ParsedType ObjectType,
                                         bool EnteringContext,
                                         TemplateTy &Result,
                                         bool AllowInjectedClassName) {
  if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
    Diag(TemplateKWLoc,
         getLangOpts().CPlusPlus11 ?
           diag::warn_cxx98_compat_template_outside_of_template :
           diag::ext_template_outside_of_template)
      << FixItHint::CreateRemoval(TemplateKWLoc);

  if (SS.isInvalid())
    return TNK_Non_template;

  // Figure out where isTemplateName is going to look.
  DeclContext *LookupCtx = nullptr;
  if (SS.isNotEmpty())
    LookupCtx = computeDeclContext(SS, EnteringContext);
  else if (ObjectType)
    LookupCtx = computeDeclContext(GetTypeFromParser(ObjectType));

  // C++0x [temp.names]p5:
  //   If a name prefixed by the keyword template is not the name of
  //   a template, the program is ill-formed. [Note: the keyword
  //   template may not be applied to non-template members of class
  //   templates. -end note ] [ Note: as is the case with the
  //   typename prefix, the template prefix is allowed in cases
  //   where it is not strictly necessary; i.e., when the
  //   nested-name-specifier or the expression on the left of the ->
  //   or . is not dependent on a template-parameter, or the use
  //   does not appear in the scope of a template. -end note]
  //
  // Note: C++03 was more strict here, because it banned the use of
  // the "template" keyword prior to a template-name that was not a
  // dependent name. C++ DR468 relaxed this requirement (the
  // "template" keyword is now permitted). We follow the C++0x
  // rules, even in C++03 mode with a warning, retroactively applying the DR.
  bool MemberOfUnknownSpecialization;
  TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
                                        ObjectType, EnteringContext, Result,
                                        MemberOfUnknownSpecialization);
  if (TNK != TNK_Non_template) {
    // We resolved this to a (non-dependent) template name. Return it.
    auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
    if (!AllowInjectedClassName && SS.isNotEmpty() && LookupRD &&
        Name.getKind() == UnqualifiedIdKind::IK_Identifier &&
        Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) {
      // C++14 [class.qual]p2:
      //   In a lookup in which function names are not ignored and the
      //   nested-name-specifier nominates a class C, if the name specified
      //   [...] is the injected-class-name of C, [...] the name is instead
      //   considered to name the constructor
      //
      // We don't get here if naming the constructor would be valid, so we
      // just reject immediately and recover by treating the
      // injected-class-name as naming the template.
      Diag(Name.getBeginLoc(),
           diag::ext_out_of_line_qualified_id_type_names_constructor)
          << Name.Identifier
          << 0 /*injected-class-name used as template name*/
          << TemplateKWLoc.isValid();
    }
    return TNK;
  }

  if (!MemberOfUnknownSpecialization) {
    // Didn't find a template name, and the lookup wasn't dependent.
    // Do the lookup again to determine if this is a "nothing found" case or
    // a "not a template" case. FIXME: Refactor isTemplateName so we don't
    // need to do this.
    DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name);
    LookupResult R(*this, DNI.getName(), Name.getBeginLoc(),
                   LookupOrdinaryName);
    // Tell LookupTemplateName that we require a template so that it diagnoses
    // cases where it finds a non-template.
    RequiredTemplateKind RTK = TemplateKWLoc.isValid()
                                   ? RequiredTemplateKind(TemplateKWLoc)
                                   : TemplateNameIsRequired;
    if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, RTK,
                            /*ATK=*/nullptr, /*AllowTypoCorrection=*/false) &&
        !R.isAmbiguous()) {
      if (LookupCtx)
        Diag(Name.getBeginLoc(), diag::err_no_member)
            << DNI.getName() << LookupCtx << SS.getRange();
      else
        Diag(Name.getBeginLoc(), diag::err_undeclared_use)
            << DNI.getName() << SS.getRange();
    }
    return TNK_Non_template;
  }

  NestedNameSpecifier *Qualifier = SS.getScopeRep();

  switch (Name.getKind()) {
  case UnqualifiedIdKind::IK_Identifier:
    Result = TemplateTy::make(Context.getDependentTemplateName(
        {Qualifier, Name.Identifier, TemplateKWLoc.isValid()}));
    return TNK_Dependent_template_name;

  case UnqualifiedIdKind::IK_OperatorFunctionId:
    Result = TemplateTy::make(Context.getDependentTemplateName(
        {Qualifier, Name.OperatorFunctionId.Operator,
         TemplateKWLoc.isValid()}));
    return TNK_Function_template;

  case UnqualifiedIdKind::IK_LiteralOperatorId:
    // This is a kind of template name, but can never occur in a dependent
    // scope (literal operators can only be declared at namespace scope).
    break;

  default:
    break;
  }

  // This name cannot possibly name a dependent template. Diagnose this now
  // rather than building a dependent template name that can never be valid.
  Diag(Name.getBeginLoc(),
       diag::err_template_kw_refers_to_dependent_non_template)
      << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange()
      << TemplateKWLoc.isValid() << TemplateKWLoc;
  return TNK_Non_template;
}

bool Sema::CheckTemplateTypeArgument(
    TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL,
    SmallVectorImpl<TemplateArgument> &SugaredConverted,
    SmallVectorImpl<TemplateArgument> &CanonicalConverted) {
  const TemplateArgument &Arg = AL.getArgument();
  QualType ArgType;
  TypeSourceInfo *TSI = nullptr;

  // Check template type parameter.
  switch(Arg.getKind()) {
  case TemplateArgument::Type:
    // C++ [temp.arg.type]p1:
    //   A template-argument for a template-parameter which is a
    //   type shall be a type-id.
    ArgType = Arg.getAsType();
    TSI = AL.getTypeSourceInfo();
    break;
  case TemplateArgument::Template:
  case TemplateArgument::TemplateExpansion: {
    // We have a template type parameter but the template argument
    // is a template without any arguments.
    SourceRange SR = AL.getSourceRange();
    TemplateName Name = Arg.getAsTemplateOrTemplatePattern();
    diagnoseMissingTemplateArguments(Name, SR.getEnd());
    return true;
  }
  case TemplateArgument::Expression: {
    // We have a template type parameter but the template argument is an
    // expression; see if maybe it is missing the "typename" keyword.
    CXXScopeSpec SS;
    DeclarationNameInfo NameInfo;

   if (DependentScopeDeclRefExpr *ArgExpr =
               dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) {
      SS.Adopt(ArgExpr->getQualifierLoc());
      NameInfo = ArgExpr->getNameInfo();
    } else if (CXXDependentScopeMemberExpr *ArgExpr =
               dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) {
      if (ArgExpr->isImplicitAccess()) {
        SS.Adopt(ArgExpr->getQualifierLoc());
        NameInfo = ArgExpr->getMemberNameInfo();
      }
    }

    if (auto *II = NameInfo.getName().getAsIdentifierInfo()) {
      LookupResult Result(*this, NameInfo, LookupOrdinaryName);
      LookupParsedName(Result, CurScope, &SS, /*ObjectType=*/QualType());

      if (Result.getAsSingle<TypeDecl>() ||
          Result.wasNotFoundInCurrentInstantiation()) {
        assert(SS.getScopeRep() && "dependent scope expr must has a scope!");
        // Suggest that the user add 'typename' before the NNS.
        SourceLocation Loc = AL.getSourceRange().getBegin();
        Diag(Loc, getLangOpts().MSVCCompat
                      ? diag::ext_ms_template_type_arg_missing_typename
                      : diag::err_template_arg_must_be_type_suggest)
            << FixItHint::CreateInsertion(Loc, "typename ");
        NoteTemplateParameterLocation(*Param);

        // Recover by synthesizing a type using the location information that we
        // already have.
        ArgType = Context.getDependentNameType(ElaboratedTypeKeyword::None,
                                               SS.getScopeRep(), II);
        TypeLocBuilder TLB;
        DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(ArgType);
        TL.setElaboratedKeywordLoc(SourceLocation(/*synthesized*/));
        TL.setQualifierLoc(SS.getWithLocInContext(Context));
        TL.setNameLoc(NameInfo.getLoc());
        TSI = TLB.getTypeSourceInfo(Context, ArgType);

        // Overwrite our input TemplateArgumentLoc so that we can recover
        // properly.
        AL = TemplateArgumentLoc(TemplateArgument(ArgType),
                                 TemplateArgumentLocInfo(TSI));

        break;
      }
    }
    // fallthrough
    [[fallthrough]];
  }
  default: {
    // We allow instantiating a template with template argument packs when
    // building deduction guides.
    if (Arg.getKind() == TemplateArgument::Pack &&
        CodeSynthesisContexts.back().Kind ==
            Sema::CodeSynthesisContext::BuildingDeductionGuides) {
      SugaredConverted.push_back(Arg);
      CanonicalConverted.push_back(Arg);
      return false;
    }
    // We have a template type parameter but the template argument
    // is not a type.
    SourceRange SR = AL.getSourceRange();
    Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
    NoteTemplateParameterLocation(*Param);

    return true;
  }
  }

  if (CheckTemplateArgument(TSI))
    return true;

  // Objective-C ARC:
  //   If an explicitly-specified template argument type is a lifetime type
  //   with no lifetime qualifier, the __strong lifetime qualifier is inferred.
  if (getLangOpts().ObjCAutoRefCount &&
      ArgType->isObjCLifetimeType() &&
      !ArgType.getObjCLifetime()) {
    Qualifiers Qs;
    Qs.setObjCLifetime(Qualifiers::OCL_Strong);
    ArgType = Context.getQualifiedType(ArgType, Qs);
  }

  SugaredConverted.push_back(TemplateArgument(ArgType));
  CanonicalConverted.push_back(
      TemplateArgument(Context.getCanonicalType(ArgType)));
  return false;
}

/// Substitute template arguments into the default template argument for
/// the given template type parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the template template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
/// \param Output the resulting substituted template argument.
///
/// \returns true if an error occurred.
static bool SubstDefaultTemplateArgument(
    Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
    SourceLocation RAngleLoc, TemplateTypeParmDecl *Param,
    ArrayRef<TemplateArgument> SugaredConverted,
    ArrayRef<TemplateArgument> CanonicalConverted,
    TemplateArgumentLoc &Output) {
  Output = Param->getDefaultArgument();

  // If the argument type is dependent, instantiate it now based
  // on the previously-computed template arguments.
  if (Output.getArgument().isInstantiationDependent()) {
    Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template,
                                     SugaredConverted,
                                     SourceRange(TemplateLoc, RAngleLoc));
    if (Inst.isInvalid())
      return true;

    // Only substitute for the innermost template argument list.
    MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted,
                                                    /*Final=*/true);
    for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
      TemplateArgLists.addOuterTemplateArguments(std::nullopt);

    bool ForLambdaCallOperator = false;
    if (const auto *Rec = dyn_cast<CXXRecordDecl>(Template->getDeclContext()))
      ForLambdaCallOperator = Rec->isLambda();
    Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(),
                                   !ForLambdaCallOperator);

    if (SemaRef.SubstTemplateArgument(Output, TemplateArgLists, Output,
                                      Param->getDefaultArgumentLoc(),
                                      Param->getDeclName()))
      return true;
  }

  return false;
}

/// Substitute template arguments into the default template argument for
/// the given non-type template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the non-type template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
/// \returns the substituted template argument, or NULL if an error occurred.
static bool SubstDefaultTemplateArgument(
    Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
    SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param,
    ArrayRef<TemplateArgument> SugaredConverted,
    ArrayRef<TemplateArgument> CanonicalConverted,
    TemplateArgumentLoc &Output) {
  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template,
                                   SugaredConverted,
                                   SourceRange(TemplateLoc, RAngleLoc));
  if (Inst.isInvalid())
    return true;

  // Only substitute for the innermost template argument list.
  MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted,
                                                  /*Final=*/true);
  for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
    TemplateArgLists.addOuterTemplateArguments(std::nullopt);

  Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
  EnterExpressionEvaluationContext ConstantEvaluated(
      SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
  return SemaRef.SubstTemplateArgument(Param->getDefaultArgument(),
                                       TemplateArgLists, Output);
}

/// Substitute template arguments into the default template argument for
/// the given template template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the template template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
/// \param QualifierLoc Will be set to the nested-name-specifier (with
/// source-location information) that precedes the template name.
///
/// \returns the substituted template argument, or NULL if an error occurred.
static TemplateName SubstDefaultTemplateArgument(
    Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
    SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param,
    ArrayRef<TemplateArgument> SugaredConverted,
    ArrayRef<TemplateArgument> CanonicalConverted,
    NestedNameSpecifierLoc &QualifierLoc) {
  Sema::InstantiatingTemplate Inst(
      SemaRef, TemplateLoc, TemplateParameter(Param), Template,
      SugaredConverted, SourceRange(TemplateLoc, RAngleLoc));
  if (Inst.isInvalid())
    return TemplateName();

  // Only substitute for the innermost template argument list.
  MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted,
                                                  /*Final=*/true);
  for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
    TemplateArgLists.addOuterTemplateArguments(std::nullopt);

  Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
  // Substitute into the nested-name-specifier first,
  QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
  if (QualifierLoc) {
    QualifierLoc =
        SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists);
    if (!QualifierLoc)
      return TemplateName();
  }

  return SemaRef.SubstTemplateName(
             QualifierLoc,
             Param->getDefaultArgument().getArgument().getAsTemplate(),
             Param->getDefaultArgument().getTemplateNameLoc(),
             TemplateArgLists);
}

TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
    TemplateDecl *Template, SourceLocation TemplateLoc,
    SourceLocation RAngleLoc, Decl *Param,
    ArrayRef<TemplateArgument> SugaredConverted,
    ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg) {
  HasDefaultArg = false;

  if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
    if (!hasReachableDefaultArgument(TypeParm))
      return TemplateArgumentLoc();

    HasDefaultArg = true;
    TemplateArgumentLoc Output;
    if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
                                     TypeParm, SugaredConverted,
                                     CanonicalConverted, Output))
      return TemplateArgumentLoc();
    return Output;
  }

  if (NonTypeTemplateParmDecl *NonTypeParm
        = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
    if (!hasReachableDefaultArgument(NonTypeParm))
      return TemplateArgumentLoc();

    HasDefaultArg = true;
    TemplateArgumentLoc Output;
    if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
                                     NonTypeParm, SugaredConverted,
                                     CanonicalConverted, Output))
      return TemplateArgumentLoc();
    return Output;
  }

  TemplateTemplateParmDecl *TempTempParm
    = cast<TemplateTemplateParmDecl>(Param);
  if (!hasReachableDefaultArgument(TempTempParm))
    return TemplateArgumentLoc();

  HasDefaultArg = true;
  NestedNameSpecifierLoc QualifierLoc;
  TemplateName TName = SubstDefaultTemplateArgument(
      *this, Template, TemplateLoc, RAngleLoc, TempTempParm, SugaredConverted,
      CanonicalConverted, QualifierLoc);
  if (TName.isNull())
    return TemplateArgumentLoc();

  return TemplateArgumentLoc(
      Context, TemplateArgument(TName),
      TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
      TempTempParm->getDefaultArgument().getTemplateNameLoc());
}

/// Convert a template-argument that we parsed as a type into a template, if
/// possible. C++ permits injected-class-names to perform dual service as
/// template template arguments and as template type arguments.
static TemplateArgumentLoc
convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) {
  // Extract and step over any surrounding nested-name-specifier.
  NestedNameSpecifierLoc QualLoc;
  if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
    if (ETLoc.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None)
      return TemplateArgumentLoc();

    QualLoc = ETLoc.getQualifierLoc();
    TLoc = ETLoc.getNamedTypeLoc();
  }
  // If this type was written as an injected-class-name, it can be used as a
  // template template argument.
  if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
    return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(),
                               QualLoc, InjLoc.getNameLoc());

  // If this type was written as an injected-class-name, it may have been
  // converted to a RecordType during instantiation. If the RecordType is
  // *not* wrapped in a TemplateSpecializationType and denotes a class
  // template specialization, it must have come from an injected-class-name.
  if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
    if (auto *CTSD =
            dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
      return TemplateArgumentLoc(Context,
                                 TemplateName(CTSD->getSpecializedTemplate()),
                                 QualLoc, RecLoc.getNameLoc());

  return TemplateArgumentLoc();
}

bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
                                 NamedDecl *Template,
                                 SourceLocation TemplateLoc,
                                 SourceLocation RAngleLoc,
                                 unsigned ArgumentPackIndex,
                                 CheckTemplateArgumentInfo &CTAI,
                                 CheckTemplateArgumentKind CTAK) {
  // Check template type parameters.
  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
    return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI.SugaredConverted,
                                     CTAI.CanonicalConverted);

  const TemplateArgument &Arg = ArgLoc.getArgument();
  // Check non-type template parameters.
  if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
    // Do substitution on the type of the non-type template parameter
    // with the template arguments we've seen thus far.  But if the
    // template has a dependent context then we cannot substitute yet.
    QualType NTTPType = NTTP->getType();
    if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
      NTTPType = NTTP->getExpansionType(ArgumentPackIndex);

    if (NTTPType->isInstantiationDependentType() &&
        !isa<TemplateTemplateParmDecl>(Template) &&
        !Template->getDeclContext()->isDependentContext()) {
      // Do substitution on the type of the non-type template parameter.
      InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP,
                                 CTAI.SugaredConverted,
                                 SourceRange(TemplateLoc, RAngleLoc));
      if (Inst.isInvalid())
        return true;

      MultiLevelTemplateArgumentList MLTAL(Template, CTAI.SugaredConverted,
                                           /*Final=*/true);
      // If the parameter is a pack expansion, expand this slice of the pack.
      if (auto *PET = NTTPType->getAs<PackExpansionType>()) {
        Sema::ArgPackSubstIndexRAII SubstIndex(*this, ArgumentPackIndex);
        NTTPType = SubstType(PET->getPattern(), MLTAL, NTTP->getLocation(),
                             NTTP->getDeclName());
      } else {
        NTTPType = SubstType(NTTPType, MLTAL, NTTP->getLocation(),
                             NTTP->getDeclName());
      }

      // If that worked, check the non-type template parameter type
      // for validity.
      if (!NTTPType.isNull())
        NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
                                                     NTTP->getLocation());
      if (NTTPType.isNull())
        return true;
    }

    auto checkExpr = [&](Expr *E) -> Expr * {
      TemplateArgument SugaredResult, CanonicalResult;
      unsigned CurSFINAEErrors = NumSFINAEErrors;
      ExprResult Res = CheckTemplateArgument(
          NTTP, NTTPType, E, SugaredResult, CanonicalResult,
          /*StrictCheck=*/CTAI.MatchingTTP || CTAI.PartialOrdering, CTAK);
      // If the current template argument causes an error, give up now.
      if (Res.isInvalid() || CurSFINAEErrors < NumSFINAEErrors)
        return nullptr;
      CTAI.SugaredConverted.push_back(SugaredResult);
      CTAI.CanonicalConverted.push_back(CanonicalResult);
      return Res.get();
    };

    switch (Arg.getKind()) {
    case TemplateArgument::Null:
      llvm_unreachable("Should never see a NULL template argument here");

    case TemplateArgument::Expression: {
      Expr *E = Arg.getAsExpr();
      Expr *R = checkExpr(E);
      if (!R)
        return true;
      // If the resulting expression is new, then use it in place of the
      // old expression in the template argument.
      if (R != E) {
        TemplateArgument TA(R, /*IsCanonical=*/false);
        ArgLoc = TemplateArgumentLoc(TA, R);
      }
      break;
    }

    // As for the converted NTTP kinds, they still might need another
    // conversion, as the new corresponding parameter might be different.
    // Ideally, we would always perform substitution starting with sugared types
    // and never need these, as we would still have expressions. Since these are
    // needed so rarely, it's probably a better tradeoff to just convert them
    // back to expressions.
    case TemplateArgument::Integral:
    case TemplateArgument::Declaration:
    case TemplateArgument::NullPtr:
    case TemplateArgument::StructuralValue: {
      // FIXME: StructuralValue is untested here.
      ExprResult R =
          BuildExpressionFromNonTypeTemplateArgument(Arg, SourceLocation());
      assert(R.isUsable());
      if (!checkExpr(R.get()))
        return true;
      break;
    }

    case TemplateArgument::Template:
    case TemplateArgument::TemplateExpansion:
      // We were given a template template argument. It may not be ill-formed;
      // see below.
      if (DependentTemplateName *DTN = Arg.getAsTemplateOrTemplatePattern()
                                           .getAsDependentTemplateName()) {
        // We have a template argument such as \c T::template X, which we
        // parsed as a template template argument. However, since we now
        // know that we need a non-type template argument, convert this
        // template name into an expression.

        DeclarationNameInfo NameInfo(DTN->getName().getIdentifier(),
                                     ArgLoc.getTemplateNameLoc());

        CXXScopeSpec SS;
        SS.Adopt(ArgLoc.getTemplateQualifierLoc());
        // FIXME: the template-template arg was a DependentTemplateName,
        // so it was provided with a template keyword. However, its source
        // location is not stored in the template argument structure.
        SourceLocation TemplateKWLoc;
        ExprResult E = DependentScopeDeclRefExpr::Create(
            Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
            nullptr);

        // If we parsed the template argument as a pack expansion, create a
        // pack expansion expression.
        if (Arg.getKind() == TemplateArgument::TemplateExpansion) {
          E = ActOnPackExpansion(E.get(), ArgLoc.getTemplateEllipsisLoc());
          if (E.isInvalid())
            return true;
        }

        TemplateArgument SugaredResult, CanonicalResult;
        E = CheckTemplateArgument(
            NTTP, NTTPType, E.get(), SugaredResult, CanonicalResult,
            /*StrictCheck=*/CTAI.PartialOrdering, CTAK_Specified);
        if (E.isInvalid())
          return true;

        CTAI.SugaredConverted.push_back(SugaredResult);
        CTAI.CanonicalConverted.push_back(CanonicalResult);
        break;
      }

      // We have a template argument that actually does refer to a class
      // template, alias template, or template template parameter, and
      // therefore cannot be a non-type template argument.
      Diag(ArgLoc.getLocation(), diag::err_template_arg_must_be_expr)
          << ArgLoc.getSourceRange();
      NoteTemplateParameterLocation(*Param);

      return true;

    case TemplateArgument::Type: {
      // We have a non-type template parameter but the template
      // argument is a type.

      // C++ [temp.arg]p2:
      //   In a template-argument, an ambiguity between a type-id and
      //   an expression is resolved to a type-id, regardless of the
      //   form of the corresponding template-parameter.
      //
      // We warn specifically about this case, since it can be rather
      // confusing for users.
      QualType T = Arg.getAsType();
      SourceRange SR = ArgLoc.getSourceRange();
      if (T->isFunctionType())
        Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
      else
        Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
      NoteTemplateParameterLocation(*Param);
      return true;
    }

    case TemplateArgument::Pack:
      llvm_unreachable("Caller must expand template argument packs");
    }

    return false;
  }


  // Check template template parameters.
  TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);

  TemplateParameterList *Params = TempParm->getTemplateParameters();
  if (TempParm->isExpandedParameterPack())
    Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex);

  // Substitute into the template parameter list of the template
  // template parameter, since previously-supplied template arguments
  // may appear within the template template parameter.
  //
  // FIXME: Skip this if the parameters aren't instantiation-dependent.
  {
    // Set up a template instantiation context.
    LocalInstantiationScope Scope(*this);
    InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm,
                               CTAI.SugaredConverted,
                               SourceRange(TemplateLoc, RAngleLoc));
    if (Inst.isInvalid())
      return true;

    Params = SubstTemplateParams(
        Params, CurContext,
        MultiLevelTemplateArgumentList(Template, CTAI.SugaredConverted,
                                       /*Final=*/true),
        /*EvaluateConstraints=*/false);
    if (!Params)
      return true;
  }

  // C++1z [temp.local]p1: (DR1004)
  //   When [the injected-class-name] is used [...] as a template-argument for
  //   a template template-parameter [...] it refers to the class template
  //   itself.
  if (Arg.getKind() == TemplateArgument::Type) {
    TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate(
        Context, ArgLoc.getTypeSourceInfo()->getTypeLoc());
    if (!ConvertedArg.getArgument().isNull())
      ArgLoc = ConvertedArg;
  }

  switch (Arg.getKind()) {
  case TemplateArgument::Null:
    llvm_unreachable("Should never see a NULL template argument here");

  case TemplateArgument::Template:
  case TemplateArgument::TemplateExpansion:
    if (CheckTemplateTemplateArgument(TempParm, Params, ArgLoc,
                                      CTAI.PartialOrdering,
                                      &CTAI.StrictPackMatch))
      return true;

    CTAI.SugaredConverted.push_back(Arg);
    CTAI.CanonicalConverted.push_back(
        Context.getCanonicalTemplateArgument(Arg));
    break;

  case TemplateArgument::Expression:
  case TemplateArgument::Type:
    // We have a template template parameter but the template
    // argument does not refer to a template.
    Diag(ArgLoc.getLocation(), diag::err_template_arg_must_be_template)
        << getLangOpts().CPlusPlus11;
    return true;

  case TemplateArgument::Declaration:
  case TemplateArgument::Integral:
  case TemplateArgument::StructuralValue:
  case TemplateArgument::NullPtr:
    llvm_unreachable("non-type argument with template template parameter");

  case TemplateArgument::Pack:
    llvm_unreachable("Caller must expand template argument packs");
  }

  return false;
}

/// Diagnose a missing template argument.
template<typename TemplateParmDecl>
static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
                                    TemplateDecl *TD,
                                    const TemplateParmDecl *D,
                                    TemplateArgumentListInfo &Args) {
  // Dig out the most recent declaration of the template parameter; there may be
  // declarations of the template that are more recent than TD.
  D = cast<TemplateParmDecl>(cast<TemplateDecl>(TD->getMostRecentDecl())
                                 ->getTemplateParameters()
                                 ->getParam(D->getIndex()));

  // If there's a default argument that's not reachable, diagnose that we're
  // missing a module import.
  llvm::SmallVector<Module*, 8> Modules;
  if (D->hasDefaultArgument() && !S.hasReachableDefaultArgument(D, &Modules)) {
    S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD),
                            D->getDefaultArgumentLoc(), Modules,
                            Sema::MissingImportKind::DefaultArgument,
                            /*Recover*/true);
    return true;
  }

  // FIXME: If there's a more recent default argument that *is* visible,
  // diagnose that it was declared too late.

  TemplateParameterList *Params = TD->getTemplateParameters();

  S.Diag(Loc, diag::err_template_arg_list_different_arity)
    << /*not enough args*/0
    << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD))
    << TD;
  S.NoteTemplateLocation(*TD, Params->getSourceRange());
  return true;
}

/// Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(
    TemplateDecl *Template, SourceLocation TemplateLoc,
    TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs,
    bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI,
    bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {

  if (ConstraintsNotSatisfied)
    *ConstraintsNotSatisfied = false;

  // Make a copy of the template arguments for processing.  Only make the
  // changes at the end when successful in matching the arguments to the
  // template.
  TemplateArgumentListInfo NewArgs = TemplateArgs;

  TemplateParameterList *Params = GetTemplateParameterList(Template);

  SourceLocation RAngleLoc = NewArgs.getRAngleLoc();

  // C++23 [temp.arg.general]p1:
  //   [...] The type and form of each template-argument specified in
  //   a template-id shall match the type and form specified for the
  //   corresponding parameter declared by the template in its
  //   template-parameter-list.
  bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template);
  SmallVector<TemplateArgument, 2> SugaredArgumentPack;
  SmallVector<TemplateArgument, 2> CanonicalArgumentPack;
  unsigned ArgIdx = 0, NumArgs = NewArgs.size();
  LocalInstantiationScope InstScope(*this, true);
  for (TemplateParameterList::iterator ParamBegin = Params->begin(),
                                       ParamEnd = Params->end(),
                                       Param = ParamBegin;
       Param != ParamEnd;
       /* increment in loop */) {
    if (size_t ParamIdx = Param - ParamBegin;
        DefaultArgs && ParamIdx >= DefaultArgs.StartPos) {
      // All written arguments should have been consumed by this point.
      assert(ArgIdx == NumArgs && "bad default argument deduction");
      if (ParamIdx == DefaultArgs.StartPos) {
        assert(Param + DefaultArgs.Args.size() <= ParamEnd);
        // Default arguments from a DeducedTemplateName are already converted.
        for (const TemplateArgument &DefArg : DefaultArgs.Args) {
          CTAI.SugaredConverted.push_back(DefArg);
          CTAI.CanonicalConverted.push_back(
              Context.getCanonicalTemplateArgument(DefArg));
          ++Param;
        }
        continue;
      }
    }

    // If we have an expanded parameter pack, make sure we don't have too
    // many arguments.
    if (UnsignedOrNone Expansions = getExpandedPackSize(*Param)) {
      if (*Expansions == SugaredArgumentPack.size()) {
        // We're done with this parameter pack. Pack up its arguments and add
        // them to the list.
        CTAI.SugaredConverted.push_back(
            TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
        SugaredArgumentPack.clear();

        CTAI.CanonicalConverted.push_back(
            TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
        CanonicalArgumentPack.clear();

        // This argument is assigned to the next parameter.
        ++Param;
        continue;
      } else if (ArgIdx == NumArgs && !PartialTemplateArgs) {
        // Not enough arguments for this parameter pack.
        Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
          << /*not enough args*/0
          << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
          << Template;
        NoteTemplateLocation(*Template, Params->getSourceRange());
        return true;
      }
    }

    if (ArgIdx < NumArgs) {
      TemplateArgumentLoc &ArgLoc = NewArgs[ArgIdx];
      bool NonPackParameter =
          !(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param);
      bool ArgIsExpansion = ArgLoc.getArgument().isPackExpansion();

      if (ArgIsExpansion && CTAI.MatchingTTP) {
        SmallVector<TemplateArgument, 4> Args(ParamEnd - Param);
        for (TemplateParameterList::iterator First = Param; Param != ParamEnd;
             ++Param) {
          TemplateArgument &Arg = Args[Param - First];
          Arg = ArgLoc.getArgument();
          if (!(*Param)->isTemplateParameterPack() ||
              getExpandedPackSize(*Param))
            Arg = Arg.getPackExpansionPattern();
          TemplateArgumentLoc NewArgLoc(Arg, ArgLoc.getLocInfo());
          SaveAndRestore _1(CTAI.PartialOrdering, false);
          SaveAndRestore _2(CTAI.MatchingTTP, true);
          if (CheckTemplateArgument(*Param, NewArgLoc, Template, TemplateLoc,
                                    RAngleLoc, SugaredArgumentPack.size(), CTAI,
                                    CTAK_Specified))
            return true;
          Arg = NewArgLoc.getArgument();
          CTAI.CanonicalConverted.back().setIsDefaulted(
              clang::isSubstitutedDefaultArgument(Context, Arg, *Param,
                                                  CTAI.CanonicalConverted,
                                                  Params->getDepth()));
        }
        ArgLoc =
            TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, Args),
                                ArgLoc.getLocInfo());
      } else {
        SaveAndRestore _1(CTAI.PartialOrdering, false);
        if (CheckTemplateArgument(*Param, ArgLoc, Template, TemplateLoc,
                                  RAngleLoc, SugaredArgumentPack.size(), CTAI,
                                  CTAK_Specified))
          return true;
        CTAI.CanonicalConverted.back().setIsDefaulted(
            clang::isSubstitutedDefaultArgument(Context, ArgLoc.getArgument(),
                                                *Param, CTAI.CanonicalConverted,
                                                Params->getDepth()));
        if (ArgIsExpansion && NonPackParameter) {
          // CWG1430/CWG2686: we have a pack expansion as an argument to an
          // alias template or concept, and it's not part of a parameter pack.
          // This can't be canonicalized, so reject it now.
          if (isa<TypeAliasTemplateDecl, ConceptDecl>(Template)) {
            Diag(ArgLoc.getLocation(),
                 diag::err_template_expansion_into_fixed_list)
                << (isa<ConceptDecl>(Template) ? 1 : 0)
                << ArgLoc.getSourceRange();
            NoteTemplateParameterLocation(**Param);
            return true;
          }
        }
      }

      // We're now done with this argument.
      ++ArgIdx;

      if (ArgIsExpansion && (CTAI.MatchingTTP || NonPackParameter)) {
        // Directly convert the remaining arguments, because we don't know what
        // parameters they'll match up with.

        if (!SugaredArgumentPack.empty()) {
          // If we were part way through filling in an expanded parameter pack,
          // fall back to just producing individual arguments.
          CTAI.SugaredConverted.insert(CTAI.SugaredConverted.end(),
                                       SugaredArgumentPack.begin(),
                                       SugaredArgumentPack.end());
          SugaredArgumentPack.clear();

          CTAI.CanonicalConverted.insert(CTAI.CanonicalConverted.end(),
                                         CanonicalArgumentPack.begin(),
                                         CanonicalArgumentPack.end());
          CanonicalArgumentPack.clear();
        }

        while (ArgIdx < NumArgs) {
          const TemplateArgument &Arg = NewArgs[ArgIdx].getArgument();
          CTAI.SugaredConverted.push_back(Arg);
          CTAI.CanonicalConverted.push_back(
              Context.getCanonicalTemplateArgument(Arg));
          ++ArgIdx;
        }

        return false;
      }

      if ((*Param)->isTemplateParameterPack()) {
        // The template parameter was a template parameter pack, so take the
        // deduced argument and place it on the argument pack. Note that we
        // stay on the same template parameter so that we can deduce more
        // arguments.
        SugaredArgumentPack.push_back(CTAI.SugaredConverted.pop_back_val());
        CanonicalArgumentPack.push_back(CTAI.CanonicalConverted.pop_back_val());
      } else {
        // Move to the next template parameter.
        ++Param;
      }
      continue;
    }

    // If we're checking a partial template argument list, we're done.
    if (PartialTemplateArgs) {
      if ((*Param)->isTemplateParameterPack() && !SugaredArgumentPack.empty()) {
        CTAI.SugaredConverted.push_back(
            TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
        CTAI.CanonicalConverted.push_back(
            TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
      }
      return false;
    }

    // If we have a template parameter pack with no more corresponding
    // arguments, just break out now and we'll fill in the argument pack below.
    if ((*Param)->isTemplateParameterPack()) {
      assert(!getExpandedPackSize(*Param) &&
             "Should have dealt with this already");

      // A non-expanded parameter pack before the end of the parameter list
      // only occurs for an ill-formed template parameter list, unless we've
      // got a partial argument list for a function template, so just bail out.
      if (Param + 1 != ParamEnd) {
        assert(
            (Template->getMostRecentDecl()->getKind() != Decl::Kind::Concept) &&
            "Concept templates must have parameter packs at the end.");
        return true;
      }

      CTAI.SugaredConverted.push_back(
          TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
      SugaredArgumentPack.clear();

      CTAI.CanonicalConverted.push_back(
          TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack));
      CanonicalArgumentPack.clear();

      ++Param;
      continue;
    }

    // Check whether we have a default argument.
    bool HasDefaultArg;

    // Retrieve the default template argument from the template
    // parameter. For each kind of template parameter, we substitute the
    // template arguments provided thus far and any "outer" template arguments
    // (when the template parameter was part of a nested template) into
    // the default argument.
    TemplateArgumentLoc Arg = SubstDefaultTemplateArgumentIfAvailable(
        Template, TemplateLoc, RAngleLoc, *Param, CTAI.SugaredConverted,
        CTAI.CanonicalConverted, HasDefaultArg);

    if (Arg.getArgument().isNull()) {
      if (!HasDefaultArg) {
        if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param))
          return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
                                         NewArgs);
        if (NonTypeTemplateParmDecl *NTTP =
                dyn_cast<NonTypeTemplateParmDecl>(*Param))
          return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
                                         NewArgs);
        return diagnoseMissingArgument(*this, TemplateLoc, Template,
                                       cast<TemplateTemplateParmDecl>(*Param),
                                       NewArgs);
      }
      return true;
    }

    // Introduce an instantiation record that describes where we are using
    // the default template argument. We're not actually instantiating a
    // template here, we just create this object to put a note into the
    // context stack.
    InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param,
                               CTAI.SugaredConverted,
                               SourceRange(TemplateLoc, RAngleLoc));
    if (Inst.isInvalid())
      return true;

    SaveAndRestore _1(CTAI.PartialOrdering, false);
    SaveAndRestore _2(CTAI.MatchingTTP, false);
    SaveAndRestore _3(CTAI.StrictPackMatch, {});
    // Check the default template argument.
    if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
                              CTAI, CTAK_Specified))
      return true;

    CTAI.SugaredConverted.back().setIsDefaulted(true);
    CTAI.CanonicalConverted.back().setIsDefaulted(true);

    // Core issue 150 (assumed resolution): if this is a template template
    // parameter, keep track of the default template arguments from the
    // template definition.
    if (isTemplateTemplateParameter)
      NewArgs.addArgument(Arg);

    // Move to the next template parameter and argument.
    ++Param;
    ++ArgIdx;
  }

  // If we're performing a partial argument substitution, allow any trailing
  // pack expansions; they might be empty. This can happen even if
  // PartialTemplateArgs is false (the list of arguments is complete but
  // still dependent).
  if (CTAI.MatchingTTP ||
      (CurrentInstantiationScope &&
       CurrentInstantiationScope->getPartiallySubstitutedPack())) {
    while (ArgIdx < NumArgs &&
           NewArgs[ArgIdx].getArgument().isPackExpansion()) {
      const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument();
      CTAI.SugaredConverted.push_back(Arg);
      CTAI.CanonicalConverted.push_back(
          Context.getCanonicalTemplateArgument(Arg));
    }
  }

  // If we have any leftover arguments, then there were too many arguments.
  // Complain and fail.
  if (ArgIdx < NumArgs) {
    Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
        << /*too many args*/1
        << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
        << Template
        << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc());
    NoteTemplateLocation(*Template, Params->getSourceRange());
    return true;
  }

  // No problems found with the new argument list, propagate changes back
  // to caller.
  if (UpdateArgsWithConversions)
    TemplateArgs = std::move(NewArgs);

  if (!PartialTemplateArgs) {
    // Setup the context/ThisScope for the case where we are needing to
    // re-instantiate constraints outside of normal instantiation.
    DeclContext *NewContext = Template->getDeclContext();

    // If this template is in a template, make sure we extract the templated
    // decl.
    if (auto *TD = dyn_cast<TemplateDecl>(NewContext))
      NewContext = Decl::castToDeclContext(TD->getTemplatedDecl());
    auto *RD = dyn_cast<CXXRecordDecl>(NewContext);

    Qualifiers ThisQuals;
    if (const auto *Method =
            dyn_cast_or_null<CXXMethodDecl>(Template->getTemplatedDecl()))
      ThisQuals = Method->getMethodQualifiers();

    ContextRAII Context(*this, NewContext);
    CXXThisScopeRAII Scope(*this, RD, ThisQuals, RD != nullptr);

    MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
        Template, NewContext, /*Final=*/false, CTAI.CanonicalConverted,
        /*RelativeToPrimary=*/true,
        /*Pattern=*/nullptr,
        /*ForConceptInstantiation=*/true);
    if (EnsureTemplateArgumentListConstraints(
            Template, MLTAL,
            SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
      if (ConstraintsNotSatisfied)
        *ConstraintsNotSatisfied = true;
      return true;
    }
  }

  return false;
}

namespace {
  class UnnamedLocalNoLinkageFinder
    : public TypeVisitor<UnnamedLocalNoLinkageFinder, bool>
  {
    Sema &S;
    SourceRange SR;

    typedef TypeVisitor<UnnamedLocalNoLinkageFinder, bool> inherited;

  public:
    UnnamedLocalNoLinkageFinder(Sema &S, SourceRange SR) : S(S), SR(SR) { }

    bool Visit(QualType T) {
      return T.isNull() ? false : inherited::Visit(T.getTypePtr());
    }

#define TYPE(Class, Parent) \
    bool Visit##Class##Type(const Class##Type *);
#define ABSTRACT_TYPE(Class, Parent) \
    bool Visit##Class##Type(const Class##Type *) { return false; }
#define NON_CANONICAL_TYPE(Class, Parent) \
    bool Visit##Class##Type(const Class##Type *) { return false; }
#include "clang/AST/TypeNodes.inc"

    bool VisitTagDecl(const TagDecl *Tag);
    bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
  };
} // end anonymous namespace

bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitPointerType(const PointerType* T) {
  return Visit(T->getPointeeType());
}

bool UnnamedLocalNoLinkageFinder::VisitBlockPointerType(
                                                    const BlockPointerType* T) {
  return Visit(T->getPointeeType());
}

bool UnnamedLocalNoLinkageFinder::VisitLValueReferenceType(
                                                const LValueReferenceType* T) {
  return Visit(T->getPointeeType());
}

bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
                                                const RValueReferenceType* T) {
  return Visit(T->getPointeeType());
}

bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
    const MemberPointerType *T) {
  if (Visit(T->getPointeeType()))
    return true;
  if (auto *RD = T->getMostRecentCXXRecordDecl())
    return VisitTagDecl(RD);
  return VisitNestedNameSpecifier(T->getQualifier());
}

bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
                                                  const ConstantArrayType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitIncompleteArrayType(
                                                 const IncompleteArrayType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitVariableArrayType(
                                                   const VariableArrayType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentSizedArrayType(
                                            const DependentSizedArrayType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
                                         const DependentSizedExtVectorType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentSizedMatrixType(
    const DependentSizedMatrixType *T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentAddressSpaceType(
    const DependentAddressSpaceType *T) {
  return Visit(T->getPointeeType());
}

bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
    const DependentVectorType *T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitConstantMatrixType(
    const ConstantMatrixType *T) {
  return Visit(T->getElementType());
}

bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
                                                  const FunctionProtoType* T) {
  for (const auto &A : T->param_types()) {
    if (Visit(A))
      return true;
  }

  return Visit(T->getReturnType());
}

bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
                                               const FunctionNoProtoType* T) {
  return Visit(T->getReturnType());
}

bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
                                                  const UnresolvedUsingType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) {
  return Visit(T->getUnmodifiedType());
}

bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitPackIndexingType(
    const PackIndexingType *) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType(
                                                    const UnaryTransformType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
  return Visit(T->getDeducedType());
}

bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType(
    const DeducedTemplateSpecializationType *T) {
  return Visit(T->getDeducedType());
}

bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
  return VisitTagDecl(T->getDecl());
}

bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) {
  return VisitTagDecl(T->getDecl());
}

bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
                                                 const TemplateTypeParmType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
                                        const SubstTemplateTypeParmPackType *) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
                                            const TemplateSpecializationType*) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType(
                                              const InjectedClassNameType* T) {
  return VisitTagDecl(T->getDecl());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
                                                   const DependentNameType* T) {
  return VisitNestedNameSpecifier(T->getQualifier());
}

bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
                                 const DependentTemplateSpecializationType* T) {
  if (auto *Q = T->getDependentTemplateName().getQualifier())
    return VisitNestedNameSpecifier(Q);

  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
                                                   const PackExpansionType* T) {
  return Visit(T->getPattern());
}

bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitObjCInterfaceType(
                                                   const ObjCInterfaceType *) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType(
                                                const ObjCObjectPointerType *) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
  return Visit(T->getValueType());
}

bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitBitIntType(const BitIntType *T) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitArrayParameterType(
    const ArrayParameterType *T) {
  return VisitConstantArrayType(T);
}

bool UnnamedLocalNoLinkageFinder::VisitDependentBitIntType(
    const DependentBitIntType *T) {
  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
  if (Tag->getDeclContext()->isFunctionOrMethod()) {
    S.Diag(SR.getBegin(),
           S.getLangOpts().CPlusPlus11 ?
             diag::warn_cxx98_compat_template_arg_local_type :
             diag::ext_template_arg_local_type)
      << S.Context.getTypeDeclType(Tag) << SR;
    return true;
  }

  if (!Tag->hasNameForLinkage()) {
    S.Diag(SR.getBegin(),
           S.getLangOpts().CPlusPlus11 ?
             diag::warn_cxx98_compat_template_arg_unnamed_type :
             diag::ext_template_arg_unnamed_type) << SR;
    S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
    return true;
  }

  return false;
}

bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
                                                    NestedNameSpecifier *NNS) {
  assert(NNS);
  if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
    return true;

  switch (NNS->getKind()) {
  case NestedNameSpecifier::Identifier:
  case NestedNameSpecifier::Namespace:
  case NestedNameSpecifier::NamespaceAlias:
  case NestedNameSpecifier::Global:
  case NestedNameSpecifier::Super:
    return false;

  case NestedNameSpecifier::TypeSpec:
    return Visit(QualType(NNS->getAsType(), 0));
  }
  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}

bool UnnamedLocalNoLinkageFinder::VisitHLSLAttributedResourceType(
    const HLSLAttributedResourceType *T) {
  if (T->hasContainedType() && Visit(T->getContainedType()))
    return true;
  return Visit(T->getWrappedType());
}

bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) {
  assert(ArgInfo && "invalid TypeSourceInfo");
  QualType Arg = ArgInfo->getType();
  SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
  QualType CanonArg = Context.getCanonicalType(Arg);

  if (CanonArg->isVariablyModifiedType()) {
    return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
  } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
    return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
  }

  // C++03 [temp.arg.type]p2:
  //   A local type, a type with no linkage, an unnamed type or a type
  //   compounded from any of these types shall not be used as a
  //   template-argument for a template type-parameter.
  //
  // C++11 allows these, and even in C++03 we allow them as an extension with
  // a warning.
  if (LangOpts.CPlusPlus11 || CanonArg->hasUnnamedOrLocalType()) {
    UnnamedLocalNoLinkageFinder Finder(*this, SR);
    (void)Finder.Visit(CanonArg);
  }

  return false;
}

enum NullPointerValueKind {
  NPV_NotNullPointer,
  NPV_NullPointer,
  NPV_Error
};

/// Determine whether the given template argument is a null pointer
/// value of the appropriate type.
static NullPointerValueKind
isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
                                   QualType ParamType, Expr *Arg,
                                   Decl *Entity = nullptr) {
  if (Arg->isValueDependent() || Arg->isTypeDependent())
    return NPV_NotNullPointer;

  // dllimport'd entities aren't constant but are available inside of template
  // arguments.
  if (Entity && Entity->hasAttr<DLLImportAttr>())
    return NPV_NotNullPointer;

  if (!S.isCompleteType(Arg->getExprLoc(), ParamType))
    llvm_unreachable(
        "Incomplete parameter type in isNullPointerValueTemplateArgument!");

  if (!S.getLangOpts().CPlusPlus11)
    return NPV_NotNullPointer;

  // Determine whether we have a constant expression.
  ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
  if (ArgRV.isInvalid())
    return NPV_Error;
  Arg = ArgRV.get();

  Expr::EvalResult EvalResult;
  SmallVector<PartialDiagnosticAt, 8> Notes;
  EvalResult.Diag = &Notes;
  if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
      EvalResult.HasSideEffects) {
    SourceLocation DiagLoc = Arg->getExprLoc();

    // If our only note is the usual "invalid subexpression" note, just point
    // the caret at its location rather than producing an essentially
    // redundant note.
    if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
        diag::note_invalid_subexpr_in_const_expr) {
      DiagLoc = Notes[0].first;
      Notes.clear();
    }

    S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
      << Arg->getType() << Arg->getSourceRange();
    for (unsigned I = 0, N = Notes.size(); I != N; ++I)
      S.Diag(Notes[I].first, Notes[I].second);

    S.NoteTemplateParameterLocation(*Param);
    return NPV_Error;
  }

  // C++11 [temp.arg.nontype]p1:
  //   - an address constant expression of type std::nullptr_t
  if (Arg->getType()->isNullPtrType())
    return NPV_NullPointer;

  //   - a constant expression that evaluates to a null pointer value (4.10); or
  //   - a constant expression that evaluates to a null member pointer value
  //     (4.11); or
  if ((EvalResult.Val.isLValue() && EvalResult.Val.isNullPointer()) ||
      (EvalResult.Val.isMemberPointer() &&
       !EvalResult.Val.getMemberPointerDecl())) {
    // If our expression has an appropriate type, we've succeeded.
    bool ObjCLifetimeConversion;
    if (S.Context.hasSameUnqualifiedType(Arg->getType(), ParamType) ||
        S.IsQualificationConversion(Arg->getType(), ParamType, false,
                                     ObjCLifetimeConversion))
      return NPV_NullPointer;

    // The types didn't match, but we know we got a null pointer; complain,
    // then recover as if the types were correct.
    S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
      << Arg->getType() << ParamType << Arg->getSourceRange();
    S.NoteTemplateParameterLocation(*Param);
    return NPV_NullPointer;
  }

  if (EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) {
    // We found a pointer that isn't null, but doesn't refer to an object.
    // We could just return NPV_NotNullPointer, but we can print a better
    // message with the information we have here.
    S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid)
      << EvalResult.Val.getAsString(S.Context, ParamType);
    S.NoteTemplateParameterLocation(*Param);
    return NPV_Error;
  }

  // If we don't have a null pointer value, but we do have a NULL pointer
  // constant, suggest a cast to the appropriate type.
  if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
    std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
    S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
        << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code)
        << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()),
                                      ")");
    S.NoteTemplateParameterLocation(*Param);
    return NPV_NullPointer;
  }

  // FIXME: If we ever want to support general, address-constant expressions
  // as non-type template arguments, we should return the ExprResult here to
  // be interpreted by the caller.
  return NPV_NotNullPointer;
}

/// Checks whether the given template argument is compatible with its
/// template parameter.
static bool CheckTemplateArgumentIsCompatibleWithParameter(
    Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
    Expr *Arg, QualType ArgType) {
  bool ObjCLifetimeConversion;
  if (ParamType->isPointerType() &&
      !ParamType->castAs<PointerType>()->getPointeeType()->isFunctionType() &&
      S.IsQualificationConversion(ArgType, ParamType, false,
                                  ObjCLifetimeConversion)) {
    // For pointer-to-object types, qualification conversions are
    // permitted.
  } else {
    if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
      if (!ParamRef->getPointeeType()->isFunctionType()) {
        // C++ [temp.arg.nontype]p5b3:
        //   For a non-type template-parameter of type reference to
        //   object, no conversions apply. The type referred to by the
        //   reference may be more cv-qualified than the (otherwise
        //   identical) type of the template- argument. The
        //   template-parameter is bound directly to the
        //   template-argument, which shall be an lvalue.

        // FIXME: Other qualifiers?
        unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
        unsigned ArgQuals = ArgType.getCVRQualifiers();

        if ((ParamQuals | ArgQuals) != ParamQuals) {
          S.Diag(Arg->getBeginLoc(),
                 diag::err_template_arg_ref_bind_ignores_quals)
              << ParamType << Arg->getType() << Arg->getSourceRange();
          S.NoteTemplateParameterLocation(*Param);
          return true;
        }
      }
    }

    // At this point, the template argument refers to an object or
    // function with external linkage. We now need to check whether the
    // argument and parameter types are compatible.
    if (!S.Context.hasSameUnqualifiedType(ArgType,
                                          ParamType.getNonReferenceType())) {
      // We can't perform this conversion or binding.
      if (ParamType->isReferenceType())
        S.Diag(Arg->getBeginLoc(), diag::err_template_arg_no_ref_bind)
            << ParamType << ArgIn->getType() << Arg->getSourceRange();
      else
        S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
            << ArgIn->getType() << ParamType << Arg->getSourceRange();
      S.NoteTemplateParameterLocation(*Param);
      return true;
    }
  }

  return false;
}

/// Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool CheckTemplateArgumentAddressOfObjectOrFunction(
    Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
    TemplateArgument &SugaredConverted, TemplateArgument &CanonicalConverted) {
  bool Invalid = false;
  Expr *Arg = ArgIn;
  QualType ArgType = Arg->getType();

  bool AddressTaken = false;
  SourceLocation AddrOpLoc;
  if (S.getLangOpts().MicrosoftExt) {
    // Microsoft Visual C++ strips all casts, allows an arbitrary number of
    // dereference and address-of operators.
    Arg = Arg->IgnoreParenCasts();

    bool ExtWarnMSTemplateArg = false;
    UnaryOperatorKind FirstOpKind;
    SourceLocation FirstOpLoc;
    while (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
      UnaryOperatorKind UnOpKind = UnOp->getOpcode();
      if (UnOpKind == UO_Deref)
        ExtWarnMSTemplateArg = true;
      if (UnOpKind == UO_AddrOf || UnOpKind == UO_Deref) {
        Arg = UnOp->getSubExpr()->IgnoreParenCasts();
        if (!AddrOpLoc.isValid()) {
          FirstOpKind = UnOpKind;
          FirstOpLoc = UnOp->getOperatorLoc();
        }
      } else
        break;
    }
    if (FirstOpLoc.isValid()) {
      if (ExtWarnMSTemplateArg)
        S.Diag(ArgIn->getBeginLoc(), diag::ext_ms_deref_template_argument)
            << ArgIn->getSourceRange();

      if (FirstOpKind == UO_AddrOf)
        AddressTaken = true;
      else if (Arg->getType()->isPointerType()) {
        // We cannot let pointers get dereferenced here, that is obviously not a
        // constant expression.
        assert(FirstOpKind == UO_Deref);
        S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
            << Arg->getSourceRange();
      }
    }
  } else {
    // See through any implicit casts we added to fix the type.
    Arg = Arg->IgnoreImpCasts();

    // C++ [temp.arg.nontype]p1:
    //
    //   A template-argument for a non-type, non-template
    //   template-parameter shall be one of: [...]
    //
    //     -- the address of an object or function with external
    //        linkage, including function templates and function
    //        template-ids but excluding non-static class members,
    //        expressed as & id-expression where the & is optional if
    //        the name refers to a function or array, or if the
    //        corresponding template-parameter is a reference; or

    // In C++98/03 mode, give an extension warning on any extra parentheses.
    // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
    bool ExtraParens = false;
    while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
      if (!Invalid && !ExtraParens) {
        S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens)
            << Arg->getSourceRange();
        ExtraParens = true;
      }

      Arg = Parens->getSubExpr();
    }

    while (SubstNonTypeTemplateParmExpr *subst =
               dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
      Arg = subst->getReplacement()->IgnoreImpCasts();

    if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
      if (UnOp->getOpcode() == UO_AddrOf) {
        Arg = UnOp->getSubExpr();
        AddressTaken = true;
        AddrOpLoc = UnOp->getOperatorLoc();
      }
    }

    while (SubstNonTypeTemplateParmExpr *subst =
               dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
      Arg = subst->getReplacement()->IgnoreImpCasts();
  }

  ValueDecl *Entity = nullptr;
  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg))
    Entity = DRE->getDecl();
  else if (CXXUuidofExpr *CUE = dyn_cast<CXXUuidofExpr>(Arg))
    Entity = CUE->getGuidDecl();

  // If our parameter has pointer type, check for a null template value.
  if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
    switch (isNullPointerValueTemplateArgument(S, Param, ParamType, ArgIn,
                                               Entity)) {
    case NPV_NullPointer:
      S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
      SugaredConverted = TemplateArgument(ParamType,
                                          /*isNullPtr=*/true);
      CanonicalConverted =
          TemplateArgument(S.Context.getCanonicalType(ParamType),
                           /*isNullPtr=*/true);
      return false;

    case NPV_Error:
      return true;

    case NPV_NotNullPointer:
      break;
    }
  }

  // Stop checking the precise nature of the argument if it is value dependent,
  // it should be checked when instantiated.
  if (Arg->isValueDependent()) {
    SugaredConverted = TemplateArgument(ArgIn, /*IsCanonical=*/false);
    CanonicalConverted =
        S.Context.getCanonicalTemplateArgument(SugaredConverted);
    return false;
  }

  if (!Entity) {
    S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
        << Arg->getSourceRange();
    S.NoteTemplateParameterLocation(*Param);
    return true;
  }

  // Cannot refer to non-static data members
  if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
    S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field)
        << Entity << Arg->getSourceRange();
    S.NoteTemplateParameterLocation(*Param);
    return true;
  }

  // Cannot refer to non-static member functions
  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
    if (!Method->isStatic()) {
      S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method)
          << Method << Arg->getSourceRange();
      S.NoteTemplateParameterLocation(*Param);
      return true;
    }
  }

  FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);
  VarDecl *Var = dyn_cast<VarDecl>(Entity);
  MSGuidDecl *Guid = dyn_cast<MSGuidDecl>(Entity);

  // A non-type template argument must refer to an object or function.
  if (!Func && !Var && !Guid) {
    // We found something, but we don't know specifically what it is.
    S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_object_or_func)
        << Arg->getSourceRange();
    S.Diag(Entity->getLocation(), diag::note_template_arg_refers_here);
    return true;
  }

  // Address / reference template args must have external linkage in C++98.
  if (Entity->getFormalLinkage() == Linkage::Internal) {
    S.Diag(Arg->getBeginLoc(),
           S.getLangOpts().CPlusPlus11
               ? diag::warn_cxx98_compat_template_arg_object_internal
               : diag::ext_template_arg_object_internal)
        << !Func << Entity << Arg->getSourceRange();
    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
      << !Func;
  } else if (!Entity->hasLinkage()) {
    S.Diag(Arg->getBeginLoc(), diag::err_template_arg_object_no_linkage)
        << !Func << Entity << Arg->getSourceRange();
    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
      << !Func;
    return true;
  }

  if (Var) {
    // A value of reference type is not an object.
    if (Var->getType()->isReferenceType()) {
      S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var)
          << Var->getType() << Arg->getSourceRange();
      S.NoteTemplateParameterLocation(*Param);
      return true;
    }

    // A template argument must have static storage duration.
    if (Var->getTLSKind()) {
      S.Diag(Arg->getBeginLoc(), diag::err_template_arg_thread_local)
          << Arg->getSourceRange();
      S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
      return true;
    }
  }

  if (AddressTaken && ParamType->isReferenceType()) {
    // If we originally had an address-of operator, but the
    // parameter has reference type, complain and (if things look
    // like they will work) drop the address-of operator.
    if (!S.Context.hasSameUnqualifiedType(Entity->getType(),
                                          ParamType.getNonReferenceType())) {
      S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
        << ParamType;
      S.NoteTemplateParameterLocation(*Param);
      return true;
    }

    S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
      << ParamType
      << FixItHint::CreateRemoval(AddrOpLoc);
    S.NoteTemplateParameterLocation(*Param);

    ArgType = Entity->getType();
  }

  // If the template parameter has pointer type, either we must have taken the
  // address or the argument must decay to a pointer.
  if (!AddressTaken && ParamType->isPointerType()) {
    if (Func) {
      // Function-to-pointer decay.
      ArgType = S.Context.getPointerType(Func->getType());
    } else if (Entity->getType()->isArrayType()) {
      // Array-to-pointer decay.
      ArgType = S.Context.getArrayDecayedType(Entity->getType());
    } else {
      // If the template parameter has pointer type but the address of
      // this object was not taken, complain and (possibly) recover by
      // taking the address of the entity.
      ArgType = S.Context.getPointerType(Entity->getType());
      if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
        S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
          << ParamType;
        S.NoteTemplateParameterLocation(*Param);
        return true;
      }

      S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
        << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&");

      S.NoteTemplateParameterLocation(*Param);
    }
  }

  if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, ArgIn,
                                                     Arg, ArgType))
    return true;

  // Create the template argument.
  SugaredConverted = TemplateArgument(Entity, ParamType);
  CanonicalConverted =
      TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
                       S.Context.getCanonicalType(ParamType));
  S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false);
  return false;
}

/// Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
static bool
CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param,
                                     QualType ParamType, Expr *&ResultArg,
                                     TemplateArgument &SugaredConverted,
                                     TemplateArgument &CanonicalConverted) {
  bool Invalid = false;

  Expr *Arg = ResultArg;
  bool ObjCLifetimeConversion;

  // C++ [temp.arg.nontype]p1:
  //
  //   A template-argument for a non-type, non-template
  //   template-parameter shall be one of: [...]
  //
  //     -- a pointer to member expressed as described in 5.3.1.
  DeclRefExpr *DRE = nullptr;

  // In C++98/03 mode, give an extension warning on any extra parentheses.
  // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
  bool ExtraParens = false;
  while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
    if (!Invalid && !ExtraParens) {
      S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens)
          << Arg->getSourceRange();
      ExtraParens = true;
    }

    Arg = Parens->getSubExpr();
  }

  while (SubstNonTypeTemplateParmExpr *subst =
           dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
    Arg = subst->getReplacement()->IgnoreImpCasts();

  // A pointer-to-member constant written &Class::member.
  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
    if (UnOp->getOpcode() == UO_AddrOf) {
      DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
      if (DRE && !DRE->getQualifier())
        DRE = nullptr;
    }
  }
  // A constant of pointer-to-member type.
  else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
    ValueDecl *VD = DRE->getDecl();
    if (VD->getType()->isMemberPointerType()) {
      if (isa<NonTypeTemplateParmDecl>(VD)) {
        if (Arg->isTypeDependent() || Arg->isValueDependent()) {
          SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
          CanonicalConverted =
              S.Context.getCanonicalTemplateArgument(SugaredConverted);
        } else {
          SugaredConverted = TemplateArgument(VD, ParamType);
          CanonicalConverted =
              TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
                               S.Context.getCanonicalType(ParamType));
        }
        return Invalid;
      }
    }

    DRE = nullptr;
  }

  ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr;

  // Check for a null pointer value.
  switch (isNullPointerValueTemplateArgument(S, Param, ParamType, ResultArg,
                                             Entity)) {
  case NPV_Error:
    return true;
  case NPV_NullPointer:
    S.Diag(ResultArg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
    SugaredConverted = TemplateArgument(ParamType,
                                        /*isNullPtr*/ true);
    CanonicalConverted = TemplateArgument(S.Context.getCanonicalType(ParamType),
                                          /*isNullPtr*/ true);
    return false;
  case NPV_NotNullPointer:
    break;
  }

  if (S.IsQualificationConversion(ResultArg->getType(),
                                  ParamType.getNonReferenceType(), false,
                                  ObjCLifetimeConversion)) {
    ResultArg = S.ImpCastExprToType(ResultArg, ParamType, CK_NoOp,
                                    ResultArg->getValueKind())
                    .get();
  } else if (!S.Context.hasSameUnqualifiedType(
                 ResultArg->getType(), ParamType.getNonReferenceType())) {
    // We can't perform this conversion.
    S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible)
        << ResultArg->getType() << ParamType << ResultArg->getSourceRange();
    S.NoteTemplateParameterLocation(*Param);
    return true;
  }

  if (!DRE)
    return S.Diag(Arg->getBeginLoc(),
                  diag::err_template_arg_not_pointer_to_member_form)
           << Arg->getSourceRange();

  if (isa<FieldDecl>(DRE->getDecl()) ||
      isa<IndirectFieldDecl>(DRE->getDecl()) ||
      isa<CXXMethodDecl>(DRE->getDecl())) {
    assert((isa<FieldDecl>(DRE->getDecl()) ||
            isa<IndirectFieldDecl>(DRE->getDecl()) ||
            cast<CXXMethodDecl>(DRE->getDecl())
                ->isImplicitObjectMemberFunction()) &&
           "Only non-static member pointers can make it here");

    // Okay: this is the address of a non-static member, and therefore
    // a member pointer constant.
    if (Arg->isTypeDependent() || Arg->isValueDependent()) {
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          S.Context.getCanonicalTemplateArgument(SugaredConverted);
    } else {
      ValueDecl *D = DRE->getDecl();
      SugaredConverted = TemplateArgument(D, ParamType);
      CanonicalConverted =
          TemplateArgument(cast<ValueDecl>(D->getCanonicalDecl()),
                           S.Context.getCanonicalType(ParamType));
    }
    return Invalid;
  }

  // We found something else, but we don't know specifically what it is.
  S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_pointer_to_member_form)
      << Arg->getSourceRange();
  S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
  return true;
}

ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                                       QualType ParamType, Expr *Arg,
                                       TemplateArgument &SugaredConverted,
                                       TemplateArgument &CanonicalConverted,
                                       bool StrictCheck,
                                       CheckTemplateArgumentKind CTAK) {
  SourceLocation StartLoc = Arg->getBeginLoc();
  auto *ArgPE = dyn_cast<PackExpansionExpr>(Arg);
  Expr *DeductionArg = ArgPE ? ArgPE->getPattern() : Arg;
  auto setDeductionArg = [&](Expr *NewDeductionArg) {
    DeductionArg = NewDeductionArg;
    if (ArgPE) {
      // Recreate a pack expansion if we unwrapped one.
      Arg = new (Context) PackExpansionExpr(
          DeductionArg, ArgPE->getEllipsisLoc(), ArgPE->getNumExpansions());
    } else {
      Arg = DeductionArg;
    }
  };

  // If the parameter type somehow involves auto, deduce the type now.
  DeducedType *DeducedT = ParamType->getContainedDeducedType();
  if (getLangOpts().CPlusPlus17 && DeducedT && !DeducedT->isDeduced()) {
    // During template argument deduction, we allow 'decltype(auto)' to
    // match an arbitrary dependent argument.
    // FIXME: The language rules don't say what happens in this case.
    // FIXME: We get an opaque dependent type out of decltype(auto) if the
    // expression is merely instantiation-dependent; is this enough?
    if (DeductionArg->isTypeDependent()) {
      auto *AT = dyn_cast<AutoType>(DeducedT);
      if (AT && AT->isDecltypeAuto()) {
        SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
        CanonicalConverted = TemplateArgument(
            Context.getCanonicalTemplateArgument(SugaredConverted));
        return Arg;
      }
    }

    // When checking a deduced template argument, deduce from its type even if
    // the type is dependent, in order to check the types of non-type template
    // arguments line up properly in partial ordering.
    TypeSourceInfo *TSI =
        Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation());
    if (isa<DeducedTemplateSpecializationType>(DeducedT)) {
      InitializedEntity Entity =
          InitializedEntity::InitializeTemplateParameter(ParamType, Param);
      InitializationKind Kind = InitializationKind::CreateForInit(
          DeductionArg->getBeginLoc(), /*DirectInit*/false, DeductionArg);
      Expr *Inits[1] = {DeductionArg};
      ParamType =
          DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, Inits);
      if (ParamType.isNull())
        return ExprError();
    } else {
      TemplateDeductionInfo Info(DeductionArg->getExprLoc(),
                                 Param->getDepth() + 1);
      ParamType = QualType();
      TemplateDeductionResult Result =
          DeduceAutoType(TSI->getTypeLoc(), DeductionArg, ParamType, Info,
                         /*DependentDeduction=*/true,
                         // We do not check constraints right now because the
                         // immediately-declared constraint of the auto type is
                         // also an associated constraint, and will be checked
                         // along with the other associated constraints after
                         // checking the template argument list.
                         /*IgnoreConstraints=*/true);
      if (Result == TemplateDeductionResult::AlreadyDiagnosed) {
        if (ParamType.isNull())
          return ExprError();
      } else if (Result != TemplateDeductionResult::Success) {
        Diag(Arg->getExprLoc(),
             diag::err_non_type_template_parm_type_deduction_failure)
            << Param->getDeclName() << Param->getType() << Arg->getType()
            << Arg->getSourceRange();
        NoteTemplateParameterLocation(*Param);
        return ExprError();
      }
    }
    // CheckNonTypeTemplateParameterType will produce a diagnostic if there's
    // an error. The error message normally references the parameter
    // declaration, but here we'll pass the argument location because that's
    // where the parameter type is deduced.
    ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc());
    if (ParamType.isNull()) {
      NoteTemplateParameterLocation(*Param);
      return ExprError();
    }
  }

  // We should have already dropped all cv-qualifiers by now.
  assert(!ParamType.hasQualifiers() &&
         "non-type template parameter type cannot be qualified");

  // If either the parameter has a dependent type or the argument is
  // type-dependent, there's nothing we can check now.
  if (ParamType->isDependentType() || DeductionArg->isTypeDependent()) {
    // Force the argument to the type of the parameter to maintain invariants.
    ExprResult E = ImpCastExprToType(
        DeductionArg, ParamType.getNonLValueExprType(Context), CK_Dependent,
        ParamType->isLValueReferenceType()   ? VK_LValue
        : ParamType->isRValueReferenceType() ? VK_XValue
                                             : VK_PRValue);
    if (E.isInvalid())
      return ExprError();
    setDeductionArg(E.get());
    SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
    CanonicalConverted = TemplateArgument(
        Context.getCanonicalTemplateArgument(SugaredConverted));
    return Arg;
  }

  // FIXME: When Param is a reference, should we check that Arg is an lvalue?
  if (CTAK == CTAK_Deduced && !StrictCheck &&
      (ParamType->isReferenceType()
           ? !Context.hasSameType(ParamType.getNonReferenceType(),
                                  DeductionArg->getType())
           : !Context.hasSameUnqualifiedType(ParamType,
                                             DeductionArg->getType()))) {
    // FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770,
    // we should actually be checking the type of the template argument in P,
    // not the type of the template argument deduced from A, against the
    // template parameter type.
    Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
        << Arg->getType() << ParamType.getUnqualifiedType();
    NoteTemplateParameterLocation(*Param);
    return ExprError();
  }

  // If the argument is a pack expansion, we don't know how many times it would
  // expand. If we continue checking the argument, this will make the template
  // definition ill-formed if it would be ill-formed for any number of
  // expansions during instantiation time. When partial ordering or matching
  // template template parameters, this is exactly what we want. Otherwise, the
  // normal template rules apply: we accept the template if it would be valid
  // for any number of expansions (i.e. none).
  if (ArgPE && !StrictCheck) {
    SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
    CanonicalConverted = TemplateArgument(
        Context.getCanonicalTemplateArgument(SugaredConverted));
    return Arg;
  }

  // Avoid making a copy when initializing a template parameter of class type
  // from a template parameter object of the same type. This is going beyond
  // the standard, but is required for soundness: in
  //   template<A a> struct X { X *p; X<a> *q; };
  // ... we need p and q to have the same type.
  //
  // Similarly, don't inject a call to a copy constructor when initializing
  // from a template parameter of the same type.
  Expr *InnerArg = DeductionArg->IgnoreParenImpCasts();
  if (ParamType->isRecordType() && isa<DeclRefExpr>(InnerArg) &&
      Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) {
    NamedDecl *ND = cast<DeclRefExpr>(InnerArg)->getDecl();
    if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {

      SugaredConverted = TemplateArgument(TPO, ParamType);
      CanonicalConverted = TemplateArgument(TPO->getCanonicalDecl(),
                                            ParamType.getCanonicalType());
      return Arg;
    }
    if (isa<NonTypeTemplateParmDecl>(ND)) {
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
      return Arg;
    }
  }

  // The initialization of the parameter from the argument is
  // a constant-evaluated context.
  EnterExpressionEvaluationContext ConstantEvaluated(
      *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);

  bool IsConvertedConstantExpression = true;
  if (isa<InitListExpr>(DeductionArg) || ParamType->isRecordType()) {
    InitializationKind Kind = InitializationKind::CreateForInit(
        StartLoc, /*DirectInit=*/false, DeductionArg);
    Expr *Inits[1] = {DeductionArg};
    InitializedEntity Entity =
        InitializedEntity::InitializeTemplateParameter(ParamType, Param);
    InitializationSequence InitSeq(*this, Entity, Kind, Inits);
    ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Inits);
    if (Result.isInvalid() || !Result.get())
      return ExprError();
    Result = ActOnConstantExpression(Result.get());
    if (Result.isInvalid() || !Result.get())
      return ExprError();
    setDeductionArg(ActOnFinishFullExpr(Result.get(), Arg->getBeginLoc(),
                                        /*DiscardedValue=*/false,
                                        /*IsConstexpr=*/true,
                                        /*IsTemplateArgument=*/true)
                        .get());
    IsConvertedConstantExpression = false;
  }

  if (getLangOpts().CPlusPlus17 || StrictCheck) {
    // C++17 [temp.arg.nontype]p1:
    //   A template-argument for a non-type template parameter shall be
    //   a converted constant expression of the type of the template-parameter.
    APValue Value;
    ExprResult ArgResult;
    if (IsConvertedConstantExpression) {
      ArgResult = BuildConvertedConstantExpression(
          DeductionArg, ParamType,
          StrictCheck ? CCEKind::TempArgStrict : CCEKind::TemplateArg, Param);
      assert(!ArgResult.isUnset());
      if (ArgResult.isInvalid()) {
        NoteTemplateParameterLocation(*Param);
        return ExprError();
      }
    } else {
      ArgResult = DeductionArg;
    }

    // For a value-dependent argument, CheckConvertedConstantExpression is
    // permitted (and expected) to be unable to determine a value.
    if (ArgResult.get()->isValueDependent()) {
      setDeductionArg(ArgResult.get());
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
      return Arg;
    }

    APValue PreNarrowingValue;
    ArgResult = EvaluateConvertedConstantExpression(
        ArgResult.get(), ParamType, Value, CCEKind::TemplateArg, /*RequireInt=*/
        false, PreNarrowingValue);
    if (ArgResult.isInvalid())
      return ExprError();
    setDeductionArg(ArgResult.get());

    if (Value.isLValue()) {
      APValue::LValueBase Base = Value.getLValueBase();
      auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
      //   For a non-type template-parameter of pointer or reference type,
      //   the value of the constant expression shall not refer to
      assert(ParamType->isPointerOrReferenceType() ||
             ParamType->isNullPtrType());
      // -- a temporary object
      // -- a string literal
      // -- the result of a typeid expression, or
      // -- a predefined __func__ variable
      if (Base &&
          (!VD ||
           isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
        Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
            << Arg->getSourceRange();
        return ExprError();
      }

      if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD &&
          VD->getType()->isArrayType() &&
          Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
          !Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
        if (ArgPE) {
          SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
          CanonicalConverted =
              Context.getCanonicalTemplateArgument(SugaredConverted);
        } else {
          SugaredConverted = TemplateArgument(VD, ParamType);
          CanonicalConverted =
              TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
                               ParamType.getCanonicalType());
        }
        return Arg;
      }

      // -- a subobject [until C++20]
      if (!getLangOpts().CPlusPlus20) {
        if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
            Value.isLValueOnePastTheEnd()) {
          Diag(StartLoc, diag::err_non_type_template_arg_subobject)
              << Value.getAsString(Context, ParamType);
          return ExprError();
        }
        assert((VD || !ParamType->isReferenceType()) &&
               "null reference should not be a constant expression");
        assert((!VD || !ParamType->isNullPtrType()) &&
               "non-null value of type nullptr_t?");
      }
    }

    if (Value.isAddrLabelDiff())
      return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);

    if (ArgPE) {
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
    } else {
      SugaredConverted = TemplateArgument(Context, ParamType, Value);
      CanonicalConverted =
          TemplateArgument(Context, ParamType.getCanonicalType(), Value);
    }
    return Arg;
  }

  // C++ [temp.arg.nontype]p5:
  //   The following conversions are performed on each expression used
  //   as a non-type template-argument. If a non-type
  //   template-argument cannot be converted to the type of the
  //   corresponding template-parameter then the program is
  //   ill-formed.
  if (ParamType->isIntegralOrEnumerationType()) {
    // C++11:
    //   -- for a non-type template-parameter of integral or
    //      enumeration type, conversions permitted in a converted
    //      constant expression are applied.
    //
    // C++98:
    //   -- for a non-type template-parameter of integral or
    //      enumeration type, integral promotions (4.5) and integral
    //      conversions (4.7) are applied.

    if (getLangOpts().CPlusPlus11) {
      // C++ [temp.arg.nontype]p1:
      //   A template-argument for a non-type, non-template template-parameter
      //   shall be one of:
      //
      //     -- for a non-type template-parameter of integral or enumeration
      //        type, a converted constant expression of the type of the
      //        template-parameter; or
      llvm::APSInt Value;
      ExprResult ArgResult = CheckConvertedConstantExpression(
          DeductionArg, ParamType, Value, CCEKind::TemplateArg);
      if (ArgResult.isInvalid())
        return ExprError();
      setDeductionArg(ArgResult.get());

      // We can't check arbitrary value-dependent arguments.
      if (DeductionArg->isValueDependent()) {
        SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
        CanonicalConverted =
            Context.getCanonicalTemplateArgument(SugaredConverted);
        return Arg;
      }

      // Widen the argument value to sizeof(parameter type). This is almost
      // always a no-op, except when the parameter type is bool. In
      // that case, this may extend the argument from 1 bit to 8 bits.
      QualType IntegerType = ParamType;
      if (const EnumType *Enum = IntegerType->getAs<EnumType>())
        IntegerType = Enum->getDecl()->getIntegerType();
      Value = Value.extOrTrunc(IntegerType->isBitIntType()
                                   ? Context.getIntWidth(IntegerType)
                                   : Context.getTypeSize(IntegerType));

      if (ArgPE) {
        SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
        CanonicalConverted =
            Context.getCanonicalTemplateArgument(SugaredConverted);
      } else {
        SugaredConverted = TemplateArgument(Context, Value, ParamType);
        CanonicalConverted = TemplateArgument(
            Context, Value, Context.getCanonicalType(ParamType));
      }
      return Arg;
    }

    ExprResult ArgResult = DefaultLvalueConversion(Arg);
    if (ArgResult.isInvalid())
      return ExprError();
    DeductionArg = ArgResult.get();

    QualType ArgType = DeductionArg->getType();

    // C++ [temp.arg.nontype]p1:
    //   A template-argument for a non-type, non-template
    //   template-parameter shall be one of:
    //
    //     -- an integral constant-expression of integral or enumeration
    //        type; or
    //     -- the name of a non-type template-parameter; or
    llvm::APSInt Value;
    if (!ArgType->isIntegralOrEnumerationType()) {
      Diag(StartLoc, diag::err_template_arg_not_integral_or_enumeral)
          << ArgType << DeductionArg->getSourceRange();
      NoteTemplateParameterLocation(*Param);
      return ExprError();
    } else if (!DeductionArg->isValueDependent()) {
      class TmplArgICEDiagnoser : public VerifyICEDiagnoser {
        QualType T;

      public:
        TmplArgICEDiagnoser(QualType T) : T(T) { }

        SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
                                             SourceLocation Loc) override {
          return S.Diag(Loc, diag::err_template_arg_not_ice) << T;
        }
      } Diagnoser(ArgType);

      DeductionArg =
          VerifyIntegerConstantExpression(DeductionArg, &Value, Diagnoser)
              .get();
      if (!DeductionArg)
        return ExprError();
    }

    // From here on out, all we care about is the unqualified form
    // of the argument type.
    ArgType = ArgType.getUnqualifiedType();

    // Try to convert the argument to the parameter's type.
    if (Context.hasSameType(ParamType, ArgType)) {
      // Okay: no conversion necessary
    } else if (ParamType->isBooleanType()) {
      // This is an integral-to-boolean conversion.
      DeductionArg =
          ImpCastExprToType(DeductionArg, ParamType, CK_IntegralToBoolean)
              .get();
    } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
               !ParamType->isEnumeralType()) {
      // This is an integral promotion or conversion.
      DeductionArg =
          ImpCastExprToType(DeductionArg, ParamType, CK_IntegralCast).get();
    } else {
      // We can't perform this conversion.
      Diag(StartLoc, diag::err_template_arg_not_convertible)
          << DeductionArg->getType() << ParamType
          << DeductionArg->getSourceRange();
      NoteTemplateParameterLocation(*Param);
      return ExprError();
    }
    setDeductionArg(DeductionArg);

    // Add the value of this argument to the list of converted
    // arguments. We use the bitwidth and signedness of the template
    // parameter.
    if (DeductionArg->isValueDependent()) {
      // The argument is value-dependent. Create a new
      // TemplateArgument with the converted expression.
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
      return Arg;
    }

    QualType IntegerType = ParamType;
    if (const EnumType *Enum = IntegerType->getAs<EnumType>()) {
      IntegerType = Enum->getDecl()->getIntegerType();
    }

    if (ParamType->isBooleanType()) {
      // Value must be zero or one.
      Value = Value != 0;
      unsigned AllowedBits = Context.getTypeSize(IntegerType);
      if (Value.getBitWidth() != AllowedBits)
        Value = Value.extOrTrunc(AllowedBits);
      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
    } else {
      llvm::APSInt OldValue = Value;

      // Coerce the template argument's value to the value it will have
      // based on the template parameter's type.
      unsigned AllowedBits = IntegerType->isBitIntType()
                                 ? Context.getIntWidth(IntegerType)
                                 : Context.getTypeSize(IntegerType);
      if (Value.getBitWidth() != AllowedBits)
        Value = Value.extOrTrunc(AllowedBits);
      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());

      // Complain if an unsigned parameter received a negative value.
      if (IntegerType->isUnsignedIntegerOrEnumerationType() &&
          (OldValue.isSigned() && OldValue.isNegative())) {
        Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative)
            << toString(OldValue, 10) << toString(Value, 10) << Param->getType()
            << Arg->getSourceRange();
        NoteTemplateParameterLocation(*Param);
      }

      // Complain if we overflowed the template parameter's type.
      unsigned RequiredBits;
      if (IntegerType->isUnsignedIntegerOrEnumerationType())
        RequiredBits = OldValue.getActiveBits();
      else if (OldValue.isUnsigned())
        RequiredBits = OldValue.getActiveBits() + 1;
      else
        RequiredBits = OldValue.getSignificantBits();
      if (RequiredBits > AllowedBits) {
        Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large)
            << toString(OldValue, 10) << toString(Value, 10) << Param->getType()
            << Arg->getSourceRange();
        NoteTemplateParameterLocation(*Param);
      }
    }

    if (ArgPE) {
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
    } else {
      QualType T = ParamType->isEnumeralType() ? ParamType : IntegerType;
      SugaredConverted = TemplateArgument(Context, Value, T);
      CanonicalConverted =
          TemplateArgument(Context, Value, Context.getCanonicalType(T));
    }
    return Arg;
  }

  QualType ArgType = DeductionArg->getType();
  DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction

  // Handle pointer-to-function, reference-to-function, and
  // pointer-to-member-function all in (roughly) the same way.
  if (// -- For a non-type template-parameter of type pointer to
      //    function, only the function-to-pointer conversion (4.3) is
      //    applied. If the template-argument represents a set of
      //    overloaded functions (or a pointer to such), the matching
      //    function is selected from the set (13.4).
      (ParamType->isPointerType() &&
       ParamType->castAs<PointerType>()->getPointeeType()->isFunctionType()) ||
      // -- For a non-type template-parameter of type reference to
      //    function, no conversions apply. If the template-argument
      //    represents a set of overloaded functions, the matching
      //    function is selected from the set (13.4).
      (ParamType->isReferenceType() &&
       ParamType->castAs<ReferenceType>()->getPointeeType()->isFunctionType()) ||
      // -- For a non-type template-parameter of type pointer to
      //    member function, no conversions apply. If the
      //    template-argument represents a set of overloaded member
      //    functions, the matching member function is selected from
      //    the set (13.4).
      (ParamType->isMemberPointerType() &&
       ParamType->castAs<MemberPointerType>()->getPointeeType()
         ->isFunctionType())) {

    if (DeductionArg->getType() == Context.OverloadTy) {
      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
                                                                true,
                                                                FoundResult)) {
        if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
          return ExprError();

        ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
        if (Res.isInvalid())
          return ExprError();
        DeductionArg = Res.get();
        ArgType = Arg->getType();
      } else
        return ExprError();
    }
    setDeductionArg(DeductionArg);

    if (!ParamType->isMemberPointerType()) {
      if (CheckTemplateArgumentAddressOfObjectOrFunction(
              *this, Param, ParamType, Arg, SugaredConverted,
              CanonicalConverted))
        return ExprError();
      return Arg;
    }

    if (CheckTemplateArgumentPointerToMember(
            *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
      return ExprError();
    return Arg;
  }

  setDeductionArg(DeductionArg);

  if (ParamType->isPointerType()) {
    //   -- for a non-type template-parameter of type pointer to
    //      object, qualification conversions (4.4) and the
    //      array-to-pointer conversion (4.2) are applied.
    // C++0x also allows a value of std::nullptr_t.
    assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
           "Only object pointers allowed here");

    // FIXME: Deal with pack expansions here.
    if (CheckTemplateArgumentAddressOfObjectOrFunction(
            *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
      return ExprError();
    return Arg;
  }

  if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
    //   -- For a non-type template-parameter of type reference to
    //      object, no conversions apply. The type referred to by the
    //      reference may be more cv-qualified than the (otherwise
    //      identical) type of the template-argument. The
    //      template-parameter is bound directly to the
    //      template-argument, which must be an lvalue.
    assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() &&
           "Only object references allowed here");

    // FIXME: Deal with pack expansions here.
    if (Arg->getType() == Context.OverloadTy) {
      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
                                                 ParamRefType->getPointeeType(),
                                                                true,
                                                                FoundResult)) {
        if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
          return ExprError();
        ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
        if (Res.isInvalid())
          return ExprError();
        Arg = Res.get();
        ArgType = Arg->getType();
      } else
        return ExprError();
    }

    if (CheckTemplateArgumentAddressOfObjectOrFunction(
            *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
      return ExprError();
    return Arg;
  }

  // Deal with parameters of type std::nullptr_t.
  if (ParamType->isNullPtrType()) {
    if (DeductionArg->isTypeDependent() || DeductionArg->isValueDependent()) {
      SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
      CanonicalConverted =
          Context.getCanonicalTemplateArgument(SugaredConverted);
      return Arg;
    }

    switch (isNullPointerValueTemplateArgument(*this, Param, ParamType,
                                               DeductionArg)) {
    case NPV_NotNullPointer:
      Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
          << DeductionArg->getType() << ParamType;
      NoteTemplateParameterLocation(*Param);
      return ExprError();

    case NPV_Error:
      return ExprError();

    case NPV_NullPointer:
      Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
      if (ArgPE) {
        SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
        CanonicalConverted =
            Context.getCanonicalTemplateArgument(SugaredConverted);
      } else {
        SugaredConverted = TemplateArgument(ParamType,
                                            /*isNullPtr=*/true);
        CanonicalConverted =
            TemplateArgument(Context.getCanonicalType(ParamType),
                             /*isNullPtr=*/true);
      }
      return Arg;
    }
  }

  //     -- For a non-type template-parameter of type pointer to data
  //        member, qualification conversions (4.4) are applied.
  assert(ParamType->isMemberPointerType() && "Only pointers to members remain");

  // FIXME: Deal with pack expansions here.
  if (CheckTemplateArgumentPointerToMember(
          *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted))
    return ExprError();
  return Arg;
}

static void DiagnoseTemplateParameterListArityMismatch(
    Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
    Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);

bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
                                         TemplateParameterList *Params,
                                         TemplateArgumentLoc &Arg,
                                         bool PartialOrdering,
                                         bool *StrictPackMatch) {
  TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
  auto [Template, DefaultArgs] = Name.getTemplateDeclAndDefaultArgs();
  if (!Template) {
    // Any dependent template name is fine.
    assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
    return false;
  }

  if (Template->isInvalidDecl())
    return true;

  // C++0x [temp.arg.template]p1:
  //   A template-argument for a template template-parameter shall be
  //   the name of a class template or an alias template, expressed as an
  //   id-expression. When the template-argument names a class template, only
  //   primary class templates are considered when matching the
  //   template template argument with the corresponding parameter;
  //   partial specializations are not considered even if their
  //   parameter lists match that of the template template parameter.
  //
  // Note that we also allow template template parameters here, which
  // will happen when we are dealing with, e.g., class template
  // partial specializations.
  if (!isa<ClassTemplateDecl>(Template) &&
      !isa<TemplateTemplateParmDecl>(Template) &&
      !isa<TypeAliasTemplateDecl>(Template) &&
      !isa<BuiltinTemplateDecl>(Template)) {
    assert(isa<FunctionTemplateDecl>(Template) &&
           "Only function templates are possible here");
    Diag(Arg.getLocation(), diag::err_template_arg_not_valid_template);
    Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
      << Template;
  }

  // C++1z [temp.arg.template]p3: (DR 150)
  //   A template-argument matches a template template-parameter P when P
  //   is at least as specialized as the template-argument A.
  if (!isTemplateTemplateParameterAtLeastAsSpecializedAs(
          Params, Param, Template, DefaultArgs, Arg.getLocation(),
          PartialOrdering, StrictPackMatch))
    return true;
  // P2113
  // C++20[temp.func.order]p2
  //   [...] If both deductions succeed, the partial ordering selects the
  // more constrained template (if one exists) as determined below.
  SmallVector<AssociatedConstraint, 3> ParamsAC, TemplateAC;
  Params->getAssociatedConstraints(ParamsAC);
  // C++20[temp.arg.template]p3
  //   [...] In this comparison, if P is unconstrained, the constraints on A
  //   are not considered.
  if (ParamsAC.empty())
    return false;

  Template->getAssociatedConstraints(TemplateAC);

  bool IsParamAtLeastAsConstrained;
  if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
                             IsParamAtLeastAsConstrained))
    return true;
  if (!IsParamAtLeastAsConstrained) {
    Diag(Arg.getLocation(),
         diag::err_template_template_parameter_not_at_least_as_constrained)
        << Template << Param << Arg.getSourceRange();
    Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
    Diag(Template->getLocation(), diag::note_entity_declared_at) << Template;
    MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
                                                  TemplateAC);
    return true;
  }
  return false;
}

static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl,
                                                unsigned HereDiagID,
                                                unsigned ExternalDiagID) {
  if (Decl.getLocation().isValid())
    return S.Diag(Decl.getLocation(), HereDiagID);

  SmallString<128> Str;
  llvm::raw_svector_ostream Out(Str);
  PrintingPolicy PP = S.getPrintingPolicy();
  PP.TerseOutput = 1;
  Decl.print(Out, PP);
  return S.Diag(Decl.getLocation(), ExternalDiagID) << Out.str();
}

void Sema::NoteTemplateLocation(const NamedDecl &Decl,
                                std::optional<SourceRange> ParamRange) {
  SemaDiagnosticBuilder DB =
      noteLocation(*this, Decl, diag::note_template_decl_here,
                   diag::note_template_decl_external);
  if (ParamRange && ParamRange->isValid()) {
    assert(Decl.getLocation().isValid() &&
           "Parameter range has location when Decl does not");
    DB << *ParamRange;
  }
}

void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) {
  noteLocation(*this, Decl, diag::note_template_param_here,
               diag::note_template_param_external);
}

ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
    const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc,
    NamedDecl *TemplateParam) {
  // C++ [temp.param]p8:
  //
  //   A non-type template-parameter of type "array of T" or
  //   "function returning T" is adjusted to be of type "pointer to
  //   T" or "pointer to function returning T", respectively.
  if (ParamType->isArrayType())
    ParamType = Context.getArrayDecayedType(ParamType);
  else if (ParamType->isFunctionType())
    ParamType = Context.getPointerType(ParamType);

  // For a NULL non-type template argument, return nullptr casted to the
  // parameter's type.
  if (Arg.getKind() == TemplateArgument::NullPtr) {
    return ImpCastExprToType(
             new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
                             ParamType,
                             ParamType->getAs<MemberPointerType>()
                               ? CK_NullToMemberPointer
                               : CK_NullToPointer);
  }
  assert(Arg.getKind() == TemplateArgument::Declaration &&
         "Only declaration template arguments permitted here");

  ValueDecl *VD = Arg.getAsDecl();

  CXXScopeSpec SS;
  if (ParamType->isMemberPointerType()) {
    // If this is a pointer to member, we need to use a qualified name to
    // form a suitable pointer-to-member constant.
    assert(VD->getDeclContext()->isRecord() &&
           (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
            isa<IndirectFieldDecl>(VD)));
    QualType ClassType
      = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
    NestedNameSpecifier *Qualifier =
        NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr());
    SS.MakeTrivial(Context, Qualifier, Loc);
  }

  ExprResult RefExpr = BuildDeclarationNameExpr(
      SS, DeclarationNameInfo(VD->getDeclName(), Loc), VD);
  if (RefExpr.isInvalid())
    return ExprError();

  // For a pointer, the argument declaration is the pointee. Take its address.
  QualType ElemT(RefExpr.get()->getType()->getArrayElementTypeNoTypeQual(), 0);
  if (ParamType->isPointerType() && !ElemT.isNull() &&
      Context.hasSimilarType(ElemT, ParamType->getPointeeType())) {
    // Decay an array argument if we want a pointer to its first element.
    RefExpr = DefaultFunctionArrayConversion(RefExpr.get());
    if (RefExpr.isInvalid())
      return ExprError();
  } else if (ParamType->isPointerType() || ParamType->isMemberPointerType()) {
    // For any other pointer, take the address (or form a pointer-to-member).
    RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
    if (RefExpr.isInvalid())
      return ExprError();
  } else if (ParamType->isRecordType()) {
    assert(isa<TemplateParamObjectDecl>(VD) &&
           "arg for class template param not a template parameter object");
    // No conversions apply in this case.
    return RefExpr;
  } else {
    assert(ParamType->isReferenceType() &&
           "unexpected type for decl template argument");
    if (NonTypeTemplateParmDecl *NTTP =
            dyn_cast_if_present<NonTypeTemplateParmDecl>(TemplateParam)) {
      QualType TemplateParamType = NTTP->getType();
      const AutoType *AT = TemplateParamType->getAs<AutoType>();
      if (AT && AT->isDecltypeAuto()) {
        RefExpr = new (getASTContext()) SubstNonTypeTemplateParmExpr(
            ParamType->getPointeeType(), RefExpr.get()->getValueKind(),
            RefExpr.get()->getExprLoc(), RefExpr.get(), VD, NTTP->getIndex(),
            /*PackIndex=*/std::nullopt,
            /*RefParam=*/true, /*Final=*/true);
      }
    }
  }

  // At this point we should have the right value category.
  assert(ParamType->isReferenceType() == RefExpr.get()->isLValue() &&
         "value kind mismatch for non-type template argument");

  // The type of the template parameter can differ from the type of the
  // argument in various ways; convert it now if necessary.
  QualType DestExprType = ParamType.getNonLValueExprType(Context);
  if (!Context.hasSameType(RefExpr.get()->getType(), DestExprType)) {
    CastKind CK;
    QualType Ignored;
    if (Context.hasSimilarType(RefExpr.get()->getType(), DestExprType) ||
        IsFunctionConversion(RefExpr.get()->getType(), DestExprType, Ignored)) {
      CK = CK_NoOp;
    } else if (ParamType->isVoidPointerType() &&
               RefExpr.get()->getType()->isPointerType()) {
      CK = CK_BitCast;
    } else {
      // FIXME: Pointers to members can need conversion derived-to-base or
      // base-to-derived conversions. We currently don't retain enough
      // information to convert properly (we need to track a cast path or
      // subobject number in the template argument).
      llvm_unreachable(
          "unexpected conversion required for non-type template argument");
    }
    RefExpr = ImpCastExprToType(RefExpr.get(), DestExprType, CK,
                                RefExpr.get()->getValueKind());
  }

  return RefExpr;
}

/// Construct a new expression that refers to the given
/// integral template argument with the given source-location
/// information.
///
/// This routine takes care of the mapping from an integral template
/// argument (which may have any integral type) to the appropriate
/// literal value.
static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
    Sema &S, QualType OrigT, const llvm::APSInt &Int, SourceLocation Loc) {
  assert(OrigT->isIntegralOrEnumerationType());

  // If this is an enum type that we're instantiating, we need to use an integer
  // type the same size as the enumerator.  We don't want to build an
  // IntegerLiteral with enum type.  The integer type of an enum type can be of
  // any integral type with C++11 enum classes, make sure we create the right
  // type of literal for it.
  QualType T = OrigT;
  if (const EnumType *ET = OrigT->getAs<EnumType>())
    T = ET->getDecl()->getIntegerType();

  Expr *E;
  if (T->isAnyCharacterType()) {
    CharacterLiteralKind Kind;
    if (T->isWideCharType())
      Kind = CharacterLiteralKind::Wide;
    else if (T->isChar8Type() && S.getLangOpts().Char8)
      Kind = CharacterLiteralKind::UTF8;
    else if (T->isChar16Type())
      Kind = CharacterLiteralKind::UTF16;
    else if (T->isChar32Type())
      Kind = CharacterLiteralKind::UTF32;
    else
      Kind = CharacterLiteralKind::Ascii;

    E = new (S.Context) CharacterLiteral(Int.getZExtValue(), Kind, T, Loc);
  } else if (T->isBooleanType()) {
    E = CXXBoolLiteralExpr::Create(S.Context, Int.getBoolValue(), T, Loc);
  } else {
    E = IntegerLiteral::Create(S.Context, Int, T, Loc);
  }

  if (OrigT->isEnumeralType()) {
    // FIXME: This is a hack. We need a better way to handle substituted
    // non-type template parameters.
    E = CStyleCastExpr::Create(S.Context, OrigT, VK_PRValue, CK_IntegralCast, E,
                               nullptr, S.CurFPFeatureOverrides(),
                               S.Context.getTrivialTypeSourceInfo(OrigT, Loc),
                               Loc, Loc);
  }

  return E;
}

static Expr *BuildExpressionFromNonTypeTemplateArgumentValue(
    Sema &S, QualType T, const APValue &Val, SourceLocation Loc) {
  auto MakeInitList = [&](ArrayRef<Expr *> Elts) -> Expr * {
    auto *ILE = new (S.Context) InitListExpr(S.Context, Loc, Elts, Loc);
    ILE->setType(T);
    return ILE;
  };

  switch (Val.getKind()) {
  case APValue::AddrLabelDiff:
    // This cannot occur in a template argument at all.
  case APValue::Array:
  case APValue::Struct:
  case APValue::Union:
    // These can only occur within a template parameter object, which is
    // represented as a TemplateArgument::Declaration.
    llvm_unreachable("unexpected template argument value");

  case APValue::Int:
    return BuildExpressionFromIntegralTemplateArgumentValue(S, T, Val.getInt(),
                                                            Loc);

  case APValue::Float:
    return FloatingLiteral::Create(S.Context, Val.getFloat(), /*IsExact=*/true,
                                   T, Loc);

  case APValue::FixedPoint:
    return FixedPointLiteral::CreateFromRawInt(
        S.Context, Val.getFixedPoint().getValue(), T, Loc,
        Val.getFixedPoint().getScale());

  case APValue::ComplexInt: {
    QualType ElemT = T->castAs<ComplexType>()->getElementType();
    return MakeInitList({BuildExpressionFromIntegralTemplateArgumentValue(
                             S, ElemT, Val.getComplexIntReal(), Loc),
                         BuildExpressionFromIntegralTemplateArgumentValue(
                             S, ElemT, Val.getComplexIntImag(), Loc)});
  }

  case APValue::ComplexFloat: {
    QualType ElemT = T->castAs<ComplexType>()->getElementType();
    return MakeInitList(
        {FloatingLiteral::Create(S.Context, Val.getComplexFloatReal(), true,
                                 ElemT, Loc),
         FloatingLiteral::Create(S.Context, Val.getComplexFloatImag(), true,
                                 ElemT, Loc)});
  }

  case APValue::Vector: {
    QualType ElemT = T->castAs<VectorType>()->getElementType();
    llvm::SmallVector<Expr *, 8> Elts;
    for (unsigned I = 0, N = Val.getVectorLength(); I != N; ++I)
      Elts.push_back(BuildExpressionFromNonTypeTemplateArgumentValue(
          S, ElemT, Val.getVectorElt(I), Loc));
    return MakeInitList(Elts);
  }

  case APValue::None:
  case APValue::Indeterminate:
    llvm_unreachable("Unexpected APValue kind.");
  case APValue::LValue:
  case APValue::MemberPointer:
    // There isn't necessarily a valid equivalent source-level syntax for
    // these; in particular, a naive lowering might violate access control.
    // So for now we lower to a ConstantExpr holding the value, wrapped around
    // an OpaqueValueExpr.
    // FIXME: We should have a better representation for this.
    ExprValueKind VK = VK_PRValue;
    if (T->isReferenceType()) {
      T = T->getPointeeType();
      VK = VK_LValue;
    }
    auto *OVE = new (S.Context) OpaqueValueExpr(Loc, T, VK);
    return ConstantExpr::Create(S.Context, OVE, Val);
  }
  llvm_unreachable("Unhandled APValue::ValueKind enum");
}

ExprResult
Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
                                                 SourceLocation Loc) {
  switch (Arg.getKind()) {
  case TemplateArgument::Null:
  case TemplateArgument::Type:
  case TemplateArgument::Template:
  case TemplateArgument::TemplateExpansion:
  case TemplateArgument::Pack:
    llvm_unreachable("not a non-type template argument");

  case TemplateArgument::Expression:
    return Arg.getAsExpr();

  case TemplateArgument::NullPtr:
  case TemplateArgument::Declaration:
    return BuildExpressionFromDeclTemplateArgument(
        Arg, Arg.getNonTypeTemplateArgumentType(), Loc);

  case TemplateArgument::Integral:
    return BuildExpressionFromIntegralTemplateArgumentValue(
        *this, Arg.getIntegralType(), Arg.getAsIntegral(), Loc);

  case TemplateArgument::StructuralValue:
    return BuildExpressionFromNonTypeTemplateArgumentValue(
        *this, Arg.getStructuralValueType(), Arg.getAsStructuralValue(), Loc);
  }
  llvm_unreachable("Unhandled TemplateArgument::ArgKind enum");
}

/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(
    Sema &S, NamedDecl *New,
    const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
    const NamedDecl *OldInstFrom, bool Complain,
    Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
  // Check the actual kind (type, non-type, template).
  if (Old->getKind() != New->getKind()) {
    if (Complain) {
      unsigned NextDiag = diag::err_template_param_different_kind;
      if (TemplateArgLoc.isValid()) {
        S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
        NextDiag = diag::note_template_param_different_kind;
      }
      S.Diag(New->getLocation(), NextDiag)
        << (Kind != Sema::TPL_TemplateMatch);
      S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
        << (Kind != Sema::TPL_TemplateMatch);
    }

    return false;
  }

  // Check that both are parameter packs or neither are parameter packs.
  // However, if we are matching a template template argument to a
  // template template parameter, the template template parameter can have
  // a parameter pack where the template template argument does not.
  if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) {
    if (Complain) {
      unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
      if (TemplateArgLoc.isValid()) {
        S.Diag(TemplateArgLoc,
             diag::err_template_arg_template_params_mismatch);
        NextDiag = diag::note_template_parameter_pack_non_pack;
      }

      unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
                      : isa<NonTypeTemplateParmDecl>(New)? 1
                      : 2;
      S.Diag(New->getLocation(), NextDiag)
        << ParamKind << New->isParameterPack();
      S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
        << ParamKind << Old->isParameterPack();
    }

    return false;
  }

  // For non-type template parameters, check the type of the parameter.
  if (NonTypeTemplateParmDecl *OldNTTP
                                    = dyn_cast<NonTypeTemplateParmDecl>(Old)) {
    NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);

    // C++20 [temp.over.link]p6:
    //   Two [non-type] template-parameters are equivalent [if] they have
    //   equivalent types ignoring the use of type-constraints for
    //   placeholder types
    QualType OldType = S.Context.getUnconstrainedType(OldNTTP->getType());
    QualType NewType = S.Context.getUnconstrainedType(NewNTTP->getType());
    if (!S.Context.hasSameType(OldType, NewType)) {
      if (Complain) {
        unsigned NextDiag = diag::err_template_nontype_parm_different_type;
        if (TemplateArgLoc.isValid()) {
          S.Diag(TemplateArgLoc,
                 diag::err_template_arg_template_params_mismatch);
          NextDiag = diag::note_template_nontype_parm_different_type;
        }
        S.Diag(NewNTTP->getLocation(), NextDiag)
            << NewNTTP->getType() << (Kind != Sema::TPL_TemplateMatch);
        S.Diag(OldNTTP->getLocation(),
               diag::note_template_nontype_parm_prev_declaration)
            << OldNTTP->getType();
      }

      return false;
    }
  }
  // For template template parameters, check the template parameter types.
  // The template parameter lists of template template
  // parameters must agree.
  else if (TemplateTemplateParmDecl *OldTTP =
               dyn_cast<TemplateTemplateParmDecl>(Old)) {
    TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);
    if (!S.TemplateParameterListsAreEqual(
            NewInstFrom, NewTTP->getTemplateParameters(), OldInstFrom,
            OldTTP->getTemplateParameters(), Complain,
            (Kind == Sema::TPL_TemplateMatch
                 ? Sema::TPL_TemplateTemplateParmMatch
                 : Kind),
            TemplateArgLoc))
      return false;
  }

  if (Kind != Sema::TPL_TemplateParamsEquivalent &&
      !isa<TemplateTemplateParmDecl>(Old)) {
    const Expr *NewC = nullptr, *OldC = nullptr;

    if (isa<TemplateTypeParmDecl>(New)) {
      if (const auto *TC = cast<TemplateTypeParmDecl>(New)->getTypeConstraint())
        NewC = TC->getImmediatelyDeclaredConstraint();
      if (const auto *TC = cast<TemplateTypeParmDecl>(Old)->getTypeConstraint())
        OldC = TC->getImmediatelyDeclaredConstraint();
    } else if (isa<NonTypeTemplateParmDecl>(New)) {
      if (const Expr *E = cast<NonTypeTemplateParmDecl>(New)
                              ->getPlaceholderTypeConstraint())
        NewC = E;
      if (const Expr *E = cast<NonTypeTemplateParmDecl>(Old)
                              ->getPlaceholderTypeConstraint())
        OldC = E;
    } else
      llvm_unreachable("unexpected template parameter type");

    auto Diagnose = [&] {
      S.Diag(NewC ? NewC->getBeginLoc() : New->getBeginLoc(),
           diag::err_template_different_type_constraint);
      S.Diag(OldC ? OldC->getBeginLoc() : Old->getBeginLoc(),
           diag::note_template_prev_declaration) << /*declaration*/0;
    };

    if (!NewC != !OldC) {
      if (Complain)
        Diagnose();
      return false;
    }

    if (NewC) {
      if (!S.AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
                                           NewC)) {
        if (Complain)
          Diagnose();
        return false;
      }
    }
  }

  return true;
}

/// Diagnose a known arity mismatch when comparing template argument
/// lists.
static
void DiagnoseTemplateParameterListArityMismatch(Sema &S,
                                                TemplateParameterList *New,
                                                TemplateParameterList *Old,
                                      Sema::TemplateParameterListEqualKind Kind,
                                                SourceLocation TemplateArgLoc) {
  unsigned NextDiag = diag::err_template_param_list_different_arity;
  if (TemplateArgLoc.isValid()) {
    S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
    NextDiag = diag::note_template_param_list_different_arity;
  }
  S.Diag(New->getTemplateLoc(), NextDiag)
    << (New->size() > Old->size())
    << (Kind != Sema::TPL_TemplateMatch)
    << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
  S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
    << (Kind != Sema::TPL_TemplateMatch)
    << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}

bool Sema::TemplateParameterListsAreEqual(
    const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
    const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
    TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
  if (Old->size() != New->size()) {
    if (Complain)
      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
                                                 TemplateArgLoc);

    return false;
  }

  // C++0x [temp.arg.template]p3:
  //   A template-argument matches a template template-parameter (call it P)
  //   when each of the template parameters in the template-parameter-list of
  //   the template-argument's corresponding class template or alias template
  //   (call it A) matches the corresponding template parameter in the
  //   template-parameter-list of P. [...]
  TemplateParameterList::iterator NewParm = New->begin();
  TemplateParameterList::iterator NewParmEnd = New->end();
  for (TemplateParameterList::iterator OldParm = Old->begin(),
                                       OldParmEnd = Old->end();
       OldParm != OldParmEnd; ++OldParm, ++NewParm) {
    if (NewParm == NewParmEnd) {
      if (Complain)
        DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
                                                   TemplateArgLoc);
      return false;
    }
    if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm,
                                    OldInstFrom, Complain, Kind,
                                    TemplateArgLoc))
      return false;
  }

  // Make sure we exhausted all of the arguments.
  if (NewParm != NewParmEnd) {
    if (Complain)
      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
                                                 TemplateArgLoc);

    return false;
  }

  if (Kind != TPL_TemplateParamsEquivalent) {
    const Expr *NewRC = New->getRequiresClause();
    const Expr *OldRC = Old->getRequiresClause();

    auto Diagnose = [&] {
      Diag(NewRC ? NewRC->getBeginLoc() : New->getTemplateLoc(),
           diag::err_template_different_requires_clause);
      Diag(OldRC ? OldRC->getBeginLoc() : Old->getTemplateLoc(),
           diag::note_template_prev_declaration) << /*declaration*/0;
    };

    if (!NewRC != !OldRC) {
      if (Complain)
        Diagnose();
      return false;
    }

    if (NewRC) {
      if (!AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
                                         NewRC)) {
        if (Complain)
          Diagnose();
        return false;
      }
    }
  }

  return true;
}

bool
Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
  if (!S)
    return false;

  // Find the nearest enclosing declaration scope.
  S = S->getDeclParent();

  // C++ [temp.pre]p6: [P2096]
  //   A template, explicit specialization, or partial specialization shall not
  //   have C linkage.
  DeclContext *Ctx = S->getEntity();
  if (Ctx && Ctx->isExternCContext()) {
    SourceRange Range =
        TemplateParams->getTemplateLoc().isInvalid() && TemplateParams->size()
            ? TemplateParams->getParam(0)->getSourceRange()
            : TemplateParams->getSourceRange();
    Diag(Range.getBegin(), diag::err_template_linkage) << Range;
    if (const LinkageSpecDecl *LSD = Ctx->getExternCContext())
      Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
    return true;
  }
  Ctx = Ctx ? Ctx->getRedeclContext() : nullptr;

  // C++ [temp]p2:
  //   A template-declaration can appear only as a namespace scope or
  //   class scope declaration.
  // C++ [temp.expl.spec]p3:
  //   An explicit specialization may be declared in any scope in which the
  //   corresponding primary template may be defined.
  // C++ [temp.class.spec]p6: [P2096]
  //   A partial specialization may be declared in any scope in which the
  //   corresponding primary template may be defined.
  if (Ctx) {
    if (Ctx->isFileContext())
      return false;
    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) {
      // C++ [temp.mem]p2:
      //   A local class shall not have member templates.
      if (RD->isLocalClass())
        return Diag(TemplateParams->getTemplateLoc(),
                    diag::err_template_inside_local_class)
          << TemplateParams->getSourceRange();
      else
        return false;
    }
  }

  return Diag(TemplateParams->getTemplateLoc(),
              diag::err_template_outside_namespace_or_class_scope)
    << TemplateParams->getSourceRange();
}

/// Determine what kind of template specialization the given declaration
/// is.
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
  if (!D)
    return TSK_Undeclared;

  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
    return Record->getTemplateSpecializationKind();
  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
    return Function->getTemplateSpecializationKind();
  if (VarDecl *Var = dyn_cast<VarDecl>(D))
    return Var->getTemplateSpecializationKind();

  return TSK_Undeclared;
}

/// Check whether a specialization is well-formed in the current
/// context.
///
/// This routine determines whether a template specialization can be declared
/// in the current context (C++ [temp.expl.spec]p2).
///
/// \param S the semantic analysis object for which this check is being
/// performed.
///
/// \param Specialized the entity being specialized or instantiated, which
/// may be a kind of template (class template, function template, etc.) or
/// a member of a class template (member function, static data member,
/// member class).
///
/// \param PrevDecl the previous declaration of this entity, if any.
///
/// \param Loc the location of the explicit specialization or instantiation of
/// this entity.
///
/// \param IsPartialSpecialization whether this is a partial specialization of
/// a class template.
///
/// \returns true if there was an error that we cannot recover from, false
/// otherwise.
static bool CheckTemplateSpecializationScope(Sema &S,
                                             NamedDecl *Specialized,
                                             NamedDecl *PrevDecl,
                                             SourceLocation Loc,
                                             bool IsPartialSpecialization) {
  // Keep these "kind" numbers in sync with the %select statements in the
  // various diagnostics emitted by this routine.
  int EntityKind = 0;
  if (isa<ClassTemplateDecl>(Specialized))
    EntityKind = IsPartialSpecialization? 1 : 0;
  else if (isa<VarTemplateDecl>(Specialized))
    EntityKind = IsPartialSpecialization ? 3 : 2;
  else if (isa<FunctionTemplateDecl>(Specialized))
    EntityKind = 4;
  else if (isa<CXXMethodDecl>(Specialized))
    EntityKind = 5;
  else if (isa<VarDecl>(Specialized))
    EntityKind = 6;
  else if (isa<RecordDecl>(Specialized))
    EntityKind = 7;
  else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11)
    EntityKind = 8;
  else {
    S.Diag(Loc, diag::err_template_spec_unknown_kind)
      << S.getLangOpts().CPlusPlus11;
    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
    return true;
  }

  // C++ [temp.expl.spec]p2:
  //   An explicit specialization may be declared in any scope in which
  //   the corresponding primary template may be defined.
  if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
    S.Diag(Loc, diag::err_template_spec_decl_function_scope)
      << Specialized;
    return true;
  }

  // C++ [temp.class.spec]p6:
  //   A class template partial specialization may be declared in any
  //   scope in which the primary template may be defined.
  DeclContext *SpecializedContext =
      Specialized->getDeclContext()->getRedeclContext();
  DeclContext *DC = S.CurContext->getRedeclContext();

  // Make sure that this redeclaration (or definition) occurs in the same
  // scope or an enclosing namespace.
  if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
                            : DC->Equals(SpecializedContext))) {
    if (isa<TranslationUnitDecl>(SpecializedContext))
      S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
        << EntityKind << Specialized;
    else {
      auto *ND = cast<NamedDecl>(SpecializedContext);
      int Diag = diag::err_template_spec_redecl_out_of_scope;
      if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
        Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
      S.Diag(Loc, Diag) << EntityKind << Specialized
                        << ND << isa<CXXRecordDecl>(ND);
    }

    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);

    // Don't allow specializing in the wrong class during error recovery.
    // Otherwise, things can go horribly wrong.
    if (DC->isRecord())
      return true;
  }

  return false;
}

static SourceRange findTemplateParameterInType(unsigned Depth, Expr *E) {
  if (!E->isTypeDependent())
    return SourceLocation();
  DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
  Checker.TraverseStmt(E);
  if (Checker.MatchLoc.isInvalid())
    return E->getSourceRange();
  return Checker.MatchLoc;
}

static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
  if (!TL.getType()->isDependentType())
    return SourceLocation();
  DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
  Checker.TraverseTypeLoc(TL);
  if (Checker.MatchLoc.isInvalid())
    return TL.getSourceRange();
  return Checker.MatchLoc;
}

/// Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
    Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
    const TemplateArgument *Args, unsigned NumArgs, bool IsDefaultArgument) {
  for (unsigned I = 0; I != NumArgs; ++I) {
    if (Args[I].getKind() == TemplateArgument::Pack) {
      if (CheckNonTypeTemplatePartialSpecializationArgs(
              S, TemplateNameLoc, Param, Args[I].pack_begin(),
              Args[I].pack_size(), IsDefaultArgument))
        return true;

      continue;
    }

    if (Args[I].getKind() != TemplateArgument::Expression)
      continue;

    Expr *ArgExpr = Args[I].getAsExpr();

    // We can have a pack expansion of any of the bullets below.
    if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
      ArgExpr = Expansion->getPattern();

    // Strip off any implicit casts we added as part of type checking.
    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
      ArgExpr = ICE->getSubExpr();

    // C++ [temp.class.spec]p8:
    //   A non-type argument is non-specialized if it is the name of a
    //   non-type parameter. All other non-type arguments are
    //   specialized.
    //
    // Below, we check the two conditions that only apply to
    // specialized non-type arguments, so skip any non-specialized
    // arguments.
    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
      if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
        continue;

    // C++ [temp.class.spec]p9:
    //   Within the argument list of a class template partial
    //   specialization, the following restrictions apply:
    //     -- A partially specialized non-type argument expression
    //        shall not involve a template parameter of the partial
    //        specialization except when the argument expression is a
    //        simple identifier.
    //     -- The type of a template parameter corresponding to a
    //        specialized non-type argument shall not be dependent on a
    //        parameter of the specialization.
    // DR1315 removes the first bullet, leaving an incoherent set of rules.
    // We implement a compromise between the original rules and DR1315:
    //     --  A specialized non-type template argument shall not be
    //         type-dependent and the corresponding template parameter
    //         shall have a non-dependent type.
    SourceRange ParamUseRange =
        findTemplateParameterInType(Param->getDepth(), ArgExpr);
    if (ParamUseRange.isValid()) {
      if (IsDefaultArgument) {
        S.Diag(TemplateNameLoc,
               diag::err_dependent_non_type_arg_in_partial_spec);
        S.Diag(ParamUseRange.getBegin(),
               diag::note_dependent_non_type_default_arg_in_partial_spec)
          << ParamUseRange;
      } else {
        S.Diag(ParamUseRange.getBegin(),
               diag::err_dependent_non_type_arg_in_partial_spec)
          << ParamUseRange;
      }
      return true;
    }

    ParamUseRange = findTemplateParameter(
        Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
    if (ParamUseRange.isValid()) {
      S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(),
             diag::err_dependent_typed_non_type_arg_in_partial_spec)
          << Param->getType();
      S.NoteTemplateParameterLocation(*Param);
      return true;
    }
  }

  return false;
}

bool Sema::CheckTemplatePartialSpecializationArgs(
    SourceLocation TemplateNameLoc, TemplateDecl *PrimaryTemplate,
    unsigned NumExplicit, ArrayRef<TemplateArgument> TemplateArgs) {
  // We have to be conservative when checking a template in a dependent
  // context.
  if (PrimaryTemplate->getDeclContext()->isDependentContext())
    return false;

  TemplateParameterList *TemplateParams =
      PrimaryTemplate->getTemplateParameters();
  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
    NonTypeTemplateParmDecl *Param
      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
    if (!Param)
      continue;

    if (CheckNonTypeTemplatePartialSpecializationArgs(*this, TemplateNameLoc,
                                                      Param, &TemplateArgs[I],
                                                      1, I >= NumExplicit))
      return true;
  }

  return false;
}

DeclResult Sema::ActOnClassTemplateSpecialization(
    Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
    SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
    TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
    MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
  assert(TUK != TagUseKind::Reference && "References are not specializations");

  SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
  SourceLocation LAngleLoc = TemplateId.LAngleLoc;
  SourceLocation RAngleLoc = TemplateId.RAngleLoc;

  // Find the class template we're specializing
  TemplateName Name = TemplateId.Template.get();
  ClassTemplateDecl *ClassTemplate
    = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());

  if (!ClassTemplate) {
    Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
      << (Name.getAsTemplateDecl() &&
          isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
    return true;
  }

  if (const auto *DSA = ClassTemplate->getAttr<NoSpecializationsAttr>()) {
    auto Message = DSA->getMessage();
    Diag(TemplateNameLoc, diag::warn_invalid_specialization)
        << ClassTemplate << !Message.empty() << Message;
    Diag(DSA->getLoc(), diag::note_marked_here) << DSA;
  }

  if (S->isTemplateParamScope())
    EnterTemplatedContext(S, ClassTemplate->getTemplatedDecl());

  DeclContext *DC = ClassTemplate->getDeclContext();

  bool isMemberSpecialization = false;
  bool isPartialSpecialization = false;

  if (SS.isSet()) {
    if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend &&
        diagnoseQualifiedDeclaration(SS, DC, ClassTemplate->getDeclName(),
                                     TemplateNameLoc, &TemplateId,
                                     /*IsMemberSpecialization=*/false))
      return true;
  }

  // Check the validity of the template headers that introduce this
  // template.
  // FIXME: We probably shouldn't complain about these headers for
  // friend declarations.
  bool Invalid = false;
  TemplateParameterList *TemplateParams =
      MatchTemplateParametersToScopeSpecifier(
          KWLoc, TemplateNameLoc, SS, &TemplateId, TemplateParameterLists,
          TUK == TagUseKind::Friend, isMemberSpecialization, Invalid);
  if (Invalid)
    return true;

  // Check that we can declare a template specialization here.
  if (TemplateParams && CheckTemplateDeclScope(S, TemplateParams))
    return true;

  if (TemplateParams && DC->isDependentContext()) {
    ContextRAII SavedContext(*this, DC);
    if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
      return true;
  }

  if (TemplateParams && TemplateParams->size() > 0) {
    isPartialSpecialization = true;

    if (TUK == TagUseKind::Friend) {
      Diag(KWLoc, diag::err_partial_specialization_friend)
        << SourceRange(LAngleLoc, RAngleLoc);
      return true;
    }

    // C++ [temp.class.spec]p10:
    //   The template parameter list of a specialization shall not
    //   contain default template argument values.
    for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
      Decl *Param = TemplateParams->getParam(I);
      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
        if (TTP->hasDefaultArgument()) {
          Diag(TTP->getDefaultArgumentLoc(),
               diag::err_default_arg_in_partial_spec);
          TTP->removeDefaultArgument();
        }
      } else if (NonTypeTemplateParmDecl *NTTP
                   = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
        if (NTTP->hasDefaultArgument()) {
          Diag(NTTP->getDefaultArgumentLoc(),
               diag::err_default_arg_in_partial_spec)
              << NTTP->getDefaultArgument().getSourceRange();
          NTTP->removeDefaultArgument();
        }
      } else {
        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
        if (TTP->hasDefaultArgument()) {
          Diag(TTP->getDefaultArgument().getLocation(),
               diag::err_default_arg_in_partial_spec)
            << TTP->getDefaultArgument().getSourceRange();
          TTP->removeDefaultArgument();
        }
      }
    }
  } else if (TemplateParams) {
    if (TUK == TagUseKind::Friend)
      Diag(KWLoc, diag::err_template_spec_friend)
        << FixItHint::CreateRemoval(
                                SourceRange(TemplateParams->getTemplateLoc(),
                                            TemplateParams->getRAngleLoc()))
        << SourceRange(LAngleLoc, RAngleLoc);
  } else {
    assert(TUK == TagUseKind::Friend &&
           "should have a 'template<>' for this decl");
  }

  // Check that the specialization uses the same tag kind as the
  // original template.
  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
  assert(Kind != TagTypeKind::Enum &&
         "Invalid enum tag in class template spec!");
  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), Kind,
                                    TUK == TagUseKind::Definition, KWLoc,
                                    ClassTemplate->getIdentifier())) {
    Diag(KWLoc, diag::err_use_with_wrong_tag)
      << ClassTemplate
      << FixItHint::CreateReplacement(KWLoc,
                            ClassTemplate->getTemplatedDecl()->getKindName());
    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
         diag::note_previous_use);
    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
  }

  // Translate the parser's template argument list in our AST format.
  TemplateArgumentListInfo TemplateArgs =
      makeTemplateArgumentListInfo(*this, TemplateId);

  // Check for unexpanded parameter packs in any of the template arguments.
  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
    if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
                                        isPartialSpecialization
                                            ? UPPC_PartialSpecialization
                                            : UPPC_ExplicitSpecialization))
      return true;

  // Check that the template argument list is well-formed for this
  // template.
  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
                                /*DefaultArgs=*/{},
                                /*PartialTemplateArgs=*/false, CTAI,
                                /*UpdateArgsWithConversions=*/true))
    return true;

  // Find the class template (partial) specialization declaration that
  // corresponds to these arguments.
  if (isPartialSpecialization) {
    if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate,
                                               TemplateArgs.size(),
                                               CTAI.CanonicalConverted))
      return true;

    // FIXME: Move this to CheckTemplatePartialSpecializationArgs so we
    // also do it during instantiation.
    if (!Name.isDependent() &&
        !TemplateSpecializationType::anyDependentTemplateArguments(
            TemplateArgs, CTAI.CanonicalConverted)) {
      Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
        << ClassTemplate->getDeclName();
      isPartialSpecialization = false;
      Invalid = true;
    }
  }

  void *InsertPos = nullptr;
  ClassTemplateSpecializationDecl *PrevDecl = nullptr;

  if (isPartialSpecialization)
    PrevDecl = ClassTemplate->findPartialSpecialization(
        CTAI.CanonicalConverted, TemplateParams, InsertPos);
  else
    PrevDecl =
        ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos);

  ClassTemplateSpecializationDecl *Specialization = nullptr;

  // Check whether we can declare a class template specialization in
  // the current scope.
  if (TUK != TagUseKind::Friend &&
      CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
                                       TemplateNameLoc,
                                       isPartialSpecialization))
    return true;

  QualType CanonType;
  if (!isPartialSpecialization) {
    // Create a new class template specialization declaration node for
    // this explicit specialization or friend declaration.
    Specialization = ClassTemplateSpecializationDecl::Create(
        Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
        ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
    Specialization->setTemplateArgsAsWritten(TemplateArgs);
    SetNestedNameSpecifier(*this, Specialization, SS);
    if (TemplateParameterLists.size() > 0) {
      Specialization->setTemplateParameterListsInfo(Context,
                                                    TemplateParameterLists);
    }

    if (!PrevDecl)
      ClassTemplate->AddSpecialization(Specialization, InsertPos);

    if (!CurContext->isDependentContext())
      CanonType = Context.getTypeDeclType(Specialization);
  }

  TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
      Name, TemplateNameLoc, TemplateArgs, CTAI.CanonicalConverted, CanonType);

  if (isPartialSpecialization) {
    if (Context.hasSameType(
            WrittenTy->getType(),
            ClassTemplate->getInjectedClassNameSpecialization()) &&
        (!Context.getLangOpts().CPlusPlus20 ||
         !TemplateParams->hasAssociatedConstraints())) {
      // C++ [temp.class.spec]p9b3:
      //
      //   -- The argument list of the specialization shall not be identical
      //      to the implicit argument list of the primary template.
      //
      // This rule has since been removed, because it's redundant given DR1495,
      // but we keep it because it produces better diagnostics and recovery.
      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
          << /*class template*/ 0 << (TUK == TagUseKind::Definition)
          << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
      return CheckClassTemplate(
          S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(),
          TemplateNameLoc, Attr, TemplateParams, AS_none,
          /*ModulePrivateLoc=*/SourceLocation(),
          /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
          TemplateParameterLists.data());
    }

    // Create a new class template partial specialization declaration node.
    ClassTemplatePartialSpecializationDecl *PrevPartial
      = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
    ClassTemplatePartialSpecializationDecl *Partial =
        ClassTemplatePartialSpecializationDecl::Create(
            Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
            ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
            PrevPartial);
    Partial->setTemplateArgsAsWritten(TemplateArgs);
    SetNestedNameSpecifier(*this, Partial, SS);
    if (TemplateParameterLists.size() > 1 && SS.isSet()) {
      Partial->setTemplateParameterListsInfo(
          Context, TemplateParameterLists.drop_back(1));
    }

    if (!PrevPartial)
      ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
    Specialization = Partial;

    // If we are providing an explicit specialization of a member class
    // template specialization, make a note of that.
    if (PrevPartial && PrevPartial->getInstantiatedFromMember())
      PrevPartial->setMemberSpecialization();

    CheckTemplatePartialSpecialization(Partial);
  }

  // C++ [temp.expl.spec]p6:
  //   If a template, a member template or the member of a class template is
  //   explicitly specialized then that specialization shall be declared
  //   before the first use of that specialization that would cause an implicit
  //   instantiation to take place, in every translation unit in which such a
  //   use occurs; no diagnostic is required.
  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
    bool Okay = false;
    for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
      // Is there any previous explicit specialization declaration?
      if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
        Okay = true;
        break;
      }
    }

    if (!Okay) {
      SourceRange Range(TemplateNameLoc, RAngleLoc);
      Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
        << Context.getTypeDeclType(Specialization) << Range;

      Diag(PrevDecl->getPointOfInstantiation(),
           diag::note_instantiation_required_here)
        << (PrevDecl->getTemplateSpecializationKind()
                                                != TSK_ImplicitInstantiation);
      return true;
    }
  }

  // If this is not a friend, note that this is an explicit specialization.
  if (TUK != TagUseKind::Friend)
    Specialization->setSpecializationKind(TSK_ExplicitSpecialization);

  // Check that this isn't a redefinition of this specialization.
  if (TUK == TagUseKind::Definition) {
    RecordDecl *Def = Specialization->getDefinition();
    NamedDecl *Hidden = nullptr;
    if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
      SkipBody->ShouldSkip = true;
      SkipBody->Previous = Def;
      makeMergedDefinitionVisible(Hidden);
    } else if (Def) {
      SourceRange Range(TemplateNameLoc, RAngleLoc);
      Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range;
      Diag(Def->getLocation(), diag::note_previous_definition);
      Specialization->setInvalidDecl();
      return true;
    }
  }

  ProcessDeclAttributeList(S, Specialization, Attr);
  ProcessAPINotes(Specialization);

  // Add alignment attributes if necessary; these attributes are checked when
  // the ASTContext lays out the structure.
  if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
    if (LangOpts.HLSL)
      Specialization->addAttr(PackedAttr::CreateImplicit(Context));
    AddAlignmentAttributesForRecord(Specialization);
    AddMsStructLayoutForRecord(Specialization);
  }

  if (ModulePrivateLoc.isValid())
    Diag(Specialization->getLocation(), diag::err_module_private_specialization)
      << (isPartialSpecialization? 1 : 0)
      << FixItHint::CreateRemoval(ModulePrivateLoc);

  // C++ [temp.expl.spec]p9:
  //   A template explicit specialization is in the scope of the
  //   namespace in which the template was defined.
  //
  // We actually implement this paragraph where we set the semantic
  // context (in the creation of the ClassTemplateSpecializationDecl),
  // but we also maintain the lexical context where the actual
  // definition occurs.
  Specialization->setLexicalDeclContext(CurContext);

  // We may be starting the definition of this specialization.
  if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
    Specialization->startDefinition();

  if (TUK == TagUseKind::Friend) {
    // Build the fully-sugared type for this class template
    // specialization as the user wrote in the specialization
    // itself. This means that we'll pretty-print the type retrieved
    // from the specialization's declaration the way that the user
    // actually wrote the specialization, rather than formatting the
    // name based on the "canonical" representation used to store the
    // template arguments in the specialization.
    FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
                                            TemplateNameLoc,
                                            WrittenTy,
                                            /*FIXME:*/KWLoc);
    Friend->setAccess(AS_public);
    CurContext->addDecl(Friend);
  } else {
    // Add the specialization into its lexical context, so that it can
    // be seen when iterating through the list of declarations in that
    // context. However, specializations are not found by name lookup.
    CurContext->addDecl(Specialization);
  }

  if (SkipBody && SkipBody->ShouldSkip)
    return SkipBody->Previous;

  Specialization->setInvalidDecl(Invalid);
  inferGslOwnerPointerAttribute(Specialization);
  return Specialization;
}

Decl *Sema::ActOnTemplateDeclarator(Scope *S,
                              MultiTemplateParamsArg TemplateParameterLists,
                                    Declarator &D) {
  Decl *NewDecl = HandleDeclarator(S, D, TemplateParameterLists);
  ActOnDocumentableDecl(NewDecl);
  return NewDecl;
}

ConceptDecl *Sema::ActOnStartConceptDefinition(
    Scope *S, MultiTemplateParamsArg TemplateParameterLists,
    const IdentifierInfo *Name, SourceLocation NameLoc) {
  DeclContext *DC = CurContext;

  if (!DC->getRedeclContext()->isFileContext()) {
    Diag(NameLoc,
      diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
    return nullptr;
  }

  if (TemplateParameterLists.size() > 1) {
    Diag(NameLoc, diag::err_concept_extra_headers);
    return nullptr;
  }

  TemplateParameterList *Params = TemplateParameterLists.front();

  if (Params->size() == 0) {
    Diag(NameLoc, diag::err_concept_no_parameters);
    return nullptr;
  }

  // Ensure that the parameter pack, if present, is the last parameter in the
  // template.
  for (TemplateParameterList::const_iterator ParamIt = Params->begin(),
                                             ParamEnd = Params->end();
       ParamIt != ParamEnd; ++ParamIt) {
    Decl const *Param = *ParamIt;
    if (Param->isParameterPack()) {
      if (++ParamIt == ParamEnd)
        break;
      Diag(Param->getLocation(),
           diag::err_template_param_pack_must_be_last_template_parameter);
      return nullptr;
    }
  }

  ConceptDecl *NewDecl =
      ConceptDecl::Create(Context, DC, NameLoc, Name, Params);

  if (NewDecl->hasAssociatedConstraints()) {
    // C++2a [temp.concept]p4:
    // A concept shall not have associated constraints.
    Diag(NameLoc, diag::err_concept_no_associated_constraints);
    NewDecl->setInvalidDecl();
  }

  DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NewDecl->getBeginLoc());
  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                        forRedeclarationInCurContext());
  LookupName(Previous, S);
  FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage=*/false,
                       /*AllowInlineNamespace*/ false);

  // We cannot properly handle redeclarations until we parse the constraint
  // expression, so only inject the name if we are sure we are not redeclaring a
  // symbol
  if (Previous.empty())
    PushOnScopeChains(NewDecl, S, true);

  return NewDecl;
}

static bool RemoveLookupResult(LookupResult &R, NamedDecl *C) {
  bool Found = false;
  LookupResult::Filter F = R.makeFilter();
  while (F.hasNext()) {
    NamedDecl *D = F.next();
    if (D == C) {
      F.erase();
      Found = true;
      break;
    }
  }
  F.done();
  return Found;
}

ConceptDecl *
Sema::ActOnFinishConceptDefinition(Scope *S, ConceptDecl *C,
                                   Expr *ConstraintExpr,
                                   const ParsedAttributesView &Attrs) {
  assert(!C->hasDefinition() && "Concept already defined");
  if (DiagnoseUnexpandedParameterPack(ConstraintExpr))
    return nullptr;
  C->setDefinition(ConstraintExpr);
  ProcessDeclAttributeList(S, C, Attrs);

  // Check for conflicting previous declaration.
  DeclarationNameInfo NameInfo(C->getDeclName(), C->getBeginLoc());
  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                        forRedeclarationInCurContext());
  LookupName(Previous, S);
  FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage=*/false,
                       /*AllowInlineNamespace*/ false);
  bool WasAlreadyAdded = RemoveLookupResult(Previous, C);
  bool AddToScope = true;
  CheckConceptRedefinition(C, Previous, AddToScope);

  ActOnDocumentableDecl(C);
  if (!WasAlreadyAdded && AddToScope)
    PushOnScopeChains(C, S);

  return C;
}

void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
                                    LookupResult &Previous, bool &AddToScope) {
  AddToScope = true;

  if (Previous.empty())
    return;

  auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
  if (!OldConcept) {
    auto *Old = Previous.getRepresentativeDecl();
    Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
        << NewDecl->getDeclName();
    notePreviousDefinition(Old, NewDecl->getLocation());
    AddToScope = false;
    return;
  }
  // Check if we can merge with a concept declaration.
  bool IsSame = Context.isSameEntity(NewDecl, OldConcept);
  if (!IsSame) {
    Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept)
        << NewDecl->getDeclName();
    notePreviousDefinition(OldConcept, NewDecl->getLocation());
    AddToScope = false;
    return;
  }
  if (hasReachableDefinition(OldConcept) &&
      IsRedefinitionInModule(NewDecl, OldConcept)) {
    Diag(NewDecl->getLocation(), diag::err_redefinition)
        << NewDecl->getDeclName();
    notePreviousDefinition(OldConcept, NewDecl->getLocation());
    AddToScope = false;
    return;
  }
  if (!Previous.isSingleResult()) {
    // FIXME: we should produce an error in case of ambig and failed lookups.
    //        Other decls (e.g. namespaces) also have this shortcoming.
    return;
  }
  // We unwrap canonical decl late to check for module visibility.
  Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl());
}

bool Sema::CheckConceptUseInDefinition(ConceptDecl *Concept,
                                       SourceLocation Loc) {
  if (!Concept->isInvalidDecl() && !Concept->hasDefinition()) {
    Diag(Loc, diag::err_recursive_concept) << Concept;
    Diag(Concept->getLocation(), diag::note_declared_at);
    return true;
  }
  return false;
}

/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D, bool MinGW) {
  if (MinGW || (isa<FunctionDecl>(D) &&
                cast<FunctionDecl>(D)->isFunctionTemplateSpecialization()))
    D->dropAttrs<DLLImportAttr, DLLExportAttr>();

  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    FD->setInlineSpecified(false);
}

/// Compute the diagnostic location for an explicit instantiation
//  declaration or definition.
static SourceLocation DiagLocForExplicitInstantiation(
    NamedDecl* D, SourceLocation PointOfInstantiation) {
  // Explicit instantiations following a specialization have no effect and
  // hence no PointOfInstantiation. In that case, walk decl backwards
  // until a valid name loc is found.
  SourceLocation PrevDiagLoc = PointOfInstantiation;
  for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid();
       Prev = Prev->getPreviousDecl()) {
    PrevDiagLoc = Prev->getLocation();
  }
  assert(PrevDiagLoc.isValid() &&
         "Explicit instantiation without point of instantiation?");
  return PrevDiagLoc;
}

bool
Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
                                             TemplateSpecializationKind NewTSK,
                                             NamedDecl *PrevDecl,
                                             TemplateSpecializationKind PrevTSK,
                                        SourceLocation PrevPointOfInstantiation,
                                             bool &HasNoEffect) {
  HasNoEffect = false;

  switch (NewTSK) {
  case TSK_Undeclared:
  case TSK_ImplicitInstantiation:
    assert(
        (PrevTSK == TSK_Undeclared || PrevTSK == TSK_ImplicitInstantiation) &&
        "previous declaration must be implicit!");
    return false;

  case TSK_ExplicitSpecialization:
    switch (PrevTSK) {
    case TSK_Undeclared:
    case TSK_ExplicitSpecialization:
      // Okay, we're just specializing something that is either already
      // explicitly specialized or has merely been mentioned without any
      // instantiation.
      return false;

    case TSK_ImplicitInstantiation:
      if (PrevPointOfInstantiation.isInvalid()) {
        // The declaration itself has not actually been instantiated, so it is
        // still okay to specialize it.
        StripImplicitInstantiation(
            PrevDecl,
            Context.getTargetInfo().getTriple().isWindowsGNUEnvironment());
        return false;
      }
      // Fall through
      [[fallthrough]];

    case TSK_ExplicitInstantiationDeclaration:
    case TSK_ExplicitInstantiationDefinition:
      assert((PrevTSK == TSK_ImplicitInstantiation ||
              PrevPointOfInstantiation.isValid()) &&
             "Explicit instantiation without point of instantiation?");

      // C++ [temp.expl.spec]p6:
      //   If a template, a member template or the member of a class template
      //   is explicitly specialized then that specialization shall be declared
      //   before the first use of that specialization that would cause an
      //   implicit instantiation to take place, in every translation unit in
      //   which such a use occurs; no diagnostic is required.
      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
        // Is there any previous explicit specialization declaration?
        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
          return false;
      }

      Diag(NewLoc, diag::err_specialization_after_instantiation)
        << PrevDecl;
      Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
        << (PrevTSK != TSK_ImplicitInstantiation);

      return true;
    }
    llvm_unreachable("The switch over PrevTSK must be exhaustive.");

  case TSK_ExplicitInstantiationDeclaration:
    switch (PrevTSK) {
    case TSK_ExplicitInstantiationDeclaration:
      // This explicit instantiation declaration is redundant (that's okay).
      HasNoEffect = true;
      return false;

    case TSK_Undeclared:
    case TSK_ImplicitInstantiation:
      // We're explicitly instantiating something that may have already been
      // implicitly instantiated; that's fine.
      return false;

    case TSK_ExplicitSpecialization:
      // C++0x [temp.explicit]p4:
      //   For a given set of template parameters, if an explicit instantiation
      //   of a template appears after a declaration of an explicit
      //   specialization for that template, the explicit instantiation has no
      //   effect.
      HasNoEffect = true;
      return false;

    case TSK_ExplicitInstantiationDefinition:
      // C++0x [temp.explicit]p10:
      //   If an entity is the subject of both an explicit instantiation
      //   declaration and an explicit instantiation definition in the same
      //   translation unit, the definition shall follow the declaration.
      Diag(NewLoc,
           diag::err_explicit_instantiation_declaration_after_definition);

      // Explicit instantiations following a specialization have no effect and
      // hence no PrevPointOfInstantiation. In that case, walk decl backwards
      // until a valid name loc is found.
      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
           diag::note_explicit_instantiation_definition_here);
      HasNoEffect = true;
      return false;
    }
    llvm_unreachable("Unexpected TemplateSpecializationKind!");

  case TSK_ExplicitInstantiationDefinition:
    switch (PrevTSK) {
    case TSK_Undeclared:
    case TSK_ImplicitInstantiation:
      // We're explicitly instantiating something that may have already been
      // implicitly instantiated; that's fine.
      return false;

    case TSK_ExplicitSpecialization:
      // C++ DR 259, C++0x [temp.explicit]p4:
      //   For a given set of template parameters, if an explicit
      //   instantiation of a template appears after a declaration of
      //   an explicit specialization for that template, the explicit
      //   instantiation has no effect.
      Diag(NewLoc, diag::warn_explicit_instantiation_after_specialization)
        << PrevDecl;
      Diag(PrevDecl->getLocation(),
           diag::note_previous_template_specialization);
      HasNoEffect = true;
      return false;

    case TSK_ExplicitInstantiationDeclaration:
      // We're explicitly instantiating a definition for something for which we
      // were previously asked to suppress instantiations. That's fine.

      // C++0x [temp.explicit]p4:
      //   For a given set of template parameters, if an explicit instantiation
      //   of a template appears after a declaration of an explicit
      //   specialization for that template, the explicit instantiation has no
      //   effect.
      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
        // Is there any previous explicit specialization declaration?
        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
          HasNoEffect = true;
          break;
        }
      }

      return false;

    case TSK_ExplicitInstantiationDefinition:
      // C++0x [temp.spec]p5:
      //   For a given template and a given set of template-arguments,
      //     - an explicit instantiation definition shall appear at most once
      //       in a program,

      // MSVCCompat: MSVC silently ignores duplicate explicit instantiations.
      Diag(NewLoc, (getLangOpts().MSVCCompat)
                       ? diag::ext_explicit_instantiation_duplicate
                       : diag::err_explicit_instantiation_duplicate)
          << PrevDecl;
      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
           diag::note_previous_explicit_instantiation);
      HasNoEffect = true;
      return false;
    }
  }

  llvm_unreachable("Missing specialization/instantiation case?");
}

bool Sema::CheckDependentFunctionTemplateSpecialization(
    FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
    LookupResult &Previous) {
  // Remove anything from Previous that isn't a function template in
  // the correct context.
  DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
  LookupResult::Filter F = Previous.makeFilter();
  enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing };
  SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates;
  while (F.hasNext()) {
    NamedDecl *D = F.next()->getUnderlyingDecl();
    if (!isa<FunctionTemplateDecl>(D)) {
      F.erase();
      DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D));
      continue;
    }

    if (!FDLookupContext->InEnclosingNamespaceSetOf(
            D->getDeclContext()->getRedeclContext())) {
      F.erase();
      DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D));
      continue;
    }
  }
  F.done();

  bool IsFriend = FD->getFriendObjectKind() != Decl::FOK_None;
  if (Previous.empty()) {
    Diag(FD->getLocation(), diag::err_dependent_function_template_spec_no_match)
        << IsFriend;
    for (auto &P : DiscardedCandidates)
      Diag(P.second->getLocation(),
           diag::note_dependent_function_template_spec_discard_reason)
          << P.first << IsFriend;
    return true;
  }

  FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
                                         ExplicitTemplateArgs);
  return false;
}

bool Sema::CheckFunctionTemplateSpecialization(
    FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
    LookupResult &Previous, bool QualifiedFriend) {
  // The set of function template specializations that could match this
  // explicit function template specialization.
  UnresolvedSet<8> Candidates;
  TemplateSpecCandidateSet FailedCandidates(FD->getLocation(),
                                            /*ForTakingAddress=*/false);

  llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8>
      ConvertedTemplateArgs;

  DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
         I != E; ++I) {
    NamedDecl *Ovl = (*I)->getUnderlyingDecl();
    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
      // Only consider templates found within the same semantic lookup scope as
      // FD.
      if (!FDLookupContext->InEnclosingNamespaceSetOf(
                                Ovl->getDeclContext()->getRedeclContext()))
        continue;

      QualType FT = FD->getType();
      // C++11 [dcl.constexpr]p8:
      //   A constexpr specifier for a non-static member function that is not
      //   a constructor declares that member function to be const.
      //
      // When matching a constexpr member function template specialization
      // against the primary template, we don't yet know whether the
      // specialization has an implicit 'const' (because we don't know whether
      // it will be a static member function until we know which template it
      // specializes). This rule was removed in C++14.
      if (auto *NewMD = dyn_cast<CXXMethodDecl>(FD);
          !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() &&
          !isa<CXXConstructorDecl, CXXDestructorDecl>(NewMD)) {
        auto *OldMD = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
        if (OldMD && OldMD->isConst()) {
          const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
          FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
          EPI.TypeQuals.addConst();
          FT = Context.getFunctionType(FPT->getReturnType(),
                                       FPT->getParamTypes(), EPI);
        }
      }

      TemplateArgumentListInfo Args;
      if (ExplicitTemplateArgs)
        Args = *ExplicitTemplateArgs;

      // C++ [temp.expl.spec]p11:
      //   A trailing template-argument can be left unspecified in the
      //   template-id naming an explicit function template specialization
      //   provided it can be deduced from the function argument type.
      // Perform template argument deduction to determine whether we may be
      // specializing this template.
      // FIXME: It is somewhat wasteful to build
      TemplateDeductionInfo Info(FailedCandidates.getLocation());
      FunctionDecl *Specialization = nullptr;
      if (TemplateDeductionResult TDK = DeduceTemplateArguments(
              cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
              ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info);
          TDK != TemplateDeductionResult::Success) {
        // Template argument deduction failed; record why it failed, so
        // that we can provide nifty diagnostics.
        FailedCandidates.addCandidate().set(
            I.getPair(), FunTmpl->getTemplatedDecl(),
            MakeDeductionFailureInfo(Context, TDK, Info));
        (void)TDK;
        continue;
      }

      // Target attributes are part of the cuda function signature, so
      // the deduced template's cuda target must match that of the
      // specialization.  Given that C++ template deduction does not
      // take target attributes into account, we reject candidates
      // here that have a different target.
      if (LangOpts.CUDA &&
          CUDA().IdentifyTarget(Specialization,
                                /* IgnoreImplicitHDAttr = */ true) !=
              CUDA().IdentifyTarget(FD, /* IgnoreImplicitHDAttr = */ true)) {
        FailedCandidates.addCandidate().set(
            I.getPair(), FunTmpl->getTemplatedDecl(),
            MakeDeductionFailureInfo(
                Context, TemplateDeductionResult::CUDATargetMismatch, Info));
        continue;
      }

      // Record this candidate.
      if (ExplicitTemplateArgs)
        ConvertedTemplateArgs[Specialization] = std::move(Args);
      Candidates.addDecl(Specialization, I.getAccess());
    }
  }

  // For a qualified friend declaration (with no explicit marker to indicate
  // that a template specialization was intended), note all (template and
  // non-template) candidates.
  if (QualifiedFriend && Candidates.empty()) {
    Diag(FD->getLocation(), diag::err_qualified_friend_no_match)
        << FD->getDeclName() << FDLookupContext;
    // FIXME: We should form a single candidate list and diagnose all
    // candidates at once, to get proper sorting and limiting.
    for (auto *OldND : Previous) {
      if (auto *OldFD = dyn_cast<FunctionDecl>(OldND->getUnderlyingDecl()))
        NoteOverloadCandidate(OldND, OldFD, CRK_None, FD->getType(), false);
    }
    FailedCandidates.NoteCandidates(*this, FD->getLocation());
    return true;
  }

  // Find the most specialized function template.
  UnresolvedSetIterator Result = getMostSpecialized(
      Candidates.begin(), Candidates.end(), FailedCandidates, FD->getLocation(),
      PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
      PDiag(diag::err_function_template_spec_ambiguous)
          << FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
      PDiag(diag::note_function_template_spec_matched));

  if (Result == Candidates.end())
    return true;

  // Ignore access information;  it doesn't figure into redeclaration checking.
  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);

  if (const auto *PT = Specialization->getPrimaryTemplate();
      const auto *DSA = PT->getAttr<NoSpecializationsAttr>()) {
    auto Message = DSA->getMessage();
    Diag(FD->getLocation(), diag::warn_invalid_specialization)
        << PT << !Message.empty() << Message;
    Diag(DSA->getLoc(), diag::note_marked_here) << DSA;
  }

  // C++23 [except.spec]p13:
  //   An exception specification is considered to be needed when:
  //   - [...]
  //   - the exception specification is compared to that of another declaration
  //     (e.g., an explicit specialization or an overriding virtual function);
  //   - [...]
  //
  //  The exception specification of a defaulted function is evaluated as
  //  described above only when needed; similarly, the noexcept-specifier of a
  //  specialization of a function template or member function of a class
  //  template is instantiated only when needed.
  //
  // The standard doesn't specify what the "comparison with another declaration"
  // entails, nor the exact circumstances in which it occurs. Moreover, it does
  // not state which properties of an explicit specialization must match the
  // primary template.
  //
  // We assume that an explicit specialization must correspond with (per
  // [basic.scope.scope]p4) and declare the same entity as (per [basic.link]p8)
  // the declaration produced by substitution into the function template.
  //
  // Since the determination whether two function declarations correspond does
  // not consider exception specification, we only need to instantiate it once
  // we determine the primary template when comparing types per
  // [basic.link]p11.1.
  auto *SpecializationFPT =
      Specialization->getType()->castAs<FunctionProtoType>();
  // If the function has a dependent exception specification, resolve it after
  // we have selected the primary template so we can check whether it matches.
  if (getLangOpts().CPlusPlus17 &&
      isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) &&
      !ResolveExceptionSpec(FD->getLocation(), SpecializationFPT))
    return true;

  FunctionTemplateSpecializationInfo *SpecInfo
    = Specialization->getTemplateSpecializationInfo();
  assert(SpecInfo && "Function template specialization info missing?");

  // Note: do not overwrite location info if previous template
  // specialization kind was explicit.
  TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
  if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
    Specialization->setLocation(FD->getLocation());
    Specialization->setLexicalDeclContext(FD->getLexicalDeclContext());
    // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
    // function can differ from the template declaration with respect to
    // the constexpr specifier.
    // FIXME: We need an update record for this AST mutation.
    // FIXME: What if there are multiple such prior declarations (for instance,
    // from different modules)?
    Specialization->setConstexprKind(FD->getConstexprKind());
  }

  // FIXME: Check if the prior specialization has a point of instantiation.
  // If so, we have run afoul of .

  // If this is a friend declaration, then we're not really declaring
  // an explicit specialization.
  bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);

  // Check the scope of this explicit specialization.
  if (!isFriend &&
      CheckTemplateSpecializationScope(*this,
                                       Specialization->getPrimaryTemplate(),
                                       Specialization, FD->getLocation(),
                                       false))
    return true;

  // C++ [temp.expl.spec]p6:
  //   If a template, a member template or the member of a class template is
  //   explicitly specialized then that specialization shall be declared
  //   before the first use of that specialization that would cause an implicit
  //   instantiation to take place, in every translation unit in which such a
  //   use occurs; no diagnostic is required.
  bool HasNoEffect = false;
  if (!isFriend &&
      CheckSpecializationInstantiationRedecl(FD->getLocation(),
                                             TSK_ExplicitSpecialization,
                                             Specialization,
                                   SpecInfo->getTemplateSpecializationKind(),
                                         SpecInfo->getPointOfInstantiation(),
                                             HasNoEffect))
    return true;

  // Mark the prior declaration as an explicit specialization, so that later
  // clients know that this is an explicit specialization.
  if (!isFriend) {
    // Since explicit specializations do not inherit '=delete' from their
    // primary function template - check if the 'specialization' that was
    // implicitly generated (during template argument deduction for partial
    // ordering) from the most specialized of all the function templates that
    // 'FD' could have been specializing, has a 'deleted' definition.  If so,
    // first check that it was implicitly generated during template argument
    // deduction by making sure it wasn't referenced, and then reset the deleted
    // flag to not-deleted, so that we can inherit that information from 'FD'.
    if (Specialization->isDeleted() && !SpecInfo->isExplicitSpecialization() &&
        !Specialization->getCanonicalDecl()->isReferenced()) {
      // FIXME: This assert will not hold in the presence of modules.
      assert(
          Specialization->getCanonicalDecl() == Specialization &&
          "This must be the only existing declaration of this specialization");
      // FIXME: We need an update record for this AST mutation.
      Specialization->setDeletedAsWritten(false);
    }
    // FIXME: We need an update record for this AST mutation.
    SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
    MarkUnusedFileScopedDecl(Specialization);
  }

  // Turn the given function declaration into a function template
  // specialization, with the template arguments from the previous
  // specialization.
  // Take copies of (semantic and syntactic) template argument lists.
  TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy(
      Context, Specialization->getTemplateSpecializationArgs()->asArray());
  FD->setFunctionTemplateSpecialization(
      Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
      SpecInfo->getTemplateSpecializationKind(),
      ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);

  // A function template specialization inherits the target attributes
  // of its template.  (We require the attributes explicitly in the
  // code to match, but a template may have implicit attributes by
  // virtue e.g. of being constexpr, and it passes these implicit
  // attributes on to its specializations.)
  if (LangOpts.CUDA)
    CUDA().inheritTargetAttrs(FD, *Specialization->getPrimaryTemplate());

  // The "previous declaration" for this function template specialization is
  // the prior function template specialization.
  Previous.clear();
  Previous.addDecl(Specialization);
  return false;
}

bool
Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
  assert(!Member->isTemplateDecl() && !Member->getDescribedTemplate() &&
         "Only for non-template members");

  // Try to find the member we are instantiating.
  NamedDecl *FoundInstantiation = nullptr;
  NamedDecl *Instantiation = nullptr;
  NamedDecl *InstantiatedFrom = nullptr;
  MemberSpecializationInfo *MSInfo = nullptr;

  if (Previous.empty()) {
    // Nowhere to look anyway.
  } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
    UnresolvedSet<8> Candidates;
    for (NamedDecl *Candidate : Previous) {
      auto *Method = dyn_cast<CXXMethodDecl>(Candidate->getUnderlyingDecl());
      // Ignore any candidates that aren't member functions.
      if (!Method)
        continue;

      QualType Adjusted = Function->getType();
      if (!hasExplicitCallingConv(Adjusted))
        Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
      // Ignore any candidates with the wrong type.
      // This doesn't handle deduced return types, but both function
      // declarations should be undeduced at this point.
      // FIXME: The exception specification should probably be ignored when
      // comparing the types.
      if (!Context.hasSameType(Adjusted, Method->getType()))
        continue;

      // Ignore any candidates with unsatisfied constraints.
      if (ConstraintSatisfaction Satisfaction;
          Method->getTrailingRequiresClause() &&
          (CheckFunctionConstraints(Method, Satisfaction,
                                    /*UsageLoc=*/Member->getLocation(),
                                    /*ForOverloadResolution=*/true) ||
           !Satisfaction.IsSatisfied))
        continue;

      Candidates.addDecl(Candidate);
    }

    // If we have no viable candidates left after filtering, we are done.
    if (Candidates.empty())
      return false;

    // Find the function that is more constrained than every other function it
    // has been compared to.
    UnresolvedSetIterator Best = Candidates.begin();
    CXXMethodDecl *BestMethod = nullptr;
    for (UnresolvedSetIterator I = Candidates.begin(), E = Candidates.end();
         I != E; ++I) {
      auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl());
      if (I == Best ||
          getMoreConstrainedFunction(Method, BestMethod) == Method) {
        Best = I;
        BestMethod = Method;
      }
    }

    FoundInstantiation = *Best;
    Instantiation = BestMethod;
    InstantiatedFrom = BestMethod->getInstantiatedFromMemberFunction();
    MSInfo = BestMethod->getMemberSpecializationInfo();

    // Make sure the best candidate is more constrained than all of the others.
    bool Ambiguous = false;
    for (UnresolvedSetIterator I = Candidates.begin(), E = Candidates.end();
         I != E; ++I) {
      auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl());
      if (I != Best &&
          getMoreConstrainedFunction(Method, BestMethod) != BestMethod) {
        Ambiguous = true;
        break;
      }
    }

    if (Ambiguous) {
      Diag(Member->getLocation(), diag::err_function_member_spec_ambiguous)
          << Member << (InstantiatedFrom ? InstantiatedFrom : Instantiation);
      for (NamedDecl *Candidate : Candidates) {
        Candidate = Candidate->getUnderlyingDecl();
        Diag(Candidate->getLocation(), diag::note_function_member_spec_matched)
            << Candidate;
      }
      return true;
    }
  } else if (isa<VarDecl>(Member)) {
    VarDecl *PrevVar;
    if (Previous.isSingleResult() &&
        (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
      if (PrevVar->isStaticDataMember()) {
        FoundInstantiation = Previous.getRepresentativeDecl();
        Instantiation = PrevVar;
        InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
        MSInfo = PrevVar->getMemberSpecializationInfo();
      }
  } else if (isa<RecordDecl>(Member)) {
    CXXRecordDecl *PrevRecord;
    if (Previous.isSingleResult() &&
        (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
      FoundInstantiation = Previous.getRepresentativeDecl();
      Instantiation = PrevRecord;
      InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
      MSInfo = PrevRecord->getMemberSpecializationInfo();
    }
  } else if (isa<EnumDecl>(Member)) {
    EnumDecl *PrevEnum;
    if (Previous.isSingleResult() &&
        (PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) {
      FoundInstantiation = Previous.getRepresentativeDecl();
      Instantiation = PrevEnum;
      InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum();
      MSInfo = PrevEnum->getMemberSpecializationInfo();
    }
  }

  if (!Instantiation) {
    // There is no previous declaration that matches. Since member
    // specializations are always out-of-line, the caller will complain about
    // this mismatch later.
    return false;
  }

  // A member specialization in a friend declaration isn't really declaring
  // an explicit specialization, just identifying a specific (possibly implicit)
  // specialization. Don't change the template specialization kind.
  //
  // FIXME: Is this really valid? Other compilers reject.
  if (Member->getFriendObjectKind() != Decl::FOK_None) {
    // Preserve instantiation information.
    if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
      cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
                                      cast<CXXMethodDecl>(InstantiatedFrom),
        cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
    } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
      cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
                                      cast<CXXRecordDecl>(InstantiatedFrom),
        cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
    }

    Previous.clear();
    Previous.addDecl(FoundInstantiation);
    return false;
  }

  // Make sure that this is a specialization of a member.
  if (!InstantiatedFrom) {
    Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
      << Member;
    Diag(Instantiation->getLocation(), diag::note_specialized_decl);
    return true;
  }

  // C++ [temp.expl.spec]p6:
  //   If a template, a member template or the member of a class template is
  //   explicitly specialized then that specialization shall be declared
  //   before the first use of that specialization that would cause an implicit
  //   instantiation to take place, in every translation unit in which such a
  //   use occurs; no diagnostic is required.
  assert(MSInfo && "Member specialization info missing?");

  bool HasNoEffect = false;
  if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
                                             TSK_ExplicitSpecialization,
                                             Instantiation,
                                     MSInfo->getTemplateSpecializationKind(),
                                           MSInfo->getPointOfInstantiation(),
                                             HasNoEffect))
    return true;

  // Check the scope of this explicit specialization.
  if (CheckTemplateSpecializationScope(*this,
                                       InstantiatedFrom,
                                       Instantiation, Member->getLocation(),
                                       false))
    return true;

  // Note that this member specialization is an "instantiation of" the
  // corresponding member of the original template.
  if (auto *MemberFunction = dyn_cast<FunctionDecl>(Member)) {
    FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);
    if (InstantiationFunction->getTemplateSpecializationKind() ==
          TSK_ImplicitInstantiation) {
      // Explicit specializations of member functions of class templates do not
      // inherit '=delete' from the member function they are specializing.
      if (InstantiationFunction->isDeleted()) {
        // FIXME: This assert will not hold in the presence of modules.
        assert(InstantiationFunction->getCanonicalDecl() ==
               InstantiationFunction);
        // FIXME: We need an update record for this AST mutation.
        InstantiationFunction->setDeletedAsWritten(false);
      }
    }

    MemberFunction->setInstantiationOfMemberFunction(
        cast<CXXMethodDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
  } else if (auto *MemberVar = dyn_cast<VarDecl>(Member)) {
    MemberVar->setInstantiationOfStaticDataMember(
        cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
  } else if (auto *MemberClass = dyn_cast<CXXRecordDecl>(Member)) {
    MemberClass->setInstantiationOfMemberClass(
        cast<CXXRecordDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
  } else if (auto *MemberEnum = dyn_cast<EnumDecl>(Member)) {
    MemberEnum->setInstantiationOfMemberEnum(
        cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
  } else {
    llvm_unreachable("unknown member specialization kind");
  }

  // Save the caller the trouble of having to figure out which declaration
  // this specialization matches.
  Previous.clear();
  Previous.addDecl(FoundInstantiation);
  return false;
}

/// Complete the explicit specialization of a member of a class template by
/// updating the instantiated member to be marked as an explicit specialization.
///
/// \param OrigD The member declaration instantiated from the template.
/// \param Loc The location of the explicit specialization of the member.
template<typename DeclT>
static void completeMemberSpecializationImpl(Sema &S, DeclT *OrigD,
                                             SourceLocation Loc) {
  if (OrigD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
    return;

  // FIXME: Inform AST mutation listeners of this AST mutation.
  // FIXME: If there are multiple in-class declarations of the member (from
  // multiple modules, or a declaration and later definition of a member type),
  // should we update all of them?
  OrigD->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
  OrigD->setLocation(Loc);
}

void Sema::CompleteMemberSpecialization(NamedDecl *Member,
                                        LookupResult &Previous) {
  NamedDecl *Instantiation = cast<NamedDecl>(Member->getCanonicalDecl());
  if (Instantiation == Member)
    return;

  if (auto *Function = dyn_cast<CXXMethodDecl>(Instantiation))
    completeMemberSpecializationImpl(*this, Function, Member->getLocation());
  else if (auto *Var = dyn_cast<VarDecl>(Instantiation))
    completeMemberSpecializationImpl(*this, Var, Member->getLocation());
  else if (auto *Record = dyn_cast<CXXRecordDecl>(Instantiation))
    completeMemberSpecializationImpl(*this, Record, Member->getLocation());
  else if (auto *Enum = dyn_cast<EnumDecl>(Instantiation))
    completeMemberSpecializationImpl(*this, Enum, Member->getLocation());
  else
    llvm_unreachable("unknown member specialization kind");
}

/// Check the scope of an explicit instantiation.
///
/// \returns true if a serious error occurs, false otherwise.
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
                                            SourceLocation InstLoc,
                                            bool WasQualifiedName) {
  DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
  DeclContext *CurContext = S.CurContext->getRedeclContext();

  if (CurContext->isRecord()) {
    S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
      << D;
    return true;
  }

  // C++11 [temp.explicit]p3:
  //   An explicit instantiation shall appear in an enclosing namespace of its
  //   template. If the name declared in the explicit instantiation is an
  //   unqualified name, the explicit instantiation shall appear in the
  //   namespace where its template is declared or, if that namespace is inline
  //   (7.3.1), any namespace from its enclosing namespace set.
  //
  // This is DR275, which we do not retroactively apply to C++98/03.
  if (WasQualifiedName) {
    if (CurContext->Encloses(OrigContext))
      return false;
  } else {
    if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
      return false;
  }

  if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
    if (WasQualifiedName)
      S.Diag(InstLoc,
             S.getLangOpts().CPlusPlus11?
               diag::err_explicit_instantiation_out_of_scope :
               diag::warn_explicit_instantiation_out_of_scope_0x)
        << D << NS;
    else
      S.Diag(InstLoc,
             S.getLangOpts().CPlusPlus11?
               diag::err_explicit_instantiation_unqualified_wrong_namespace :
               diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
        << D << NS;
  } else
    S.Diag(InstLoc,
           S.getLangOpts().CPlusPlus11?
             diag::err_explicit_instantiation_must_be_global :
             diag::warn_explicit_instantiation_must_be_global_0x)
      << D;
  S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
  return false;
}

/// Common checks for whether an explicit instantiation of \p D is valid.
static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D,
                                       SourceLocation InstLoc,
                                       bool WasQualifiedName,
                                       TemplateSpecializationKind TSK) {
  // C++ [temp.explicit]p13:
  //   An explicit instantiation declaration shall not name a specialization of
  //   a template with internal linkage.
  if (TSK == TSK_ExplicitInstantiationDeclaration &&
      D->getFormalLinkage() == Linkage::Internal) {
    S.Diag(InstLoc, diag::err_explicit_instantiation_internal_linkage) << D;
    return true;
  }

  // C++11 [temp.explicit]p3: [DR 275]
  //   An explicit instantiation shall appear in an enclosing namespace of its
  //   template.
  if (CheckExplicitInstantiationScope(S, D, InstLoc, WasQualifiedName))
    return true;

  return false;
}

/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
  if (!SS.isSet())
    return false;

  // C++11 [temp.explicit]p3:
  //   If the explicit instantiation is for a member function, a member class
  //   or a static data member of a class template specialization, the name of
  //   the class template specialization in the qualified-id for the member
  //   name shall be a simple-template-id.
  //
  // C++98 has the same restriction, just worded differently.
  for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
       NNS = NNS->getPrefix())
    if (const Type *T = NNS->getAsType())
      if (isa<TemplateSpecializationType>(T))
        return true;

  return false;
}

/// Make a dllexport or dllimport attr on a class template specialization take
/// effect.
static void dllExportImportClassTemplateSpecialization(
    Sema &S, ClassTemplateSpecializationDecl *Def) {
  auto *A = cast_or_null<InheritableAttr>(getDLLAttr(Def));
  assert(A && "dllExportImportClassTemplateSpecialization called "
              "on Def without dllexport or dllimport");

  // We reject explicit instantiations in class scope, so there should
  // never be any delayed exported classes to worry about.
  assert(S.DelayedDllExportClasses.empty() &&
         "delayed exports present at explicit instantiation");
  S.checkClassLevelDLLAttribute(Def);

  // Propagate attribute to base class templates.
  for (auto &B : Def->bases()) {
    if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
            B.getType()->getAsCXXRecordDecl()))
      S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getBeginLoc());
  }

  S.referenceDLLExportedClassMethods();
}

DeclResult Sema::ActOnExplicitInstantiation(
    Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
    unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
    TemplateTy TemplateD, SourceLocation TemplateNameLoc,
    SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn,
    SourceLocation RAngleLoc, const ParsedAttributesView &Attr) {
  // Find the class template we're specializing
  TemplateName Name = TemplateD.get();
  TemplateDecl *TD = Name.getAsTemplateDecl();
  // Check that the specialization uses the same tag kind as the
  // original template.
  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
  assert(Kind != TagTypeKind::Enum &&
         "Invalid enum tag in class template explicit instantiation!");

  ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD);

  if (!ClassTemplate) {
    NonTagKind NTK = getNonTagTypeDeclKind(TD, Kind);
    Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << TD << NTK << Kind;
    Diag(TD->getLocation(), diag::note_previous_use);
    return true;
  }

  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
                                    Kind, /*isDefinition*/false, KWLoc,
                                    ClassTemplate->getIdentifier())) {
    Diag(KWLoc, diag::err_use_with_wrong_tag)
      << ClassTemplate
      << FixItHint::CreateReplacement(KWLoc,
                            ClassTemplate->getTemplatedDecl()->getKindName());
    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
         diag::note_previous_use);
    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
  }

  // C++0x [temp.explicit]p2:
  //   There are two forms of explicit instantiation: an explicit instantiation
  //   definition and an explicit instantiation declaration. An explicit
  //   instantiation declaration begins with the extern keyword. [...]
  TemplateSpecializationKind TSK = ExternLoc.isInvalid()
                                       ? TSK_ExplicitInstantiationDefinition
                                       : TSK_ExplicitInstantiationDeclaration;

  if (TSK == TSK_ExplicitInstantiationDeclaration &&
      !Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) {
    // Check for dllexport class template instantiation declarations,
    // except for MinGW mode.
    for (const ParsedAttr &AL : Attr) {
      if (AL.getKind() == ParsedAttr::AT_DLLExport) {
        Diag(ExternLoc,
             diag::warn_attribute_dllexport_explicit_instantiation_decl);
        Diag(AL.getLoc(), diag::note_attribute);
        break;
      }
    }

    if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) {
      Diag(ExternLoc,
           diag::warn_attribute_dllexport_explicit_instantiation_decl);
      Diag(A->getLocation(), diag::note_attribute);
    }
  }

  // In MSVC mode, dllimported explicit instantiation definitions are treated as
  // instantiation declarations for most purposes.
  bool DLLImportExplicitInstantiationDef = false;
  if (TSK == TSK_ExplicitInstantiationDefinition &&
      Context.getTargetInfo().getCXXABI().isMicrosoft()) {
    // Check for dllimport class template instantiation definitions.
    bool DLLImport =
        ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>();
    for (const ParsedAttr &AL : Attr) {
      if (AL.getKind() == ParsedAttr::AT_DLLImport)
        DLLImport = true;
      if (AL.getKind() == ParsedAttr::AT_DLLExport) {
        // dllexport trumps dllimport here.
        DLLImport = false;
        break;
      }
    }
    if (DLLImport) {
      TSK = TSK_ExplicitInstantiationDeclaration;
      DLLImportExplicitInstantiationDef = true;
    }
  }

  // Translate the parser's template argument list in our AST format.
  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
  translateTemplateArguments(TemplateArgsIn, TemplateArgs);

  // Check that the template argument list is well-formed for this
  // template.
  CheckTemplateArgumentInfo CTAI;
  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
                                /*DefaultArgs=*/{}, false, CTAI,
                                /*UpdateArgsWithConversions=*/true,
                                /*ConstraintsNotSatisfied=*/nullptr))
    return true;

  // Find the class template specialization declaration that
  // corresponds to these arguments.
  void *InsertPos = nullptr;
  ClassTemplateSpecializationDecl *PrevDecl =
      ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos);

  TemplateSpecializationKind PrevDecl_TSK
    = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;

  if (TSK == TSK_ExplicitInstantiationDefinition && PrevDecl != nullptr &&
      Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) {
    // Check for dllexport class template instantiation definitions in MinGW
    // mode, if a previous declaration of the instantiation was seen.
    for (const ParsedAttr &AL : Attr) {
      if (AL.getKind() == ParsedAttr::AT_DLLExport) {
        Diag(AL.getLoc(),
             diag::warn_attribute_dllexport_explicit_instantiation_def);
        break;
      }
    }
  }

  if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc,
                                 SS.isSet(), TSK))
    return true;

  ClassTemplateSpecializationDecl *Specialization = nullptr;

  bool HasNoEffect = false;
  if (PrevDecl) {
    if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
                                               PrevDecl, PrevDecl_TSK,
                                            PrevDecl->getPointOfInstantiation(),
                                               HasNoEffect))
      return PrevDecl;

    // Even though HasNoEffect == true means that this explicit instantiation
    // has no effect on semantics, we go on to put its syntax in the AST.

    if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
        PrevDecl_TSK == TSK_Undeclared) {
      // Since the only prior class template specialization with these
      // arguments was referenced but not declared, reuse that
      // declaration node as our own, updating the source location
      // for the template name to reflect our new declaration.
      // (Other source locations will be updated later.)
      Specialization = PrevDecl;
      Specialization->setLocation(TemplateNameLoc);
      PrevDecl = nullptr;
    }

    if (PrevDecl_TSK == TSK_ExplicitInstantiationDeclaration &&
        DLLImportExplicitInstantiationDef) {
      // The new specialization might add a dllimport attribute.
      HasNoEffect = false;
    }
  }

  if (!Specialization) {
    // Create a new class template specialization declaration node for
    // this explicit specialization.
    Specialization = ClassTemplateSpecializationDecl::Create(
        Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
        ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
    SetNestedNameSpecifier(*this, Specialization, SS);

    // A MSInheritanceAttr attached to the previous declaration must be
    // propagated to the new node prior to instantiation.
    if (PrevDecl) {
      if (const auto *A = PrevDecl->getAttr<MSInheritanceAttr>()) {
        auto *Clone = A->clone(getASTContext());
        Clone->setInherited(true);
        Specialization->addAttr(Clone);
        Consumer.AssignInheritanceModel(Specialization);
      }
    }

    if (!HasNoEffect && !PrevDecl) {
      // Insert the new specialization.
      ClassTemplate->AddSpecialization(Specialization, InsertPos);
    }
  }

  Specialization->setTemplateArgsAsWritten(TemplateArgs);

  // Set source locations for keywords.
  Specialization->setExternKeywordLoc(ExternLoc);
  Specialization->setTemplateKeywordLoc(TemplateLoc);
  Specialization->setBraceRange(SourceRange());

  bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
  ProcessDeclAttributeList(S, Specialization, Attr);
  ProcessAPINotes(Specialization);

  // Add the explicit instantiation into its lexical context. However,
  // since explicit instantiations are never found by name lookup, we
  // just put it into the declaration context directly.
  Specialization->setLexicalDeclContext(CurContext);
  CurContext->addDecl(Specialization);

  // Syntax is now OK, so return if it has no other effect on semantics.
  if (HasNoEffect) {
    // Set the template specialization kind.
    Specialization->setTemplateSpecializationKind(TSK);
    return Specialization;
  }

  // C++ [temp.explicit]p3:
  //   A definition of a class template or class member template
  //   shall be in scope at the point of the explicit instantiation of
  //   the class template or class member template.
  //
  // This check comes when we actually try to perform the
  // instantiation.
  ClassTemplateSpecializationDecl *Def
    = cast_or_null<ClassTemplateSpecializationDecl>(
                                              Specialization->getDefinition());
  if (!Def)
    InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK,
                                           /*Complain=*/true,
                                           CTAI.StrictPackMatch);
  else if (TSK == TSK_ExplicitInstantiationDefinition) {
    MarkVTableUsed(TemplateNameLoc, Specialization, true);
    Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
  }

  // Instantiate the members of this class template specialization.
  Def = cast_or_null<ClassTemplateSpecializationDecl>(
                                       Specialization->getDefinition());
  if (Def) {
    TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind();
    // Fix a TSK_ExplicitInstantiationDeclaration followed by a
    // TSK_ExplicitInstantiationDefinition
    if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
        (TSK == TSK_ExplicitInstantiationDefinition ||
         DLLImportExplicitInstantiationDef)) {
      // FIXME: Need to notify the ASTMutationListener that we did this.
      Def->setTemplateSpecializationKind(TSK);

      if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
          Context.getTargetInfo().shouldDLLImportComdatSymbols()) {
        // An explicit instantiation definition can add a dll attribute to a
        // template with a previous instantiation declaration. MinGW doesn't
        // allow this.
        auto *A = cast<InheritableAttr>(
            getDLLAttr(Specialization)->clone(getASTContext()));
        A->setInherited(true);
        Def->addAttr(A);
        dllExportImportClassTemplateSpecialization(*this, Def);
      }
    }

    // Fix a TSK_ImplicitInstantiation followed by a
    // TSK_ExplicitInstantiationDefinition
    bool NewlyDLLExported =
        !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
    if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported &&
        Context.getTargetInfo().shouldDLLImportComdatSymbols()) {
      // An explicit instantiation definition can add a dll attribute to a
      // template with a previous implicit instantiation. MinGW doesn't allow
      // this. We limit clang to only adding dllexport, to avoid potentially
      // strange codegen behavior. For example, if we extend this conditional
      // to dllimport, and we have a source file calling a method on an
      // implicitly instantiated template class instance and then declaring a
      // dllimport explicit instantiation definition for the same template
      // class, the codegen for the method call will not respect the dllimport,
      // while it will with cl. The Def will already have the DLL attribute,
      // since the Def and Specialization will be the same in the case of
      // Old_TSK == TSK_ImplicitInstantiation, and we already added the
      // attribute to the Specialization; we just need to make it take effect.
      assert(Def == Specialization &&
             "Def and Specialization should match for implicit instantiation");
      dllExportImportClassTemplateSpecialization(*this, Def);
    }

    // In MinGW mode, export the template instantiation if the declaration
    // was marked dllexport.
    if (PrevDecl_TSK == TSK_ExplicitInstantiationDeclaration &&
        Context.getTargetInfo().getTriple().isWindowsGNUEnvironment() &&
        PrevDecl->hasAttr<DLLExportAttr>()) {
      dllExportImportClassTemplateSpecialization(*this, Def);
    }

    // Set the template specialization kind. Make sure it is set before
    // instantiating the members which will trigger ASTConsumer callbacks.
    Specialization->setTemplateSpecializationKind(TSK);
    InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
  } else {

    // Set the template specialization kind.
    Specialization->setTemplateSpecializationKind(TSK);
  }

  return Specialization;
}

DeclResult
Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
                                 SourceLocation TemplateLoc, unsigned TagSpec,
                                 SourceLocation KWLoc, CXXScopeSpec &SS,
                                 IdentifierInfo *Name, SourceLocation NameLoc,
                                 const ParsedAttributesView &Attr) {

  bool Owned = false;
  bool IsDependent = false;
  Decl *TagD =
      ActOnTag(S, TagSpec, TagUseKind::Reference, KWLoc, SS, Name, NameLoc,
               Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(),
               MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(),
               false, TypeResult(), /*IsTypeSpecifier*/ false,
               /*IsTemplateParamOrArg*/ false, /*OOK=*/OffsetOfKind::Outside)
          .get();
  assert(!IsDependent && "explicit instantiation of dependent name not yet handled");

  if (!TagD)
    return true;

  TagDecl *Tag = cast<TagDecl>(TagD);
  assert(!Tag->isEnum() && "shouldn't see enumerations here");

  if (Tag->isInvalidDecl())
    return true;

  CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
  CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
  if (!Pattern) {
    Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
      << Context.getTypeDeclType(Record);
    Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
    return true;
  }

  // C++0x [temp.explicit]p2:
  //   If the explicit instantiation is for a class or member class, the
  //   elaborated-type-specifier in the declaration shall include a
  //   simple-template-id.
  //
  // C++98 has the same restriction, just worded differently.
  if (!ScopeSpecifierHasTemplateId(SS))
    Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id)
      << Record << SS.getRange();

  // C++0x [temp.explicit]p2:
  //   There are two forms of explicit instantiation: an explicit instantiation
  //   definition and an explicit instantiation declaration. An explicit
  //   instantiation declaration begins with the extern keyword. [...]
  TemplateSpecializationKind TSK
    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
                           : TSK_ExplicitInstantiationDeclaration;

  CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK);

  // Verify that it is okay to explicitly instantiate here.
  CXXRecordDecl *PrevDecl
    = cast_or_null<CXXRecordDecl>(Record->getPreviousDecl());
  if (!PrevDecl && Record->getDefinition())
    PrevDecl = Record;
  if (PrevDecl) {
    MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
    bool HasNoEffect = false;
    assert(MSInfo && "No member specialization information?");
    if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
                                               PrevDecl,
                                        MSInfo->getTemplateSpecializationKind(),
                                             MSInfo->getPointOfInstantiation(),
                                               HasNoEffect))
      return true;
    if (HasNoEffect)
      return TagD;
  }

  CXXRecordDecl *RecordDef
    = cast_or_null<CXXRecordDecl>(Record->getDefinition());
  if (!RecordDef) {
    // C++ [temp.explicit]p3:
    //   A definition of a member class of a class template shall be in scope
    //   at the point of an explicit instantiation of the member class.
    CXXRecordDecl *Def
      = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
    if (!Def) {
      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
        << 0 << Record->getDeclName() << Record->getDeclContext();
      Diag(Pattern->getLocation(), diag::note_forward_declaration)
        << Pattern;
      return true;
    } else {
      if (InstantiateClass(NameLoc, Record, Def,
                           getTemplateInstantiationArgs(Record),
                           TSK))
        return true;

      RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition());
      if (!RecordDef)
        return true;
    }
  }

  // Instantiate all of the members of the class.
  InstantiateClassMembers(NameLoc, RecordDef,
                          getTemplateInstantiationArgs(Record), TSK);

  if (TSK == TSK_ExplicitInstantiationDefinition)
    MarkVTableUsed(NameLoc, RecordDef, true);

  // FIXME: We don't have any representation for explicit instantiations of
  // member classes. Such a representation is not needed for compilation, but it
  // should be available for clients that want to see all of the declarations in
  // the source code.
  return TagD;
}

DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
                                            SourceLocation ExternLoc,
                                            SourceLocation TemplateLoc,
                                            Declarator &D) {
  // Explicit instantiations always require a name.
  // TODO: check if/when DNInfo should replace Name.
  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
  DeclarationName Name = NameInfo.getName();
  if (!Name) {
    if (!D.isInvalidType())
      Diag(D.getDeclSpec().getBeginLoc(),
           diag::err_explicit_instantiation_requires_name)
          << D.getDeclSpec().getSourceRange() << D.getSourceRange();

    return true;
  }

  // Get the innermost enclosing declaration scope.
  S = S->getDeclParent();

  // Determine the type of the declaration.
  TypeSourceInfo *T = GetTypeForDeclarator(D);
  QualType R = T->getType();
  if (R.isNull())
    return true;

  // C++ [dcl.stc]p1:
  //   A storage-class-specifier shall not be specified in [...] an explicit
  //   instantiation (14.7.2) directive.
  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
      << Name;
    return true;
  } else if (D.getDeclSpec().getStorageClassSpec()
                                                != DeclSpec::SCS_unspecified) {
    // Complain about then remove the storage class specifier.
    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
      << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());

    D.getMutableDeclSpec().ClearStorageClassSpecs();
  }

  // C++0x [temp.explicit]p1:
  //   [...] An explicit instantiation of a function template shall not use the
  //   inline or constexpr specifiers.
  // Presumably, this also applies to member functions of class templates as
  // well.
  if (D.getDeclSpec().isInlineSpecified())
    Diag(D.getDeclSpec().getInlineSpecLoc(),
         getLangOpts().CPlusPlus11 ?
           diag::err_explicit_instantiation_inline :
           diag::warn_explicit_instantiation_inline_0x)
      << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
  if (D.getDeclSpec().hasConstexprSpecifier() && R->isFunctionType())
    // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
    // not already specified.
    Diag(D.getDeclSpec().getConstexprSpecLoc(),
         diag::err_explicit_instantiation_constexpr);

  // A deduction guide is not on the list of entities that can be explicitly
  // instantiated.
  if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
    Diag(D.getDeclSpec().getBeginLoc(), diag::err_deduction_guide_specialized)
        << /*explicit instantiation*/ 0;
    return true;
  }

  // C++0x [temp.explicit]p2:
  //   There are two forms of explicit instantiation: an explicit instantiation
  //   definition and an explicit instantiation declaration. An explicit
  //   instantiation declaration begins with the extern keyword. [...]
  TemplateSpecializationKind TSK
    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
                           : TSK_ExplicitInstantiationDeclaration;

  LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
  LookupParsedName(Previous, S, &D.getCXXScopeSpec(),
                   /*ObjectType=*/QualType());

  if (!R->isFunctionType()) {
    // C++ [temp.explicit]p1:
    //   A [...] static data member of a class template can be explicitly
    //   instantiated from the member definition associated with its class
    //   template.
    // C++1y [temp.explicit]p1:
    //   A [...] variable [...] template specialization can be explicitly
    //   instantiated from its template.
    if (Previous.isAmbiguous())
      return true;

    VarDecl *Prev = Previous.getAsSingle<VarDecl>();
    VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>();

    if (!PrevTemplate) {
      if (!Prev || !Prev->isStaticDataMember()) {
        // We expect to see a static data member here.
        Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
            << Name;
        for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
             P != PEnd; ++P)
          Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
        return true;
      }

      if (!Prev->getInstantiatedFromStaticDataMember()) {
        // FIXME: Check for explicit specialization?
        Diag(D.getIdentifierLoc(),
             diag::err_explicit_instantiation_data_member_not_instantiated)
            << Prev;
        Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
        // FIXME: Can we provide a note showing where this was declared?
        return true;
      }
    } else {
      // Explicitly instantiate a variable template.

      // C++1y [dcl.spec.auto]p6:
      //   ... A program that uses auto or decltype(auto) in a context not
      //   explicitly allowed in this section is ill-formed.
      //
      // This includes auto-typed variable template instantiations.
      if (R->isUndeducedType()) {
        Diag(T->getTypeLoc().getBeginLoc(),
             diag::err_auto_not_allowed_var_inst);
        return true;
      }

      if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
        // C++1y [temp.explicit]p3:
        //   If the explicit instantiation is for a variable, the unqualified-id
        //   in the declaration shall be a template-id.
        Diag(D.getIdentifierLoc(),
             diag::err_explicit_instantiation_without_template_id)
          << PrevTemplate;
        Diag(PrevTemplate->getLocation(),
             diag::note_explicit_instantiation_here);
        return true;
      }

      // Translate the parser's template argument list into our AST format.
      TemplateArgumentListInfo TemplateArgs =
          makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);

      DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
                                          D.getIdentifierLoc(), TemplateArgs);
      if (Res.isInvalid())
        return true;

      if (!Res.isUsable()) {
        // We somehow specified dependent template arguments in an explicit
        // instantiation. This should probably only happen during error
        // recovery.
        Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_dependent);
        return true;
      }

      // Ignore access control bits, we don't need them for redeclaration
      // checking.
      Prev = cast<VarDecl>(Res.get());
    }

    // C++0x [temp.explicit]p2:
    //   If the explicit instantiation is for a member function, a member class
    //   or a static data member of a class template specialization, the name of
    //   the class template specialization in the qualified-id for the member
    //   name shall be a simple-template-id.
    //
    // C++98 has the same restriction, just worded differently.
    //
    // This does not apply to variable template specializations, where the
    // template-id is in the unqualified-id instead.
    if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()) && !PrevTemplate)
      Diag(D.getIdentifierLoc(),
           diag::ext_explicit_instantiation_without_qualified_id)
        << Prev << D.getCXXScopeSpec().getRange();

    CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK);

    // Verify that it is okay to explicitly instantiate here.
    TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
    SourceLocation POI = Prev->getPointOfInstantiation();
    bool HasNoEffect = false;
    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
                                               PrevTSK, POI, HasNoEffect))
      return true;

    if (!HasNoEffect) {
      // Instantiate static data member or variable template.
      Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
      if (auto *VTSD = dyn_cast<VarTemplatePartialSpecializationDecl>(Prev)) {
        VTSD->setExternKeywordLoc(ExternLoc);
        VTSD->setTemplateKeywordLoc(TemplateLoc);
      }

      // Merge attributes.
      ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
      if (PrevTemplate)
        ProcessAPINotes(Prev);

      if (TSK == TSK_ExplicitInstantiationDefinition)
        InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
    }

    // Check the new variable specialization against the parsed input.
    if (PrevTemplate && !Context.hasSameType(Prev->getType(), R)) {
      Diag(T->getTypeLoc().getBeginLoc(),
           diag::err_invalid_var_template_spec_type)
          << 0 << PrevTemplate << R << Prev->getType();
      Diag(PrevTemplate->getLocation(), diag::note_template_declared_here)
          << 2 << PrevTemplate->getDeclName();
      return true;
    }

    // FIXME: Create an ExplicitInstantiation node?
    return (Decl*) nullptr;
  }

  // If the declarator is a template-id, translate the parser's template
  // argument list into our AST format.
  bool HasExplicitTemplateArgs = false;
  TemplateArgumentListInfo TemplateArgs;
  if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
    TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
    HasExplicitTemplateArgs = true;
  }

  // C++ [temp.explicit]p1:
  //   A [...] function [...] can be explicitly instantiated from its template.
  //   A member function [...] of a class template can be explicitly
  //  instantiated from the member definition associated with its class
  //  template.
  UnresolvedSet<8> TemplateMatches;
  OverloadCandidateSet NonTemplateMatches(D.getBeginLoc(),
                                          OverloadCandidateSet::CSK_Normal);
  TemplateSpecCandidateSet FailedTemplateCandidates(D.getIdentifierLoc());
  for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
       P != PEnd; ++P) {
    NamedDecl *Prev = *P;
    if (!HasExplicitTemplateArgs) {
      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
        QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
                                                /*AdjustExceptionSpec*/true);
        if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
          if (Method->getPrimaryTemplate()) {
            TemplateMatches.addDecl(Method, P.getAccess());
          } else {
            OverloadCandidate &C = NonTemplateMatches.addCandidate();
            C.FoundDecl = P.getPair();
            C.Function = Method;
            C.Viable = true;
            ConstraintSatisfaction S;
            if (Method->getTrailingRequiresClause() &&
                (CheckFunctionConstraints(Method, S, D.getIdentifierLoc(),
                                          /*ForOverloadResolution=*/true) ||
                 !S.IsSatisfied)) {
              C.Viable = false;
              C.FailureKind = ovl_fail_constraints_not_satisfied;
            }
          }
        }
      }
    }

    FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev);
    if (!FunTmpl)
      continue;

    TemplateDeductionInfo Info(FailedTemplateCandidates.getLocation());
    FunctionDecl *Specialization = nullptr;
    if (TemplateDeductionResult TDK = DeduceTemplateArguments(
            FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), R,
            Specialization, Info);
        TDK != TemplateDeductionResult::Success) {
      // Keep track of almost-matches.
      FailedTemplateCandidates.addCandidate().set(
          P.getPair(), FunTmpl->getTemplatedDecl(),
          MakeDeductionFailureInfo(Context, TDK, Info));
      (void)TDK;
      continue;
    }

    // Target attributes are part of the cuda function signature, so
    // the cuda target of the instantiated function must match that of its
    // template.  Given that C++ template deduction does not take
    // target attributes into account, we reject candidates here that
    // have a different target.
    if (LangOpts.CUDA &&
        CUDA().IdentifyTarget(Specialization,
                              /* IgnoreImplicitHDAttr = */ true) !=
            CUDA().IdentifyTarget(D.getDeclSpec().getAttributes())) {
      FailedTemplateCandidates.addCandidate().set(
          P.getPair(), FunTmpl->getTemplatedDecl(),
          MakeDeductionFailureInfo(
              Context, TemplateDeductionResult::CUDATargetMismatch, Info));
      continue;
    }

    TemplateMatches.addDecl(Specialization, P.getAccess());
  }

  FunctionDecl *Specialization = nullptr;
  if (!NonTemplateMatches.empty()) {
    unsigned Msg = 0;
    OverloadCandidateDisplayKind DisplayKind;
    OverloadCandidateSet::iterator Best;
    switch (NonTemplateMatches.BestViableFunction(*this, D.getIdentifierLoc(),
                                                  Best)) {
    case OR_Success:
    case OR_Deleted:
      Specialization = cast<FunctionDecl>(Best->Function);
      break;
    case OR_Ambiguous:
      Msg = diag::err_explicit_instantiation_ambiguous;
      DisplayKind = OCD_AmbiguousCandidates;
      break;
    case OR_No_Viable_Function:
      Msg = diag::err_explicit_instantiation_no_candidate;
      DisplayKind = OCD_AllCandidates;
      break;
    }
    if (Msg) {
      PartialDiagnostic Diag = PDiag(Msg) << Name;
      NonTemplateMatches.NoteCandidates(
          PartialDiagnosticAt(D.getIdentifierLoc(), Diag), *this, DisplayKind,
          {});
      return true;
    }
  }

  if (!Specialization) {
    // Find the most specialized function template specialization.
    UnresolvedSetIterator Result = getMostSpecialized(
        TemplateMatches.begin(), TemplateMatches.end(),
        FailedTemplateCandidates, D.getIdentifierLoc(),
        PDiag(diag::err_explicit_instantiation_not_known) << Name,
        PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
        PDiag(diag::note_explicit_instantiation_candidate));

    if (Result == TemplateMatches.end())
      return true;

    // Ignore access control bits, we don't need them for redeclaration checking.
    Specialization = cast<FunctionDecl>(*Result);
  }

  // C++11 [except.spec]p4
  // In an explicit instantiation an exception-specification may be specified,
  // but is not required.
  // If an exception-specification is specified in an explicit instantiation
  // directive, it shall be compatible with the exception-specifications of
  // other declarations of that function.
  if (auto *FPT = R->getAs<FunctionProtoType>())
    if (FPT->hasExceptionSpec()) {
      unsigned DiagID =
          diag::err_mismatched_exception_spec_explicit_instantiation;
      if (getLangOpts().MicrosoftExt)
        DiagID = diag::ext_mismatched_exception_spec_explicit_instantiation;
      bool Result = CheckEquivalentExceptionSpec(
          PDiag(DiagID) << Specialization->getType(),
          PDiag(diag::note_explicit_instantiation_here),
          Specialization->getType()->getAs<FunctionProtoType>(),
          Specialization->getLocation(), FPT, D.getBeginLoc());
      // In Microsoft mode, mismatching exception specifications just cause a
      // warning.
      if (!getLangOpts().MicrosoftExt && Result)
        return true;
    }

  if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
    Diag(D.getIdentifierLoc(),
         diag::err_explicit_instantiation_member_function_not_instantiated)
      << Specialization
      << (Specialization->getTemplateSpecializationKind() ==
          TSK_ExplicitSpecialization);
    Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
    return true;
  }

  FunctionDecl *PrevDecl = Specialization->getPreviousDecl();
  if (!PrevDecl && Specialization->isThisDeclarationADefinition())
    PrevDecl = Specialization;

  if (PrevDecl) {
    bool HasNoEffect = false;
    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
                                               PrevDecl,
                                     PrevDecl->getTemplateSpecializationKind(),
                                          PrevDecl->getPointOfInstantiation(),
                                               HasNoEffect))
      return true;

    // FIXME: We may still want to build some representation of this
    // explicit specialization.
    if (HasNoEffect)
      return (Decl*) nullptr;
  }

  // HACK: libc++ has a bug where it attempts to explicitly instantiate the
  // functions
  //     valarray<size_t>::valarray(size_t) and
  //     valarray<size_t>::~valarray()
  // that it declared to have internal linkage with the internal_linkage
  // attribute. Ignore the explicit instantiation declaration in this case.
  if (Specialization->hasAttr<InternalLinkageAttr>() &&
      TSK == TSK_ExplicitInstantiationDeclaration) {
    if (auto *RD = dyn_cast<CXXRecordDecl>(Specialization->getDeclContext()))
      if (RD->getIdentifier() && RD->getIdentifier()->isStr("valarray") &&
          RD->isInStdNamespace())
        return (Decl*) nullptr;
  }

  ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());
  ProcessAPINotes(Specialization);

  // In MSVC mode, dllimported explicit instantiation definitions are treated as
  // instantiation declarations.
  if (TSK == TSK_ExplicitInstantiationDefinition &&
      Specialization->hasAttr<DLLImportAttr>() &&
      Context.getTargetInfo().getCXXABI().isMicrosoft())
    TSK = TSK_ExplicitInstantiationDeclaration;

  Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());

  if (Specialization->isDefined()) {
    // Let the ASTConsumer know that this function has been explicitly
    // instantiated now, and its linkage might have changed.
    Consumer.HandleTopLevelDecl(DeclGroupRef(Specialization));
  } else if (TSK == TSK_ExplicitInstantiationDefinition)
    InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);

  // C++0x [temp.explicit]p2:
  //   If the explicit instantiation is for a member function, a member class
  //   or a static data member of a class template specialization, the name of
  //   the class template specialization in the qualified-id for the member
  //   name shall be a simple-template-id.
  //
  // C++98 has the same restriction, just worded differently.
  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
  if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl &&
      D.getCXXScopeSpec().isSet() &&
      !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
    Diag(D.getIdentifierLoc(),
         diag::ext_explicit_instantiation_without_qualified_id)
    << Specialization << D.getCXXScopeSpec().getRange();

  CheckExplicitInstantiation(
      *this,
      FunTmpl ? (NamedDecl *)FunTmpl
              : Specialization->getInstantiatedFromMemberFunction(),
      D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK);

  // FIXME: Create some kind of ExplicitInstantiationDecl here.
  return (Decl*) nullptr;
}

TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
                                   const CXXScopeSpec &SS,
                                   const IdentifierInfo *Name,
                                   SourceLocation TagLoc,
                                   SourceLocation NameLoc) {
  // This has to hold, because SS is expected to be defined.
  assert(Name && "Expected a name in a dependent tag");

  NestedNameSpecifier *NNS = SS.getScopeRep();
  if (!NNS)
    return true;

  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);

  if (TUK == TagUseKind::Declaration || TUK == TagUseKind::Definition) {
    Diag(NameLoc, diag::err_dependent_tag_decl)
        << (TUK == TagUseKind::Definition) << Kind << SS.getRange();
    return true;
  }

  // Create the resulting type.
  ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
  QualType Result = Context.getDependentNameType(Kwd, NNS, Name);

  // Create type-source location information for this type.
  TypeLocBuilder TLB;
  DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
  TL.setElaboratedKeywordLoc(TagLoc);
  TL.setQualifierLoc(SS.getWithLocInContext(Context));
  TL.setNameLoc(NameLoc);
  return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}

TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
                                   const CXXScopeSpec &SS,
                                   const IdentifierInfo &II,
                                   SourceLocation IdLoc,
                                   ImplicitTypenameContext IsImplicitTypename) {
  if (SS.isInvalid())
    return true;

  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
    DiagCompat(TypenameLoc, diag_compat::typename_outside_of_template)
        << FixItHint::CreateRemoval(TypenameLoc);

  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
  TypeSourceInfo *TSI = nullptr;
  QualType T =
      CheckTypenameType(TypenameLoc.isValid() ? ElaboratedTypeKeyword::Typename
                                              : ElaboratedTypeKeyword::None,
                        TypenameLoc, QualifierLoc, II, IdLoc, &TSI,
                        /*DeducedTSTContext=*/true);
  if (T.isNull())
    return true;
  return CreateParsedType(T, TSI);
}

TypeResult
Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
                        const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
                        TemplateTy TemplateIn, const IdentifierInfo *TemplateII,
                        SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
                        ASTTemplateArgsPtr TemplateArgsIn,
                        SourceLocation RAngleLoc) {
  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
    Diag(TypenameLoc, getLangOpts().CPlusPlus11
                          ? diag::compat_cxx11_typename_outside_of_template
                          : diag::compat_pre_cxx11_typename_outside_of_template)
        << FixItHint::CreateRemoval(TypenameLoc);

  // Strangely, non-type results are not ignored by this lookup, so the
  // program is ill-formed if it finds an injected-class-name.
  if (TypenameLoc.isValid()) {
    auto *LookupRD =
        dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, false));
    if (LookupRD && LookupRD->getIdentifier() == TemplateII) {
      Diag(TemplateIILoc,
           diag::ext_out_of_line_qualified_id_type_names_constructor)
        << TemplateII << 0 /*injected-class-name used as template name*/
        << (TemplateKWLoc.isValid() ? 1 : 0 /*'template'/'typename' keyword*/);
    }
  }

  // Translate the parser's template argument list in our AST format.
  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
  translateTemplateArguments(TemplateArgsIn, TemplateArgs);

  auto Keyword = TypenameLoc.isValid() ? ElaboratedTypeKeyword::Typename
                                       : ElaboratedTypeKeyword::None;

  TemplateName Template = TemplateIn.get();
  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
    // Construct a dependent template specialization type.
    assert(DTN && "dependent template has non-dependent name?");
    assert(DTN->getQualifier() == SS.getScopeRep());

    if (!DTN->getName().getIdentifier()) {
      Diag(TemplateIILoc, diag::err_template_id_not_a_type) << Template;
      NoteAllFoundTemplates(Template);
      return true;
    }

    QualType T = Context.getDependentTemplateSpecializationType(
        Keyword, *DTN, TemplateArgs.arguments());

    // Create source-location information for this type.
    TypeLocBuilder Builder;
    DependentTemplateSpecializationTypeLoc SpecTL
    = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
    SpecTL.setElaboratedKeywordLoc(TypenameLoc);
    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
    SpecTL.setTemplateNameLoc(TemplateIILoc);
    SpecTL.setLAngleLoc(LAngleLoc);
    SpecTL.setRAngleLoc(RAngleLoc);
    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
    return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
  }

  QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
  if (T.isNull())
    return true;

  // Provide source-location information for the template specialization type.
  TypeLocBuilder Builder;
  TemplateSpecializationTypeLoc SpecTL
    = Builder.push<TemplateSpecializationTypeLoc>(T);
  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
  SpecTL.setTemplateNameLoc(TemplateIILoc);
  SpecTL.setLAngleLoc(LAngleLoc);
  SpecTL.setRAngleLoc(RAngleLoc);
  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
    SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());

  T = Context.getElaboratedType(Keyword, SS.getScopeRep(), T);
  ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
  TL.setElaboratedKeywordLoc(TypenameLoc);
  TL.setQualifierLoc(SS.getWithLocInContext(Context));

  TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
  return CreateParsedType(T, TSI);
}

/// Determine whether this failed name lookup should be treated as being
/// disabled by a usage of std::enable_if.
static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
                       SourceRange &CondRange, Expr *&Cond) {
  // We must be looking for a ::type...
  if (!II.isStr("type"))
    return false;

  // ... within an explicitly-written template specialization...
  if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
    return false;
  TypeLoc EnableIfTy = NNS.getTypeLoc();
  TemplateSpecializationTypeLoc EnableIfTSTLoc =
      EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
  if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
    return false;
  const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();

  // ... which names a complete class template declaration...
  const TemplateDecl *EnableIfDecl =
    EnableIfTST->getTemplateName().getAsTemplateDecl();
  if (!EnableIfDecl || EnableIfTST->isIncompleteType())
    return false;

  // ... called "enable_if".
  const IdentifierInfo *EnableIfII =
    EnableIfDecl->getDeclName().getAsIdentifierInfo();
  if (!EnableIfII || !EnableIfII->isStr("enable_if"))
    return false;

  // Assume the first template argument is the condition.
  CondRange = EnableIfTSTLoc.getArgLoc(0).getSourceRange();

  // Dig out the condition.
  Cond = nullptr;
  if (EnableIfTSTLoc.getArgLoc(0).getArgument().getKind()
        != TemplateArgument::Expression)
    return true;

  Cond = EnableIfTSTLoc.getArgLoc(0).getSourceExpression();

  // Ignore Boolean literals; they add no value.
  if (isa<CXXBoolLiteralExpr>(Cond->IgnoreParenCasts()))
    Cond = nullptr;

  return true;
}

QualType
Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
                        SourceLocation KeywordLoc,
                        NestedNameSpecifierLoc QualifierLoc,
                        const IdentifierInfo &II,
                        SourceLocation IILoc,
                        TypeSourceInfo **TSI,
                        bool DeducedTSTContext) {
  QualType T = CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, II, IILoc,
                                 DeducedTSTContext);
  if (T.isNull())
    return QualType();

  *TSI = Context.CreateTypeSourceInfo(T);
  if (isa<DependentNameType>(T)) {
    DependentNameTypeLoc TL =
        (*TSI)->getTypeLoc().castAs<DependentNameTypeLoc>();
    TL.setElaboratedKeywordLoc(KeywordLoc);
    TL.setQualifierLoc(QualifierLoc);
    TL.setNameLoc(IILoc);
  } else {
    ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs<ElaboratedTypeLoc>();
    TL.setElaboratedKeywordLoc(KeywordLoc);
    TL.setQualifierLoc(QualifierLoc);
    TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IILoc);
  }
  return T;
}

/// Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
                        SourceLocation KeywordLoc,
                        NestedNameSpecifierLoc QualifierLoc,
                        const IdentifierInfo &II,
                        SourceLocation IILoc, bool DeducedTSTContext) {
  assert((Keyword != ElaboratedTypeKeyword::None) == KeywordLoc.isValid());

  CXXScopeSpec SS;
  SS.Adopt(QualifierLoc);

  DeclContext *Ctx = nullptr;
  if (QualifierLoc) {
    Ctx = computeDeclContext(SS);
    if (!Ctx) {
      // If the nested-name-specifier is dependent and couldn't be
      // resolved to a type, build a typename type.
      assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
      return Context.getDependentNameType(Keyword,
                                          QualifierLoc.getNestedNameSpecifier(),
                                          &II);
    }

    // If the nested-name-specifier refers to the current instantiation,
    // the "typename" keyword itself is superfluous. In C++03, the
    // program is actually ill-formed. However, DR 382 (in C++0x CD1)
    // allows such extraneous "typename" keywords, and we retroactively
    // apply this DR to C++03 code with only a warning. In any case we continue.

    if (RequireCompleteDeclContext(SS, Ctx))
      return QualType();
  }

  DeclarationName Name(&II);
  LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
  if (Ctx)
    LookupQualifiedName(Result, Ctx, SS);
  else
    LookupName(Result, CurScope);
  unsigned DiagID = 0;
  Decl *Referenced = nullptr;
  switch (Result.getResultKind()) {
  case LookupResultKind::NotFound: {
    // If we're looking up 'type' within a template named 'enable_if', produce
    // a more specific diagnostic.
    SourceRange CondRange;
    Expr *Cond = nullptr;
    if (Ctx && isEnableIf(QualifierLoc, II, CondRange, Cond)) {
      // If we have a condition, narrow it down to the specific failed
      // condition.
      if (Cond) {
        Expr *FailedCond;
        std::string FailedDescription;
        std::tie(FailedCond, FailedDescription) =
          findFailedBooleanCondition(Cond);

        Diag(FailedCond->getExprLoc(),
             diag::err_typename_nested_not_found_requirement)
          << FailedDescription
          << FailedCond->getSourceRange();
        return QualType();
      }

      Diag(CondRange.getBegin(),
           diag::err_typename_nested_not_found_enable_if)
          << Ctx << CondRange;
      return QualType();
    }

    DiagID = Ctx ? diag::err_typename_nested_not_found
                 : diag::err_unknown_typename;
    break;
  }

  case LookupResultKind::FoundUnresolvedValue: {
    // We found a using declaration that is a value. Most likely, the using
    // declaration itself is meant to have the 'typename' keyword.
    SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
                          IILoc);
    Diag(IILoc, diag::err_typename_refers_to_using_value_decl)
      << Name << Ctx << FullRange;
    if (UnresolvedUsingValueDecl *Using
          = dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
      SourceLocation Loc = Using->getQualifierLoc().getBeginLoc();
      Diag(Loc, diag::note_using_value_decl_missing_typename)
        << FixItHint::CreateInsertion(Loc, "typename ");
    }
  }
    // Fall through to create a dependent typename type, from which we can
    // recover better.
    [[fallthrough]];

  case LookupResultKind::NotFoundInCurrentInstantiation:
    // Okay, it's a member of an unknown instantiation.
    return Context.getDependentNameType(Keyword,
                                        QualifierLoc.getNestedNameSpecifier(),
                                        &II);

  case LookupResultKind::Found:
    if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
      // C++ [class.qual]p2:
      //   In a lookup in which function names are not ignored and the
      //   nested-name-specifier nominates a class C, if the name specified
      //   after the nested-name-specifier, when looked up in C, is the
      //   injected-class-name of C [...] then the name is instead considered
      //   to name the constructor of class C.
      //
      // Unlike in an elaborated-type-specifier, function names are not ignored
      // in typename-specifier lookup. However, they are ignored in all the
      // contexts where we form a typename type with no keyword (that is, in
      // mem-initializer-ids, base-specifiers, and elaborated-type-specifiers).
      //
      // FIXME: That's not strictly true: mem-initializer-id lookup does not
      // ignore functions, but that appears to be an oversight.
      QualType T = getTypeDeclType(Ctx,
                                   Keyword == ElaboratedTypeKeyword::Typename
                                       ? DiagCtorKind::Typename
                                       : DiagCtorKind::None,
                                   Type, IILoc);
      // We found a type. Build an ElaboratedType, since the
      // typename-specifier was just sugar.
      return Context.getElaboratedType(
          Keyword, QualifierLoc.getNestedNameSpecifier(), T);
    }

    // C++ [dcl.type.simple]p2:
    //   A type-specifier of the form
    //     typename[opt] nested-name-specifier[opt] template-name
    //   is a placeholder for a deduced class type [...].
    if (getLangOpts().CPlusPlus17) {
      if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
        if (!DeducedTSTContext) {
          QualType T(QualifierLoc
                         ? QualifierLoc.getNestedNameSpecifier()->getAsType()
                         : nullptr, 0);
          if (!T.isNull())
            Diag(IILoc, diag::err_dependent_deduced_tst)
              << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T;
          else
            Diag(IILoc, diag::err_deduced_tst)
              << (int)getTemplateNameKindForDiagnostics(TemplateName(TD));
          NoteTemplateLocation(*TD);
          return QualType();
        }
        return Context.getElaboratedType(
            Keyword, QualifierLoc.getNestedNameSpecifier(),
            Context.getDeducedTemplateSpecializationType(TemplateName(TD),
                                                         QualType(), false));
      }
    }

    DiagID = Ctx ? diag::err_typename_nested_not_type
                 : diag::err_typename_not_type;
    Referenced = Result.getFoundDecl();
    break;

  case LookupResultKind::FoundOverloaded:
    DiagID = Ctx ? diag::err_typename_nested_not_type
                 : diag::err_typename_not_type;
    Referenced = *Result.begin();
    break;

  case LookupResultKind::Ambiguous:
    return QualType();
  }

  // If we get here, it's because name lookup did not find a
  // type. Emit an appropriate diagnostic and return an error.
  SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
                        IILoc);
  if (Ctx)
    Diag(IILoc, DiagID) << FullRange << Name << Ctx;
  else
    Diag(IILoc, DiagID) << FullRange << Name;
  if (Referenced)
    Diag(Referenced->getLocation(),
         Ctx ? diag::note_typename_member_refers_here
             : diag::note_typename_refers_here)
      << Name;
  return QualType();
}

namespace {
  // See Sema::RebuildTypeInCurrentInstantiation
  class CurrentInstantiationRebuilder
    : public TreeTransform<CurrentInstantiationRebuilder> {
    SourceLocation Loc;
    DeclarationName Entity;

  public:
    typedef TreeTransform<CurrentInstantiationRebuilder> inherited;

    CurrentInstantiationRebuilder(Sema &SemaRef,
                                  SourceLocation Loc,
                                  DeclarationName Entity)
    : TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
      Loc(Loc), Entity(Entity) { }

    /// Determine whether the given type \p T has already been
    /// transformed.
    ///
    /// For the purposes of type reconstruction, a type has already been
    /// transformed if it is NULL or if it is not dependent.
    bool AlreadyTransformed(QualType T) {
      return T.isNull() || !T->isInstantiationDependentType();
    }

    /// Returns the location of the entity whose type is being
    /// rebuilt.
    SourceLocation getBaseLocation() { return Loc; }

    /// Returns the name of the entity whose type is being rebuilt.
    DeclarationName getBaseEntity() { return Entity; }

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

    ExprResult TransformLambdaExpr(LambdaExpr *E) {
      // Lambdas never need to be transformed.
      return E;
    }
  };
} // end anonymous namespace

TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
                                                        SourceLocation Loc,
                                                        DeclarationName Name) {
  if (!T || !T->getType()->isInstantiationDependentType())
    return T;

  CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
  return Rebuilder.TransformType(T);
}

ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
  CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(),
                                          DeclarationName());
  return Rebuilder.TransformExpr(E);
}

bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
  if (SS.isInvalid())
    return true;

  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
  CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
                                          DeclarationName());
  NestedNameSpecifierLoc Rebuilt
    = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
  if (!Rebuilt)
    return true;

  SS.Adopt(Rebuilt);
  return false;
}

bool Sema::RebuildTemplateParamsInCurrentInstantiation(
                                               TemplateParameterList *Params) {
  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
    Decl *Param = Params->getParam(I);

    // There is nothing to rebuild in a type parameter.
    if (isa<TemplateTypeParmDecl>(Param))
      continue;

    // Rebuild the template parameter list of a template template parameter.
    if (TemplateTemplateParmDecl *TTP
        = dyn_cast<TemplateTemplateParmDecl>(Param)) {
      if (RebuildTemplateParamsInCurrentInstantiation(
            TTP->getTemplateParameters()))
        return true;

      continue;
    }

    // Rebuild the type of a non-type template parameter.
    NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param);
    TypeSourceInfo *NewTSI
      = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(),
                                          NTTP->getLocation(),
                                          NTTP->getDeclName());
    if (!NewTSI)
      return true;

    if (NewTSI->getType()->isUndeducedType()) {
      // C++17 [temp.dep.expr]p3:
      //   An id-expression is type-dependent if it contains
      //    - an identifier associated by name lookup with a non-type
      //      template-parameter declared with a type that contains a
      //      placeholder type (7.1.7.4),
      NewTSI = SubstAutoTypeSourceInfoDependent(NewTSI);
    }

    if (NewTSI != NTTP->getTypeSourceInfo()) {
      NTTP->setTypeSourceInfo(NewTSI);
      NTTP->setType(NewTSI->getType());
    }
  }

  return false;
}

std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
                                      const TemplateArgumentList &Args) {
  return getTemplateArgumentBindingsText(Params, Args.data(), Args.size());
}

std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
                                      const TemplateArgument *Args,
                                      unsigned NumArgs) {
  SmallString<128> Str;
  llvm::raw_svector_ostream Out(Str);

  if (!Params || Params->size() == 0 || NumArgs == 0)
    return std::string();

  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
    if (I >= NumArgs)
      break;

    if (I == 0)
      Out << "[with ";
    else
      Out << ", ";

    if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
      Out << Id->getName();
    } else {
      Out << '$' << I;
    }

    Out << " = ";
    Args[I].print(getPrintingPolicy(), Out,
                  TemplateParameterList::shouldIncludeTypeForArgument(
                      getPrintingPolicy(), Params, I));
  }

  Out << ']';
  return std::string(Out.str());
}

void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
                                    CachedTokens &Toks) {
  if (!FD)
    return;

  auto LPT = std::make_unique<LateParsedTemplate>();

  // Take tokens to avoid allocations
  LPT->Toks.swap(Toks);
  LPT->D = FnD;
  LPT->FPO = getCurFPFeatures();
  LateParsedTemplateMap.insert(std::make_pair(FD, std::move(LPT)));

  FD->setLateTemplateParsed(true);
}

void Sema::UnmarkAsLateParsedTemplate(FunctionDecl *FD) {
  if (!FD)
    return;
  FD->setLateTemplateParsed(false);
}

bool Sema::IsInsideALocalClassWithinATemplateFunction() {
  DeclContext *DC = CurContext;

  while (DC) {
    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
      const FunctionDecl *FD = RD->isLocalClass();
      return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate);
    } else if (DC->isTranslationUnit() || DC->isNamespace())
      return false;

    DC = DC->getParent();
  }
  return false;
}

namespace {
/// Walk the path from which a declaration was instantiated, and check
/// that every explicit specialization along that path is visible. This enforces
/// C++ [temp.expl.spec]/6:
///
///   If a template, a member template or a member of a class template is
///   explicitly specialized then that specialization shall be declared before
///   the first use of that specialization that would cause an implicit
///   instantiation to take place, in every translation unit in which such a
///   use occurs; no diagnostic is required.
///
/// and also C++ [temp.class.spec]/1:
///
///   A partial specialization shall be declared before the first use of a
///   class template specialization that would make use of the partial
///   specialization as the result of an implicit or explicit instantiation
///   in every translation unit in which such a use occurs; no diagnostic is
///   required.
class ExplicitSpecializationVisibilityChecker {
  Sema &S;
  SourceLocation Loc;
  llvm::SmallVector<Module *, 8> Modules;
  Sema::AcceptableKind Kind;

public:
  ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc,
                                          Sema::AcceptableKind Kind)
      : S(S), Loc(Loc), Kind(Kind) {}

  void check(NamedDecl *ND) {
    if (auto *FD = dyn_cast<FunctionDecl>(ND))
      return checkImpl(FD);
    if (auto *RD = dyn_cast<CXXRecordDecl>(ND))
      return checkImpl(RD);
    if (auto *VD = dyn_cast<VarDecl>(ND))
      return checkImpl(VD);
    if (auto *ED = dyn_cast<EnumDecl>(ND))
      return checkImpl(ED);
  }

private:
  void diagnose(NamedDecl *D, bool IsPartialSpec) {
    auto Kind = IsPartialSpec ? Sema::MissingImportKind::PartialSpecialization
                              : Sema::MissingImportKind::ExplicitSpecialization;
    const bool Recover = true;

    // If we got a custom set of modules (because only a subset of the
    // declarations are interesting), use them, otherwise let
    // diagnoseMissingImport intelligently pick some.
    if (Modules.empty())
      S.diagnoseMissingImport(Loc, D, Kind, Recover);
    else
      S.diagnoseMissingImport(Loc, D, D->getLocation(), Modules, Kind, Recover);
  }

  bool CheckMemberSpecialization(const NamedDecl *D) {
    return Kind == Sema::AcceptableKind::Visible
               ? S.hasVisibleMemberSpecialization(D)
               : S.hasReachableMemberSpecialization(D);
  }

  bool CheckExplicitSpecialization(const NamedDecl *D) {
    return Kind == Sema::AcceptableKind::Visible
               ? S.hasVisibleExplicitSpecialization(D)
               : S.hasReachableExplicitSpecialization(D);
  }

  bool CheckDeclaration(const NamedDecl *D) {
    return Kind == Sema::AcceptableKind::Visible ? S.hasVisibleDeclaration(D)
                                                 : S.hasReachableDeclaration(D);
  }

  // Check a specific declaration. There are three problematic cases:
  //
  //  1) The declaration is an explicit specialization of a template
  //     specialization.
  //  2) The declaration is an explicit specialization of a member of an
  //     templated class.
  //  3) The declaration is an instantiation of a template, and that template
  //     is an explicit specialization of a member of a templated class.
  //
  // We don't need to go any deeper than that, as the instantiation of the
  // surrounding class / etc is not triggered by whatever triggered this
  // instantiation, and thus should be checked elsewhere.
  template<typename SpecDecl>
  void checkImpl(SpecDecl *Spec) {
    bool IsHiddenExplicitSpecialization = false;
    if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
      IsHiddenExplicitSpecialization = Spec->getMemberSpecializationInfo()
                                           ? !CheckMemberSpecialization(Spec)
                                           : !CheckExplicitSpecialization(Spec);
    } else {
      checkInstantiated(Spec);
    }

    if (IsHiddenExplicitSpecialization)
      diagnose(Spec->getMostRecentDecl(), false);
  }

  void checkInstantiated(FunctionDecl *FD) {
    if (auto *TD = FD->getPrimaryTemplate())
      checkTemplate(TD);
  }

  void checkInstantiated(CXXRecordDecl *RD) {
    auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
    if (!SD)
      return;

    auto From = SD->getSpecializedTemplateOrPartial();
    if (auto *TD = From.dyn_cast<ClassTemplateDecl *>())
      checkTemplate(TD);
    else if (auto *TD =
                 From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
      if (!CheckDeclaration(TD))
        diagnose(TD, true);
      checkTemplate(TD);
    }
  }

  void checkInstantiated(VarDecl *RD) {
    auto *SD = dyn_cast<VarTemplateSpecializationDecl>(RD);
    if (!SD)
      return;

    auto From = SD->getSpecializedTemplateOrPartial();
    if (auto *TD = From.dyn_cast<VarTemplateDecl *>())
      checkTemplate(TD);
    else if (auto *TD =
                 From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
      if (!CheckDeclaration(TD))
        diagnose(TD, true);
      checkTemplate(TD);
    }
  }

  void checkInstantiated(EnumDecl *FD) {}

  template<typename TemplDecl>
  void checkTemplate(TemplDecl *TD) {
    if (TD->isMemberSpecialization()) {
      if (!CheckMemberSpecialization(TD))
        diagnose(TD->getMostRecentDecl(), false);
    }
  }
};
} // end anonymous namespace

void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
  if (!getLangOpts().Modules)
    return;

  ExplicitSpecializationVisibilityChecker(*this, Loc,
                                          Sema::AcceptableKind::Visible)
      .check(Spec);
}

void Sema::checkSpecializationReachability(SourceLocation Loc,
                                           NamedDecl *Spec) {
  if (!getLangOpts().CPlusPlusModules)
    return checkSpecializationVisibility(Loc, Spec);

  ExplicitSpecializationVisibilityChecker(*this, Loc,
                                          Sema::AcceptableKind::Reachable)
      .check(Spec);
}

SourceLocation Sema::getTopMostPointOfInstantiation(const NamedDecl *N) const {
  if (!getLangOpts().CPlusPlus || CodeSynthesisContexts.empty())
    return N->getLocation();
  if (const auto *FD = dyn_cast<FunctionDecl>(N)) {
    if (!FD->isFunctionTemplateSpecialization())
      return FD->getLocation();
  } else if (!isa<ClassTemplateSpecializationDecl,
                  VarTemplateSpecializationDecl>(N)) {
    return N->getLocation();
  }
  for (const CodeSynthesisContext &CSC : CodeSynthesisContexts) {
    if (!CSC.isInstantiationRecord() || CSC.PointOfInstantiation.isInvalid())
      continue;
    return CSC.PointOfInstantiation;
  }
  return N->getLocation();
}
