mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-28 06:14:10 +08:00
c++: TARGET_EXPR collapsing [PR107303]
In r13-2978 I tried to eliminate TARGET_EXPR around TARGET_EXPR by discarding the outer one, but as in this testcase that breaks if the TARGET_EXPR_SLOT of the outer one is used elsewhere. But it should always be safe to strip the inner one; if its slot were reused, there would be a COMPOUND_EXPR around the TARGET_EXPR. For 107329, if we're setting *walk_subtrees, we also need to fold TARGET_EXPR_CLEANUP. PR c++/107303 PR c++/107329 gcc/cp/ChangeLog: * cp-gimplify.cc (cp_fold_r) [TARGET_EXPR]: In case of double TARGET_EXPR, keep the outer one instead of the inner one. (maybe_replace_decl): New. gcc/testsuite/ChangeLog: * g++.dg/ext/builtin-shufflevector-5.C: New test. * g++.dg/init/new51.C: New test.
This commit is contained in:
parent
607f278a35
commit
049a529090
@ -952,6 +952,28 @@ cp_genericize_target_expr (tree *stmt_p)
|
||||
gcc_assert (!DECL_INITIAL (slot));
|
||||
}
|
||||
|
||||
/* Similar to if (target_expr_needs_replace) replace_decl, but TP is the
|
||||
TARGET_EXPR_INITIAL, and this also updates *_SLOT. We need this extra
|
||||
replacement when cp_folding TARGET_EXPR to preserve the invariant that
|
||||
AGGR_INIT_EXPR_SLOT agrees with the enclosing TARGET_EXPR_SLOT. */
|
||||
|
||||
bool
|
||||
maybe_replace_decl (tree *tp, tree decl, tree replacement)
|
||||
{
|
||||
if (!*tp || !VOID_TYPE_P (TREE_TYPE (*tp)))
|
||||
return false;
|
||||
tree t = *tp;
|
||||
while (TREE_CODE (t) == COMPOUND_EXPR)
|
||||
t = TREE_OPERAND (t, 1);
|
||||
if (TREE_CODE (t) == AGGR_INIT_EXPR)
|
||||
replace_decl (&AGGR_INIT_EXPR_SLOT (t), decl, replacement);
|
||||
else if (TREE_CODE (t) == VEC_INIT_EXPR)
|
||||
replace_decl (&VEC_INIT_EXPR_SLOT (t), decl, replacement);
|
||||
else
|
||||
replace_decl (tp, decl, replacement);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Genericization context. */
|
||||
|
||||
struct cp_genericize_data
|
||||
@ -1116,15 +1138,18 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
|
||||
cp_genericize_target_expr (stmt_p);
|
||||
|
||||
/* Folding might replace e.g. a COND_EXPR with a TARGET_EXPR; in
|
||||
that case, use it in place of this one. */
|
||||
that case, strip it in favor of this one. */
|
||||
if (tree &init = TARGET_EXPR_INITIAL (stmt))
|
||||
{
|
||||
cp_walk_tree (&init, cp_fold_r, data, NULL);
|
||||
cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
|
||||
*walk_subtrees = 0;
|
||||
if (TREE_CODE (init) == TARGET_EXPR)
|
||||
{
|
||||
TARGET_EXPR_ELIDING_P (init) = TARGET_EXPR_ELIDING_P (stmt);
|
||||
*stmt_p = init;
|
||||
tree sub = TARGET_EXPR_INITIAL (init);
|
||||
maybe_replace_decl (&sub, TARGET_EXPR_SLOT (init),
|
||||
TARGET_EXPR_SLOT (stmt));
|
||||
init = sub;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
14
gcc/testsuite/g++.dg/ext/builtin-shufflevector-5.C
Normal file
14
gcc/testsuite/g++.dg/ext/builtin-shufflevector-5.C
Normal file
@ -0,0 +1,14 @@
|
||||
// PR c++/107303
|
||||
// { dg-options "-Wno-psabi" }
|
||||
|
||||
typedef __attribute__((__vector_size__ (2))) unsigned short U;
|
||||
typedef __attribute__((__vector_size__ (8))) unsigned short V;
|
||||
|
||||
U u0, u1, u2;
|
||||
V v;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
u0 *= +__builtin_shufflevector (__builtin_shufflevector (u1, v, 3, 1), u2, 0);
|
||||
}
|
10
gcc/testsuite/g++.dg/init/new51.C
Normal file
10
gcc/testsuite/g++.dg/init/new51.C
Normal file
@ -0,0 +1,10 @@
|
||||
// PR c++/107329
|
||||
|
||||
struct RexxClass {
|
||||
void *operator new(unsigned long, unsigned long, const char *, RexxClass *,
|
||||
RexxClass *);
|
||||
void operator delete(void *, unsigned long, const char *, RexxClass *,
|
||||
RexxClass *);
|
||||
RexxClass();
|
||||
};
|
||||
void createInstance() { new (sizeof(RexxClass), "", 0, 0) RexxClass; }
|
Loading…
Reference in New Issue
Block a user