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
This commit is contained in:
Jason Merrill 2011-04-27 21:53:34 -04:00 committed by Jason Merrill
parent fbaf0d0c08
commit c12ff9d8f0
13 changed files with 166 additions and 45 deletions

View File

@ -1,3 +1,8 @@
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

View File

@ -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) *

View File

@ -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 */

View File

@ -1,5 +1,15 @@
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.

View File

@ -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);

View File

@ -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. */

View File

@ -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);

View File

@ -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

View File

@ -842,11 +842,17 @@ 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;

View File

@ -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

View File

@ -1,3 +1,8 @@
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

View File

@ -0,0 +1,18 @@
// 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;
}

View File

@ -0,0 +1,15 @@
// 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;