aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-01-18 09:39:13 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-01-18 09:39:13 +0000
commit9f724b6ae48e21f50e0b00461ba30b8c20b43d5a (patch)
tree29a0df5076c898f0202634ee73aed7b8e52ac616 /gcc
parent522d6614c50ecd386854d7e46010d1b74672f42d (diff)
downloadgcc-9f724b6ae48e21f50e0b00461ba30b8c20b43d5a.zip
gcc-9f724b6ae48e21f50e0b00461ba30b8c20b43d5a.tar.gz
gcc-9f724b6ae48e21f50e0b00461ba30b8c20b43d5a.tar.bz2
decl.c (finish_destructor_body): Convert to vbase pointer here.
cp: * decl.c (finish_destructor_body): Convert to vbase pointer here. testsuite: * g++.old-deja/g++.abi/vbase1.C: New test. From-SVN: r39114
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/decl.c26
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vbase1.C114
4 files changed, 140 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c020cfa..56b8483 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2001-01-18 Nathan Sidwell <nathan@codesourcery.com>
+ * decl.c (finish_destructor_body): Convert to vbase pointer here.
+
+2001-01-18 Nathan Sidwell <nathan@codesourcery.com>
+
* 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 ff3084e..e5fd61e 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 4b00c04..3064360 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2001-01-18 Nathan Sidwell <nathan@codesourcery.com>
+ * g++.old-deja/g++.abi/vbase1.C: New test.
+
+2001-01-18 Nathan Sidwell <nathan@codesourcery.com>
+
* g++.old-deja/g++.pt/crash65.C: New test.
2001-01-18 Neil Booth <neil@daikokuya.demon.co.uk>
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 0000000..a85e00d
--- /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 <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) */