OSDN Git Service

Fix PR c++/47666
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Feb 2011 19:53:13 +0000 (19:53 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Feb 2011 19:53:13 +0000 (19:53 +0000)
gcc/cp/

PR c++/47666
* class.c (dfs_declare_virt_assop_and_dtor)
(declare_virt_assop_and_dtor): New static functions.
(add_implicitly_declared_members): Use
declare_virt_assop_and_dtor.

gcc/testsuite/

PR c++/47666
* g++.dg/inherit/virtual7.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/virtual7.C [new file with mode: 0644]

index 208bb8c..b532371 100644 (file)
@@ -1,3 +1,11 @@
+2011-02-22  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/47666
+       * class.c (dfs_declare_virt_assop_and_dtor)
+       (declare_virt_assop_and_dtor): New static functions.
+       (add_implicitly_declared_members): Use
+       declare_virt_assop_and_dtor.
+
 2011-02-21  Jason Merrill  <jason@redhat.com>
 
        PR c++/47207
index 66c85bd..0d485fc 100644 (file)
@@ -2637,6 +2637,70 @@ maybe_add_class_template_decl_list (tree type, tree t, int friend_p)
                   t, CLASSTYPE_DECL_LIST (type));
 }
 
+/* This function is called from declare_virt_assop_and_dtor via
+   dfs_walk_all.
+
+   DATA is a type that direcly or indirectly inherits the base
+   represented by BINFO.  If BINFO contains a virtual assignment [copy
+   assignment or move assigment] operator or a virtual constructor,
+   declare that function in DATA if it hasn't been already declared.  */
+
+static tree
+dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
+{
+  tree bv, fn, t = (tree)data;
+  tree opname = ansi_assopname (NOP_EXPR);
+
+  gcc_assert (t && CLASS_TYPE_P (t));
+  gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
+
+  if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
+    /* A base without a vtable needs no modification, and its bases
+       are uninteresting.  */
+    return dfs_skip_bases;
+
+  if (BINFO_PRIMARY_P (binfo))
+    /* If this is a primary base, then we have already looked at the
+       virtual functions of its vtable.  */
+    return NULL_TREE;
+
+  for (bv = BINFO_VIRTUALS (binfo); bv; bv = TREE_CHAIN (bv))
+    {
+      fn = BV_FN (bv);
+
+      if (DECL_NAME (fn) == opname)
+       {
+         if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
+           lazily_declare_fn (sfk_copy_assignment, t);
+         if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+           lazily_declare_fn (sfk_move_assignment, t);
+       }
+      else if (DECL_DESTRUCTOR_P (fn)
+              && CLASSTYPE_LAZY_DESTRUCTOR (t))
+       lazily_declare_fn (sfk_destructor, t);
+    }
+
+  return NULL_TREE;
+}
+
+/* If the class type T has a direct or indirect base that contains a
+   virtual assignment operator or a virtual destructor, declare that
+   function in T if it hasn't been already declared.  */
+
+static void
+declare_virt_assop_and_dtor (tree t)
+{
+  if (!(TYPE_POLYMORPHIC_P (t)
+       && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
+           || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
+           || CLASSTYPE_LAZY_DESTRUCTOR (t))))
+    return;
+
+  dfs_walk_all (TYPE_BINFO (t),
+               dfs_declare_virt_assop_and_dtor,
+               NULL, t);
+}
+
 /* Create default constructors, assignment operators, and so forth for
    the type indicated by T, if they are needed.  CANT_HAVE_CONST_CTOR,
    and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason,
@@ -2706,34 +2770,7 @@ add_implicitly_declared_members (tree t,
 
   /* We can't be lazy about declaring functions that might override
      a virtual function from a base class.  */
-  if (TYPE_POLYMORPHIC_P (t)
-      && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
-         || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
-         || CLASSTYPE_LAZY_DESTRUCTOR (t)))
-    {
-      tree binfo = TYPE_BINFO (t);
-      tree base_binfo;
-      int ix;
-      tree opname = ansi_assopname (NOP_EXPR);
-      for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix)
-       {
-         tree bv;
-         for (bv = BINFO_VIRTUALS (base_binfo); bv; bv = TREE_CHAIN (bv))
-           {
-             tree fn = BV_FN (bv);
-             if (DECL_NAME (fn) == opname)
-               {
-                 if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
-                   lazily_declare_fn (sfk_copy_assignment, t);
-                 if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
-                   lazily_declare_fn (sfk_move_assignment, t);
-               }
-             else if (DECL_DESTRUCTOR_P (fn)
-                      && CLASSTYPE_LAZY_DESTRUCTOR (t))
-               lazily_declare_fn (sfk_destructor, t);
-           }
-       }
-    }
+  declare_virt_assop_and_dtor (t);
 }
 
 /* Subroutine of finish_struct_1.  Recursively count the number of fields
index 3260461..227f290 100644 (file)
@@ -1,3 +1,8 @@
+2011-02-22  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/47666
+       * g++.dg/inherit/virtual7.C: New test.
+
 2011-02-22  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        PR objc/47832
diff --git a/gcc/testsuite/g++.dg/inherit/virtual7.C b/gcc/testsuite/g++.dg/inherit/virtual7.C
new file mode 100644 (file)
index 0000000..bcbe71f
--- /dev/null
@@ -0,0 +1,27 @@
+// Origin: PR c++/47666
+// { dg-do "compile" }
+
+template <typename T>
+struct A
+{
+  int a;
+};
+
+template <typename T>
+struct B : public A <T>
+{
+};
+
+class D : public B <D *>
+{
+  virtual D & operator= (const D &);
+};
+
+class E : virtual public D
+{
+};
+
+class F : public E
+{
+  virtual void foo ();
+};