On 5/14/24 09:48, Marek Polacek wrote:
On Thu, May 09, 2024 at 03:47:54PM -0400, Jason Merrill wrote:
On 5/9/24 12:04, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

        /* A TARGET_EXPR that expresses direct-initialization should have been
           elided by cp_gimplify_init_expr.  */
        gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

    class Vector { int m_size; };
    struct S {
      const Vector &vec{};
    };

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

    D.2848 = {.vec=(const struct Vector &) &TARGET_EXPR <D.2840, {.m_size=0}>}

where the TARGET_EXPR is no longer direct-initializing anything.

Seems like the problem is in convert_like_internal:

             bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
             if (abstract_virtuals_error (NULL_TREE, totype, complain))
               return error_mark_node;
             expr = build_value_init (totype, complain);
             expr = get_target_expr (expr, complain);
             if (expr != error_mark_node)
               {
                 TARGET_EXPR_LIST_INIT_P (expr) = true;
=>              TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
               }

My patch for 50930 assumed that if a CONSTRUCTOR represents syntactic
direct-initialization, a resulting TARGET_EXPR is itself the direct
initializer, but that isn't the case here; the temporary is
copy-initialized.

We could calculate direct-initializanity from cand->flags, but perhaps we
can just stop trying to set TARGET_EXPR_DIRECT_INIT_P here at all? We don't
do that for other list-initialization in ck_user, I don't know why I thought
it was needed for {} specifically.  It doesn't seem to be needed for the
50930 testcase.

...and it doesn't seem to be needed for any other test.  Then not setting
the flag in the first place is better than resetting it later, sure.

I thought about leaving a gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P)
in cp_build_addr_expr_1, but since we already have that assert when
gimplifying, I dropped it.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/branches?

OK.

-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

       /* A TARGET_EXPR that expresses direct-initialization should have been
          elided by cp_gimplify_init_expr.  */
       gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

   class Vector { int m_size; };
   struct S {
     const Vector &vec{};
   };

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

   D.2848 = {.vec=(const struct Vector &) &TARGET_EXPR <D.2840, {.m_size=0}>}

where the TARGET_EXPR is no longer direct-initializing anything.

Fixed by not setting TARGET_EXPR_DIRECT_INIT_P in convert_like_internal/ck_user.

        PR c++/114854

gcc/cp/ChangeLog:

        * call.cc (convert_like_internal) <case ck_user>: Don't set
        TARGET_EXPR_DIRECT_INIT_P.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp1y/nsdmi-aggr22.C: New test.
---
  gcc/cp/call.cc                            |  6 +-----
  gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C | 12 ++++++++++++
  2 files changed, 13 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index e058da7735f..ed68eb3c568 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8597,16 +8597,12 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
            && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
            && !processing_template_decl)
          {
-           bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
            if (abstract_virtuals_error (NULL_TREE, totype, complain))
              return error_mark_node;
            expr = build_value_init (totype, complain);
            expr = get_target_expr (expr, complain);
            if (expr != error_mark_node)
-             {
-               TARGET_EXPR_LIST_INIT_P (expr) = true;
-               TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
-             }
+             TARGET_EXPR_LIST_INIT_P (expr) = true;
            return expr;
          }
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C
new file mode 100644
index 00000000000..a4f9ae19ca9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C
@@ -0,0 +1,12 @@
+// PR c++/114854
+// { dg-do compile { target c++14 } }
+
+struct Vector {
+  int m_size;
+};
+struct S {
+  const Vector &vec{};
+};
+
+void spawn(S);
+void test() { spawn({}); }

base-commit: 0a99ad5c52caa06c113b1889bbe6634812b89be5

Reply via email to