Commit c12ff9d8 by Jason Merrill Committed by Jason Merrill

re PR c++/40975 (ICE in copy_tree_r on array new)

	PR c++/40975
	* cp-tree.def (VEC_INIT_EXPR): Add third operand.
	* cp-tree.h (VEC_INIT_EXPR_NELTS): New.
	* cp-gimplify.c (cp_gimplify_expr) [VEC_INIT_EXPR]: Handle it.
	* tree.c (build_vec_init_expr): Handle getting pointer/nelts.
	(build_vec_init_elt): Don't expect an array type.
	(build_array_copy): Adjust.
	* init.c (perform_member_init): Adjust.
	(build_new_1): Use build_vec_init_expr.

From-SVN: r173056
parent fbaf0d0c
2011-04-27 Jason Merrill <jason@redhat.com>
* c-common.c (make_tree_vector_from_list): New.
* c-common.h: Declare it.
2011-04-26 Richard Guenther <rguenther@suse.de> 2011-04-26 Richard Guenther <rguenther@suse.de>
PR preprocessor/48248 PR preprocessor/48248
......
...@@ -9580,6 +9580,17 @@ make_tree_vector_single (tree t) ...@@ -9580,6 +9580,17 @@ make_tree_vector_single (tree t)
return ret; return ret;
} }
/* Get a new tree vector of the TREE_VALUEs of a TREE_LIST chain. */
VEC(tree,gc) *
make_tree_vector_from_list (tree list)
{
VEC(tree,gc) *ret = make_tree_vector ();
for (; list; list = TREE_CHAIN (list))
VEC_safe_push (tree, gc, ret, TREE_VALUE (list));
return ret;
}
/* Get a new tree vector which is a copy of an existing one. */ /* Get a new tree vector which is a copy of an existing one. */
VEC(tree,gc) * VEC(tree,gc) *
......
...@@ -959,6 +959,7 @@ extern void set_underlying_type (tree x); ...@@ -959,6 +959,7 @@ extern void set_underlying_type (tree x);
extern VEC(tree,gc) *make_tree_vector (void); extern VEC(tree,gc) *make_tree_vector (void);
extern void release_tree_vector (VEC(tree,gc) *); extern void release_tree_vector (VEC(tree,gc) *);
extern VEC(tree,gc) *make_tree_vector_single (tree); extern VEC(tree,gc) *make_tree_vector_single (tree);
extern VEC(tree,gc) *make_tree_vector_from_list (tree);
extern VEC(tree,gc) *make_tree_vector_copy (const VEC(tree,gc) *); extern VEC(tree,gc) *make_tree_vector_copy (const VEC(tree,gc) *);
/* In c-gimplify.c */ /* In c-gimplify.c */
......
2011-04-27 Jason Merrill <jason@redhat.com> 2011-04-27 Jason Merrill <jason@redhat.com>
PR c++/40975
* cp-tree.def (VEC_INIT_EXPR): Add third operand.
* cp-tree.h (VEC_INIT_EXPR_NELTS): New.
* cp-gimplify.c (cp_gimplify_expr) [VEC_INIT_EXPR]: Handle it.
* tree.c (build_vec_init_expr): Handle getting pointer/nelts.
(build_vec_init_elt): Don't expect an array type.
(build_array_copy): Adjust.
* init.c (perform_member_init): Adjust.
(build_new_1): Use build_vec_init_expr.
* class.c (resolve_address_of_overloaded_function): Don't * class.c (resolve_address_of_overloaded_function): Don't
change OVERLOAD to TREE_LIST. change OVERLOAD to TREE_LIST.
* pt.c (print_candidates_1): Remove nonsensical assert. * pt.c (print_candidates_1): Remove nonsensical assert.
......
...@@ -530,10 +530,12 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) ...@@ -530,10 +530,12 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
{ {
location_t loc = input_location; location_t loc = input_location;
tree init = VEC_INIT_EXPR_INIT (*expr_p); tree init = VEC_INIT_EXPR_INIT (*expr_p);
int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE); int from_array = (init && TREE_TYPE (init)
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
gcc_assert (EXPR_HAS_LOCATION (*expr_p)); gcc_assert (EXPR_HAS_LOCATION (*expr_p));
input_location = EXPR_LOCATION (*expr_p); input_location = EXPR_LOCATION (*expr_p);
*expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p),
VEC_INIT_EXPR_NELTS (*expr_p),
init, VEC_INIT_EXPR_VALUE_INIT (*expr_p), init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
from_array, from_array,
tf_warning_or_error); tf_warning_or_error);
......
...@@ -83,8 +83,8 @@ DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3) ...@@ -83,8 +83,8 @@ DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3)
/* Initialization of an array from another array, expressed at a high level /* Initialization of an array from another array, expressed at a high level
so that it works with TARGET_EXPR. Operand 0 is the target, operand 1 so that it works with TARGET_EXPR. Operand 0 is the target, operand 1
is the initializer. */ is the initializer, operand 2 is the number of elements or NULL_TREE. */
DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", tcc_expression, 2) DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", tcc_expression, 3)
/* A throw expression. operand 0 is the expression, if there was one, /* A throw expression. operand 0 is the expression, if there was one,
else it is NULL_TREE. */ else it is NULL_TREE. */
......
...@@ -2896,8 +2896,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -2896,8 +2896,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
(arg) = next_aggr_init_expr_arg (&(iter))) (arg) = next_aggr_init_expr_arg (&(iter)))
/* VEC_INIT_EXPR accessors. */ /* VEC_INIT_EXPR accessors. */
#define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (NODE, 0) #define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 0)
#define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (NODE, 1) #define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 1)
#define VEC_INIT_EXPR_NELTS(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 2)
/* Indicates that a VEC_INIT_EXPR is a potential constant expression. /* Indicates that a VEC_INIT_EXPR is a potential constant expression.
Only set when the current function is constexpr. */ Only set when the current function is constexpr. */
...@@ -5022,6 +5023,7 @@ extern tree get_copy_ctor (tree); ...@@ -5022,6 +5023,7 @@ extern tree get_copy_ctor (tree);
extern tree get_copy_assign (tree); extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree); extern tree get_default_ctor (tree);
extern tree get_dtor (tree); extern tree get_dtor (tree);
extern tree get_dtor_sfinae (tree, tsubst_flags_t);
extern tree locate_ctor (tree); extern tree locate_ctor (tree);
/* In optimize.c */ /* In optimize.c */
...@@ -5418,7 +5420,7 @@ extern tree get_target_expr_sfinae (tree, tsubst_flags_t); ...@@ -5418,7 +5420,7 @@ extern tree get_target_expr_sfinae (tree, tsubst_flags_t);
extern tree build_cplus_array_type (tree, tree); extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int); extern tree build_array_of_n_type (tree, int);
extern tree build_array_copy (tree); extern tree build_array_copy (tree);
extern tree build_vec_init_expr (tree, tree); extern tree build_vec_init_expr (tree, tree, tree, tsubst_flags_t);
extern void diagnose_non_constexpr_vec_init (tree); extern void diagnose_non_constexpr_vec_init (tree);
extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree); extern tree hash_tree_chain (tree, tree);
......
...@@ -506,7 +506,8 @@ perform_member_init (tree member, tree init) ...@@ -506,7 +506,8 @@ perform_member_init (tree member, tree init)
/* mem() means value-initialization. */ /* mem() means value-initialization. */
if (TREE_CODE (type) == ARRAY_TYPE) if (TREE_CODE (type) == ARRAY_TYPE)
{ {
init = build_vec_init_expr (type, init); init = build_vec_init_expr (type, init, NULL_TREE,
tf_warning_or_error);
init = build2 (INIT_EXPR, type, decl, init); init = build2 (INIT_EXPR, type, decl, init);
finish_expr_stmt (init); finish_expr_stmt (init);
} }
...@@ -541,7 +542,8 @@ perform_member_init (tree member, tree init) ...@@ -541,7 +542,8 @@ perform_member_init (tree member, tree init)
|| same_type_ignoring_top_level_qualifiers_p (type, || same_type_ignoring_top_level_qualifiers_p (type,
TREE_TYPE (init))) TREE_TYPE (init)))
{ {
init = build_vec_init_expr (type, init); init = build_vec_init_expr (type, init, NULL_TREE,
tf_warning_or_error);
init = build2 (INIT_EXPR, type, decl, init); init = build2 (INIT_EXPR, type, decl, init);
finish_expr_stmt (init); finish_expr_stmt (init);
} }
...@@ -2384,15 +2386,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -2384,15 +2386,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
vecinit = build_tree_list_vec (*init); vecinit = build_tree_list_vec (*init);
} }
init_expr init_expr
= build_vec_init (data_addr, = build_vec_init_expr (data_addr,
cp_build_binary_op (input_location, (explicit_value_init_p
MINUS_EXPR, outer_nelts, ? void_type_node: vecinit),
integer_one_node, cp_build_binary_op (input_location,
complain), MINUS_EXPR, outer_nelts,
vecinit, integer_one_node,
explicit_value_init_p, complain),
/*from_array=*/0, complain);
complain);
/* An array initialization is stable because the initialization /* An array initialization is stable because the initialization
of each element is a full-expression, so the temporaries don't of each element is a full-expression, so the temporaries don't
......
...@@ -843,10 +843,16 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags, ...@@ -843,10 +843,16 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
/* Locate the dtor of TYPE. */ /* Locate the dtor of TYPE. */
tree tree
get_dtor_sfinae (tree type, tsubst_flags_t complain)
{
return locate_fn_flags (type, complete_dtor_identifier, NULL_TREE,
LOOKUP_NORMAL, complain);
}
tree
get_dtor (tree type) get_dtor (tree type)
{ {
tree fn = locate_fn_flags (type, complete_dtor_identifier, NULL_TREE, tree fn = get_dtor_sfinae (type, tf_warning_or_error);
LOOKUP_NORMAL, tf_warning_or_error);
if (fn == error_mark_node) if (fn == error_mark_node)
return NULL_TREE; return NULL_TREE;
return fn; return fn;
......
...@@ -473,45 +473,80 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain) ...@@ -473,45 +473,80 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain)
another array to copy. */ another array to copy. */
static tree static tree
build_vec_init_elt (tree type, tree init) build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
{ {
tree inner_type = strip_array_types (type); tree inner_type = strip_array_types (TREE_TYPE (type));
VEC(tree,gc) *argvec; VEC(tree,gc) *argvec;
if (integer_zerop (array_type_nelts_total (type)) if (!CLASS_TYPE_P (inner_type))
|| !CLASS_TYPE_P (inner_type))
/* No interesting initialization to do. */ /* No interesting initialization to do. */
return integer_zero_node; return integer_zero_node;
else if (init == void_type_node) else if (init == void_type_node)
return build_value_init (inner_type, tf_warning_or_error); return build_value_init (inner_type, tf_warning_or_error);
gcc_assert (init == NULL_TREE if (init == NULL_TREE)
|| (same_type_ignoring_top_level_qualifiers_p argvec = make_tree_vector ();
(type, TREE_TYPE (init)))); else if (TREE_CODE (init) == TREE_LIST)
/* Array init extension, i.e. g++.robertl/eb58.C. */
argvec = make_tree_vector (); argvec = make_tree_vector_from_list (init);
if (init) else if (same_type_ignoring_top_level_qualifiers_p
(inner_type, strip_array_types (TREE_TYPE (init))))
{ {
/* Array copy or list-initialization. */
tree dummy = build_dummy_object (inner_type); tree dummy = build_dummy_object (inner_type);
if (!real_lvalue_p (init)) if (!real_lvalue_p (init))
dummy = move (dummy); dummy = move (dummy);
VEC_quick_push (tree, argvec, dummy); argvec = make_tree_vector_single (dummy);
} }
return build_special_member_call (NULL_TREE, complete_ctor_identifier, else
gcc_unreachable ();
init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&argvec, inner_type, LOOKUP_NORMAL, &argvec, inner_type, LOOKUP_NORMAL,
tf_warning_or_error); complain);
release_tree_vector (argvec);
/* For array new, also mark the destructor as used. */
if (TREE_CODE (type) == POINTER_TYPE
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type))
{
tree dtor = get_dtor_sfinae (inner_type, complain);
if (dtor == error_mark_node)
return error_mark_node;
else if (dtor)
mark_used (dtor);
}
return init;
} }
/* Return a TARGET_EXPR which expresses the initialization of an array to /* Return a TARGET_EXPR which expresses the initialization of an array. If
be named later, either default-initialization or copy-initialization TARGET is an array type, the initialization is of an array to be named
from another array of the same type. */ later, and the initialization will be wrapped in a TARGET_EXPR. If
TARGET is an expression, it is the array to be initialized. INIT is the
initializer, or void_type_node for value-initialization. If TARGET is
an expression, NELTS is the number of elements to initialize. */
tree tree
build_vec_init_expr (tree type, tree init) build_vec_init_expr (tree target, tree init, tree nelts,
tsubst_flags_t complain)
{ {
tree slot; tree slot, type;
bool value_init = false; bool value_init = false;
tree elt_init = build_vec_init_elt (type, init); tree elt_init;
tree real_nelts;
if (TYPE_P (target))
{
gcc_assert (TREE_CODE (target) == ARRAY_TYPE && nelts == NULL_TREE);
type = target;
slot = build_local_temp (type);
}
else
{
gcc_assert (EXPR_P (target));
slot = target;
type = TREE_TYPE (slot);
gcc_assert (TREE_CODE (type) == POINTER_TYPE && nelts != NULL_TREE);
}
if (init == void_type_node) if (init == void_type_node)
{ {
...@@ -519,8 +554,14 @@ build_vec_init_expr (tree type, tree init) ...@@ -519,8 +554,14 @@ build_vec_init_expr (tree type, tree init)
init = NULL_TREE; init = NULL_TREE;
} }
slot = build_local_temp (type); real_nelts = nelts ? nelts : array_type_nelts_total (type);
init = build2 (VEC_INIT_EXPR, type, slot, init); if (integer_zerop (real_nelts))
/* No elements to initialize. */
elt_init = integer_zero_node;
else
elt_init = build_vec_init_elt (type, init, complain);
init = build3 (VEC_INIT_EXPR, type, slot, init, nelts);
SET_EXPR_LOCATION (init, input_location); SET_EXPR_LOCATION (init, input_location);
if (cxx_dialect >= cxx0x if (cxx_dialect >= cxx0x
...@@ -528,8 +569,11 @@ build_vec_init_expr (tree type, tree init) ...@@ -528,8 +569,11 @@ build_vec_init_expr (tree type, tree init)
VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
VEC_INIT_EXPR_VALUE_INIT (init) = value_init; VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
init = build_target_expr (slot, init, tf_warning_or_error); if (slot != target)
TARGET_EXPR_IMPLICIT_P (init) = 1; {
init = build_target_expr (slot, init, complain);
TARGET_EXPR_IMPLICIT_P (init) = 1;
}
return init; return init;
} }
...@@ -547,14 +591,15 @@ diagnose_non_constexpr_vec_init (tree expr) ...@@ -547,14 +591,15 @@ diagnose_non_constexpr_vec_init (tree expr)
else else
init = VEC_INIT_EXPR_INIT (expr); init = VEC_INIT_EXPR_INIT (expr);
elt_init = build_vec_init_elt (type, init); elt_init = build_vec_init_elt (type, init, tf_warning_or_error);
require_potential_constant_expression (elt_init); require_potential_constant_expression (elt_init);
} }
tree tree
build_array_copy (tree init) build_array_copy (tree init)
{ {
return build_vec_init_expr (TREE_TYPE (init), init); return build_vec_init_expr (TREE_TYPE (init), init, NULL_TREE,
tf_warning_or_error);
} }
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the /* Build a TARGET_EXPR using INIT to initialize a new temporary of the
......
2011-04-27 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/initlist49.C: New.
* g++.dg/init/new30.C: New.
2011-04-27 Tobias Burnus <burnus@net-b.de> 2011-04-27 Tobias Burnus <burnus@net-b.de>
PR fortran/48788 PR fortran/48788
......
// Test for non-trivial list-initialization with array new.
// { dg-options -std=c++0x }
// { dg-do run }
struct A
{
enum E { c_string, number } e;
A(const char *): e(c_string) {}
A(int): e(number) {}
};
int main()
{
A* ap = new A[2]{1, ""};
if (ap[0].e != A::number || ap[1].e != A::c_string)
return 1;
delete[] ap;
}
// PR c++/40975
struct data_type
{
// constructor required to reproduce compiler bug
data_type() {}
};
struct ptr_type
{
// array new as default argument required to reproduce compiler bug
ptr_type (data_type* ptr = new data_type[1]) { delete[] ptr; }
};
ptr_type obj;
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