aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-10-26 14:10:53 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-10-26 14:10:53 -0400
commit534ecb17516c5db7a96245ebb90beb206e22eaff (patch)
tree0f1b677728d44296d9537a0c12aa3f3f1615257d /gcc
parent73c982bc87c8eb33a37ba3242f8d82bc512e4189 (diff)
downloadgcc-534ecb17516c5db7a96245ebb90beb206e22eaff.zip
gcc-534ecb17516c5db7a96245ebb90beb206e22eaff.tar.gz
gcc-534ecb17516c5db7a96245ebb90beb206e22eaff.tar.bz2
tree.c (build_vec_init_expr): Split out from...
* tree.c (build_vec_init_expr): Split out from... (build_array_copy): ...here. * init.c (perform_member_init): Use it. * cp-tree.h: Declare it. * cp-gimplify.c (cp_gimplify_init_expr): Don't gimplify the slot for VEC_INIT_EXPR and AGGR_INIT_EXPR here. Drop pre/post parameters. (cp_gimplify_expr): Handle array default-initialization via VEC_INIT_EXPR. From-SVN: r165976
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-gimplify.c10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/init.c25
-rw-r--r--gcc/cp/tree.c43
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/init10.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/array3.C2
7 files changed, 72 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1ec3c63..c0da1fa 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
2010-10-26 Jason Merrill <jason@redhat.com>
+ * tree.c (build_vec_init_expr): Split out from...
+ (build_array_copy): ...here.
+ * init.c (perform_member_init): Use it.
+ * cp-tree.h: Declare it.
+ * cp-gimplify.c (cp_gimplify_init_expr): Don't gimplify the slot for
+ VEC_INIT_EXPR and AGGR_INIT_EXPR here. Drop pre/post parameters.
+ (cp_gimplify_expr): Handle array default-initialization via
+ VEC_INIT_EXPR.
+
* pt.c (lookup_template_class): push_tinst_level around call to
coerce_template_parms.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e5a7f26..dd879c6 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -424,7 +424,7 @@ gimplify_expr_stmt (tree *stmt_p)
/* Gimplify initialization from an AGGR_INIT_EXPR. */
static void
-cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
+cp_gimplify_init_expr (tree *expr_p)
{
tree from = TREE_OPERAND (*expr_p, 1);
tree to = TREE_OPERAND (*expr_p, 0);
@@ -451,7 +451,6 @@ cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
if (TREE_CODE (sub) == AGGR_INIT_EXPR
|| TREE_CODE (sub) == VEC_INIT_EXPR)
{
- gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
if (TREE_CODE (sub) == AGGR_INIT_EXPR)
AGGR_INIT_EXPR_SLOT (sub) = to;
else
@@ -531,10 +530,13 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
case VEC_INIT_EXPR:
{
location_t loc = input_location;
+ tree init = VEC_INIT_EXPR_INIT (*expr_p);
+ int from_array = (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,
- VEC_INIT_EXPR_INIT (*expr_p), false, 1,
+ init, /*explicit_value_init_p*/false,
+ from_array,
tf_warning_or_error);
ret = GS_OK;
input_location = loc;
@@ -556,7 +558,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
LHS of an assignment might also be involved in the RHS, as in bug
25979. */
case INIT_EXPR:
- cp_gimplify_init_expr (expr_p, pre_p, post_p);
+ cp_gimplify_init_expr (expr_p);
if (TREE_CODE (*expr_p) != INIT_EXPR)
return GS_OK;
/* Otherwise fall through. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index da839ec..05282ba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5377,6 +5377,7 @@ extern tree get_target_expr (tree);
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 hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 72fcf78..9c2afba 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -486,16 +486,23 @@ perform_member_init (tree member, tree init)
}
else if (TYPE_NEEDS_CONSTRUCTING (type))
{
- if (init != NULL_TREE
- && TREE_CODE (type) == ARRAY_TYPE
- && TREE_CHAIN (init) == NULL_TREE
- && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
+ if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* Initialization of one array from another. */
- finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
- /*explicit_value_init_p=*/false,
- /* from_array=*/1,
- tf_warning_or_error));
+ if (init)
+ {
+ gcc_assert (TREE_CHAIN (init) == NULL_TREE);
+ init = TREE_VALUE (init);
+ }
+ if (init == NULL_TREE
+ || same_type_ignoring_top_level_qualifiers_p (type,
+ TREE_TYPE (init)))
+ {
+ init = build_vec_init_expr (type, init);
+ init = build2 (INIT_EXPR, type, decl, init);
+ finish_expr_stmt (init);
+ }
+ else
+ error ("invalid initializer for array member %q#D", member);
}
else
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 18ed554..31f5845 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -452,14 +452,41 @@ build_cplus_new (tree type, tree init)
return rval;
}
-/* Return a TARGET_EXPR which expresses the direct-initialization of one
- array from another. */
+/* 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. */
tree
-build_array_copy (tree init)
+build_vec_init_expr (tree type, tree init)
{
- tree type = TREE_TYPE (init);
- tree slot = build_local_temp (type);
+ tree slot;
+ tree inner_type = strip_array_types (type);
+
+ gcc_assert (init == NULL_TREE
+ || (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init))));
+
+ /* Since we're deferring building the actual constructor calls until
+ gimplification time, we need to build one now and throw it away so
+ that the relevant constructor gets mark_used before cgraph decides
+ what functions are needed. Here we assume that init is either
+ NULL_TREE or another array to copy. */
+ if (CLASS_TYPE_P (inner_type))
+ {
+ VEC(tree,gc) *argvec = make_tree_vector ();
+ if (init)
+ {
+ tree dummy = build_dummy_object (inner_type);
+ if (!real_lvalue_p (init))
+ dummy = move (dummy);
+ VEC_quick_push (tree, argvec, dummy);
+ }
+ build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &argvec, inner_type, LOOKUP_NORMAL,
+ tf_warning_or_error);
+ }
+
+ slot = build_local_temp (type);
init = build2 (VEC_INIT_EXPR, type, slot, init);
SET_EXPR_LOCATION (init, input_location);
init = build_target_expr (slot, init);
@@ -468,6 +495,12 @@ build_array_copy (tree init)
return init;
}
+tree
+build_array_copy (tree init)
+{
+ return build_vec_init_expr (TREE_TYPE (init), init);
+}
+
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
diff --git a/gcc/testsuite/g++.old-deja/g++.law/init10.C b/gcc/testsuite/g++.old-deja/g++.law/init10.C
index 4d567fe..90e3e45 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/init10.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/init10.C
@@ -20,7 +20,7 @@ public:
b();
};
-b::b() : three(this) // { dg-error "bad array initializer" }
+b::b() : three(this) // { dg-error "array" }
{
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/array3.C b/gcc/testsuite/g++.old-deja/g++.other/array3.C
index fc37c9b..f89090f 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/array3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/array3.C
@@ -20,6 +20,6 @@ class B
};
B::B (const A a[])
- : ary(a) // { dg-error "bad array initializer" }
+ : ary(a) // { dg-error "array" }
{
}