]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: constinit and value-initialization [PR119652]
authorJason Merrill <jason@redhat.com>
Mon, 7 Apr 2025 15:49:19 +0000 (11:49 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 7 Apr 2025 17:15:45 +0000 (13:15 -0400)
Value-initialization built an AGGR_INIT_EXPR to set AGGR_INIT_ZERO_FIRST on.
Passing that AGGR_INIT_EXPR to maybe_constant_value returned a TARGET_EXPR,
which potential_constant_expression_1 mistook for a temporary.

We shouldn't add a TARGET_EXPR to the AGGR_INIT_EXPR in this case, just like
we already avoid adding it to CONSTRUCTOR or CALL_EXPR.

PR c++/119652

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_outermost_constant_expr): Also don't add a
TARGET_EXPR around AGGR_INIT_EXPR.

gcc/testsuite/ChangeLog:

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

(cherry picked from commit c7dc9b6f889fa8f9e4ef060c3af107eaf54265c5)

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

index 2da5ddfffe3729c4de0ff87c34fe207f40145e92..14e4bf7f03a5255d795bdc0b77c0f41f35985f0e 100644 (file)
@@ -9034,7 +9034,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
       if (TREE_CODE (t) == TARGET_EXPR
          && TARGET_EXPR_INITIAL (t) == r)
        return t;
-      else if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == CALL_EXPR)
+      else if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == CALL_EXPR
+              || TREE_CODE (t) == AGGR_INIT_EXPR)
        /* Don't add a TARGET_EXPR if our argument didn't have one.  */;
       else if (TREE_CODE (t) == TARGET_EXPR && TARGET_EXPR_CLEANUP (t))
        r = get_target_expr (r);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit20.C b/gcc/testsuite/g++.dg/cpp2a/constinit20.C
new file mode 100644 (file)
index 0000000..9b04391
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/119652
+// { dg-do compile { target c++20 } }
+
+struct __shared_count {
+  constexpr __shared_count() {}
+  ~__shared_count();
+  int _M_pi = 0;
+};
+struct shared_ptr {
+  __shared_count _M_refcount;
+};
+struct A {
+  A() = default;
+  shared_ptr m;
+};
+constinit A a;
+constinit A b {};
+constinit A c = {};