https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/106055
>From 33ff4f03257c9af03192b92cbd425b731e0f238c Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Mon, 26 Aug 2024 12:28:07 +0200 Subject: [PATCH 1/2] [Clang] Correctly finds subexpressions of immediate invocations We were not correctly ignoring implicit casts. Fixes #105558 --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaExpr.cpp | 17 ++++++++++++++--- clang/test/AST/ByteCode/new-delete.cpp | 16 +++++----------- clang/test/SemaCXX/cxx2a-consteval.cpp | 23 +++++++++++++++++++++++ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8f98167dff31ef..7d3eebb604a244 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -292,6 +292,7 @@ Bug Fixes to C++ Support - Correctly check constraints of explicit instantiations of member functions. (#GH46029) - Fixed an assertion failure about a constraint of a friend function template references to a value with greater template depth than the friend function template. (#GH98258) +- Correctly handle subexpressions of an immediate invocation in the presence of implicit casts. (#GH105558) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c67183df335dd5..1dd0f4bd717c3f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17464,11 +17464,22 @@ static void RemoveNestedImmediateInvocation( ExprResult TransformInitializer(Expr *Init, bool NotCopyInit) { if (!Init) return Init; + + // We cannot use IgnoreImpCasts because we need to preserve + // full expressions. + while (true) { + if (auto *ICE = dyn_cast<ImplicitCastExpr>(Init)) + Init = ICE->getSubExpr(); + else if (auto *ICE = dyn_cast<MaterializeTemporaryExpr>(Init)) + Init = ICE->getSubExpr(); + else + break; + } /// ConstantExpr are the first layer of implicit node to be removed so if /// Init isn't a ConstantExpr, no ConstantExpr will be skipped. - if (auto *CE = dyn_cast<ConstantExpr>(Init)) - if (CE->isImmediateInvocation()) - RemoveImmediateInvocation(CE); + if (auto *CE = dyn_cast<ConstantExpr>(Init); + CE && CE->isImmediateInvocation()) + RemoveImmediateInvocation(CE); return Base::TransformInitializer(Init, NotCopyInit); } ExprResult TransformDeclRefExpr(DeclRefExpr *E) { diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index 6bb30bc19f110c..b90897d66795f3 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -404,7 +404,7 @@ constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept { namespace cxx2a { struct A { - int* p = new int(42); // both-note 7{{heap allocation performed here}} + int* p = new int(42); // both-note 3{{heap allocation performed here}} consteval int ret_i() const { return p ? *p : 0; } consteval A ret_a() const { return A{}; } constexpr ~A() { delete p; } @@ -433,9 +433,7 @@ void test() { { A k = to_lvalue_ref(A()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \ // both-note {{reference to temporary is not a constant expression}} \ // both-note {{temporary created here}} - { A k = to_lvalue_ref(A().ret_a()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ - // both-note {{heap-allocated object is not a constant expression}} \ - // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \ + { A k = to_lvalue_ref(A().ret_a()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \ // both-note {{reference to temporary is not a constant expression}} \ // both-note {{temporary created here}} { int k = A().ret_a().ret_i(); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ @@ -445,19 +443,15 @@ void test() { { int k = const_a_ref(a); } { int k = rvalue_ref(A()); } { int k = rvalue_ref(std::move(a)); } - { int k = const_a_ref(A().ret_a()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ - // both-note {{is not a constant expression}} - { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ - // both-note {{is not a constant expression}} + { int k = const_a_ref(A().ret_a()); } + { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } { int k = by_value_a(to_lvalue_ref(static_cast<const A&&>(a))); } { int k = (A().ret_a(), A().ret_i()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ // both-note {{is not a constant expression}} \ // both-warning {{left operand of comma operator has no effect}} - { int k = (const_a_ref(A().ret_a()), A().ret_i()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \ - // both-note {{is not a constant expression}} \ - // both-warning {{left operand of comma operator has no effect}} + { int k = (const_a_ref(A().ret_a()), A().ret_i()); } // both-warning {{left operand of comma operator has no effect}} } } diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 6b0609a26c5882..f96be6cf0424a9 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -1232,4 +1232,27 @@ consteval void immediate() { } +} + +namespace GH105558 { + +consteval int* alloc() { return new int(0); } +consteval void f(int* p) { delete p; } +consteval void g1(int*&& p) { delete p; } +consteval void g2(const int* p) { delete p; } +consteval void g3(int*const& p) { delete p; } +struct X { + int* p; + explicit(false) constexpr X(int* p) : p(p) {} +}; +consteval void g4(X x) { delete x.p; } + +void test() { + f(alloc()); + g1(alloc()); + g2(alloc()); + g3(alloc()); + g4(alloc()); +} + } >From 52a6a267a932ae820e8fc8edd7554d0d07408ac6 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Mon, 26 Aug 2024 13:18:40 +0200 Subject: [PATCH 2/2] fix tests --- clang/test/SemaCXX/cxx2a-consteval.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index f96be6cf0424a9..81923617f637e8 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -380,11 +380,9 @@ void test() { { A k = to_lvalue_ref(A()); } // expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} { A k = to_lvalue_ref(A().ret_a()); } - // expected-error@-1 {{'alloc::A::ret_a' is not a constant expression}} - // expected-note@-2 {{heap-allocated object is not a constant expression}} - // expected-error@-3 {{'alloc::to_lvalue_ref' is not a constant expression}} - // expected-note@-4 {{reference to temporary is not a constant expression}} - // expected-note@-5 {{temporary created here}} + // expected-note@-1 {{reference to temporary is not a constant expression}} + // expected-error@-2 {{'alloc::to_lvalue_ref' is not a constant expression}} + // expected-note@-3 {{temporary created here}} { int k = A().ret_a().ret_i(); } // expected-error@-1 {{'alloc::A::ret_a' is not a constant expression}} // expected-note@-2 {{heap-allocated object is not a constant expression}} @@ -394,19 +392,13 @@ void test() { { int k = rvalue_ref(A()); } { int k = rvalue_ref(std::move(a)); } { int k = const_a_ref(A().ret_a()); } - // expected-error@-1 {{'alloc::A::ret_a' is not a constant expression}} - // expected-note@-2 {{is not a constant expression}} { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } - // expected-error@-1 {{'alloc::A::ret_a' is not a constant expression}} - // expected-note@-2 {{is not a constant expression}} { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } { int k = by_value_a(to_lvalue_ref(static_cast<const A&&>(a))); } { int k = (A().ret_a(), A().ret_i()); }// expected-error {{is not a constant expression}} // expected-note@-1 {{is not a constant expression}} { int k = (const_a_ref(A().ret_a()), A().ret_i()); } - // expected-error@-1 {{'alloc::A::ret_a' is not a constant expression}} - // expected-note@-2 {{is not a constant expression}} } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits