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 <[email protected]>
Backport from trunk r220489.
2015-02-06 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backport from trunk r220489.
2015-02-06 Jakub Jelinek <[email protected]>
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 ();
+ }
+};