mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 11:41:07 +08:00
gimplify: prevent some C++ temporary elision
In this testcase, we were optimizing away the temporary for f(), but C++17 and above are clear that there is a temporary, and because its destructor has visible side-effects we can't optimize it away under the as-if rule. So disable this optimization for TREE_ADDRESSABLE type. I moved the declaration of volatile_p after the call to gimple_fold_indirect_ref_rhs to minimize indentation changes; I don't see any way the value of that flag could be affected by the call. gcc/ChangeLog: * gimplify.cc (gimplify_modify_expr_rhs): Don't optimize x = *(A*)&<expr> to x = <expr> for a TREE_ADDRESSABLE type. gcc/testsuite/ChangeLog: * g++.dg/init/elide9.C: New test.
This commit is contained in:
parent
89228e3985
commit
d3e5465757
@ -5620,7 +5620,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
|
||||
}
|
||||
break;
|
||||
case INDIRECT_REF:
|
||||
{
|
||||
if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
|
||||
/* If we have code like
|
||||
|
||||
*(const A*)(A*)&x
|
||||
@ -5629,11 +5629,13 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
|
||||
of "A"), treat the entire expression as identical to "x".
|
||||
This kind of code arises in C++ when an object is bound
|
||||
to a const reference, and if "x" is a TARGET_EXPR we want
|
||||
to take advantage of the optimization below. */
|
||||
bool volatile_p = TREE_THIS_VOLATILE (*from_p);
|
||||
tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
|
||||
if (t)
|
||||
to take advantage of the optimization below. But not if
|
||||
the type is TREE_ADDRESSABLE; then C++17 says that the
|
||||
TARGET_EXPR needs to be a temporary. */
|
||||
if (tree t
|
||||
= gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
|
||||
{
|
||||
bool volatile_p = TREE_THIS_VOLATILE (*from_p);
|
||||
if (TREE_THIS_VOLATILE (t) != volatile_p)
|
||||
{
|
||||
if (DECL_P (t))
|
||||
@ -5646,8 +5648,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
|
||||
ret = GS_OK;
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TARGET_EXPR:
|
||||
{
|
||||
|
25
gcc/testsuite/g++.dg/init/elide9.C
Normal file
25
gcc/testsuite/g++.dg/init/elide9.C
Normal file
@ -0,0 +1,25 @@
|
||||
// The static_cast should prevent temporary elision.
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
int d;
|
||||
struct A
|
||||
{
|
||||
int i;
|
||||
A() { }
|
||||
~A() { ++d; }
|
||||
};
|
||||
|
||||
A f() { return A(); }
|
||||
|
||||
struct B
|
||||
{
|
||||
A a;
|
||||
B(): a(static_cast<A&&>(f())) {}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{ B b; }
|
||||
if (d != 2)
|
||||
return -1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user