Hi,

when Roberto Agostino and I implemented the front-end devirtualization of final overriders we missed this case, where it comes from the base. It seems to me that by way of access_path the existing approach can be neatly extended. Tested x86_64-linux.

Thanks, Paolo.

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

/cp
2019-05-17  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/67184
        PR c++/69445
        * call.c (build_over_call): Devirtualize when the final overrider
        comes from the base.

/testsuite
2019-05-17  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/67184
        PR c++/69445
        * g++.dg/other/final3.C: New.
        * g++.dg/other/final4.C: Likewise.
        * g++.dg/other/final5.C: Likewise.
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 271296)
+++ cp/call.c   (working copy)
@@ -8241,7 +8241,7 @@ build_over_call (struct z_candidate *cand, int fla
       /* 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))))
+         || CLASSTYPE_FINAL (TREE_TYPE (cand->access_path)))
        flags |= LOOKUP_NONVIRTUAL;
 
       /* [class.mfct.nonstatic]: If a nonstatic member function of a class
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,26 @@
+// 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();
+}
+
+void call(oV& x)
+{
+  x.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