This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: ABI patch for destructor order
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: oldham at codesourcery dot com
- Date: Thu, 7 Nov 2002 13:30:35 -0800
- Subject: C++ PATCH: ABI patch for destructor order
- Reply-to: mark at codesourcery dot com
Jeffrey figured out this morning that G++ was emitting virtual
function table entries for implicitly defined virtual destructors in
the wrong place.
Fixed thus; tested on i686-pc-linux-gnu, applied on the mainline.
2002-11-07 Mark Mitchell <mark@codesourcery.com>
* class.c (add_implicitly_declared_members): Put implicitly
declared functions at the end of TYPE_METHODs when -fabi-version
is at least 2.
2002-11-07 Mark Mitchell <mark@codesourcery.com>
* testsuite/g++.dg/abi/dtor1.C: New test.
* testsuite/g++.dg/abi/dtor2.C: Likewise.
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.490
diff -c -5 -p -r1.490 class.c
*** cp/class.c 4 Nov 2002 01:45:55 -0000 1.490
--- cp/class.c 7 Nov 2002 20:58:09 -0000
*************** static tree modify_all_vtables PARAMS ((
*** 123,133 ****
static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
static int field_decl_cmp PARAMS ((const tree *, const tree *));
static int method_name_cmp PARAMS ((const tree *, const tree *));
! static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree));
static tree build_vtable_entry_ref PARAMS ((tree, tree, tree));
static tree build_vtbl_ref_1 PARAMS ((tree, tree));
--- 123,133 ----
static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
static int field_decl_cmp PARAMS ((const tree *, const tree *));
static int method_name_cmp PARAMS ((const tree *, const tree *));
! static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree));
static tree build_vtable_entry_ref PARAMS ((tree, tree, tree));
static tree build_vtbl_ref_1 PARAMS ((tree, tree));
*************** maybe_add_class_template_decl_list (type
*** 2740,2750 ****
class cannot have a default constructor, copy constructor taking a
const reference argument, or an assignment operator taking a const
reference, respectively. If a virtual destructor is created, its
DECL is returned; otherwise the return value is NULL_TREE. */
! static tree
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
cant_have_const_assignment)
tree t;
int cant_have_default_ctor;
--- 2740,2750 ----
class cannot have a default constructor, copy constructor taking a
const reference argument, or an assignment operator taking a const
reference, respectively. If a virtual destructor is created, its
DECL is returned; otherwise the return value is NULL_TREE. */
! static void
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
cant_have_const_assignment)
tree t;
int cant_have_default_ctor;
*************** add_implicitly_declared_members (t, cant
*** 2815,2830 ****
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
{
add_method (t, *f, /*error_p=*/0);
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
}
! *f = TYPE_METHODS (t);
! TYPE_METHODS (t) = implicit_fns;
--adding_implicit_members;
-
- return virtual_dtor;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
in TYPE, including anonymous union members. */
--- 2815,2841 ----
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
{
add_method (t, *f, /*error_p=*/0);
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
}
! if (abi_version_at_least (2))
! /* G++ 3.2 put the implicit destructor at the *beginning* of the
! list, which cause the destructor to be emitted in an incorrect
! location in the vtable. */
! TYPE_METHODS (t) = chainon (TYPE_METHODS (t), implicit_fns);
! else
! {
! if (warn_abi && virtual_dtor)
! warning ("vtable layout for class `%T' may not be ABI-compliant "
! "and may change in a future version of GCC due to implicit "
! "virtual destructor",
! t);
! *f = TYPE_METHODS (t);
! TYPE_METHODS (t) = implicit_fns;
! }
--adding_implicit_members;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
in TYPE, including anonymous union members. */
Index: testsuite/g++.dg/abi/dtor1.C
===================================================================
RCS file: testsuite/g++.dg/abi/dtor1.C
diff -N testsuite/g++.dg/abi/dtor1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/dtor1.C 7 Nov 2002 20:58:09 -0000
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile { target i?86-*-* } }
+ // { dg-options "-fabi-version=0" }
+
+ struct A {
+ virtual void a ();
+ };
+
+ struct B {
+ virtual ~B ();
+ };
+
+ struct C : public A, public B {
+ virtual void c ();
+ };
+
+ struct D : virtual public C {
+ virtual void d ();
+ };
+
+ void D::d () {}
+
+ // { dg-final { scan-assembler _ZTv0_n20_N1DD1Ev } }
Index: testsuite/g++.dg/abi/dtor2.C
===================================================================
RCS file: testsuite/g++.dg/abi/dtor2.C
diff -N testsuite/g++.dg/abi/dtor2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/dtor2.C 7 Nov 2002 20:58:09 -0000
***************
*** 0 ****
--- 1,14 ----
+ // { dg-do compile }
+ // { dg-options "-Wabi" }
+
+ struct A {
+ virtual void a ();
+ };
+
+ struct B {
+ virtual ~B ();
+ };
+
+ struct C : public A, public B { // { dg-warning "virtual" }
+ virtual void c ();
+ };