From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 0EBE53856DC9; Wed, 11 May 2022 06:23:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0EBE53856DC9 From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/70796] [DR 1030] Initialization order with braced-init-lists still broken Date: Wed, 11 May 2022 06:23:19 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 7.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: jakub at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2022 06:23:20 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D70796 --- Comment #11 from CVS Commits --- The releases/gcc-9 branch has been updated by Jakub Jelinek : https://gcc.gnu.org/g:547692808b419da9ed33a9259d031cf62c614dfc commit r9-10111-g547692808b419da9ed33a9259d031cf62c614dfc Author: Jakub Jelinek Date: Fri Nov 19 10:05:01 2021 +0100 c++: Fix up -fstrong-eval-order handling of call arguments [PR70796] For -fstrong-eval-order (default for C++17 and later) we make sure to gimplify arguments in the right order, but as the following testcase shows that is not enough. The problem is that some lvalues can satisfy the is_gimple_val / fb_rva= lue predicate used by gimplify_arg for is_gimple_reg_type typed expressions, or is_gimple_lvalue / fb_either used for other types. E.g. in foo we have: C::C (&p, ++i, ++i) before gimplification where i is an automatic int variable and without = this patch gimplify that as: i =3D i + 1; i =3D i + 1; C::C (&p, i, i); which means that the ctor is called with the original i value increment= ed by 2 in both arguments, while because the call is CALL_EXPR_ORDERED_ARGS the first argument should be different. Similarly in qux we have: B::B (&p, TARGET_EXPR , TARGET_EXPR ) and gimplify it as: _1 =3D A::operator++ (&i); _2 =3D A::operator++ (&i); B::B (&p, MEM[(const struct A &)_1], MEM[(const struct A &)_2]); but because A::operator++ returns the passed in argument, again we have the same value in both cases due to gimplify_arg doing: /* Also strip a TARGET_EXPR that would force an extra copy. */ if (TREE_CODE (*arg_p) =3D=3D TARGET_EXPR) { tree init =3D TARGET_EXPR_INITIAL (*arg_p); if (init && !VOID_TYPE_P (TREE_TYPE (init))) *arg_p =3D init; } which is perfectly fine optimization for calls with unordered arguments, but breaks the ordered ones. Lastly, in corge, we have before gimplification: D::foo (NON_LVALUE_EXPR

, 3, ++p) and gimplify it as p =3D p + 4; D::foo (p, 3, p); which is again wrong, because the this argument isn't before the side-effects but after it. The following patch adds cp_gimplify_arg wrapper, which if ordered and is_gimple_reg_type forces non-SSA_NAME is_gimple_variable result into a temporary, and if ordered, not is_gimple_reg_type and argument is TARGET_EXPR bypasses the gimplify_arg optimization. So, in foo with this patch we gimplify it as: i =3D i + 1; i.0_1 =3D i; i =3D i + 1; C::C (&p, i.0_1, i); in qux as: _1 =3D A::operator++ (&i); D.2312 =3D MEM[(const struct A &)_1]; _2 =3D A::operator++ (&i); B::B (&p, D.2312, MEM[(const struct A &)_2]); where D.2312 is a temporary and in corge as: p.9_1 =3D p; p =3D p + 4; D::foo (p.9_1, 3, p); The is_gimple_reg_type forcing into a temporary should be really cheap (I think even at -O0 it should be optimized if there is no modification= in between), the aggregate copies might be more expensive but I think e.g.= SRA or FRE should be able to deal with those if there are no intervening changes. But still, the patch tries to avoid those when it is cheaply provable that nothing bad happens (if no argument following it in the strong evaluation order doesn't have TREE_SIDE_EFFECTS, then even VAR_D= ECLs etc. shouldn't be modified after it). There is also an optimization to avoid doing that for this or for arguments with reference types as noth= ing can modify the parameter values during evaluation of other argument's side-effects. I've tried if e.g. int i =3D 1; return i << ++i; doesn't suffer from this problem as well, but it doesn't, the FE uses SAVE_EXPR , SAVE_EXPR << ++i; in that case which gimplifies the way we want (temporary in the first operand). 2021-11-19 Jakub Jelinek PR c++/70796 * cp-gimplify.c (cp_gimplify_arg): New function. (cp_gimplify_expr): Use cp_gimplify_arg instead of gimplify_arg, pass true as last argument to it if there are any following arguments in strong evaluation order with side-effects. * g++.dg/cpp1z/eval-order11.C: New test. (cherry picked from commit a84177aff7ca86f501d6aa5ef407fac5e71f56fb)=