OSDN Git Service

PR c++/11309
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 31 Jul 2008 05:07:10 +0000 (05:07 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 31 Jul 2008 05:07:10 +0000 (05:07 +0000)
        * tree.c (build_aggr_init_expr): Split out...
        (build_cplus_new): ...from here.
        (stabilize_init): Don't mess with AGGR_INIT_EXPR either.
        * init.c (build_new_1): new T() means value-initialization,
        not default-initialization.
        (build_vec_init): Likewise.
        (build_value_init_1): Use build_aggr_init_expr.

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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/expr/anew4.C
gcc/testsuite/g++.dg/init/value3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/new1.C
gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C

index e98283a..f01593d 100644 (file)
@@ -1,3 +1,14 @@
+2008-07-31  Jason Merrill  <jason@redhat.com>
+
+       PR c++/11309
+       * tree.c (build_aggr_init_expr): Split out...
+       (build_cplus_new): ...from here.
+       (stabilize_init): Don't mess with AGGR_INIT_EXPR either.
+       * init.c (build_new_1): new T() means value-initialization, 
+       not default-initialization.
+       (build_vec_init): Likewise.
+       (build_value_init_1): Use build_aggr_init_expr.
+       
 2008-07-30  Dodji Seketeli  <dseketel@redhat.com>
 
        PR c++/36767
index f9a2af8..02d358a 100644 (file)
@@ -4742,6 +4742,7 @@ extern tree build_min_nt                  (enum tree_code, ...);
 extern tree build_min_non_dep                  (enum tree_code, tree, ...);
 extern tree build_min_non_dep_call_list                (tree, tree, tree);
 extern tree build_cplus_new                    (tree, tree);
+extern tree build_aggr_init_expr               (tree, tree);
 extern tree get_target_expr                    (tree);
 extern tree build_cplus_array_type             (tree, tree);
 extern tree build_array_of_n_type              (tree, int);
index 3deb85d..5535033 100644 (file)
@@ -347,7 +347,7 @@ build_value_init_1 (tree type, bool have_ctor)
   if (CLASS_TYPE_P (type))
     {
       if (type_has_user_provided_constructor (type) && !have_ctor)
-       return build_cplus_new
+       return build_aggr_init_expr
          (type,
           build_special_member_call (NULL_TREE, complete_ctor_identifier,
                                      NULL_TREE, type, LOOKUP_NORMAL,
@@ -511,7 +511,7 @@ perform_member_init (tree member, tree init)
        {
          /* Initialization of one array from another.  */
          finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
-                                           /*explicit_default_init_p=*/false,
+                                           /*explicit_value_init_p=*/false,
                                            /* from_array=*/1,
                                             tf_warning_or_error));
        }
@@ -1286,7 +1286,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
       if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
        itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
-                                 /*explicit_default_init_p=*/false,
+                                 /*explicit_value_init_p=*/false,
                                  itype && same_type_p (itype,
                                                        TREE_TYPE (exp)),
                                   complain);
@@ -2154,19 +2154,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (is_initialized)
     {
       bool stable;
+      bool explicit_value_init_p = false;
 
       init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
 
-      if (array_p)
+      if (init == void_zero_node)
        {
-         bool explicit_default_init_p = false;
+         init = NULL_TREE;
+         explicit_value_init_p = true;
+       }
 
-         if (init == void_zero_node)
-           {
-             init = NULL_TREE;
-             explicit_default_init_p = true;
-           }
-         else if (init)
+      if (array_p)
+       {
+         if (init)
             {
               if (complain & tf_error)
                 permerror ("ISO C++ forbids initialization in array new");
@@ -2179,7 +2179,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
                                                  integer_one_node,
                                                  complain),
                              init,
-                             explicit_default_init_p,
+                             explicit_value_init_p,
                              /*from_array=*/0,
                               complain);
 
@@ -2190,17 +2190,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
        }
       else
        {
-         if (init == void_zero_node)
-           init = build_default_init (full_type, nelts);
-
-         if (TYPE_NEEDS_CONSTRUCTING (type))
+         if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
            {
              init_expr = build_special_member_call (init_expr,
                                                     complete_ctor_identifier,
                                                     init, elt_type,
                                                     LOOKUP_NORMAL,
                                                      complain);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
+           }
+         else if (explicit_value_init_p)
+           {
+             /* Something like `new int()'.  */
+             init_expr = build2 (INIT_EXPR, full_type,
+                                 init_expr, build_value_init (full_type));
            }
          else
            {
@@ -2216,8 +2218,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
              init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
                                                complain);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
            }
+         stable = stabilize_init (init_expr, &init_preeval_expr);
        }
 
       if (init_expr == error_mark_node)
@@ -2662,8 +2664,8 @@ get_temp_regvar (tree type, tree init)
 
    INIT is the (possibly NULL) initializer.
 
-   If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL.  All
-   elements in the array are default-initialized.
+   If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL.  All
+   elements in the array are value-initialized.
 
    FROM_ARRAY is 0 if we should init everything with INIT
    (i.e., every element initialized from INIT).
@@ -2674,7 +2676,7 @@ get_temp_regvar (tree type, tree init)
 
 tree
 build_vec_init (tree base, tree maxindex, tree init,
-               bool explicit_default_init_p,
+               bool explicit_value_init_p,
                int from_array, tsubst_flags_t complain)
 {
   tree rval;
@@ -2704,7 +2706,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
-  if (explicit_default_init_p)
+  if (explicit_value_init_p)
     gcc_assert (!init);
 
   inner_elt_type = strip_array_types (atype);
@@ -2840,7 +2842,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      We do need to keep going if we're copying an array.  */
 
   if (from_array
-      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p)
+      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
          && ! (host_integerp (maxindex, 0)
                && (num_initialized_elts
                    == tree_low_cst (maxindex, 0) + 1))))
@@ -2889,17 +2891,17 @@ build_vec_init (tree base, tree maxindex, tree init,
              ("cannot initialize multi-dimensional array with initializer");
          elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
                                     0, 0,
-                                    /*explicit_default_init_p=*/false,
+                                    explicit_value_init_p,
                                     0, complain);
        }
-      else if (!TYPE_NEEDS_CONSTRUCTING (type))
-       elt_init = (cp_build_modify_expr
-                   (to, INIT_EXPR,
-                    build_zero_init (type, size_one_node,
-                                     /*static_storage_p=*/false),
-                    complain));
+      else if (explicit_value_init_p)
+       elt_init = build2 (INIT_EXPR, type, to,
+                          build_value_init (type));
       else
-       elt_init = build_aggr_init (to, init, 0, complain);
+       {
+         gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+         elt_init = build_aggr_init (to, init, 0, complain);
+       }
 
       current_stmt_tree ()->stmts_are_full_exprs_p = 1;
       finish_expr_stmt (elt_init);
index 50c3049..4114f86 100644 (file)
@@ -339,15 +339,17 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
 }
 
 /* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
-   target.  TYPE is the type that this initialization should appear to
-   have.
+   target.  TYPE is the type to be initialized.
 
-   Build an encapsulation of the initialization to perform
-   and return it so that it can be processed by language-independent
-   and language-specific expression expanders.  */
+   Build an AGGR_INIT_EXPR to represent the initialization.  This function
+   differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
+   to initialize another object, whereas a TARGET_EXPR can either
+   initialize another object or create its own temporary object, and as a
+   result building up a TARGET_EXPR requires that the type's destructor be
+   callable.  */
 
 tree
-build_cplus_new (tree type, tree init)
+build_aggr_init_expr (tree type, tree init)
 {
   tree fn;
   tree slot;
@@ -369,8 +371,6 @@ build_cplus_new (tree type, tree init)
             && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
             && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
 
-  slot = build_local_temp (type);
-
   /* We split the CALL_EXPR into its function and its arguments here.
      Then, in expand_expr, we put them back together.  The reason for
      this is that this expression might be a default argument
@@ -384,6 +384,8 @@ build_cplus_new (tree type, tree init)
      type, don't mess with AGGR_INIT_EXPR.  */
   if (is_ctor || TREE_ADDRESSABLE (type))
     {
+      slot = build_local_temp (type);
+
       if (TREE_CODE(init) == CALL_EXPR)
        rval = build_aggr_init_array (void_type_node, fn, slot,
                                      call_expr_nargs (init),
@@ -398,6 +400,30 @@ build_cplus_new (tree type, tree init)
   else
     rval = init;
 
+  return rval;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+   target.  TYPE is the type that this initialization should appear to
+   have.
+
+   Build an encapsulation of the initialization to perform
+   and return it so that it can be processed by language-independent
+   and language-specific expression expanders.  */
+
+tree
+build_cplus_new (tree type, tree init)
+{
+  tree rval = build_aggr_init_expr (type, init);
+  tree slot;
+
+  if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+    slot = AGGR_INIT_EXPR_SLOT (rval);
+  else if (TREE_CODE (rval) == CALL_EXPR)
+    slot = build_local_temp (type);
+  else
+    return rval;
+
   rval = build_target_expr (slot, rval);
   TARGET_EXPR_IMPLICIT_P (rval) = 1;
 
@@ -2687,7 +2713,8 @@ stabilize_init (tree init, tree *initp)
     return true;
 
   if (TREE_CODE (t) == INIT_EXPR
-      && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+      && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+      && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
     {
       TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
       return true;
index ba1d028..feb6b5f 100644 (file)
@@ -6114,7 +6114,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
       from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
                   ? 1 + (modifycode != INIT_EXPR): 0;
       return build_vec_init (lhs, NULL_TREE, newrhs,
-                            /*explicit_default_init_p=*/false,
+                            /*explicit_value_init_p=*/false,
                             from_array, complain);
     }
 
index d86d525..4ce1d88 100644 (file)
@@ -1,5 +1,4 @@
-// { dg-do run { xfail *-*-* } }
-// XFAILed until PR2123 is fixed
+// { dg-do run }
 // PR 11228: array operator new, with zero-initialization and a variable sized array.
 // Regression test for PR 
 // Author: Matt Austern <austern@apple.com>
diff --git a/gcc/testsuite/g++.dg/init/value3.C b/gcc/testsuite/g++.dg/init/value3.C
new file mode 100644 (file)
index 0000000..487baab
--- /dev/null
@@ -0,0 +1,31 @@
+// Testcase for value-initialization in new-expressions.
+// { dg-do run }
+
+#include <stdlib.h>
+#include <string.h>
+
+// Make sure that we return memory that isn't already set to 0.
+void *operator new(size_t s)
+{
+  void *p = malloc (s);
+  memset (p, 42, s);
+  return p;
+}
+
+struct A { A() {} ~A() {} };
+struct B { A a; int i; };
+
+int main()
+{
+  B *p = new B();
+  if (p->i != 0)
+    abort();
+
+  p = new B[2]();
+  if (p[0].i != 0 || p[1].i != 0)
+    abort();
+
+  B(*p2)[2] = new B[2][2]();
+  if (p2[0][0].i != 0 || p2[0][1].i != 0)
+    abort();
+}
index b9d0bef..ae11213 100644 (file)
@@ -4,10 +4,10 @@
 
 int main() {
   int i;
-  void* operator new(unsigned s, int* p);
+  void* operator new(__SIZE_TYPE__ s, int* p);
   int* e = new(&i) int;                    // { dg-error "no matching function" }
   int* f = new int;
   return 0;
 }
 
-// { dg-excess-errors "operator new" }
+// { dg-error "candidate" "" { target *-*-* } 0 }
index 0fd6027..d2edb19 100644 (file)
@@ -20,5 +20,5 @@ double foo (void)
   return v.a[2];
 }
 
-/* { dg-final { scan-tree-dump "Replaced .*iftmp.* != 0B. with .1" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "Replaced .* != 0B. with .1" "forwprop1" } } */
 /* { dg-final { cleanup-tree-dump "forwprop1" } } */