The following testcase taken from testsuite (and many others): // PR 14535 // { dg-do run } // { dg-options "-O -finline" } // // Original test case failure required that Raiser constructor be inlined.
extern "C" void abort(); bool destructor_called = false; struct B { virtual void Run(){}; }; struct D : public B { virtual void Run() { struct O { ~O() { destructor_called = true; }; } o; struct Raiser { Raiser() throw( int ) {throw 1;}; } raiser; }; }; int main() { try { D d; static_cast<B&>(d).Run(); } catch (...) {} if (!destructor_called) abort (); } leads to following in .optimized dump: <bb 2>: MEM[(struct B *)&d]._vptr.B = &_ZTV1B[2]; d.D.2108._vptr.B = &_ZTV1D[2]; D.2210_2 = _ZTV1D[2]; OBJ_TYPE_REF(D.2210_2;&d.D.2108->0) (&d.D.2108); Obviously OBJ_TYPE_REF can be optimized here since we know the virtual table. Why it is missed? I run into it because my new folding code is actually smart enough to lead to: int (*__vtbl_ptr_type) (void) void D::<T400> (struct D *) D.2210_2 = Run; The error comes because we pick from initializer of VTBL the following ADDR_EXPR: <addr_expr 0x7ffff7ec8b10 type <pointer_type 0x7ffff6b7db28 __vtbl_ptr_type type <function_type 0x7ffff6b7da80 type <integer_type 0x7ffff7edb498 int> type_6 QI size <integer_cst 0x7ffff7ec54d8 constant 8> unit size <integer_cst 0x7ffff7ec5500 constant 1> align 8 symtab 0 alias set -1 canonical type 0x7ffff6b7da80 pointer_to_this <pointer_type 0x7ffff6b7db28 __vtbl_ptr_type>> unsigned type_6 DI size <integer_cst 0x7ffff7ec57d0 constant 64> unit size <integer_cst 0x7ffff7ec57f8 constant 8> align 64 symtab 0 alias set -1 canonical type 0x7ffff6b7db28 pointer_to_this <pointer_type 0x7ffff6b7dc78>> constant arg 0 <function_decl 0x7ffff6b8e500 Run type <method_type 0x7ffff6b9b9d8 type <void_type 0x7ffff7edbe70 void> type_6 QI size <integer_cst 0x7ffff7ec54d8 8> unit size <integer_cst 0x7ffff7ec5500 1> align 8 symtab 0 alias set -1 canonical type 0x7ffff6b9b9d8 method basetype <record_type 0x7ffff6b9b7e0 D> arg-types <tree_list 0x7ffff6b80af0 value <pointer_type 0x7ffff6b9ba80> chain <tree_list 0x7ffff7eed398 value <void_type 0x7ffff7edbe70 void>>> pointer_to_this <pointer_type 0x7ffff6bab150>> addressable volatile asm_written used public static weak autoinline virtual decl_5 QI file /home/jh/a.C line 15 col 18 align 16 context <record_type 0x7ffff6b9b7e0 D> initial <error_mark 0x7ffff7ecdb28> arguments <parm_decl 0x7ffff7ece990 this type <pointer_type 0x7ffff6b9bb28> readonly unsigned DI file /home/jh/a.C line 15 col 22 size <integer_cst 0x7ffff7ec57d0 64> unit size <integer_cst 0x7ffff7ec57f8 8> align 64 context <function_decl 0x7ffff6b8e500 Run> (reg/f:DI 62 [ this ]) arg-type <pointer_type 0x7ffff6b9bb28> incoming-rtl (reg:DI 5 di [ this ])> result <result_decl 0x7ffff7ed0380 D.2112 type <void_type 0x7ffff7edbe70 void> ignored VOID file /home/jh/a.C line 16 col 7 align 8 context <function_decl 0x7ffff6b8e500 Run>> full-name "virtual void D::Run()" pending-inline-info 0x7ffff6ba42a0 (mem:QI (symbol_ref/i:DI ("_ZN1D3RunEv") [flags 0x1] <function_decl 0x7ffff6b8e500 Run>) [0 S1 A8])>> Note the differece in between type of address and the method RUN. This is what makes verifier unhappy. How to fix this? Should FE put there some NOP_EXPR somewhere? Still devirtualizing should realize this case a lot earlier. Honza -- Summary: Missed devirtualization Product: gcc Version: 4.6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: hubicka at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45605