OSDN Git Service

PR c++/50618
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Oct 2011 18:01:51 +0000 (18:01 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Oct 2011 18:01:51 +0000 (18:01 +0000)
* init.c (expand_aggr_init_1): Don't zero-initialize virtual
bases of a base subobject.

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

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/vbase1.C [new file with mode: 0644]

index e7c5b49..e70f5c8 100644 (file)
@@ -1,3 +1,9 @@
+2011-10-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50618
+       * init.c (expand_aggr_init_1): Don't zero-initialize virtual
+       bases of a base subobject.
+
 2011-10-12  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/50594
index 7897fff..a21e566 100644 (file)
@@ -1588,27 +1588,25 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
      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_build_ctor_call (type))
-       {
-         init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+      /* If no user-provided ctor, we need to zero out the object.  */
+      if (!type_has_user_provided_constructor (type))
+       {
+         tree field_size = NULL_TREE;
+         if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type)
+           /* Don't clobber already initialized virtual bases.  */
+           field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type));
+         init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false,
+                                   field_size);
          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, complain));
-         finish_expr_stmt (init);
-         return;
-       }
+        then we're done.  */
+      if (! type_build_ctor_call (type))
+       return;
+
+      /* Otherwise fall through and call the constructor.  */
       init = NULL_TREE;
     }
 
index 9f06ab4..283b699 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50618
+       * g++.dg/init/vbase1.C: New.
+
 2011-10-13  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.target/i386/sse4_1-phminposuw-2.c: New test.
diff --git a/gcc/testsuite/g++.dg/init/vbase1.C b/gcc/testsuite/g++.dg/init/vbase1.C
new file mode 100644 (file)
index 0000000..bbfd58f
--- /dev/null
@@ -0,0 +1,39 @@
+// PR c++/50618
+// { dg-do run }
+
+struct Base
+{
+    const int text;
+    Base():text(1) {}
+    Base(int aText)
+    : text(aText) {}
+};
+struct SubA : public virtual Base
+{
+protected:
+  int x;
+public:
+  SubA(int aX)
+  : x(aX) {}
+};
+class SubB : public virtual Base
+{};
+struct Diamond : public SubA, public SubB
+{
+    Diamond(int text)
+    : Base(text), SubA(5), SubB() {}
+
+    void printText()
+    {
+        if(text != 2)
+          __builtin_abort();
+        if(x!=5)
+          __builtin_abort();
+    }
+};
+
+int main(int, char**)
+{
+    Diamond x(2);
+    x.printText();
+}