https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127710

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Marek Polacek <[email protected]>:

https://gcc.gnu.org/g:7ae49df44393ea4ce5024511a3d1b2ba81deca90

commit r17-5007-g7ae49df44393ea4ce5024511a3d1b2ba81deca90
Author: Marek Polacek <[email protected]>
Date:   Wed Oct 7 15:56:28 2026 -0400

    c++: TARGET_EXPR in assignment [PR127710]

    Here we crash on

      auto foo = [] {} = {};

    on the assert in build_over_call:

      gcc_assert (TREE_CODE (arg) != TARGET_EXPR
                  || force_elide
                  /* It's from binding the ref parm to a packed field. */
                  || convs[0]->need_temporary_p
                  || ... )

    which makes sure that we are initializing directly from class prvalues
    rather than copying them.  The problem is that we created
    *&TARGET_EXPR <D.2704, {}> in

          if (is_really_empty_class (type, /*ignore_vptr*/true))
            {
              /* Avoid copying empty classes, but ensure op= returns an lvalue
even
                 if the object argument isn't one.  */
              to = force_lvalue (to, complain);
              val = build2 (COMPOUND_EXPR, type, arg, to);
              suppress_warning (val, OPT_Wunused);
            }

    where we want an lvalue, but then in cp_build_addr_expr_1 (Let &* cancel
out
    to simplify resulting code) we get &TARGET_EXPR and then build_over_call
    strips the & and we end up with a prvalue.

    The test is actually ([]{}).operator=({}) where binding the []{}
    object materializes a temporary, operator= returns an lvalue and foo is
    copy-initialized from that lvalue.

    My fix is to follow what cp_build_modify_expr (and other places) do:
    build up a COMPOUND_EXPR and use the TARGET_EXPR_SLOT so that the
    TARGET_EXPR can't become a prvalue.

            PR c++/127710

    gcc/cp/ChangeLog:

            * cvt.cc (force_lvalue): For a TARGET_EXPR, build
            (TARGET_EXPR<...>, slot).

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp2a/class-copy1.C: New test.
            * g++.dg/cpp2a/lambda-assign1.C: New test.

    Reviewed-by: Jason Merrill <[email protected]>

Reply via email to