From: Jakub Jelinek Date: Wed, 15 Jan 2014 08:03:53 +0000 (+0100) Subject: re PR c/58943 (wrong calculation of indirect structure member arithmetic via function... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=241f845ab3717714234437e28bbaf2b1cc5f4426;p=gcc.git re PR c/58943 (wrong calculation of indirect structure member arithmetic via function call) PR c/58943 * c-typeck.c (build_modify_expr): For lhs op= rhs, if rhs has side effects, preevaluate rhs using SAVE_EXPR first. * c-omp.c (c_finish_omp_atomic): Set in_late_binary_op around build_modify_expr with non-NOP_EXPR opcode. Handle return from it being COMPOUND_EXPR. (c_finish_omp_for): Handle incr being COMPOUND_EXPR with first operand a SAVE_EXPR and second MODIFY_EXPR. * gcc.c-torture/execute/pr58943.c: New test. * gcc.dg/tree-ssa/ssa-fre-33.c (main): Avoid using += in the test. From-SVN: r206620 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d9b69b32c41..80dd632a632 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2014-01-15 Jakub Jelinek + + PR c/58943 + * c-omp.c (c_finish_omp_atomic): Set in_late_binary_op around + build_modify_expr with non-NOP_EXPR opcode. Handle return from it + being COMPOUND_EXPR. + (c_finish_omp_for): Handle incr being COMPOUND_EXPR with first + operand a SAVE_EXPR and second MODIFY_EXPR. + 2014-01-09 Jakub Jelinek PR target/58115 diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index ac380ee7e1d..4ce51e4a9d2 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -136,7 +136,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst) { - tree x, type, addr; + tree x, type, addr, pre = NULL_TREE; if (lhs == error_mark_node || rhs == error_mark_node || v == error_mark_node || lhs1 == error_mark_node @@ -194,9 +194,18 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs); opcode = NOP_EXPR; } + bool save = in_late_binary_op; + in_late_binary_op = true; x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE); + in_late_binary_op = save; if (x == error_mark_node) return error_mark_node; + if (TREE_CODE (x) == COMPOUND_EXPR) + { + pre = TREE_OPERAND (x, 0); + gcc_assert (TREE_CODE (pre) == SAVE_EXPR); + x = TREE_OPERAND (x, 1); + } gcc_assert (TREE_CODE (x) == MODIFY_EXPR); rhs = TREE_OPERAND (x, 1); @@ -264,6 +273,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, x = omit_one_operand_loc (loc, type, x, rhs1addr); } + if (pre) + x = omit_one_operand_loc (loc, type, x, pre); return x; } @@ -555,6 +566,12 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr); break; + case COMPOUND_EXPR: + if (TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR + || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR) + break; + incr = TREE_OPERAND (incr, 1); + /* FALLTHRU */ case MODIFY_EXPR: if (TREE_OPERAND (incr, 0) != decl) break; diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index d3b338a5b8e..4754bdf2b99 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2014-01-15 Jakub Jelinek + + PR c/58943 + * c-typeck.c (build_modify_expr): For lhs op= rhs, if rhs has side + effects, preevaluate rhs using SAVE_EXPR first. + 2014-01-09 Balaji V. Iyer PR c++/59631 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index d9dc69495e3..09049e2a3ca 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -5193,6 +5193,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, { tree result; tree newrhs; + tree rhseval = NULL_TREE; tree rhs_semantic_type = NULL_TREE; tree lhstype = TREE_TYPE (lhs); tree olhstype = lhstype; @@ -5254,8 +5255,17 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, /* Construct the RHS for any non-atomic compound assignemnt. */ if (!is_atomic_op) { + /* If in LHS op= RHS the RHS has side-effects, ensure they + are preevaluated before the rest of the assignment expression's + side-effects, because RHS could contain e.g. function calls + that modify LHS. */ + if (TREE_SIDE_EFFECTS (rhs)) + { + newrhs = in_late_binary_op ? save_expr (rhs) : c_save_expr (rhs); + rhseval = newrhs; + } newrhs = build_binary_op (location, - modifycode, lhs, rhs, 1); + modifycode, lhs, newrhs, 1); /* The original type of the right hand side is no longer meaningful. */ @@ -5269,7 +5279,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, if so, we need to generate setter calls. */ result = objc_maybe_build_modify_expr (lhs, newrhs); if (result) - return result; + goto return_result; /* Else, do the check that we postponed for Objective-C. */ if (!lvalue_or_else (location, lhs, lv_assign)) @@ -5363,7 +5373,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, if (result) { protected_set_expr_location (result, location); - return result; + goto return_result; } } @@ -5384,11 +5394,15 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, as the LHS argument. */ if (olhstype == TREE_TYPE (result)) - return result; + goto return_result; result = convert_for_assignment (location, olhstype, result, rhs_origtype, ic_assign, false, NULL_TREE, NULL_TREE, 0); protected_set_expr_location (result, location); + +return_result: + if (rhseval) + result = build2 (COMPOUND_EXPR, TREE_TYPE (result), rhseval, result); return result; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2f033c09ebb..c9eba447839 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-01-15 Jakub Jelinek + + PR c/58943 + * gcc.c-torture/execute/pr58943.c: New test. + * gcc.dg/tree-ssa/ssa-fre-33.c (main): Avoid using += in the test. + 2014-01-14 H.J. Lu PR target/59794 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58943.c b/gcc/testsuite/gcc.c-torture/execute/pr58943.c new file mode 100644 index 00000000000..75e87ae0950 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr58943.c @@ -0,0 +1,19 @@ +/* PR c/58943 */ + +unsigned int x[1] = { 2 }; + +unsigned int +foo (void) +{ + x[0] |= 128; + return 1; +} + +int +main () +{ + x[0] |= foo (); + if (x[0] != 131) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c index 41081884601..ead6a183d02 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c @@ -11,8 +11,8 @@ struct { float x; int main(int argc) { - vector float res = (vector float){0.0f,0.0f,0.0f,1.0f}; - res += (vector float){1.0f,2.0f,3.0f,4.0f}; + vector float res; + res = (vector float){1.0f,2.0f,3.0f,5.0f}; s.global_res = res; x = *((float*)&s.global_res + 1); return 0;