This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: ABI patch for destructor order


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 ();
+ };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]