https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68148
Jan Hubicka <hubicka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2016-01-10 Assignee|unassigned at gcc dot gnu.org |hubicka at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #3 from Jan Hubicka <hubicka at gcc dot gnu.org> --- This is the result of analysis: Procesing function void test(Interface&)/12 Introduced new external node (void __cxa_pure_virtual()/26). Targets of polymorphic call of type 0:struct Interface token 3 Outer type (dynamic):struct Interface (or a derived type) offset 0 This is partial list; extra targets may be defined in other units. (derived types included) virtual void Concrete::virtualFunc2()/11 code.C:16:19: note: speculatively devirtualizing call in void test(Interface&)/12 to virtual void Concrete::virtualFunc2()/11 Indirect call -> speculative call void test(Interface&)/12 => virtual void Concrete::virtualFunc2()/11 Targets of polymorphic call of type 0:struct Interface token 2 Outer type (dynamic):struct Interface (or a derived type) offset 0 This is partial list; extra targets may be defined in other units. (derived types included) virtual void Concrete::virtualFunc()/10 (no definition inline) Speculative targets: the problem is that list of Speculative targets is empty which makes us to ignore the fact that even non-speculatively there is only one possible target. The reason is that the second function does not pass can_refer_decl_in_current_unit_p: 149 snode = symtab_node::get (decl); 150 if (!snode 151 || ((!snode->definition || DECL_EXTERNAL (decl)) 152 && (!snode->in_other_partition 153 || (!snode->forced_by_abi && !snode->force_output)))) 154 return false; and node is: (gdb) p snode->debug () _ZN8Concrete11virtualFuncEv/10 (virtual void Concrete::virtualFunc()) @0x7ffff6c4f170 Type: function Body removed by symtab_remove_unreachable_nodes Visibility: externally_visible public weak comdat comdat_group:_ZN8Concrete11virtualFuncEv one_only virtual References: Referring: Availability: not_available First run: 0 Function flags: icf_merged Called by: Calls: which is done by ipa-icf::merge: Wrapper cannot be created because of COMDAT Unified; Function body was removed. This is because ipa-icf thinks that since there are no calls or direct uses, it may get rid of the function. I am testing the following: Index: ../../gcc/ipa-icf.c =================================================================== --- ../../gcc/ipa-icf.c (revision 232179) +++ ../../gcc/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;