Hi, this patch avoid ipa-icf to take away body of a virtual function which is a subject of later devirtualization.
Bootstrapped/regtested x86_64-linux, comitted. Honza PR ipa/68148 * ipa-icf.c (sem_function::merge): Virtual functions may become reachable even if they address is not taken and there are no idrect calls. * testsuite/g++.dg/ipa/devirt-49.C: New testcase. Index: ipa-icf.c =================================================================== --- ipa-icf.c (revision 232407) +++ ipa-icf.c (working copy) @@ -1305,6 +1305,7 @@ sem_function::merge (sem_item *alias_ite /* If all callers was redirected, do not produce wrapper. */ if (alias->can_remove_if_no_direct_calls_p () + && !DECL_VIRTUAL_P (alias->decl) && !alias->has_aliases_p ()) { create_wrapper = false; Index: testsuite/g++.dg/ipa/devirt-49.C =================================================================== --- testsuite/g++.dg/ipa/devirt-49.C (revision 0) +++ testsuite/g++.dg/ipa/devirt-49.C (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-devirt" } */ +struct Interface { + virtual ~Interface() {} + virtual void virtualFunc() = 0; + virtual void virtualFunc2() = 0; +}; + +struct Concrete : Interface { + int counter_; + Concrete() : counter_(0) {} + void virtualFunc() { counter_++; } + void virtualFunc2() { counter_++; } +}; + +void test(Interface &c) { + c.virtualFunc(); + c.virtualFunc2(); +} +/* { dg-final { scan-ipa-dump "2 speculatively devirtualized" "devirt" } } */