]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix cxx_eval_store_expression {REAL,IMAG}PART_EXPR handling [PR119045]
authorJakub Jelinek <jakub@redhat.com>
Fri, 28 Feb 2025 14:22:47 +0000 (15:22 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 28 Feb 2025 14:22:47 +0000 (15:22 +0100)
I've added the asserts that probe == target because {REAL,IMAG}PART_EXPR
always implies a scalar type and so applying ARRAY_REF/COMPONENT_REF
etc. on it further doesn't make sense and the later code relies on it
to be the last one in refs array.  But as the following testcase shows,
we can fail those assertions in case there is a reference or pointer
to the __real__ or __imag__ part, in that case we just evaluate the
constant expression and so probe won't be the same as target.
That case doesn't push anything into the refs array though.

The following patch changes those asserts to verify that refs is still
empty, which fixes it.

2025-02-28  Jakub Jelinek  <jakub@redhat.com>

PR c++/119045
* constexpr.cc (cxx_eval_store_expression) <case REALPART_EXPR>:
Assert that refs->is_empty () rather than probe == target.
(cxx_eval_store_expression) <case IMAGPART_EXPR>: Likewise.

* g++.dg/cpp1y/constexpr-complex2.C: New test.

gcc/cp/constexpr.cc
gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C [new file with mode: 0644]

index c68666cc5ddc7ab2b37342102b0f02226129bed2..3cbc9c8b302e0f008a87362c1ce0d17561f012e9 100644 (file)
@@ -6415,7 +6415,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
          break;
 
        case REALPART_EXPR:
-         gcc_assert (probe == target);
+         gcc_assert (refs->is_empty ());
          vec_safe_push (refs, NULL_TREE);
          vec_safe_push (refs, probe);
          vec_safe_push (refs, TREE_TYPE (probe));
@@ -6423,7 +6423,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
          break;
 
        case IMAGPART_EXPR:
-         gcc_assert (probe == target);
+         gcc_assert (refs->is_empty ());
          vec_safe_push (refs, NULL_TREE);
          vec_safe_push (refs, probe);
          vec_safe_push (refs, TREE_TYPE (probe));
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C
new file mode 100644 (file)
index 0000000..7baafd8
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/119045
+// { dg-do compile { target c++14 } }
+
+constexpr float
+foo ()
+{
+  __complex__ float f {1, 2};
+  float s = __real__ f + __imag__ f;
+  float &r = __real__ f;
+  float &i = __imag__ f;
+  r = 42;
+  s += __real__ f;
+  i = 3;
+  s += __imag__ f;
+  return s;
+}
+
+static_assert (foo () == 48.0f, "");