diff mbox

C++ PATCH for c++/58678 (devirt vs. KDE)

Message ID 5323AF71.8060909@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 15, 2014, 1:40 a.m. UTC
Oops, need to make sure dtor is non-null before looking at it...

We also might as well handle this after the dfs is done.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 142f595d2474a05c59991e8ea7a5f6712d9982ff
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 14 20:38:10 2014 -0400

    	PR c++/60532
    	PR c++/58678
    	* search.c (get_pure_virtuals): Handle abstract dtor here.
    	(dfs_get_pure_virtuals): Not here.

diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 66c6df5..d99e182 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2096,22 +2096,6 @@  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;
 }
@@ -2131,6 +2115,22 @@  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/testsuite/g++.dg/other/abstract6.C b/gcc/testsuite/g++.dg/other/abstract6.C
new file mode 100644
index 0000000..ceba1a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/abstract6.C
@@ -0,0 +1,10 @@ 
+// PR c++/60532
+
+class A
+{
+  ~A ();
+};
+class B : A
+{
+  virtual void m () = 0;
+};