This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix bug 1611
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH] Fix bug 1611
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Thu, 18 Jan 2001 09:47:34 +0000
- Organization: Codesourcery LLC
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) */