Hi! Apparently my r236430 change (trunk) and r236431 (6.x) broke the following testcase. In the later similar change to gimple-fold.c in r236506 I've added code to tweak gimple_call_fntype if we have newly one of the void something (void) __attribute__((noreturn)) functions like __builtin_unreachable or __cxa_pure_virtual, and drop the lhs even if it has been before non-POD, but the new fntype has void return type, but apparently we need to do the same in cgraph.c as well.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2? 2016-06-02 Jakub Jelinek <ja...@redhat.com> PR middle-end/71387 * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): If redirecting to noreturn e->callee->decl that has void return type and void arguments, adjust gimple_call_fntype and remove lhs even if it had previously addressable type. * g++.dg/opt/pr71387.C: New test. --- gcc/cgraph.c.jj 2016-05-26 10:37:54.000000000 +0200 +++ gcc/cgraph.c 2016-06-02 17:17:58.963052785 +0200 @@ -1512,8 +1512,20 @@ cgraph_edge::redirect_call_stmt_to_calle update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); } + /* If changing the call to __cxa_pure_virtual or similar noreturn function, + adjust gimple_call_fntype too. */ + if (gimple_call_noreturn_p (new_stmt) + && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (e->callee->decl))) + && TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl)) + && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl))) + == void_type_node)) + gimple_call_set_fntype (new_stmt, TREE_TYPE (e->callee->decl)); + /* If the call becomes noreturn, remove the LHS if possible. */ - if (gimple_call_noreturn_p (new_stmt) && should_remove_lhs_p (lhs)) + if (lhs + && gimple_call_noreturn_p (new_stmt) + && (VOID_TYPE_P (TREE_TYPE (gimple_call_fntype (new_stmt))) + || should_remove_lhs_p (lhs))) { if (TREE_CODE (lhs) == SSA_NAME) { --- gcc/testsuite/g++.dg/opt/pr71387.C.jj 2016-06-02 17:37:59.868769557 +0200 +++ gcc/testsuite/g++.dg/opt/pr71387.C 2016-06-02 17:23:51.000000000 +0200 @@ -0,0 +1,52 @@ +// PR middle-end/71387 +// { dg-do compile } +// { dg-options "-Og" } + +struct A +{ + A (); + inline A (const A &); +}; + +struct B +{ + explicit B (unsigned long) : b(0), c(1) {} + A a; + unsigned long b; + int c; +}; + +struct C {}; + +struct D +{ + explicit D (const C *) {} +}; + +struct E : public D +{ + E (const C *x) : D(x) {} + virtual A foo () const = 0; + virtual A bar () const = 0; +}; + +struct F : public B +{ + inline void baz (); + F (const E *); + const E *f; +}; + +inline void +F::baz () +{ + if (b == 0) + a = f->bar (); + else + a = f->foo (); +} + +F::F (const E *) : B(4) +{ + baz (); +} Jakub