diff options
author | Jason Merrill <jason@redhat.com> | 2010-06-15 16:11:00 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-06-15 16:11:00 -0400 |
commit | d1a115f895b6bd7658f1222d57d38caec192dbcc (patch) | |
tree | 784dfd74b5289fd564a132ffa75080dffd7552ed /gcc | |
parent | 0842c29f7b4560244ff3038f90896c745a0bb77d (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/class.c | 74 | ||||
-rw-r--r-- | gcc/cp/method.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/virtual5.C | 29 |
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; +} |