aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-04-27 21:53:34 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-04-27 21:53:34 -0400
commitc12ff9d8f0f20cd2de63de6f14b9f0330e7ceb66 (patch)
tree7fc7f017ff214e07e3790efe9c01bfe2b4b52bdb /gcc/cp
parentfbaf0d0c082815cf67d958b7c9f596b1f814eca0 (diff)
downloadgcc-c12ff9d8f0f20cd2de63de6f14b9f0330e7ceb66.zip
gcc-c12ff9d8f0f20cd2de63de6f14b9f0330e7ceb66.tar.gz
gcc-c12ff9d8f0f20cd2de63de6f14b9f0330e7ceb66.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-gimplify.c6
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/init.c23
-rw-r--r--gcc/cp/method.c10
-rw-r--r--gcc/cp/tree.c95
7 files changed, 111 insertions, 45 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 349434f..737ba2e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index ca62df3..dc2e0fb 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 7bd35e0..c9fc970 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -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. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 26da4b3..a65998d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 25beba8..883734f 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 6b26806..8b1b4dc 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8fe8832..2f082a6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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