From 42cb62b7ab0ad3eb3a322f69dca438fcba79bb55 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 18 Jan 2001 09:39:13 +0000 Subject: [PATCH] cp: * decl.c (finish_destructor_body): Convert to vbase pointer here. testsuite: * g++.old-deja/g++.abi/vbase1.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39114 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 4 + gcc/cp/decl.c | 26 +++++-- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.old-deja/g++.abi/vbase1.C | 114 ++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vbase1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c020cfaf3d0..56b84835a42 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2001-01-18 Nathan Sidwell + * decl.c (finish_destructor_body): Convert to vbase pointer here. + +2001-01-18 Nathan Sidwell + * semantics.c (begin_class_definition): Check we're not inside a template parm list. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ff3084e8dfe..e5fd61e73dc 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13862,16 +13862,26 @@ finish_destructor_body () vbases = TREE_CHAIN (vbases)) { tree vbase = TREE_VALUE (vbases); + tree base_type = BINFO_TYPE (vbase); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbase))) + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type)) { - 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)); + 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); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4b00c044efc..30643601bff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2001-01-18 Nathan Sidwell + * g++.old-deja/g++.abi/vbase1.C: New test. + +2001-01-18 Nathan Sidwell + * g++.old-deja/g++.pt/crash65.C: New test. 2001-01-18 Neil Booth diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase1.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase1.C new file mode 100644 index 00000000000..a85e00d7b50 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase1.C @@ -0,0 +1,114 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 16 Jan 2001 + +// 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 +#include + +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) */ -- 2.11.4.GIT