Commit 4063e61b by Jason Merrill Committed by Jason Merrill

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
parent 2fda8e14
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
......
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.
......
...@@ -213,6 +213,27 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl) ...@@ -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;
} }
......
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.
......
...@@ -6663,6 +6663,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, ...@@ -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, ...@@ -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, ...@@ -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 ())
......
...@@ -6451,6 +6451,13 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, ...@@ -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;
} }
......
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
......
// 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;
}
...@@ -62,7 +62,7 @@ foo (int a, int b, int n, int p, int *ptr, struct s *sptr, ...@@ -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" } */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment