diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5326,8 +5326,13 @@ Var->setImplicitlyInline(); if (OldVar->getInit()) { - EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + ExpressionEvaluationContext Context = + ExpressionEvaluationContext::PotentiallyEvaluated; + // If current context is constant evaluated, the variable initializer + // context is also constant evaluated + if (isConstantEvaluated()) + Context = ExpressionEvaluationContext::ConstantEvaluated; + EnterExpressionEvaluationContext Evaluated(*this, Context, Var); // Instantiate the initializer. ExprResult Init; diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -613,6 +613,24 @@ } // namespace unevaluated +namespace templated { + +consteval int f(int v) { + return v; +} + +template +consteval int g(T a) { + // Previously this call was rejected due to incorrect evaluation context + // type in instantiations. Now we show that this call is OK. + int n = f(a); + return n; +} + +static_assert(g(100) == 100); + +} // namespace templated + namespace PR50779 { struct derp { int b = 0;