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] Fix bug 1611


Hi,
I've installed this patch for bug 1611. Under the new ABI, vtables can
get clobbered during destruction, therefore the complete object dtor
cannot rely on it to locate the virtual bases for their destruction.
This happens to be an optimization too!

built & tested on i686-pc-linux-gnu, approved by Mark

nathan

-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-01-16  Nathan Sidwell  <nathan@codesourcery.com>

	* decl.c (finish_destructor_body): Convert to vbase pointer here.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.737
diff -c -3 -p -r1.737 decl.c
*** decl.c	2001/01/11 12:29:16	1.737
--- decl.c	2001/01/16 13:10:03
*************** finish_destructor_body ()
*** 13862,13877 ****
  	       vbases = TREE_CHAIN (vbases))
  	    {
  	      tree vbase = TREE_VALUE (vbases);
  
! 	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbase)))
  		{
! 		  tree vb = get_vbase
! 		    (BINFO_TYPE (vbase),
! 		     TYPE_BINFO (current_class_type));
! 		  finish_expr_stmt
! 		    (build_scoped_method_call
! 		     (current_class_ref, vb, base_dtor_identifier,
! 		      NULL_TREE));
  		}
  	    }
  
--- 13862,13887 ----
  	       vbases = TREE_CHAIN (vbases))
  	    {
  	      tree vbase = TREE_VALUE (vbases);
+ 	      tree base_type = BINFO_TYPE (vbase);
  
! 	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
  		{
!                   tree base_ptr_type = build_pointer_type (base_type);
! 	          tree expr = current_class_ptr;
! 	          
! 	          /* Convert to the basetype here, as we know the layout is
!                      fixed. What is more, if we let build_method_call do it,
!                      it will use the vtable, which may have been clobbered
!                      by the deletion of our primary base.  */
!                   
!                   expr = build1 (NOP_EXPR, base_ptr_type, expr);
! 	          expr = build (PLUS_EXPR, base_ptr_type, expr,
! 	                        BINFO_OFFSET (vbase));
! 	          expr = build_indirect_ref (expr, NULL);
! 	          expr = build_method_call (expr, base_dtor_identifier,
! 	                                    NULL_TREE, vbase,
! 	                                    LOOKUP_NORMAL);
! 		  finish_expr_stmt (expr);
  		}
  	    }
  
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 16 Jan 2001 <nathan@codesourcery.com>

// Bug 1611. Under the new ABI, the vtable can be clobered during dtoring our
// primary vbase. We mustn't use the vtable after that to locate our vbases.

#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
#include <stdio.h>
#include <stdlib.h>

int *ctorVBase = 0;
int *dtorVBase = 0;
int *ctorVDerived = 0;
int *dtorVDerived = 0;
int *ctorB = 0;
int *dtorB = 0;

struct VBase
{
  int member;
  VBase ()
    {
      if (ctorVBase) exit (1);
      ctorVBase = &member;
    }
  virtual ~VBase ()
    {
      if (dtorVBase) exit (2);
      dtorVBase = &member;
      if (dtorVBase != ctorVBase) exit (3);
    }
  void Offset () const
  {
    printf ("VBase\n");
    printf ("  VBase::member %d\n", &this->VBase::member - (int *)this);
  }
};

struct VDerived : virtual VBase
{
  int member;
  
  VDerived ()
    {
      if (ctorVDerived) exit (4);
      ctorVDerived = &member;
    }
  virtual ~VDerived ()
    {
      if (dtorVDerived) exit (5);
      dtorVDerived = &member;
      if (dtorVDerived != ctorVDerived) exit (6);
    }
  void Offset () const
  {
    printf ("VDerived\n");
    printf ("  VBase::member %d\n", &this->VBase::member - (int *)this);
    printf ("  VDerived::member %d\n", &this->VDerived::member - (int *)this);
  }
};
struct B : virtual VBase
{
  int member;
  void Offset () const
  {
    printf ("B\n");
    printf ("  VBase::member %d\n", &this->VBase::member - (int *)this);
    printf ("  B::member %d\n", &this->B::member - (int *)this);
  }
};
struct MostDerived : B, virtual VDerived
{
  int member;
  void Offset () const
  {
    printf ("MostDerived\n");
    printf ("  VBase::member %d\n", &this->VBase::member - (int *)this);
    printf ("  B::member %d\n", &this->B::member - (int *)this);
    printf ("  VDerived::member %d\n", &this->VDerived::member - (int *)this);
    printf ("  MostDerived::member %d\n", &this->MostDerived::member - (int *)this);
  }
};


int main ()
{
  {
    MostDerived dum;
    
    int *this_ = (int *)&dum;
    
    if (ctorVBase != &dum.VBase::member)
      return 23;
    if (ctorVDerived != &dum.VDerived::member)
      return 24;
    
    printf ("  VBase::member %d\n", &dum.VBase::member - this_);
    printf ("  B::member %d\n", &dum.B::member - this_);
    printf ("  VDerived::member %d\n", &dum.VDerived::member - this_);
    printf ("  MostDerived::member %d\n", &dum.MostDerived::member - this_);
    dum.MostDerived::Offset ();
    dum.B::Offset ();
    dum.VDerived::Offset ();
    dum.VBase::Offset ();
  }
  return 0;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */

int main () 
{
}

#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */

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