]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix ICE with constant evaluation of a = {CLOBBER} with ptrmemfn [PR123677]
authorJakub Jelinek <jakub@redhat.com>
Wed, 21 Jan 2026 13:30:03 +0000 (14:30 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 21 Jan 2026 13:30:03 +0000 (14:30 +0100)
The following testcase ICEs when we evaluate a = {CLOBBER} stmt.
The code assumes that if type is an aggregate type and *valp is
non-NULL, then it must be a CONSTRUCTOR.
That is usually the case, but there is one exception, *valp can
be a PTRMEM_CST if TYPE_PTRMEMFUNC_P (type) and in that
case CONSTRUCTOR_ELTS (*valp) obviously ICEs or misbehaves.

Now, while I could do something like
  if (*valp && (!TYPE_PTRMEMFUNC_P (type) || TREE_CODE (*valp) != PTRMEM_CST))
just making sure TREE_CODE (*valp) == CONSTRUCTOR seems much easier
and more readable.

2026-01-21  Jakub Jelinek  <jakub@redhat.com>

PR c++/123677
* constexpr.cc (cxx_eval_store_expression): Only clear
CONSTRUCTOR_ELTS (*valp) if *valp is CONSTRUCTOR.

* g++.dg/cpp2a/pr123677.C: New test.

gcc/cp/constexpr.cc
gcc/testsuite/g++.dg/cpp2a/pr123677.C [new file with mode: 0644]

index 0873226bc06198e8c2567cdca552576e9f318591..b850bd7ced26678469e5c862ce0c07b9fb305f32 100644 (file)
@@ -8197,7 +8197,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
     {
       if (AGGREGATE_TYPE_P (type))
        {
-         if (*valp)
+         if (*valp && TREE_CODE (*valp) == CONSTRUCTOR)
            CONSTRUCTOR_ELTS (*valp) = nullptr;
          else
            *valp = build_constructor (type, nullptr);
diff --git a/gcc/testsuite/g++.dg/cpp2a/pr123677.C b/gcc/testsuite/g++.dg/cpp2a/pr123677.C
new file mode 100644 (file)
index 0000000..160f190
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/123677
+// { dg-do compile { target c++20 } }
+
+struct B { void foo (); };
+typedef void (B::*A) ();
+struct C { constexpr C (A d) { auto e = new A (d); e->~A (); } };
+C c { &B::foo };