http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58585
Jan Hubicka <hubicka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at redhat dot com Blocks| |58252 --- Comment #3 from Jan Hubicka <hubicka at gcc dot gnu.org> --- Thanks for nice testcase. The problem here is that record_binfos and get_binfo_at_offset do not agree. I think it may be the same problem as in PR58252. Here we have class C with one (virtual) base B that has one (virtual) base A. record_binfos starts walk in binfo of C and it looks at base B. It passes two binfos around. type_binfo is binfo pointing to a virtual table to use, while binfo is the BINFo being walked. For non-virtual inheritance the first base share virtual table with outer class and its BINFO has no pointer to any vtable. So there is a conditional setting type_binfo to the base only if its vtable is non-NULL. Now for virtual inheritance, B have its own table defined, so we switch to B and eventually we look into vtable assigned to A. get_binfo_at_offset works slightly differently. It first walks fields of the structure identifying the field at proper offset. If it is abstract it is considered to represent base type. Then if offset is non-0 it uses BINFO of the base, while otherwise it stays on BINFO of outer type. For the testcase get_binfo_at_offsets is called with offset 0 and it makes lookup in the vtable pointed by BINFO of C that contains a thunk, while record_binfos looks into vtable pointer by BINFO representing base A within C that has directly method foo. Obviously both functions must be made to agree. C::C seems to be compiled as: _ZN1CC1Ev: .LFB12: .cfi_startproc .cfi_personality 0x3,__gxx_personality_v0 movq _ZTT1C+24(%rip), %rax movq _ZTT1C+32(%rip), %rdx movq -32(%rax), %rax movq %rdx, 8(%rdi,%rax) movq $_ZTV1C+88, 8(%rdi) movq $_ZTV1C+40, (%rdi) movq _ZTV1C+40(%rip), %rax jmp *%rax and _ZTV1C: .quad 0 .quad 8 .quad 8 .quad 0 .quad _ZTI1C .quad _ZTv0_n24_N1B3fooEv so we really call thunk here and probably record_binfos is incorrect. I can fix it by also waking fields and handling fields at offset 0 specially, but I would hope there is direct way how to do so via BASE_BINFOs walk.... I tried to change conditional in record_binfos to only switch type_binfo if BINFO_OFFSET != 0, but in this case it is 8. This also seems incorect to me... Jason, any ideas about the proper fix? Honza