re PR c++/30111 (Value-initialization of POD base class doesn't initialize members)
authorJason Merrill <jason@redhat.com>
Wed, 11 Feb 2009 22:38:37 +0000 (17:38 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 11 Feb 2009 22:38:37 +0000 (17:38 -0500)
        PR c++/30111
        * init.c (build_value_init_noctor): Split out from...
        (build_value_init): ...here.
        (expand_aggr_init_1): Handle value-initialization.
        * cp-tree.h: Add declaration.
        * class.c (type_has_user_provided_constructor):
        Handle non-class arguments.

From-SVN: r144112

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/value7.C [new file with mode: 0644]

index 513465d..58bffd7 100644 (file)
@@ -1,3 +1,13 @@
+2009-02-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/30111
+       * init.c (build_value_init_noctor): Split out from...
+       (build_value_init): ...here.
+       (expand_aggr_init_1): Handle value-initialization.
+       * cp-tree.h: Add declaration.
+       * class.c (type_has_user_provided_constructor): 
+       Handle non-class arguments.
+
 2009-02-10  Jason Merrill  <jason@redhat.com>
 
        PR c++/38649
index d852acd..cef2371 100644 (file)
@@ -4090,6 +4090,9 @@ type_has_user_provided_constructor (tree t)
 {
   tree fns;
 
+  if (!CLASS_TYPE_P (t))
+    return false;
+
   if (!TYPE_HAS_USER_CONSTRUCTOR (t))
     return false;
 
index 5bf8595..5a9b891 100644 (file)
@@ -4476,6 +4476,7 @@ extern int is_class_type                  (tree, int);
 extern tree get_type_value                     (tree);
 extern tree build_zero_init                    (tree, tree, bool);
 extern tree build_value_init                   (tree);
+extern tree build_value_init_noctor            (tree);
 extern tree build_offset_ref                   (tree, tree, bool);
 extern tree build_new                          (tree, tree, tree, tree, int,
                                                  tsubst_flags_t);
index d4dafed..d583e3b 100644 (file)
@@ -318,7 +318,21 @@ build_value_init (tree type)
          AGGR_INIT_ZERO_FIRST (ctor) = 1;
          return ctor;
        }
-      else if (TREE_CODE (type) != UNION_TYPE)
+    }
+  return build_value_init_noctor (type);
+}
+
+/* Like build_value_init, but don't call the constructor for TYPE.  Used
+   for base initializers.  */
+
+tree
+build_value_init_noctor (tree type)
+{
+  if (CLASS_TYPE_P (type))
+    {
+      gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type));
+       
+      if (TREE_CODE (type) != UNION_TYPE)
        {
          tree field;
          VEC(constructor_elt,gc) *v = NULL;
@@ -800,11 +814,6 @@ emit_mem_initializers (tree mem_inits)
                 "copy constructor",
                 current_function_decl, BINFO_TYPE (subobject));
 
-      /* If an explicit -- but empty -- initializer list was present,
-        treat it just like default initialization at this point.  */
-      if (arguments == void_type_node)
-       arguments = NULL_TREE;
-
       /* Initialize the base.  */
       if (BINFO_VIRTUAL_P (subobject))
        construct_virtual_base (subobject, arguments);
@@ -1385,6 +1394,33 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
       return;
     }
 
+  /* If an explicit -- but empty -- initializer list was present,
+     that's value-initialization.  */
+  if (init == void_type_node)
+    {
+      /* If there's a user-provided constructor, we just call that.  */
+      if (type_has_user_provided_constructor (type))
+       /* Fall through.  */;
+      /* If there isn't, but we still need to call the constructor,
+        zero out the object first.  */
+      else if (TYPE_NEEDS_CONSTRUCTING (type))
+       {
+         init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+         init = build2 (INIT_EXPR, type, exp, init);
+         finish_expr_stmt (init);
+         /* And then call the constructor.  */
+       }
+      /* If we don't need to mess with the constructor at all,
+        then just zero out the object and we're done.  */
+      else
+       {
+         init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type));
+         finish_expr_stmt (init);
+         return;
+       }
+      init = NULL_TREE;
+    }
+
   /* We know that expand_default_init can handle everything we want
      at this point.  */
   expand_default_init (binfo, true_exp, exp, init, flags, complain);
index 9b64184..7c08865 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/30111
+       * g++.dg/init/value7.C: New test.
+
 2009-02-11  Paolo Bonzini  <bonzini@gnu.org>
 
        * gcc.target/i386/pr38824.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/init/value7.C b/gcc/testsuite/g++.dg/init/value7.C
new file mode 100644 (file)
index 0000000..c79de4a
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/30111
+// { dg-do run }
+
+struct pod {
+  int i;
+};
+
+struct inherit : pod {
+  inherit() : pod() {}
+};
+
+int main()
+{
+  inherit i;
+  return i.i != 0;
+}
+