diff options
author | Jason Merrill <jason@redhat.com> | 2011-07-08 23:33:54 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-07-08 23:33:54 -0400 |
commit | 4063e61bc63c3803f8ab2d625ebe8432ac06b3da (patch) | |
tree | 2933e4a1c40cd6d7cb203f1eec34d632fcacf4b8 /gcc | |
parent | 2fda8e144a7db5ba6025cfe643da0c6111cc2b0f (diff) | |
download | gcc-4063e61bc63c3803f8ab2d625ebe8432ac06b3da.zip gcc-4063e61bc63c3803f8ab2d625ebe8432ac06b3da.tar.gz gcc-4063e61bc63c3803f8ab2d625ebe8432ac06b3da.tar.bz2 |
re PR c++/45437 (Loses reference during update)
PR c++/45437
gcc/
* gimplify.c (goa_stabilize_expr): Handle RHS preevaluation in
compound assignment.
gcc/c-family/
* c-omp.c (check_omp_for_incr_expr): Handle preevaluation.
gcc/cp/
* typeck.c (cp_build_modify_expr): Preevaluate RHS.
From-SVN: r176072
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 21 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 15 | ||||
-rw-r--r-- | gcc/gimplify.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/compound-asn1.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/sequence-pt-1.C | 2 |
9 files changed, 75 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c2d866d..9bf2942 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2011-07-08 Jason Merrill <jason@redhat.com> + PR c++/45437 + * gimplify.c (goa_stabilize_expr): Handle RHS preevaluation in + compound assignment. + * cgraph.c (cgraph_add_to_same_comdat_group): New. * cgraph.h: Declare it. * ipa.c (function_and_variable_visibility): Make sure thunks diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 72a118a..87930c2 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,5 +1,8 @@ 2011-07-08 Jason Merrill <jason@redhat.com> + PR c++/45437 + * c-omp.c (check_omp_for_incr_expr): Handle preevaluation. + PR c++/49673 * c-common.c (c_apply_type_quals_to_decl): Don't check TYPE_NEEDS_CONSTRUCTING. diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 1ee0bf0..d2256ff 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -213,6 +213,27 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl) return fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t); break; + case COMPOUND_EXPR: + { + /* cp_build_modify_expr forces preevaluation of the RHS to make + sure that it is evaluated before the lvalue-rvalue conversion + is applied to the LHS. Reconstruct the original expression. */ + tree op0 = TREE_OPERAND (exp, 0); + if (TREE_CODE (op0) == TARGET_EXPR + && !VOID_TYPE_P (TREE_TYPE (op0))) + { + tree op1 = TREE_OPERAND (exp, 1); + tree temp = TARGET_EXPR_SLOT (op0); + if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary + && TREE_OPERAND (op1, 1) == temp) + { + op1 = copy_node (op1); + TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0); + return check_omp_for_incr_expr (loc, op1, decl); + } + } + break; + } default: break; } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f776b0..cbdc4d8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2011-07-08 Jason Merrill <jason@redhat.com> + PR c++/45437 + * typeck.c (cp_build_modify_expr): Preevaluate RHS. + * method.c (use_thunk): Use cgraph_add_to_same_comdat_group. * optimize.c (maybe_clone_body): Likewise. * semantics.c (maybe_add_lambda_conv_op): Likewise. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5febff5..d87c107 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6663,6 +6663,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, } else { + tree init = NULL_TREE; + /* A binary op has been requested. Combine the old LHS value with the RHS producing the value we should actually store into the LHS. */ @@ -6670,7 +6672,17 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, && MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype))) || MAYBE_CLASS_TYPE_P (lhstype))); + /* Preevaluate the RHS to make sure its evaluation is complete + before the lvalue-to-rvalue conversion of the LHS: + + [expr.ass] With respect to an indeterminately-sequenced + function call, the operation of a compound assignment is a + single evaluation. [ Note: Therefore, a function call shall + not intervene between the lvalue-to-rvalue conversion and the + side effect associated with any single compound assignment + operator. -- end note ] */ lhs = stabilize_reference (lhs); + rhs = stabilize_expr (rhs, &init); newrhs = cp_build_binary_op (input_location, modifycode, lhs, rhs, complain); @@ -6682,6 +6694,9 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, return error_mark_node; } + if (init) + newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), init, newrhs); + /* Now it looks like a plain assignment. */ modifycode = NOP_EXPR; if (c_dialect_objc ()) diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 4ff7e933..5a928be 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6451,6 +6451,13 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr, lhs_var); break; + case COMPOUND_EXPR: + /* Break out any preevaluations from cp_build_modify_expr. */ + for (; TREE_CODE (expr) == COMPOUND_EXPR; + expr = TREE_OPERAND (expr, 1)) + gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p); + *expr_p = expr; + return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var); default: break; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc6931a..5b8be33 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-07-08 Jason Merrill <jason@redhat.com> + + PR c++/45437 + * g++.dg/expr/compound-asn1.C: New. + * g++.dg/warn/sequence-pt-1.C: Change one dg-error to dg-bogus. + 2011-07-08 Jakub Jelinek <jakub@redhat.com> PR target/49621 diff --git a/gcc/testsuite/g++.dg/expr/compound-asn1.C b/gcc/testsuite/g++.dg/expr/compound-asn1.C new file mode 100644 index 0000000..194235c --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/compound-asn1.C @@ -0,0 +1,15 @@ +// PR c++/45437 +// { dg-options -Wsequence-point } +// { dg-do run } + +bool f(bool& b) { + b = true; + return false; +} + +int main() { + bool b = false; + b |= f(b); + if (!b) + return 1; +} diff --git a/gcc/testsuite/g++.dg/warn/sequence-pt-1.C b/gcc/testsuite/g++.dg/warn/sequence-pt-1.C index 05eee82..6a98fd7 100644 --- a/gcc/testsuite/g++.dg/warn/sequence-pt-1.C +++ b/gcc/testsuite/g++.dg/warn/sequence-pt-1.C @@ -62,7 +62,7 @@ foo (int a, int b, int n, int p, int *ptr, struct s *sptr, (a = a++) && b; /* { dg-warning "undefined" "sequence point warning" } */ b, (a = a++); /* { dg-warning "undefined" "sequence point warning" } */ (a = a++), b; /* { dg-warning "undefined" "sequence point warning" } */ - a ^= b ^= a ^= b; /* { dg-warning "undefined" "sequence point warning" } */ + a ^= b ^= a ^= b; /* { dg-bogus "undefined" "sequence point warning" } */ a = a; /* { dg-bogus "undefined" "bogus sequence point warning" } */ a = (a++ && 4); /* { dg-bogus "undefined" "bogus sequence point warning" } */ |