[C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

Paolo Carlini paolo.carlini@oracle.com
Sun Jun 23 11:53:00 GMT 2019


... hi again ;)

The other day I was having a look at using declarations for this issue 
and noticed that only a few lines below the de-virtualization check we 
have to handle functions found by a using declaration, for various 
reasons. In particular, we know whether we found a function fn where has 
been declared or in a derived class. Thus the idea: for the purpose of 
making some progress, in particular all the cases in c++/67184 & co, 
would it make sense for the time being to simply add a check to the 
de-virtualization condition restricting it to non-using declarations? 
See the below (it also moves the conditional a few lines below only for 
clarity and consistency with the code handling using declarations, no 
functional impact) What do you think?

Thanks, Paolo.

///////////////////

-------------- next part --------------
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 272583)
+++ cp/call.c	(working copy)
@@ -8241,12 +8241,6 @@ build_over_call (struct z_candidate *cand, int fla
 	    return error_mark_node;
 	}
 
-      /* See if the function member or the whole class type is declared
-	 final and the call can be devirtualized.  */
-      if (DECL_FINAL_P (fn)
-	  || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn))))
-	flags |= LOOKUP_NONVIRTUAL;
-
       /* [class.mfct.nonstatic]: If a nonstatic member function of a class
 	 X is called for an object that is not of type X, or of a type
 	 derived from X, the behavior is undefined.
@@ -8271,6 +8265,17 @@ build_over_call (struct z_candidate *cand, int fla
 	  else
 	    return error_mark_node;
 	}
+
+      /* See if the function member or the whole class type is declared
+	 final and the call can be devirtualized.  */
+      if (DECL_FINAL_P (fn)
+	  || (CLASSTYPE_FINAL (TREE_TYPE (argtype))
+	      /* Give up for now if fn was found by a using declaration,
+		 the complex case, see c++/90909.  */
+	      && (TREE_TYPE (TREE_TYPE (converted_arg))
+		  == TREE_TYPE (parmtype))))
+	flags |= LOOKUP_NONVIRTUAL;
+
       /* If fn was found by a using declaration, the conversion path
 	 will be to the derived class, not the base declaring fn. We
 	 must convert from derived to base.  */
Index: testsuite/g++.dg/other/final3.C
===================================================================
--- testsuite/g++.dg/other/final3.C	(nonexistent)
+++ testsuite/g++.dg/other/final3.C	(working copy)
@@ -0,0 +1,28 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct V {
+ virtual void foo(); 
+};
+
+struct wV final : V {
+};
+
+struct oV final : V {
+  void foo();
+};
+
+void call(wV& x)
+{
+  x.foo();
+  x.V::foo();
+}
+
+void call(oV& x)
+{
+  x.foo();
+  x.V::foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final4.C
===================================================================
--- testsuite/g++.dg/other/final4.C	(nonexistent)
+++ testsuite/g++.dg/other/final4.C	(working copy)
@@ -0,0 +1,16 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct B
+{
+  virtual void operator()();
+  virtual operator int();
+  virtual int operator++();
+};
+
+struct D final : B { };
+
+void foo(D& d) { d(); int t = d; ++d; }
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final5.C
===================================================================
--- testsuite/g++.dg/other/final5.C	(nonexistent)
+++ testsuite/g++.dg/other/final5.C	(working copy)
@@ -0,0 +1,19 @@
+// PR c++/69445
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct Base {
+  virtual void foo() const = 0;
+  virtual void bar() const {}
+};
+
+struct C final : Base {
+  void foo() const { }
+};
+
+void func(const C & c) {
+  c.bar();
+  c.foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }


More information about the Gcc-patches mailing list