aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-03-26 12:50:26 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-03-26 12:50:26 -0400
commitd74db8ff1c8f126c3d45ab9e72458ead0422865b (patch)
tree50d4baaeda9834b83184bd2181f60f3b85f9f5b8
parent3a2700f61bd54868e8572b18f3dadf994adb45ea (diff)
downloadgcc-d74db8ff1c8f126c3d45ab9e72458ead0422865b.zip
gcc-d74db8ff1c8f126c3d45ab9e72458ead0422865b.tar.gz
gcc-d74db8ff1c8f126c3d45ab9e72458ead0422865b.tar.bz2
re PR c++/60566 (r208573 omits needed thunks)
PR c++/60566 PR c++/58678 * class.c (build_vtbl_initializer): Handle abstract dtors here. * search.c (get_pure_virtuals): Not here. From-SVN: r208845
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/class.c10
-rw-r--r--gcc/cp/search.c16
-rw-r--r--gcc/ipa-devirt.c2
-rw-r--r--gcc/testsuite/g++.dg/abi/thunk6.C18
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-21.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-23.C2
7 files changed, 36 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 23a2c8f..518eb22 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2014-03-25 Jason Merrill <jason@redhat.com>
+ PR c++/60566
+ PR c++/58678
+ * class.c (build_vtbl_initializer): Handle abstract dtors here.
+ * search.c (get_pure_virtuals): Not here.
+
PR c++/60375
* parser.c (cp_parser_lambda_expression): Don't parse the body of
a lambda in unevaluated context.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b46391b..d277e07 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -9017,6 +9017,16 @@ build_vtbl_initializer (tree binfo,
if (!TARGET_VTABLE_USES_DESCRIPTORS)
init = fold_convert (vfunc_ptr_type_node,
build_fold_addr_expr (fn));
+ /* Don't refer to a virtual destructor from a constructor
+ vtable or a vtable for an abstract class, since destroying
+ an object under construction is undefined behavior and we
+ don't want it to be considered a candidate for speculative
+ devirtualization. But do create the thunk for ABI
+ compliance. */
+ if (DECL_DESTRUCTOR_P (fn_original)
+ && (CLASSTYPE_PURE_VIRTUALS (DECL_CONTEXT (fn_original))
+ || orig_binfo != binfo))
+ init = size_zero_node;
}
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index d99e182..c3eed90 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2115,22 +2115,6 @@ get_pure_virtuals (tree type)
which it is a primary base will contain vtable entries for the
pure virtuals in the base class. */
dfs_walk_once (TYPE_BINFO (type), NULL, dfs_get_pure_virtuals, type);
-
- /* Treat a virtual destructor in an abstract class as pure even if it
- isn't declared as pure; there is no way it would be called through the
- vtable except during construction, which causes undefined behavior. */
- if (CLASSTYPE_PURE_VIRTUALS (type)
- && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- {
- tree dtor = CLASSTYPE_DESTRUCTORS (type);
- if (dtor && DECL_VIRTUAL_P (dtor) && !DECL_PURE_VIRTUAL_P (dtor))
- {
- tree clone;
- DECL_PURE_VIRTUAL_P (dtor) = true;
- FOR_EACH_CLONE (clone, dtor)
- DECL_PURE_VIRTUAL_P (clone) = true;
- }
- }
}
/* Debug info for C++ classes can get very large; try to avoid
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 2f84f17..6fb1449 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -1261,7 +1261,7 @@ get_polymorphic_call_info (tree fndecl,
}
/* If the function is constructor or destructor, then
- the type is possibly in consturction, but we know
+ the type is possibly in construction, but we know
it is not derived type. */
if (DECL_CXX_CONSTRUCTOR_P (fndecl)
|| DECL_CXX_DESTRUCTOR_P (fndecl))
diff --git a/gcc/testsuite/g++.dg/abi/thunk6.C b/gcc/testsuite/g++.dg/abi/thunk6.C
new file mode 100644
index 0000000..e3d07f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/thunk6.C
@@ -0,0 +1,18 @@
+// PR c++/60566
+// We need to emit the construction vtable thunk for ~C even if we aren't
+// going to use it.
+
+struct A
+{
+ virtual void f() = 0;
+ virtual ~A() {}
+};
+
+struct B: virtual A { int i; };
+struct C: virtual A { int i; ~C(); };
+
+C::~C() {}
+
+int main() {}
+
+// { dg-final { scan-assembler "_ZTv0_n32_N1CD1Ev" } }
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-21.C b/gcc/testsuite/g++.dg/ipa/devirt-21.C
index 99f60af..675bd08 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-21.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-21.C
@@ -37,5 +37,5 @@ main()
{
class C c;
}
-/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" } } */
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-23.C b/gcc/testsuite/g++.dg/ipa/devirt-23.C
index a32c7d6..98d86ae 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-23.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-23.C
@@ -45,5 +45,5 @@ main()
{
class C c;
}
-/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" } } */
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */