From: Jason Merrill Date: Sat, 9 Jul 2011 03:33:54 +0000 (-0400) Subject: re PR c++/45437 (Loses reference during update) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4063e61bc63c3803f8ab2d625ebe8432ac06b3da;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c2d866da6a2..9bf29427b60 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2011-07-08 Jason Merrill + 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 72a118a942f..87930c21fcf 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,5 +1,8 @@ 2011-07-08 Jason Merrill + 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 1ee0bf0f8d5..d2256ffd376 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 3f776b097ad..cbdc4d83df2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2011-07-08 Jason Merrill + 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 5febff5cba9..d87c107ab76 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 4ff7e933834..5a928be9434 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 fc6931a24d2..5b8be3309cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-07-08 Jason Merrill + + 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 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 00000000000..194235c64af --- /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 05eee82c176..6a98fd703cd 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" } */