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.

Reply via email to