OSDN Git Service

* class.c (add_implicitly_declared_members): Implicit assignment
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Jun 2010 20:11:00 +0000 (20:11 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Jun 2010 20:11:00 +0000 (20:11 +0000)
operators can also be virtual overriders.
* method.c (lazily_declare_fn): Likewise.

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

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

index 4e30814..34593ad 100644 (file)
@@ -1,5 +1,9 @@
 2010-06-15  Jason Merrill  <jason@redhat.com>
 
+       * class.c (add_implicitly_declared_members): Implicit assignment
+       operators can also be virtual overriders.
+       * method.c (lazily_declare_fn): Likewise.
+
        * call.c (convert_like_real): Give "initializing argument of"
        information for ambiguous conversion.  Give source position
        of function.
index 340fe87..60908ff 100644 (file)
@@ -2618,47 +2618,13 @@ add_implicitly_declared_members (tree t,
     {
       /* In general, we create destructors lazily.  */
       CLASSTYPE_LAZY_DESTRUCTOR (t) = 1;
-      /* However, if the implicit destructor is non-trivial
-        destructor, we sometimes have to create it at this point.  */
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
-       {
-         bool lazy_p = true;
-
-         if (TYPE_FOR_JAVA (t))
-           /* If this a Java class, any non-trivial destructor is
-              invalid, even if compiler-generated.  Therefore, if the
-              destructor is non-trivial we create it now.  */
-           lazy_p = false;
-         else
-           {
-             tree binfo;
-             tree base_binfo;
-             int ix;
-
-             /* If the implicit destructor will be virtual, then we must
-                generate it now because (unfortunately) we do not
-                generate virtual tables lazily.  */
-             binfo = TYPE_BINFO (t);
-             for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
-               {
-                 tree base_type;
-                 tree dtor;
-
-                 base_type = BINFO_TYPE (base_binfo);
-                 dtor = CLASSTYPE_DESTRUCTORS (base_type);
-                 if (dtor && DECL_VIRTUAL_P (dtor))
-                   {
-                     lazy_p = false;
-                     break;
-                   }
-               }
-           }
 
-         /* If we can't get away with being lazy, generate the destructor
-            now.  */
-         if (!lazy_p)
-           lazily_declare_fn (sfk_destructor, t);
-       }
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+         && TYPE_FOR_JAVA (t))
+       /* But if this is a Java class, any non-trivial destructor is
+          invalid, even if compiler-generated.  Therefore, if the
+          destructor is non-trivial we create it now.  */
+       lazily_declare_fn (sfk_destructor, t);
     }
 
   /* [class.ctor]
@@ -2697,6 +2663,34 @@ add_implicitly_declared_members (tree t,
       TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
       CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1;
     }
+
+  /* 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_ASSIGNMENT_OP (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_ASSIGNMENT_OP (t))
+                   lazily_declare_fn (sfk_assignment_operator, t);
+               }
+             else if (DECL_DESTRUCTOR_P (fn)
+                      && CLASSTYPE_LAZY_DESTRUCTOR (t))
+               lazily_declare_fn (sfk_destructor, t);
+           }
+       }
+    }
 }
 
 /* Subroutine of finish_struct_1.  Recursively count the number of fields
index 124a83c..97f3566 100644 (file)
@@ -1108,7 +1108,8 @@ lazily_declare_fn (special_function_kind sfk, tree type)
   /* Declare the function.  */
   fn = implicitly_declare_fn (sfk, type, const_p);
   /* A destructor may be virtual.  */
-  if (sfk == sfk_destructor)
+  if (sfk == sfk_destructor
+      || sfk == sfk_assignment_operator)
     check_for_override (fn, type);
   /* Add it to CLASSTYPE_METHOD_VEC.  */
   add_method (type, fn, NULL_TREE);
index 8ca6527..369f3b5 100644 (file)
@@ -1,5 +1,7 @@
 2010-06-15  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/inherit/virtual5.C: New.
+
        * g++.dg/cpp0x/defaulted18.C: New.
 
        * g++.dg/cpp0x/initlist40.C: New.
diff --git a/gcc/testsuite/g++.dg/inherit/virtual5.C b/gcc/testsuite/g++.dg/inherit/virtual5.C
new file mode 100644 (file)
index 0000000..bed0ef3
--- /dev/null
@@ -0,0 +1,29 @@
+// Test that a synthesized op= can override one from a base.
+// { dg-do run }
+
+struct B;
+
+struct A
+{
+  virtual B& operator=(const B&);
+};
+
+struct B: A
+{
+  B(int i): i(i) { }
+  int i;
+  // implicitly-declared op=
+};
+
+B& A::operator=(const B& b) { return static_cast<B&>(*this); }
+
+int main()
+{
+  B b1 (123);
+  B b2 (0);
+
+  A& ar = b1;
+  ar = b2;
+
+  return b1.i;
+}