aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-15 16:11:00 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-06-15 16:11:00 -0400
commitd1a115f895b6bd7658f1222d57d38caec192dbcc (patch)
tree784dfd74b5289fd564a132ffa75080dffd7552ed
parent0842c29f7b4560244ff3038f90896c745a0bb77d (diff)
downloadgcc-d1a115f895b6bd7658f1222d57d38caec192dbcc.zip
gcc-d1a115f895b6bd7658f1222d57d38caec192dbcc.tar.gz
gcc-d1a115f895b6bd7658f1222d57d38caec192dbcc.tar.bz2
class.c (add_implicitly_declared_members): Implicit assignment operators can also be virtual overriders.
* class.c (add_implicitly_declared_members): Implicit assignment operators can also be virtual overriders. * method.c (lazily_declare_fn): Likewise. From-SVN: r160810
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/class.c74
-rw-r--r--gcc/cp/method.c3
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/inherit/virtual5.C29
5 files changed, 71 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4e30814..34593ad 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 340fe87..60908ff 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 124a83c..97f3566 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8ca6527..369f3b5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..bed0ef3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/virtual5.C
@@ -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;
+}