]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/58678 (pykde4-4.11.2 link error (devirtualization too trigger happy))
authorJason Merrill <jason@redhat.com>
Fri, 14 Mar 2014 19:06:54 +0000 (15:06 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 14 Mar 2014 19:06:54 +0000 (15:06 -0400)
PR c++/58678
* search.c (dfs_get_pure_virtuals): Treat the destructor of an
abstract class as pure.

From-SVN: r208573

gcc/cp/ChangeLog
gcc/cp/search.c
gcc/testsuite/g++.dg/ipa/devirt-30.C [new file with mode: 0644]

index d90b9881c313959392b28412f9f8e41dc5c32ba6..b752ebe914f0d6b88753f0f04bb8f5270d22cd68 100644 (file)
@@ -1,3 +1,9 @@
+2014-03-14  Jason Merrill  <jason@redhat.com>
+
+       PR c++/58678
+       * search.c (dfs_get_pure_virtuals): Treat the destructor of an
+       abstract class as pure.
+
 2014-03-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/60383
index c3eed90f6c3632b5a9ade786e0c09e3a2444131d..66c6df5215e74c26f34cc4e7a41e0aeadeaa3ced 100644 (file)
@@ -2096,6 +2096,22 @@ dfs_get_pure_virtuals (tree binfo, void *data)
        if (DECL_PURE_VIRTUAL_P (BV_FN (virtuals)))
          vec_safe_push (CLASSTYPE_PURE_VIRTUALS (type), BV_FN (virtuals));
     }
+  /* 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 (binfo == TYPE_BINFO (type)
+      && CLASSTYPE_PURE_VIRTUALS (type)
+      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+    {
+      tree dtor = CLASSTYPE_DESTRUCTORS (type);
+      if (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;
+       }
+    }
 
   return NULL_TREE;
 }
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-30.C b/gcc/testsuite/g++.dg/ipa/devirt-30.C
new file mode 100644 (file)
index 0000000..c4ac694
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/58678
+// { dg-options "-O3 -fdump-ipa-devirt" }
+
+// We shouldn't speculatively devirtualize to ~B because B is an abstract
+// class; any actual object passed to f will be of some derived class which
+// has its own destructor.
+
+struct A
+{
+  virtual void f() = 0;
+  virtual ~A();
+};
+
+struct B : A
+{
+  virtual ~B() {}
+};
+
+void f(B* b)
+{
+  delete b;
+}
+
+// { dg-final { scan-ipa-dump-not "Speculatively devirtualizing" "devirt" } }
+// { dg-final { cleanup-ipa-dump "devirt" } }