diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16637,6 +16637,11 @@ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, LambdaContextDecl, ExprContext); + assert( + !(ExprEvalContexts.back().Context == + ExpressionEvaluationContext::PotentiallyEvaluated && + ExprEvalContexts[ExprEvalContexts.size() - 2].isConstantEvaluated()) && + "Can't have an evaluated context within an unevaluated context!"); // Discarded statements and immediate contexts nested in other // discarded statements or immediate context are themselves 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;