aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-07-02 22:09:58 +0200
committerJakub Jelinek <jakub@redhat.com>2024-07-02 22:09:58 +0200
commit1250540a98e0a1dfa4d7834672d88d8543ea70b1 (patch)
tree60d3d4a4cc447a31fb3ed4fd9a38caf783c85484 /gcc
parentbeb7a418aaef2ec8a812712110b007c091a73491 (diff)
downloadgcc-1250540a98e0a1dfa4d7834672d88d8543ea70b1.zip
gcc-1250540a98e0a1dfa4d7834672d88d8543ea70b1.tar.gz
gcc-1250540a98e0a1dfa4d7834672d88d8543ea70b1.tar.bz2
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 <jakub@redhat.com> Jason Merrill <jason@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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.cc5
-rw-r--r--gcc/testsuite/g++.dg/cpp26/pr115754.C36
2 files changed, 40 insertions, 1 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index bd72533..0cdac0a 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 0000000..45a8efc
--- /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 ();