@@ -517,6 +517,26 @@ d_save_expr (tree exp)
517517 return exp;
518518}
519519
520+ /* Adjust LVALUE, a MODIFY_EXPR, PREINCREMENT_EXPR or PREDECREMENT_EXPR, so
521+ that it is a valid lvalue, and can be evaluated multiple times. */
522+
523+ static tree
524+ genericize_compound_lvalue (tree lvalue)
525+ {
526+ const tree_code code = TREE_CODE (lvalue);
527+
528+ gcc_assert (code == MODIFY_EXPR
529+ || code == PREINCREMENT_EXPR
530+ || code == PREDECREMENT_EXPR);
531+
532+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (lvalue, 0 )))
533+ lvalue = build2 (TREE_CODE (lvalue), TREE_TYPE (lvalue),
534+ stabilize_reference (TREE_OPERAND (lvalue, 0 )),
535+ TREE_OPERAND (lvalue, 1 ));
536+
537+ return compound_expr (lvalue, TREE_OPERAND (lvalue, 0 ));
538+ }
539+
520540/* Build an unary op CODE to the expression ARG. If the expression can be
521541 broken down so that the operation is applied only to the part whose value we
522542 care about, then handle lowering to keep lvalues trivial. */
@@ -536,17 +556,7 @@ build_unary_op (tree_code code, tree type, tree arg)
536556 if (TREE_CODE (arg) == MODIFY_EXPR
537557 || TREE_CODE (arg) == PREINCREMENT_EXPR
538558 || TREE_CODE (arg) == PREDECREMENT_EXPR)
539- {
540- if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0 )))
541- {
542- arg = build2 (TREE_CODE (arg), TREE_TYPE (arg),
543- stabilize_reference (TREE_OPERAND (arg, 0 )),
544- TREE_OPERAND (arg, 1 ));
545- gcc_unreachable ();
546- }
547- return build_unary_op (code, type,
548- compound_expr (arg, TREE_OPERAND (arg, 0 )));
549- }
559+ return build_unary_op (code, type, genericize_compound_lvalue (arg));
550560
551561 if (code == ADDR_EXPR)
552562 {
@@ -587,6 +597,16 @@ stabilize_expr2 (tree *valuep)
587597 || VOID_TYPE_P (TREE_TYPE (expr)))
588598 return NULL_TREE;
589599
600+ /* Stabilize only the right hand side of compound expressions. */
601+ if (TREE_CODE (expr) == COMPOUND_EXPR)
602+ {
603+ tree lhs = TREE_OPERAND (expr, 0 );
604+ tree rhs = TREE_OPERAND (expr, 1 );
605+ lhs = compound_expr (lhs, stabilize_expr2 (&rhs));
606+ *valuep = rhs;
607+ return lhs;
608+ }
609+
590610 tree init = force_target_expr (expr);
591611 *valuep = TARGET_EXPR_SLOT (init);
592612
@@ -929,13 +949,10 @@ build_struct_comparison (tree_code code, StructDeclaration *sd,
929949 return build_boolop (code, integer_zero_node, integer_zero_node);
930950
931951 /* Make temporaries to prevent multiple evaluations. */
932- tree t1init = stabilize_expr (&t1);
933- tree t2init = stabilize_expr (&t2);
952+ tree t1init = stabilize_expr2 (&t1);
953+ tree t2init = stabilize_expr2 (&t2);
934954 tree result;
935955
936- t1 = d_save_expr (t1);
937- t2 = d_save_expr (t2);
938-
939956 /* Bitwise comparison of structs not returned in memory may not work
940957 due to data holes loosing its zero padding upon return.
941958 As a heuristic, small structs are not compared using memcmp either. */
@@ -1337,6 +1354,12 @@ component_ref (tree object, tree field)
13371354 if (error_operand_p (object) || error_operand_p (field))
13381355 return error_mark_node;
13391356
1357+ if (TREE_CODE (object) == COMPOUND_EXPR)
1358+ {
1359+ tree result = component_ref (TREE_OPERAND (object, 1 ), field);
1360+ return compound_expr (TREE_OPERAND (object, 0 ), result);
1361+ }
1362+
13401363 gcc_assert (TREE_CODE (field) == FIELD_DECL);
13411364
13421365 /* If the FIELD is from an anonymous aggregate, generate a reference
@@ -1359,8 +1382,21 @@ component_ref (tree object, tree field)
13591382tree
13601383build_assign (tree_code code, tree lhs, tree rhs)
13611384{
1362- tree init = stabilize_expr (&lhs);
1363- init = compound_expr (init, stabilize_expr (&rhs));
1385+ /* Handle control structure constructs used as lvalues. */
1386+ if (TREE_CODE (lhs) == COMPOUND_EXPR)
1387+ {
1388+ tree result = build_assign (code, TREE_OPERAND (lhs, 1 ), rhs);
1389+ return compound_expr (TREE_OPERAND (lhs, 0 ), result);
1390+ }
1391+
1392+ if (TREE_CODE (lhs) == MODIFY_EXPR
1393+ || TREE_CODE (lhs) == PREINCREMENT_EXPR
1394+ || TREE_CODE (lhs) == PREDECREMENT_EXPR)
1395+ lhs = genericize_compound_lvalue (lhs);
1396+ else if (TREE_CODE (lhs) == COND_EXPR)
1397+ gcc_unreachable ();
1398+
1399+ // tree init = stabilize_expr2 (&lhs);
13641400
13651401 /* If initializing the LHS using a function that returns via NRVO. */
13661402 if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR
@@ -1390,7 +1426,8 @@ build_assign (tree_code code, tree lhs, tree rhs)
13901426
13911427 tree result = fold_build2_loc (input_location, code,
13921428 TREE_TYPE (lhs), lhs, rhs);
1393- return compound_expr (init, result);
1429+ // return compound_expr (init, result);
1430+ return result;
13941431}
13951432
13961433/* Build an assignment expression of lvalue LHS from value RHS. */
@@ -1558,7 +1595,11 @@ indirect_ref (tree type, tree exp)
15581595 return exp;
15591596
15601597 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1561- tree init = stabilize_expr2 (&exp);
1598+ if (TREE_CODE (exp) == COMPOUND_EXPR)
1599+ {
1600+ tree result = indirect_ref (type, TREE_OPERAND (exp, 1 ));
1601+ return compound_expr (TREE_OPERAND (exp, 0 ), result);
1602+ }
15621603
15631604 if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE)
15641605 exp = fold_build1 (INDIRECT_REF, type, exp);
@@ -1568,7 +1609,7 @@ indirect_ref (tree type, tree exp)
15681609 exp = build_deref (exp);
15691610 }
15701611
1571- return compound_expr (init, exp) ;
1612+ return exp;
15721613}
15731614
15741615/* Returns indirect reference of EXP, which must be a pointer type. */
@@ -1580,7 +1621,11 @@ build_deref (tree exp)
15801621 return exp;
15811622
15821623 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1583- tree init = stabilize_expr2 (&exp);
1624+ if (TREE_CODE (exp) == COMPOUND_EXPR)
1625+ {
1626+ tree result = build_deref (TREE_OPERAND (exp, 1 ));
1627+ return compound_expr (TREE_OPERAND (exp, 0 ), result);
1628+ }
15841629
15851630 gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));
15861631
@@ -1589,7 +1634,7 @@ build_deref (tree exp)
15891634 else
15901635 exp = build_fold_indirect_ref (exp);
15911636
1592- return compound_expr (init, exp) ;
1637+ return exp;
15931638}
15941639
15951640/* Builds pointer offset expression PTR[INDEX]. */
0 commit comments