diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index af3632322b845..29d549efc7382 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1008,6 +1008,7 @@ Bug Fixes to C++ Support - Fix type of expression when calling a template which returns an ``__array_rank`` querying a type depending on a template parameter. Now, such expression can be used with ``static_assert`` and ``constexpr``. (#GH123498) - Correctly determine the implicit constexprness of lambdas in dependent contexts. (#GH97958) (#GH114234) +- Fix that some dependent immediate expressions did not cause immediate escalation (#GH119046) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fe68eadc951b5..3cad9827fdab6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16019,7 +16019,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!FD->isDeletedAsWritten()) FD->setBody(Body); FD->setWillHaveBody(false); - CheckImmediateEscalatingFunctionDefinition(FD, FSI); if (getLangOpts().CPlusPlus14) { if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() && @@ -16397,6 +16396,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // the declaration context below. Otherwise, we're unable to transform // 'this' expressions when transforming immediate context functions. + if (FD) + CheckImmediateEscalatingFunctionDefinition(FD, getCurFunction()); + if (!IsInstantiation) PopDeclContext(); diff --git a/clang/test/CodeGenCXX/gh119046.cpp b/clang/test/CodeGenCXX/gh119046.cpp new file mode 100644 index 0000000000000..cad76879f0862 --- /dev/null +++ b/clang/test/CodeGenCXX/gh119046.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++2a -triple x86_64-elf-gnu %s -emit-llvm -o - | FileCheck %s + +struct S { + consteval void operator()() {} +}; + +template +constexpr void dispatch(Fn fn) { + fn(); +} + +template +struct value_visitor { + constexpr void operator()() { visitor(); } + Visitor&& visitor; +}; + +template +constexpr auto make_dispatch() { + return dispatch>; +} + +template +constexpr void visit(Visitor&&) { + make_dispatch(); +} + +void f() { visit(S{}); } + +// CHECK: define {{.*}} @_Z1fv +// CHECK-NOT: define {{.*}} @_Z5visitI1SEvOT_ +// CHECK-NOT: define {{.*}} @_Z13make_dispatchI1SEDav diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp index 05904d9ade067..dd5063cb29c5b 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -560,3 +560,19 @@ void foo() { S s; } } // namespace GH118000 + +namespace GH119046 { + +template constexpr auto tfn(int) { + return (unsigned long long)(&Cls::sfn); + //expected-note@-1 {{'tfn' is an immediate function because its body evaluates the address of a consteval function 'sfn'}} +}; +struct S { static consteval void sfn() {} }; + +int f() { + int a = 0; // expected-note{{declared here}} + return tfn(a); + //expected-error@-1 {{call to immediate function 'GH119046::tfn' is not a constant expression}} + //expected-note@-2 {{read of non-const variable 'a' is not allowed in a constant expression}} +} +}