Hi, As added in the PR, this issue is also present on 4.9 branch and affects at least arm-linux-gnueabihf target (as reported in PR61207).
I've backported it in the 4.9 branch with the attached patch. The difference with the trunk code is due the code introduced by PR63587 fix (I didn't checked on power7, on which the PR was initially reported, but I didn't managed to reproduce the issue for arm targets on 4.9 branch). Boostrapped on x86_64, and tested on arm/aarch64 targets (regression testing is ongoing). is ok for 4.9 branch when validation is done ? Thanks Yvan gcc/ 2015-03-09 Yvan Roux <yvan.r...@linaro.org> Backport from trunk r220489. 2015-02-06 Jakub Jelinek <ja...@redhat.com> PR ipa/64896 * cgraphunit.c (cgraph_node::expand_thunk): If restype is not is_gimple_reg_type nor the thunk_fndecl returns aggregate_value_p, set restmp to a temporary variable instead of resdecl. gcc/testsuite/ 2015-03-09 Yvan Roux <yvan.r...@linaro.org> Backport from trunk r220489. 2015-02-06 Jakub Jelinek <ja...@redhat.com> PR ipa/64896 * g++.dg/ipa/pr64896.C: New test.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 8f57607..130fc0d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1572,9 +1572,14 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks) restmp = gimple_fold_indirect_ref (resdecl); else if (!is_gimple_reg_type (restype)) { - restmp = resdecl; - add_local_decl (cfun, restmp); - BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp; + if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl))) + { + restmp = resdecl; + add_local_decl (cfun, restmp); + BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp; + } + else + restmp = create_tmp_var (restype, "retval"); } else restmp = create_tmp_reg (restype, "retval"); diff --git a/gcc/testsuite/g++.dg/ipa/pr64896.C b/gcc/testsuite/g++.dg/ipa/pr64896.C new file mode 100644 index 0000000..0a78220 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr64896.C @@ -0,0 +1,29 @@ +// PR ipa/64896 +// { dg-do compile } +// { dg-options "-O2" } + +struct A { int a, b; }; +struct B { A c; int d; }; +struct C { virtual B fn1 () const; }; +struct D { B fn2 () const; int fn3 () const; C *fn4 () const; }; + +int +D::fn3 () const +{ + fn4 ()->fn1 (); +} + +B +D::fn2 () const +{ + return B (); +} + +class F : C +{ + B + fn1 () const + { + return B (); + } +};