https://gcc.gnu.org/g:1250540a98e0a1dfa4d7834672d88d8543ea70b1

commit r15-1795-g1250540a98e0a1dfa4d7834672d88d8543ea70b1
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Tue Jul 2 22:09:58 2024 +0200

    c++: Fix ICE on constexpr placement new [PR115754]
    
    C++26 is making in P2747R2 paper placement new constexpr.
    While working on a patch for that, I've noticed we ICE starting with
    GCC 14 on the following testcase.
    The problem is that e.g. for the void * to sometype * casts checks,
    we really assume the casts have their operand constant evaluated
    as prvalue, but on the testcase the cast itself is evaluated with
    vc_discard and that means op can end up e.g. a VAR_DECL which the
    later code doesn't like and asserts on.
    If the result type is void, we don't really need the cast operand
    for anything, so can use vc_discard for the recursive call,
    VIEW_CONVERT_EXPR can appear on the lhs, so we need to honor the
    lval but otherwise the patch uses vc_prvalue.
    I'd like to get this patch in before the rest of P2747R2 implementation,
    so that it can be backported to 14.2 later on.
    
    2024-07-02  Jakub Jelinek  <ja...@redhat.com>
                Jason Merrill  <ja...@redhat.com>
    
            PR c++/115754
            * constexpr.cc (cxx_eval_constant_expression) <case CONVERT_EXPR>:
            For conversions to void, pass vc_discard to the recursive call
            and otherwise for tcode other than VIEW_CONVERT_EXPR pass 
vc_prvalue.
    
            * g++.dg/cpp26/pr115754.C: New test.

Diff:
---
 gcc/cp/constexpr.cc                   |  5 ++++-
 gcc/testsuite/g++.dg/cpp26/pr115754.C | 36 +++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index bd72533491e..0cdac0af7de 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8103,7 +8103,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
        tree oldop = TREE_OPERAND (t, 0);
 
        tree op = cxx_eval_constant_expression (ctx, oldop,
-                                               lval,
+                                               VOID_TYPE_P (TREE_TYPE (t))
+                                               ? vc_discard
+                                               : tcode == VIEW_CONVERT_EXPR
+                                               ? lval : vc_prvalue,
                                                non_constant_p, overflow_p);
        if (*non_constant_p)
          return t;
diff --git a/gcc/testsuite/g++.dg/cpp26/pr115754.C 
b/gcc/testsuite/g++.dg/cpp26/pr115754.C
new file mode 100644
index 00000000000..45a8efcd9a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/pr115754.C
@@ -0,0 +1,36 @@
+// PR c++/115754
+// { dg-do compile { target c++26 } }
+
+namespace std
+{
+  using size_t = decltype (sizeof 0);
+
+  template <typename T>
+  struct allocator
+  {
+    constexpr allocator () noexcept {}
+
+    constexpr T *allocate (size_t n)
+    { return static_cast<T *> (::operator new (n * sizeof(T))); }
+
+    constexpr void
+    deallocate (T *p, size_t n)
+    { ::operator delete (p); }
+  };
+}
+
+constexpr void *
+operator new (std::size_t, void *p) noexcept
+{ return p; }
+
+constexpr bool
+foo ()
+{
+  std::allocator<int> a;
+  auto b = a.allocate (1);
+  ::new (b) int ();
+  a.deallocate (b, 1);
+  return true;
+}
+
+constexpr bool a = foo ();

Reply via email to