* tree.c (build_vec_init_expr): Split out from...
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Oct 2010 18:10:53 +0000 (18:10 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Oct 2010 18:10:53 +0000 (18:10 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165976 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.law/init10.C
gcc/testsuite/g++.old-deja/g++.other/array3.C

index 1ec3c63..c0da1fa 100644 (file)
@@ -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.
 
index e5a7f26..dd879c6 100644 (file)
@@ -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.  */
index da839ec..05282ba 100644 (file)
@@ -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);
index 72fcf78..9c2afba 100644 (file)
@@ -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
        {
index 18ed554..31f5845 100644 (file)
@@ -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.  */
 
index 4d567fe..90e3e45 100644 (file)
@@ -20,7 +20,7 @@ public:
         b();
 };
 
-b::b() : three(this)  // { dg-error "bad array initializer" }
+b::b() : three(this)  // { dg-error "array" }
 {
 }
 
index fc37c9b..f89090f 100644 (file)
@@ -20,6 +20,6 @@ class B
 };
 
 B::B (const A a[])
-  : ary(a)        // { dg-error "bad array initializer" }
+  : ary(a)        // { dg-error "array" }
 {
 }