mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-23 00:51:00 +08:00
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
This commit is contained in:
parent
0842c29f7b
commit
d1a115f895
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
29
gcc/testsuite/g++.dg/inherit/virtual5.C
Normal file
29
gcc/testsuite/g++.dg/inherit/virtual5.C
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user