[Bug ipa/59226] [4.9 Regression] ICE: in record_target_from_binfo, at ipa-devirt.c:661
hubicka at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sun Dec 15 21:40:00 GMT 2013
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59226
--- Comment #7 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
This testcase manifest the other virtual inehritance problem.
Here it is algorithm of get_binfo_at_offset that first walks fields of a
structure and if it finds corresponding field at given offset, it walks bases
of structure to dive recursively into.
I am speaking of testcase in #1
Here get_binfo_at_offset is called on binfo of class D looking for class A at
offset 0. The binfo of class D itself is one nested in E. The inheritance
tree
looks as follows:
A B
v/v\ / (v marks virtual inheritance)
C D
\ /
E
ipa-devirt does not expect get_binfo_at_offset to fail since it knows D derives
A.
Now get_binfo_at_offset looks into memory layout of type D.
<record_type 0x7ffff76b17e0 D addressable tree_2 needs-constructing type_5 BLK
size <integer_cst 0x7ffff753e140 type <integer_type 0x7ffff753c150
bitsizetype> constant 128>
unit size <integer_cst 0x7ffff753e160 type <integer_type 0x7ffff753c0a8
sizetype> constant 16>
align 64 symtab 0 alias set -1 canonical type 0x7ffff76b17e0
fields <field_decl 0x7ffff769eed8 D.2255
type <record_type 0x7ffff76a87e0 B addressable tree_2
needs-constructing type_5 BLK
size <integer_cst 0x7ffff753e0c0 constant 64>
unit size <integer_cst 0x7ffff753e0e0 constant 8>
align 64 symtab 0 alias set -1 canonical type 0x7ffff76a87e0 fields
<field_decl 0x7ffff769e4c0 _vptr.B> context <translation_unit_decl
0x7ffff7546170 D.1>
full-name "struct B"
needs-constructor X() X(constX&) this=(X&) n_parents=0
use_template=0 interface-unknown
pointer_to_this <pointer_type 0x7ffff76a8a80> chain <type_decl
0x7ffff7693ac8 B>>
ignored decl_6 BLK file /home/jan/t.C line 13 col 8 size <integer_cst
0x7ffff753e0c0 64> unit size <integer_cst 0x7ffff753e0e0 8>
align 64 offset_align 128
offset <integer_cst 0x7ffff753e100 constant 0>
bit offset <integer_cst 0x7ffff753e180 constant 0> context <record_type
0x7ffff76b17e0 D>
chain <type_decl 0x7ffff76b3170 D type <record_type 0x7ffff76b1888 D>
nonlocal decl_4 VOID file /home/jan/t.C line 14 col 1
align 1 context <record_type 0x7ffff76b17e0 D> result <record_type
0x7ffff76b17e0 D>
chain <field_decl 0x7ffff76b4098 D.2257>>> context
<translation_unit_decl 0x7ffff7546170 D.1>
full-name "struct D"
needs-constructor X() X(constX&) this=(X&) n_parents=2 use_template=0
interface-unknown
pointer_to_this <pointer_type 0x7ffff76b1a80> chain <type_decl
0x7ffff76b30b8 D>>
and here it finds B that is a wrong turn and gives up after looking into B.
Now if it looked further
(gdb) p debug_tree (fld->common.chain->common.chain)
<field_decl 0x7ffff76b4098 D.2257
type <record_type 0x7ffff76a8000 A addressable tree_2 needs-constructing
type_5 BLK
size <integer_cst 0x7ffff753e0c0 constant 64>
unit size <integer_cst 0x7ffff753e0e0 constant 8>
align 64 symtab 0 alias set -1 canonical type 0x7ffff76a8000
fields <field_decl 0x7ffff769e1c8 _vptr.A type <pointer_type
0x7ffff768ec78>
unsigned virtual DI file /home/jan/t.C line 1 col 8 size
<integer_cst 0x7ffff753e0c0 64> unit size <integer_cst 0x7ffff753e0e0 8>
align 64 offset_align 128
offset <integer_cst 0x7ffff753e100 constant 0>
bit offset <integer_cst 0x7ffff753e180 constant 0> context
<record_type 0x7ffff76a8000 A> chain <type_decl 0x7ffff7693958 A>> context
<translation_unit_decl 0x7ffff7546170 D.1>
full-name "struct A"
needs-constructor X() X(constX&) this=(X&) n_parents=0 use_template=0
interface-unknown
pointer_to_this <pointer_type 0x7ffff76a82a0> chain <type_decl
0x7ffff76938a0 A>>
ignored decl_6 BLK file /home/jan/t.C line 13 col 8 size <integer_cst
0x7ffff753e0c0 64> unit size <integer_cst 0x7ffff753e0e0 8>
align 64 offset_align 128 offset <integer_cst 0x7ffff753e100 0> bit offset
<integer_cst 0x7ffff753e0c0 64> context <record_type 0x7ffff76b17e0 D>>
$20 = void
here it would find A, but this time at offset 64.
So perhaps we are looking for A at wrong offset? Or are we taking wrong vtable?
type_binfo is D since it is last on the walk down to A with virtual table
attached. Maybe it is because all references to A in D go via C's vtable and we
are safe to give up. Or do we need to compensate for offsets here like this?
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c (revision 205941)
+++ ipa-devirt.c (working copy)
@@ -646,8 +646,11 @@
if (types_same_for_odr (type, outer_type))
{
- tree inner_binfo = get_binfo_at_offset (type_binfo,
- offset, otr_type);
+ tree inner_binfo = get_binfo_at_offset
+ (type_binfo, offset
+ + (tree_to_uhwi (BINFO_OFFSET (type_binfo))
+ - tree_to_uhwi (BINFO_OFFSET (binfo)))
+ * BITS_PER_UNIT, otr_type);
/* For types in anonymous namespace first check if the respective vtable
is alive. If not, we know the type can't be called. */
if (!flag_ltrans && anonymous)
(in single inheritance case this is not needed, since every binfo with non-zero
offset must have vtable attached).
Other option would be to simply return NULL when inner_binfo is NULL with a
comment that this is virtual multiple inheritance case where vtable was already
taken care on at different branch of recursion.
Jason, what do you think?
Markus, I do not have my usual firefox testing setup until christmas. Would be
nice to know if the proposed patch works on anything else than this testcase.
More information about the Gcc-bugs
mailing list