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>
PR preprocessor/48248
......
......@@ -9580,6 +9580,17 @@ make_tree_vector_single (tree t)
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. */
VEC(tree,gc) *
......
......@@ -959,6 +959,7 @@ extern void set_underlying_type (tree x);
extern VEC(tree,gc) *make_tree_vector (void);
extern void release_tree_vector (VEC(tree,gc) *);
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) *);
/* In c-gimplify.c */
......
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
change OVERLOAD to TREE_LIST.
* 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)
{
location_t loc = input_location;
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));
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),
from_array,
tf_warning_or_error);
......
......@@ -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
so that it works with TARGET_EXPR. Operand 0 is the target, operand 1
is the initializer. */
DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", tcc_expression, 2)
is the initializer, operand 2 is the number of elements or NULL_TREE. */
DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", tcc_expression, 3)
/* A throw expression. operand 0 is the expression, if there was one,
else it is NULL_TREE. */
......
......@@ -2896,8 +2896,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
(arg) = next_aggr_init_expr_arg (&(iter)))
/* VEC_INIT_EXPR accessors. */
#define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (NODE, 0)
#define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (NODE, 1)
#define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 0)
#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.
Only set when the current function is constexpr. */
......@@ -5022,6 +5023,7 @@ extern tree get_copy_ctor (tree);
extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree);
extern tree get_dtor (tree);
extern tree get_dtor_sfinae (tree, tsubst_flags_t);
extern tree locate_ctor (tree);
/* In optimize.c */
......@@ -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_array_of_n_type (tree, int);
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 tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
......
......@@ -506,7 +506,8 @@ perform_member_init (tree member, tree init)
/* mem() means value-initialization. */
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);
finish_expr_stmt (init);
}
......@@ -541,7 +542,8 @@ perform_member_init (tree member, tree init)
|| same_type_ignoring_top_level_qualifiers_p (type,
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);
finish_expr_stmt (init);
}
......@@ -2384,15 +2386,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
vecinit = build_tree_list_vec (*init);
}
init_expr
= build_vec_init (data_addr,
cp_build_binary_op (input_location,
MINUS_EXPR, outer_nelts,
integer_one_node,
complain),
vecinit,
explicit_value_init_p,
/*from_array=*/0,
complain);
= build_vec_init_expr (data_addr,
(explicit_value_init_p
? void_type_node: vecinit),
cp_build_binary_op (input_location,
MINUS_EXPR, outer_nelts,
integer_one_node,
complain),
complain);
/* An array initialization is stable because the initialization
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,
/* Locate the dtor of TYPE. */
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)
{
tree fn = locate_fn_flags (type, complete_dtor_identifier, NULL_TREE,
LOOKUP_NORMAL, tf_warning_or_error);
tree fn = get_dtor_sfinae (type, tf_warning_or_error);
if (fn == error_mark_node)
return NULL_TREE;
return fn;
......
......@@ -473,45 +473,80 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain)
another array to copy. */
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;
if (integer_zerop (array_type_nelts_total (type))
|| !CLASS_TYPE_P (inner_type))
if (!CLASS_TYPE_P (inner_type))
/* No interesting initialization to do. */
return integer_zero_node;
else if (init == void_type_node)
return build_value_init (inner_type, tf_warning_or_error);
gcc_assert (init == NULL_TREE
|| (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (init))));
argvec = make_tree_vector ();
if (init)
if (init == NULL_TREE)
argvec = make_tree_vector ();
else if (TREE_CODE (init) == TREE_LIST)
/* Array init extension, i.e. g++.robertl/eb58.C. */
argvec = make_tree_vector_from_list (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);
if (!real_lvalue_p (init))
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,
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
be named later, either default-initialization or copy-initialization
from another array of the same type. */
/* Return a TARGET_EXPR which expresses the initialization of an array. If
TARGET is an array type, the initialization is of an array to be named
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
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;
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)
{
......@@ -519,8 +554,14 @@ build_vec_init_expr (tree type, tree init)
init = NULL_TREE;
}
slot = build_local_temp (type);
init = build2 (VEC_INIT_EXPR, type, slot, init);
real_nelts = nelts ? nelts : array_type_nelts_total (type);
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);
if (cxx_dialect >= cxx0x
......@@ -528,8 +569,11 @@ build_vec_init_expr (tree type, tree init)
VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
init = build_target_expr (slot, init, tf_warning_or_error);
TARGET_EXPR_IMPLICIT_P (init) = 1;
if (slot != target)
{
init = build_target_expr (slot, init, complain);
TARGET_EXPR_IMPLICIT_P (init) = 1;
}
return init;
}
......@@ -547,14 +591,15 @@ diagnose_non_constexpr_vec_init (tree expr)
else
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);
}
tree
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
......
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>
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