... 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.

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

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" } }

Reply via email to