aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-01-15 09:03:53 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-01-15 09:03:53 +0100
commit241f845ab3717714234437e28bbaf2b1cc5f4426 (patch)
treecc04f22cb2a16aa9af9055fefe1388107a5c0f7b /gcc
parenteb6eb8623701589015d966a71970c1893a92884c (diff)
downloadgcc-241f845ab3717714234437e28bbaf2b1cc5f4426.zip
gcc-241f845ab3717714234437e28bbaf2b1cc5f4426.tar.gz
gcc-241f845ab3717714234437e28bbaf2b1cc5f4426.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog9
-rw-r--r--gcc/c-family/c-omp.c19
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-typeck.c22
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58943.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c4
7 files changed, 78 insertions, 7 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d9b69b3..80dd632 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,12 @@
+2014-01-15 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <jakub@redhat.com>
PR target/58115
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index ac380ee..4ce51e4 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 d3b338a5..4754bdf 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-15 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <balaji.v.iyer@intel.com>
PR c++/59631
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index d9dc694..09049e2 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 2f033c0..c9eba44 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-15 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <hongjiu.lu@intel.com>
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 0000000..75e87ae
--- /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 4108188..ead6a18 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;