diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -271,6 +271,9 @@ (`#60887 `_) - Fix incorrect merging of lambdas across modules. (`#60985 `_) +- Fix assertion hit when template consteval function appears in nested + consteval/constexpr call chain. + (`#61142 `_) Bug Fixes to Compiler Builtins diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15175,6 +15175,16 @@ FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext : ExprEvalContexts.back().Context); + // Each ExpressionEvaluationContextRecord also keeps track on whether the + // context is nested in an immediate function context, so smaller contexts + // that appear inside immediate functions (like variable initializers) are + // considered to be inside an immediate function context even though by + // themselves they are not immediate function contexts. But when the new + // function is entered, we need to reset this tracking, since entered function + // might be not an immediate one and therefore everything inside of it needs + // different handling. + ExprEvalContexts.back().InImmediateFunctionContext = FD->isConsteval(); + // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0; diff --git a/clang/test/CodeGenCXX/cxx20-consteval-crash.cpp b/clang/test/CodeGenCXX/cxx20-consteval-crash.cpp --- a/clang/test/CodeGenCXX/cxx20-consteval-crash.cpp +++ b/clang/test/CodeGenCXX/cxx20-consteval-crash.cpp @@ -116,3 +116,23 @@ } } // namespace GH60166 + +namespace GH61142 { + +template +struct Test { + constexpr static void g() { + f(); + } + consteval static void f() {}; +}; + +consteval void a() { + Test::g(); +} + +void b() { + Test::g(); +} + +} // namespace GH61142