https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82107
--- Comment #3 from Martin Liška <marxin at gcc dot gnu.org> ---
Huh, very nice example I must admit.
Following bad happens:
In FooImpl.cpp content of real_payload is inlined to payload function. Then ICF
does merge operation:
FooImpl::real_payload (struct FooImpl * const this, struct wstring & result1,
struct wstring & result2)
{
<bb 2> [100.00%] [count: INV]:
FooBase<FooImpl>::payload (this_2(D), result1_3(D), result2_4(D)); [tail
call]
return;
}
On the other hand in main.cpp a tail call is generated from original source
code:
FooBase<FooImpl>::payload (struct FooBase * const this, struct wstring &
result1, struct wstring & result2)
{
<bb 2> [100.00%] [count: INV]:
FooImpl::real_payload (this_2(D), result1_3(D), result2_4(D)); [tail call]
return;
}
And as both are COMDATs wrong combination of function is selected and one can
see the infinite loop:
0x400b80
<_ZN7FooImpl12real_payloadERNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEES6_>
jmpq 0x400a30
<_ZN7FooBaseI7FooImplE7payloadERNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEES8_>
0x400a30
<_ZN7FooBaseI7FooImplE7payloadERNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEES8_>
jmpq 0x400b80
<_ZN7FooImpl12real_payloadERNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEES6_>_>
Well, we would need to somehow preserve the original order, probably based on
inlining decisions that were done.
Let me discuss that with Honza.