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
This commit is contained in:
Jason Merrill 2011-07-08 23:33:54 -04:00 committed by Jason Merrill
parent 2fda8e144a
commit 4063e61bc6
9 changed files with 75 additions and 1 deletions

View File

@ -1,5 +1,9 @@
2011-07-08 Jason Merrill <jason@redhat.com> 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.c (cgraph_add_to_same_comdat_group): New.
* cgraph.h: Declare it. * cgraph.h: Declare it.
* ipa.c (function_and_variable_visibility): Make sure thunks * ipa.c (function_and_variable_visibility): Make sure thunks

View File

@ -1,5 +1,8 @@
2011-07-08 Jason Merrill <jason@redhat.com> 2011-07-08 Jason Merrill <jason@redhat.com>
PR c++/45437
* c-omp.c (check_omp_for_incr_expr): Handle preevaluation.
PR c++/49673 PR c++/49673
* c-common.c (c_apply_type_quals_to_decl): Don't check * c-common.c (c_apply_type_quals_to_decl): Don't check
TYPE_NEEDS_CONSTRUCTING. TYPE_NEEDS_CONSTRUCTING.

View File

@ -213,6 +213,27 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
return fold_build2_loc (loc, PLUS_EXPR, return fold_build2_loc (loc, PLUS_EXPR,
TREE_TYPE (exp), TREE_OPERAND (exp, 0), t); TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
break; 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: default:
break; break;
} }

View File

@ -1,5 +1,8 @@
2011-07-08 Jason Merrill <jason@redhat.com> 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. * method.c (use_thunk): Use cgraph_add_to_same_comdat_group.
* optimize.c (maybe_clone_body): Likewise. * optimize.c (maybe_clone_body): Likewise.
* semantics.c (maybe_add_lambda_conv_op): Likewise. * semantics.c (maybe_add_lambda_conv_op): Likewise.

View File

@ -6663,6 +6663,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
} }
else else
{ {
tree init = NULL_TREE;
/* A binary op has been requested. Combine the old LHS /* A binary op has been requested. Combine the old LHS
value with the RHS producing the value we should actually value with the RHS producing the value we should actually
store into the LHS. */ 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 (TREE_TYPE (lhstype)))
|| MAYBE_CLASS_TYPE_P (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); lhs = stabilize_reference (lhs);
rhs = stabilize_expr (rhs, &init);
newrhs = cp_build_binary_op (input_location, newrhs = cp_build_binary_op (input_location,
modifycode, lhs, rhs, modifycode, lhs, rhs,
complain); complain);
@ -6682,6 +6694,9 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
return error_mark_node; return error_mark_node;
} }
if (init)
newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), init, newrhs);
/* Now it looks like a plain assignment. */ /* Now it looks like a plain assignment. */
modifycode = NOP_EXPR; modifycode = NOP_EXPR;
if (c_dialect_objc ()) if (c_dialect_objc ())

View File

@ -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, saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
lhs_addr, lhs_var); lhs_addr, lhs_var);
break; 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: default:
break; break;
} }

View File

@ -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> 2011-07-08 Jakub Jelinek <jakub@redhat.com>
PR target/49621 PR target/49621

View File

@ -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;
}

View File

@ -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" } */ (a = a++) && b; /* { dg-warning "undefined" "sequence point warning" } */
b, (a = a++); /* { 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 = 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; /* { dg-bogus "undefined" "bogus sequence point warning" } */
a = (a++ && 4); /* { dg-bogus "undefined" "bogus sequence point warning" } */ a = (a++ && 4); /* { dg-bogus "undefined" "bogus sequence point warning" } */