On 12/12/24 1:42 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This ICE started with the recent prvalue optimization (r15-6052).  In
cp_fold_r we have:

       if (tree &init = TARGET_EXPR_INITIAL (stmt))
         {
           cp_walk_tree (&init, cp_fold_r, data, NULL);
           // ...
          tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));

What can happen here is that originally the TARGET_EXPR is:

     TARGET_EXPR <D.2747, <<< Unknown tree: aggr_init_expr
       5
       __ct_comp
       D.2747
       (struct subrange *) <<< Unknown tree: void_cst >>>
       &TARGET_EXPR <D.2707, {.it=TARGET_EXPR <D.2695, ...>}> >>>>

but after the first cp_walk_tree we fold the D.2707 TARGET_EXPR into:

     TARGET_EXPR <D.2707, <<< Unknown tree: expr_stmt
       D.2707.it = TARGET_EXPR <D.2695, ...> >>>>

and then we pass the EXPR_STMT to maybe_constant_init, with D.2707 as
the object.  But their types don't match anymore, so we crash.  We'd
have to pass D.2707.it as the object for it to work.

But I don't think we need to pass any object to maybe_constant_init;
it'll grab the appropriate one itself.

Hmm, it seems to me that the crash is happening because the deduced type is wrong, and so with this change we'll end up only producing an initializer for the first member. Because cp_fold_r throws away the information that initialized_type needs to know the type of the complete object being initialized.

What if we move cp_fold_r of init after the maybe_constant_init?

constexpr-prvalue3.C is reduced from a large std::ranges libstdc++ test.

        PR c++/117980

gcc/cp/ChangeLog:

        * cp-gimplify.cc (cp_fold_r) <case TARGET_EXPR>: Don't pass an object
        to maybe_constant_init.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/constexpr-prvalue2.C: New test.
        * g++.dg/cpp0x/constexpr-prvalue3.C: New test.
---
  gcc/cp/cp-gimplify.cc                         |  2 +-
  .../g++.dg/cpp0x/constexpr-prvalue2.C         | 15 +++++++++++
  .../g++.dg/cpp0x/constexpr-prvalue3.C         | 26 +++++++++++++++++++
  3 files changed, 42 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 623e2ee6e96..a861331c7c7 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1477,7 +1477,7 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
          *walk_subtrees = 0;
          if (!flag_no_inline)
            {
-             tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
+             tree folded = maybe_constant_init (init);
              if (folded != init && TREE_CONSTANT (folded))
                init = folded;
            }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C
new file mode 100644
index 00000000000..46053231cf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C
@@ -0,0 +1,15 @@
+// PR c++/117980
+// { dg-do compile { target c++11 } }
+// { dg-options "-O" }
+
+struct S {
+  constexpr S(S &); // { dg-warning "used but never defined" }
+  ~S();
+};
+struct B {
+  S s;
+};
+struct A {
+  B b;
+};
+void fn(B b) { A{b}; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C
new file mode 100644
index 00000000000..a2eb12c02d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C
@@ -0,0 +1,26 @@
+// PR c++/117980
+// { dg-do compile { target c++11 } }
+// { dg-options "-O" }
+
+struct _Safe_iterator  {
+ _Safe_iterator();
+  ~_Safe_iterator();
+};
+template <typename _Tp>
+struct vector {
+  vector(int) {}
+  constexpr _Safe_iterator end() {
+    return _Safe_iterator();
+  }
+};
+template <typename It> struct sentinel {
+  It it;
+};
+template <typename _Sent>
+struct subrange {
+  subrange(sentinel<_Safe_iterator>) {}
+};
+void test01() {
+  vector<int> v{0};
+  subrange<sentinel<_Safe_iterator>>{sentinel<_Safe_iterator>{v.end()}};
+}

base-commit: 2cbb2408a830a63fbd901a4da3bfd341cec4b6ef

Reply via email to