mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
fbaf0d0c08
commit
c12ff9d8f0
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,14 +2386,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
|
|||
vecinit = build_tree_list_vec (*init);
|
||||
}
|
||||
init_expr
|
||||
= build_vec_init (data_addr,
|
||||
= 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),
|
||||
vecinit,
|
||||
explicit_value_init_p,
|
||||
/*from_array=*/0,
|
||||
complain);
|
||||
|
||||
/* An array initialization is stable because the initialization
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))));
|
||||
|
||||
if (init == NULL_TREE)
|
||||
argvec = make_tree_vector ();
|
||||
if (init)
|
||||
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);
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
Loading…
Reference in New Issue