Commit 6d729f28 by Jason Merrill Committed by Jason Merrill

re PR c++/43787 (memory copy of empty class (sizeof is one))

	PR c++/43787
gcc:
	* gimplify.c (gimplify_expr): Keep working if gimplify_modify_expr
	returns GS_OK.
	(gimplify_modify_expr_rhs): Return GS_OK if anything changed.
gcc/cp:
	* cp-gimplify.c (cp_gimplify_expr): Remove copies of empty classes.
	* call.c (build_over_call): Don't try to avoid INIT_EXPR copies here.

From-SVN: r159072
parent a2c9b836
2010-05-05 Jason Merrill <jason@redhat.com>
PR c++/43787
* gimplify.c (gimplify_expr): Keep working if gimplify_modify_expr
returns GS_OK.
(gimplify_modify_expr_rhs): Return GS_OK if anything changed.
2010-05-05 Alexandre Oliva <aoliva@redhat.com>
Jakub Jelinek <jakub@redhat.com>
......
2010-05-05 Jason Merrill <jason@redhat.com>
PR c++/43787
* cp-gimplify.c (cp_gimplify_expr): Remove copies of empty classes.
* call.c (build_over_call): Don't try to avoid INIT_EXPR copies here.
2010-05-04 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/43028
......
......@@ -5778,19 +5778,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
complain));
tree type = TREE_TYPE (to);
if (TREE_CODE (arg) != TARGET_EXPR
&& TREE_CODE (arg) != AGGR_INIT_EXPR
&& is_really_empty_class (type))
{
/* Avoid copying empty classes. */
val = build2 (COMPOUND_EXPR, void_type_node, to, arg);
TREE_NO_WARNING (val) = 1;
val = build2 (COMPOUND_EXPR, type, val, to);
TREE_NO_WARNING (val) = 1;
}
else
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
}
......
......@@ -569,6 +569,26 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
&& !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
TREE_TYPE (op0), op1);
else if ((rhs_predicate_for (op0)) (op1)
&& !(TREE_CODE (op1) == CALL_EXPR
&& CALL_EXPR_RETURN_SLOT_OPT (op1))
&& is_really_empty_class (TREE_TYPE (op0)))
{
/* Remove any copies of empty classes. We check that the RHS
has a simple form so that TARGET_EXPRs and CONSTRUCTORs get
reduced properly, and we leave the return slot optimization
alone because it isn't a copy.
Also drop volatile variables on the RHS to avoid infinite
recursion from gimplify_expr trying to load the value. */
if (!TREE_SIDE_EFFECTS (op1)
|| (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
*expr_p = op0;
else
*expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
op0, op1);
}
}
ret = GS_OK;
break;
......
......@@ -4089,9 +4089,12 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
gimple_seq *pre_p, gimple_seq *post_p,
bool want_value)
{
enum gimplify_status ret = GS_OK;
enum gimplify_status ret = GS_UNHANDLED;
bool changed;
while (ret != GS_UNHANDLED)
do
{
changed = false;
switch (TREE_CODE (*from_p))
{
case VAR_DECL:
......@@ -4106,25 +4109,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
&& TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
{
tree old_from = *from_p;
enum gimplify_status subret;
/* Move the constructor into the RHS. */
*from_p = unshare_expr (DECL_INITIAL (*from_p));
/* Let's see if gimplify_init_constructor will need to put
it in memory. If so, revert the change. */
ret = gimplify_init_constructor (expr_p, NULL, NULL, false, true);
if (ret == GS_ERROR)
it in memory. */
subret = gimplify_init_constructor (expr_p, NULL, NULL,
false, true);
if (subret == GS_ERROR)
{
/* If so, revert the change. */
*from_p = old_from;
/* Fall through. */
}
else
{
ret = GS_OK;
break;
changed = true;
}
}
ret = GS_UNHANDLED;
break;
case INDIRECT_REF:
{
......@@ -4142,9 +4146,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
{
*from_p = t;
ret = GS_OK;
changed = true;
}
else
ret = GS_UNHANDLED;
break;
}
......@@ -4167,9 +4170,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
{
*from_p = init;
ret = GS_OK;
changed = true;
}
else
ret = GS_UNHANDLED;
}
break;
......@@ -4178,6 +4180,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
caught. */
gimplify_compound_expr (from_p, pre_p, true);
ret = GS_OK;
changed = true;
break;
case CONSTRUCTOR:
......@@ -4224,8 +4227,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
*expr_p = cond;
return ret;
}
else
ret = GS_UNHANDLED;
break;
case CALL_EXPR:
......@@ -4269,8 +4270,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
mark_addressable (*to_p);
}
}
ret = GS_UNHANDLED;
break;
case WITH_SIZE_EXPR:
......@@ -4280,9 +4279,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
{
*from_p = TREE_OPERAND (*from_p, 0);
ret = GS_OK;
changed = true;
}
else
ret = GS_UNHANDLED;
break;
/* If we're initializing from a container, push the initialization
......@@ -4333,9 +4331,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
}
default:
ret = GS_UNHANDLED;
break;
}
}
while (changed);
return ret;
}
......@@ -6616,8 +6615,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case MODIFY_EXPR:
case INIT_EXPR:
{
tree from = TREE_OPERAND (*expr_p, 1);
ret = gimplify_modify_expr (expr_p, pre_p, post_p,
fallback != fb_none);
/* Don't let the end of loop logic change GS_OK into GS_ALL_DONE
if the RHS has changed. */
if (ret == GS_OK && *expr_p == save_expr
&& TREE_OPERAND (*expr_p, 1) != from)
continue;
}
break;
case TRUTH_ANDIF_EXPR:
......
2010-05-05 Jason Merrill <jason@redhat.com>
PR c++/43787
* g++.dg/opt/empty1.C: New.
2010-05-05 Janus Weil <janus@gcc.gnu.org>
PR fortran/43696
......
// PR c++/43787
// Test that we don't try to copy *x.
// { dg-do run }
class empty_t {};
int main()
{
empty_t* x = 0;
empty_t y = *x;
}
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