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]

C++ PATCH for vtable initialization



I missed a spot where we were still generating RTL during semantic
analysis; this showed up on targets that don't use vtable thunks.
With this patch, there are now no regressions in the C++ testsuite on
IRIX6, relative to 2.95.

I also found a bug whereby implicitly generated destructors could
cause calls to the wrong virtual function; see the attached test-case.
This bug looks to have been around for ages; it predates the 1.0.x
series.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-10-05  Mark Mitchell  <mark@codesourcery.com>

	* method.c (synthesize_method): Call setup_vtbl_ptr for destructors.

	* decl.c (start_function): Set current_in_charge_parm for
	constructors, too, where appropriate.
	* search.c (fixup_all_virtual_upcast_offsets): New function.
	(expand_indirect_vtbls_init): Use it.
	
Index: testsuite/g++.old-deja/g++.other/dtor5.C
===================================================================
RCS file: dtor5.C
diff -N dtor5.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- dtor5.C	Tue Oct  5 09:14:45 1999
***************
*** 0 ****
--- 1,36 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ extern "C" void abort ();
+ 
+ struct B;
+ 
+ struct S 
+ {
+   S (B*);
+   ~S ();
+ 
+   B* b_;
+ };
+ 
+ struct B 
+ {
+   B () : s (this) { }
+       
+   virtual void f () { }
+   
+   S s;
+ };
+ 
+ S::S (B* b) : b_ (b) { }
+ 
+ S::~S () { b_->f (); }
+   
+ struct D : public B
+ {
+   virtual void f () { abort (); }
+ };
+ 
+ int main ()
+ {
+   D d;
+ }
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.478
diff -c -p -r1.478 decl.c
*** decl.c	1999/10/04 09:15:14	1.478
--- decl.c	1999/10/05 16:14:57
*************** start_function (declspecs, declarator, a
*** 12971,12977 ****
--- 12971,12985 ----
  	= build_indirect_ref (t, NULL_PTR);
        cp_function_chain->x_current_class_ptr = t;
  
+       /* Constructors and destructors need to know whether they're "in
+ 	 charge" of initializing virtual base classes.  */
        if (DECL_DESTRUCTOR_P (decl1))
+ 	current_in_charge_parm = TREE_CHAIN (t);
+       else if (DECL_CONSTRUCTOR_P (decl1)
+ 	       && TREE_CHAIN (t)
+ 	       && DECL_ARTIFICIAL (TREE_CHAIN (t))
+ 	       && (DECL_NAME (TREE_CHAIN (t))
+ 		   == in_charge_identifier))
  	current_in_charge_parm = TREE_CHAIN (t);
      }
  
Index: cp/method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.122
diff -c -p -r1.122 method.c
*** method.c	1999/10/04 09:33:30	1.122
--- method.c	1999/10/05 16:14:58
*************** synthesize_method (fndecl)
*** 2384,2390 ****
        need_body = 0;
      }
    else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
!     ;
    else
      {
        tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);
--- 2384,2390 ----
        need_body = 0;
      }
    else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
!     setup_vtbl_ptr ();
    else
      {
        tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.127
diff -c -p -r1.127 search.c
*** search.c	1999/10/04 09:15:16	1.127
--- search.c	1999/10/05 16:15:06
*************** static int protected_accessible_p PROTO 
*** 149,154 ****
--- 149,155 ----
  static int friend_accessible_p PROTO ((tree, tree, tree, tree));
  static void setup_class_bindings PROTO ((tree, int));
  static int template_self_reference_p PROTO ((tree, tree));
+ static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
  
  /* Allocate a level of searching.  */
  
*************** fixup_virtual_upcast_offsets (real_binfo
*** 2774,2792 ****
      }
  }
  
! /* Build a COMPOUND_EXPR which when expanded will generate the code
!    needed to initialize all the virtual function table slots of all
!    the virtual baseclasses.  MAIN_BINFO is the binfo which determines
!    the virtual baseclasses to use; TYPE is the type of the object to
!    which the initialization applies.  TRUE_EXP is the true object we
!    are initializing, and DECL_PTR is the pointer to the sub-object we
!    are initializing.
! 
!    When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
!    object was laid out by a top-level constructor and the computed
!    offsets are valid to store vtables.  When zero, we must store new
!    vtables through virtual baseclass pointers.  */
  
  void
  expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
       tree binfo;
--- 2775,2837 ----
      }
  }
  
! /* Fixup all the virtual upcast offsets for TYPE.  DECL_PTR is the
!    address of the sub-object being initialized.  */
  
+ static void
+ fixup_all_virtual_upcast_offsets (type, decl_ptr)
+      tree type;
+      tree decl_ptr;
+ {
+   tree if_stmt;
+   tree in_charge_node;
+   tree vbases;
+ 
+   /* Only tweak the vtables if we're in charge.  */
+   in_charge_node = current_in_charge_parm;
+   if (!in_charge_node)
+     /* There's no need for any fixups in this case.  */
+     return;
+   in_charge_node = build_binary_op (EQ_EXPR, 
+ 				    in_charge_node, integer_zero_node);
+   if_stmt = begin_if_stmt ();
+   finish_if_stmt_cond (in_charge_node, if_stmt);
+   
+   /* Iterate through the virtual bases, fixing up the upcast offset
+      for each one.  */
+   for (vbases = CLASSTYPE_VBASECLASSES (type);
+        vbases;
+        vbases = TREE_CHAIN (vbases))
+     {
+       if (flag_vtable_thunks)
+ 	/* We don't have dynamic thunks yet!  So for now, just fail
+ 	   silently.  */
+ 	;
+       else
+ 	{
+ 	  tree vbase_offsets;
+ 	  tree addr;
+ 
+ 	  vbase_offsets = NULL_TREE;
+ 	  addr = convert_pointer_to_vbase (TREE_TYPE (vbases), decl_ptr);
+ 	  fixup_virtual_upcast_offsets (vbases,
+ 					TYPE_BINFO (BINFO_TYPE (vbases)),
+ 					1, 0, addr, decl_ptr,
+ 					type, vbases, &vbase_offsets);
+ 	}
+     }
+ 
+   /* Close out the if-statement.  */
+   finish_then_clause (if_stmt);
+   finish_if_stmt ();
+ }
+ 
+ /* Generate the code needed to initialize all the virtual function
+    table slots of all the virtual baseclasses.  BINFO is the binfo
+    which determines the virtual baseclasses to use.  TRUE_EXP is the
+    true object we are initializing, and DECL_PTR is the pointer to the
+    sub-object we are initializing.  */
+ 
  void
  expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
       tree binfo;
*************** expand_indirect_vtbls_init (binfo, true_
*** 2807,2813 ****
  
    if (TYPE_USES_VIRTUAL_BASECLASSES (type))
      {
-       rtx fixup_insns = NULL_RTX;
        tree vbases = CLASSTYPE_VBASECLASSES (type);
        struct vbase_info vi;
        vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) 
--- 2852,2857 ----
*************** expand_indirect_vtbls_init (binfo, true_
*** 2828,2871 ****
  	     binfos.  (in the CLASSTYPE_VFIELD_PARENT sense)  */
  	  expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
  				    1, 0, addr);
- 
- 	  /* Now we adjust the offsets for virtual functions that
- 	     cross virtual boundaries on an implicit upcast on vf call
- 	     so that the layout of the most complete type is used,
- 	     instead of assuming the layout of the virtual bases from
- 	     our current type.  */
- 
- 	  if (flag_vtable_thunks)
- 	    {
- 	      /* We don't have dynamic thunks yet!
- 		 So for now, just fail silently.  */
- 	    }
- 	  else
- 	    {
- 	      tree vbase_offsets = NULL_TREE;
- 	      push_to_sequence (fixup_insns);
- 	      fixup_virtual_upcast_offsets (vbases,
- 					    TYPE_BINFO (BINFO_TYPE (vbases)),
- 					    1, 0, addr, vi.decl_ptr,
- 					    type, vbases, &vbase_offsets);
- 	      fixup_insns = get_insns ();
- 	      end_sequence ();
- 	    }
  	}
  
!       if (fixup_insns)
! 	{
! 	  tree in_charge_node = current_in_charge_parm;
! 	  if (! in_charge_node)
! 	    {
! 	      warning ("recoverable internal compiler error, nobody's in charge!");
! 	      in_charge_node = integer_zero_node;
! 	    }
! 	  in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node);
! 	  expand_start_cond (in_charge_node, 0);
! 	  emit_insns (fixup_insns);
! 	  expand_end_cond ();
! 	}
  
        dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
      }
--- 2872,2881 ----
  	     binfos.  (in the CLASSTYPE_VFIELD_PARENT sense)  */
  	  expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
  				    1, 0, addr);
  	}
  
!       fixup_all_virtual_upcast_offsets (type,
! 					vi.decl_ptr);
  
        dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
      }


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