[C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")
Paolo Carlini
paolo.carlini@oracle.com
Thu Jun 20 04:24:00 GMT 2019
Hi,
this bug notices that the more aggressive de-virtualization check that
we have now in place (fixed c++/67184) doesn't work correctly for the
below reproducer, which involves a pure virtual: we de-virtualize and
the build fails at link-time. To cure this I believe we simply want an
additional DECL_PURE_VIRTUAL_P in the condition. I also checked that the
other compilers I have at hand appear to do the same, that is, they
compile the reproducer both as-is and without the final specifier to the
same assembly.
Note, in principle we have the option of not doing the additional
DECL_PURE_VIRTUAL_P check when the final overrider comes from the class
itself, not from a base, that is in the cases that we were already
de-virtualizing pre-67184. That is, for something like:
struct A final
{
 virtual void foo () = 0;
};
void fun(A* a, B* b)
{
 a->foo();
}
devirtualize anyway (which then doesn't link). We could add back an '||
CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)))' for that. ICC
appears to behave this way.
Tested x86_64-linux.
Thanks, Paolo.
////////////////////////
-------------- next part --------------
/cp
2019-06-20 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/90909
* call.c (build_over_call): Do not try to devirtualize when
then function is pure virtual.
/testsuite
2019-06-20 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/90909
* g++.dg/other/final6.C: New.
-------------- next part --------------
Index: testsuite/g++.dg/other/final6.C
===================================================================
--- testsuite/g++.dg/other/final6.C (nonexistent)
+++ testsuite/g++.dg/other/final6.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/90909
+// { dg-do link { target c++11 } }
+
+struct S1 { virtual void f() = 0; };
+struct S2: S1 { virtual void f() {} };
+struct S3: S2 { using S1::f; };
+struct S4 final: S3 { void g(); };
+void S4::g() { f(); }
+int main() { S4().g(); }
Index: cp/call.c
===================================================================
--- cp/call.c (revision 272410)
+++ cp/call.c (working copy)
@@ -8244,7 +8244,8 @@ 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 (TREE_TYPE (argtype)))
+ || (CLASSTYPE_FINAL (TREE_TYPE (argtype))
+ && !DECL_PURE_VIRTUAL_P (fn)))
flags |= LOOKUP_NONVIRTUAL;
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
More information about the Gcc-patches
mailing list