https://gcc.gnu.org/g:887bdabfe3e315d661bed55800cd4f64542c7029

commit r15-7348-g887bdabfe3e315d661bed55800cd4f64542c7029
Author: Simon Martin <si...@nasilyan.com>
Date:   Tue Feb 4 10:44:10 2025 +0100

    c++: Properly detect calls to digest_init in build_vec_init [PR114619]
    
    We currently ICE in checking mode with cxx_dialect < 17 on the following
    valid code
    
    === cut here ===
    struct X {
      X(const X&) {}
    };
    extern X x;
    void foo () {
      new X[1]{x};
    }
    === cut here ===
    
    We trip on a gcc_checking_assert in cp_gimplify_expr due to a
    TARGET_EXPR that is not TARGET_EXPR_ELIDING_P. As pointed by Jason, the
    problem is that build_vec_init does not recognize that digest_init has
    been called, and we end up calling the copy constructor twice.
    
    This happens because the detection in build_vec_init assumes that BASE
    is a reference to the array, while it's a pointer to its first element
    here. This patch makes sure that the detection works in both cases.
    
            PR c++/114619
    
    gcc/cp/ChangeLog:
    
            * init.cc (build_vec_init): Properly determine whether
            digest_init has been called.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/init/no-elide4.C: New test.

Diff:
---
 gcc/cp/init.cc                        |  3 ++-
 gcc/testsuite/g++.dg/init/no-elide4.C | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 3ab7f96335c9..613775c5a7c8 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4786,7 +4786,8 @@ build_vec_init (tree base, tree maxindex, tree init,
       tree field, elt;
       /* If the constructor already has the array type, it's been through
         digest_init, so we shouldn't try to do anything more.  */
-      bool digested = same_type_p (atype, TREE_TYPE (init));
+      bool digested = (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
+                      && same_type_p (type, TREE_TYPE (TREE_TYPE (init))));
       from_array = 0;
 
       if (length_check)
diff --git a/gcc/testsuite/g++.dg/init/no-elide4.C 
b/gcc/testsuite/g++.dg/init/no-elide4.C
new file mode 100644
index 000000000000..9377d9f01611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/no-elide4.C
@@ -0,0 +1,11 @@
+// PR c++/114619
+// { dg-do "compile" { target c++11 } }
+// { dg-options "-fno-elide-constructors" }
+
+struct X {
+  X(const X&) {}
+};
+extern X x;
+void foo () {
+  new X[1]{x};
+}

Reply via email to