Commit 570f86f9 by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/79937 (ICE in replace_placeholders_r)

	PR c++/79937
	PR c++/82410
	* tree.h (TARGET_EXPR_NO_ELIDE): Define.
	* gimplify.c (gimplify_modify_expr_rhs): Don't elide TARGET_EXPRs with
	TARGET_EXPR_NO_ELIDE flag set unless *expr_p is INIT_EXPR.

	* cp-tree.h (CONSTRUCTOR_PLACEHOLDER_BOUNDARY): Define.
	(find_placeholder): Declare.
	* tree.c (struct replace_placeholders_t): Add exp member.
	(replace_placeholders_r): Don't walk into ctors with
	CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set, unless they are equal to
	d->exp.  Replace PLACEHOLDER_EXPR with unshare_expr (x) rather than x.
	(replace_placeholders): Initialize data.exp.
	(find_placeholders_r, find_placeholders): New functions.
	* typeck2.c (process_init_constructor_record,
	process_init_constructor_union): Set CONSTRUCTOR_PLACEHOLDER_BOUNDARY
	if adding NSDMI on which find_placeholder returns true.
	* call.c (build_over_call): Don't call replace_placeholders here.
	* cp-gimplify.c (cp_genericize_r): Set TARGET_EXPR_NO_ELIDE on
	TARGET_EXPRs with CONSTRUCTOR_PLACEHOLDER_BOUNDARY set on
	TARGET_EXPR_INITIAL.
	(cp_fold): Copy over CONSTRUCTOR_PLACEHOLDER_BOUNDARY bit to new
	ctor.

	* g++.dg/cpp1y/pr79937-1.C: New test.
	* g++.dg/cpp1y/pr79937-2.C: New test.
	* g++.dg/cpp1y/pr79937-3.C: New test.
	* g++.dg/cpp1y/pr79937-4.C: New test.
	* g++.dg/cpp1y/pr82410.C: New test.

From-SVN: r258593
parent aafdbe06
2018-03-16 Jakub Jelinek <jakub@redhat.com>
PR c++/79937
PR c++/82410
* tree.h (TARGET_EXPR_NO_ELIDE): Define.
* gimplify.c (gimplify_modify_expr_rhs): Don't elide TARGET_EXPRs with
TARGET_EXPR_NO_ELIDE flag set unless *expr_p is INIT_EXPR.
2018-03-16 Julia Koval <julia.koval@intel.com> 2018-03-16 Julia Koval <julia.koval@intel.com>
* doc/invoke.texi (Skylake Server): Add CLWB. * doc/invoke.texi (Skylake Server): Add CLWB.
......
2018-03-16 Jakub Jelinek <jakub@redhat.com>
PR c++/79937
PR c++/82410
* cp-tree.h (CONSTRUCTOR_PLACEHOLDER_BOUNDARY): Define.
(find_placeholder): Declare.
* tree.c (struct replace_placeholders_t): Add exp member.
(replace_placeholders_r): Don't walk into ctors with
CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set, unless they are equal to
d->exp. Replace PLACEHOLDER_EXPR with unshare_expr (x) rather than x.
(replace_placeholders): Initialize data.exp.
(find_placeholders_r, find_placeholders): New functions.
* typeck2.c (process_init_constructor_record,
process_init_constructor_union): Set CONSTRUCTOR_PLACEHOLDER_BOUNDARY
if adding NSDMI on which find_placeholder returns true.
* call.c (build_over_call): Don't call replace_placeholders here.
* cp-gimplify.c (cp_genericize_r): Set TARGET_EXPR_NO_ELIDE on
TARGET_EXPRs with CONSTRUCTOR_PLACEHOLDER_BOUNDARY set on
TARGET_EXPR_INITIAL.
(cp_fold): Copy over CONSTRUCTOR_PLACEHOLDER_BOUNDARY bit to new
ctor.
2018-03-16 Jason Merrill <jason@redhat.com> 2018-03-16 Jason Merrill <jason@redhat.com>
PR c++/83911 - ICE with multiversioned constructor. PR c++/83911 - ICE with multiversioned constructor.
......
...@@ -8164,8 +8164,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -8164,8 +8164,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{ {
arg = cp_build_fold_indirect_ref (arg); arg = cp_build_fold_indirect_ref (arg);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg); val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
/* Handle NSDMI that refer to the object being initialized. */
replace_placeholders (arg, to);
} }
else else
{ {
......
...@@ -1538,6 +1538,13 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) ...@@ -1538,6 +1538,13 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
} }
break; break;
case TARGET_EXPR:
if (TARGET_EXPR_INITIAL (stmt)
&& TREE_CODE (TARGET_EXPR_INITIAL (stmt)) == CONSTRUCTOR
&& CONSTRUCTOR_PLACEHOLDER_BOUNDARY (TARGET_EXPR_INITIAL (stmt)))
TARGET_EXPR_NO_ELIDE (stmt) = 1;
break;
default: default:
if (IS_TYPE_OR_DECL_P (stmt)) if (IS_TYPE_OR_DECL_P (stmt))
*walk_subtrees = 0; *walk_subtrees = 0;
...@@ -2492,7 +2499,11 @@ cp_fold (tree x) ...@@ -2492,7 +2499,11 @@ cp_fold (tree x)
} }
} }
if (nelts) if (nelts)
x = build_constructor (TREE_TYPE (x), nelts); {
x = build_constructor (TREE_TYPE (x), nelts);
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (x)
= CONSTRUCTOR_PLACEHOLDER_BOUNDARY (org_x);
}
break; break;
} }
case TREE_VEC: case TREE_VEC:
......
...@@ -425,6 +425,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; ...@@ -425,6 +425,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
DECL_VTABLE_OR_VTT_P (in VAR_DECL) DECL_VTABLE_OR_VTT_P (in VAR_DECL)
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR)
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE) 6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL) DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE) TYPE_MARKED_P (in _TYPE)
...@@ -4144,6 +4145,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -4144,6 +4145,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define CONSTRUCTOR_C99_COMPOUND_LITERAL(NODE) \ #define CONSTRUCTOR_C99_COMPOUND_LITERAL(NODE) \
(TREE_LANG_FLAG_3 (CONSTRUCTOR_CHECK (NODE))) (TREE_LANG_FLAG_3 (CONSTRUCTOR_CHECK (NODE)))
/* True if this CONSTRUCTOR contains PLACEHOLDER_EXPRs referencing the
CONSTRUCTOR's type not nested inside another CONSTRUCTOR marked with
CONSTRUCTOR_PLACEHOLDER_BOUNDARY. */
#define CONSTRUCTOR_PLACEHOLDER_BOUNDARY(NODE) \
(TREE_LANG_FLAG_5 (CONSTRUCTOR_CHECK (NODE)))
#define DIRECT_LIST_INIT_P(NODE) \ #define DIRECT_LIST_INIT_P(NODE) \
(BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE))
...@@ -7021,6 +7028,7 @@ extern tree array_type_nelts_top (tree); ...@@ -7021,6 +7028,7 @@ extern tree array_type_nelts_top (tree);
extern tree break_out_target_exprs (tree); extern tree break_out_target_exprs (tree);
extern tree build_ctor_subob_ref (tree, tree, tree); extern tree build_ctor_subob_ref (tree, tree, tree);
extern tree replace_placeholders (tree, tree, bool * = NULL); extern tree replace_placeholders (tree, tree, bool * = NULL);
extern bool find_placeholders (tree);
extern tree get_type_decl (tree); extern tree get_type_decl (tree);
extern tree decl_namespace_context (tree); extern tree decl_namespace_context (tree);
extern bool decl_anon_ns_mem_p (const_tree); extern bool decl_anon_ns_mem_p (const_tree);
......
...@@ -3096,6 +3096,7 @@ build_ctor_subob_ref (tree index, tree type, tree obj) ...@@ -3096,6 +3096,7 @@ build_ctor_subob_ref (tree index, tree type, tree obj)
struct replace_placeholders_t struct replace_placeholders_t
{ {
tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. */ tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. */
tree exp; /* The outermost exp. */
bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */ bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */
hash_set<tree> *pset; /* To avoid walking same trees multiple times. */ hash_set<tree> *pset; /* To avoid walking same trees multiple times. */
}; };
...@@ -3124,7 +3125,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) ...@@ -3124,7 +3125,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
TREE_TYPE (x)); TREE_TYPE (x));
x = TREE_OPERAND (x, 0)) x = TREE_OPERAND (x, 0))
gcc_assert (TREE_CODE (x) == COMPONENT_REF); gcc_assert (TREE_CODE (x) == COMPONENT_REF);
*t = x; *t = unshare_expr (x);
*walk_subtrees = false; *walk_subtrees = false;
d->seen = true; d->seen = true;
} }
...@@ -3134,7 +3135,12 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) ...@@ -3134,7 +3135,12 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
{ {
constructor_elt *ce; constructor_elt *ce;
vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t); vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t);
if (d->pset->add (*t)) /* Don't walk into CONSTRUCTOR_PLACEHOLDER_BOUNDARY ctors
other than the d->exp one, those have PLACEHOLDER_EXPRs
related to another object. */
if ((CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t)
&& *t != d->exp)
|| d->pset->add (*t))
{ {
*walk_subtrees = false; *walk_subtrees = false;
return NULL_TREE; return NULL_TREE;
...@@ -3192,16 +3198,57 @@ replace_placeholders (tree exp, tree obj, bool *seen_p) ...@@ -3192,16 +3198,57 @@ replace_placeholders (tree exp, tree obj, bool *seen_p)
return exp; return exp;
tree *tp = &exp; tree *tp = &exp;
hash_set<tree> pset;
replace_placeholders_t data = { obj, false, &pset };
if (TREE_CODE (exp) == TARGET_EXPR) if (TREE_CODE (exp) == TARGET_EXPR)
tp = &TARGET_EXPR_INITIAL (exp); tp = &TARGET_EXPR_INITIAL (exp);
hash_set<tree> pset;
replace_placeholders_t data = { obj, *tp, false, &pset };
cp_walk_tree (tp, replace_placeholders_r, &data, NULL); cp_walk_tree (tp, replace_placeholders_r, &data, NULL);
if (seen_p) if (seen_p)
*seen_p = data.seen; *seen_p = data.seen;
return exp; return exp;
} }
/* Callback function for find_placeholders. */
static tree
find_placeholders_r (tree *t, int *walk_subtrees, void *)
{
if (TYPE_P (*t) || TREE_CONSTANT (*t))
{
*walk_subtrees = false;
return NULL_TREE;
}
switch (TREE_CODE (*t))
{
case PLACEHOLDER_EXPR:
return *t;
case CONSTRUCTOR:
if (CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t))
*walk_subtrees = false;
break;
default:
break;
}
return NULL_TREE;
}
/* Return true if EXP contains a PLACEHOLDER_EXPR. Don't walk into
ctors with CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set. */
bool
find_placeholders (tree exp)
{
/* This is only relevant for C++14. */
if (cxx_dialect < cxx14)
return false;
return cp_walk_tree_without_duplicates (&exp, find_placeholders_r, NULL);
}
/* Similar to `build_nt', but for template definitions of dependent /* Similar to `build_nt', but for template definitions of dependent
expressions */ expressions */
......
...@@ -1470,6 +1470,9 @@ process_init_constructor_record (tree type, tree init, int nested, ...@@ -1470,6 +1470,9 @@ process_init_constructor_record (tree type, tree init, int nested,
} }
/* C++14 aggregate NSDMI. */ /* C++14 aggregate NSDMI. */
next = get_nsdmi (field, /*ctor*/false, complain); next = get_nsdmi (field, /*ctor*/false, complain);
if (!CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init)
&& find_placeholders (next))
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = 1;
} }
else if (type_build_ctor_call (TREE_TYPE (field))) else if (type_build_ctor_call (TREE_TYPE (field)))
{ {
...@@ -1608,10 +1611,11 @@ process_init_constructor_union (tree type, tree init, int nested, ...@@ -1608,10 +1611,11 @@ process_init_constructor_union (tree type, tree init, int nested,
if (TREE_CODE (field) == FIELD_DECL if (TREE_CODE (field) == FIELD_DECL
&& DECL_INITIAL (field) != NULL_TREE) && DECL_INITIAL (field) != NULL_TREE)
{ {
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (init), tree val = get_nsdmi (field, /*in_ctor=*/false, complain);
field, if (!CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init)
get_nsdmi (field, /*in_ctor=*/false, && find_placeholders (val))
complain)); CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = 1;
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (init), field, val);
break; break;
} }
} }
......
...@@ -5211,6 +5211,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, ...@@ -5211,6 +5211,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
tree init = TARGET_EXPR_INITIAL (*from_p); tree init = TARGET_EXPR_INITIAL (*from_p);
if (init if (init
&& (TREE_CODE (*expr_p) != MODIFY_EXPR
|| !TARGET_EXPR_NO_ELIDE (*from_p))
&& !VOID_TYPE_P (TREE_TYPE (init))) && !VOID_TYPE_P (TREE_TYPE (init)))
{ {
*from_p = init; *from_p = init;
......
2018-03-16 Jakub Jelinek <jakub@redhat.com>
PR c++/79937
PR c++/82410
* g++.dg/cpp1y/pr79937-1.C: New test.
* g++.dg/cpp1y/pr79937-2.C: New test.
* g++.dg/cpp1y/pr79937-3.C: New test.
* g++.dg/cpp1y/pr79937-4.C: New test.
* g++.dg/cpp1y/pr82410.C: New test.
2018-03-16 Tom de Vries <tom@codesourcery.com> 2018-03-16 Tom de Vries <tom@codesourcery.com>
* gcc.dg/tree-ssa/pr84512.c: Require effective target vect_int_mult. * gcc.dg/tree-ssa/pr84512.c: Require effective target vect_int_mult.
......
// PR c++/79937
// { dg-do run { target c++14 } }
struct C {};
struct X {
unsigned i;
unsigned n = i;
};
C
bar (X x)
{
if (x.i != 1 || x.n != 1)
__builtin_abort ();
return {};
}
int
main ()
{
C c = bar (X {1});
}
// PR c++/79937
// { dg-do run { target c++14 } }
struct C {};
struct X {
unsigned i;
unsigned n = i;
unsigned m = i;
};
C
bar (X x)
{
if (x.i != 1 || x.n != 2 || x.m != 1)
__builtin_abort ();
return {};
}
int
main ()
{
C c = bar (X {1, X {2}.n});
}
// PR c++/79937
// { dg-do run { target c++14 } }
struct X {
unsigned i;
unsigned n = i;
unsigned m = i;
};
X
bar (X x)
{
if (x.i != 1 || x.n != 2 || x.m != 1)
__builtin_abort ();
return x;
}
int
main ()
{
X x = bar (X {1, X {2}.n});
if (x.i != 1 || x.n != 2 || x.m != 1)
__builtin_abort ();
}
// PR c++/79937
// { dg-do run { target c++14 } }
struct X {
unsigned i;
unsigned n = i;
};
X
bar (X x)
{
return x;
}
struct Y
{
static Y bar (Y y) { return y; }
unsigned i;
unsigned n = bar (Y{2,i}).n;
};
int
main ()
{
X x { 1, bar (X{2}).n };
if (x.n != 2)
__builtin_abort ();
Y y { 1 };
if (y.n != 1)
__builtin_abort ();
}
// PR c++/82410
// { dg-do compile { target c++14 } }
int
main ()
{
struct A {};
struct S
{
int & p;
int x = p;
operator A () { return {}; }
};
int l;
[] (A) {} (S{l});
}
...@@ -1197,6 +1197,9 @@ extern tree maybe_wrap_with_location (tree, location_t); ...@@ -1197,6 +1197,9 @@ extern tree maybe_wrap_with_location (tree, location_t);
#define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0) #define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
#define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1) #define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1)
#define TARGET_EXPR_CLEANUP(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 2) #define TARGET_EXPR_CLEANUP(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 2)
/* Don't elide the initialization of TARGET_EXPR_SLOT for this TARGET_EXPR
on rhs of MODIFY_EXPR. */
#define TARGET_EXPR_NO_ELIDE(NODE) (TARGET_EXPR_CHECK (NODE)->base.private_flag)
/* DECL_EXPR accessor. This gives access to the DECL associated with /* DECL_EXPR accessor. This gives access to the DECL associated with
the given declaration statement. */ the given declaration statement. */
......
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