diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c6f6b12cc5..c2eeb9033e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,8 +1,16 @@ +2016-06-03 Jakub Jelinek + + 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. + 2016-06-02 Jeff Law PR tree-optimization/71328 * tree-ssa-threadupdate.c (duplicate_thread_path): Fix off-by-one - error when checking for a jump back onto the copied path. */ + error when checking for a jump back onto the copied path. 2016-06-02 David Malcolm diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 08bf9bf96a2..e256dd05d35 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1512,8 +1512,20 @@ cgraph_edge::redirect_call_stmt_to_callee (void) 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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 263d91b585b..c6d6392b144 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-03 Jakub Jelinek + + PR middle-end/71387 + * g++.dg/opt/pr71387.C: New test. + 2016-06-02 Jeff Law PR tree-optimization/71328 diff --git a/gcc/testsuite/g++.dg/opt/pr71387.C b/gcc/testsuite/g++.dg/opt/pr71387.C new file mode 100644 index 00000000000..56f4a4d38b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr71387.C @@ -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 (); +}