2012-01-19 Jakub Jelinek PR middle-end/51895 * expr.c (expand_expr_real_1): Handle BLKmode MEM_REF of non-addressable non-BLKmode base correctly. * g++.dg/opt/pr51895.C: New test. --- gcc/expr.c.jj 2012-01-13 21:47:35.000000000 +0100 +++ gcc/expr.c 2012-01-19 13:12:14.218760812 +0100 @@ -9328,6 +9328,16 @@ expand_expr_real_1 (tree exp, rtx target bftype = TREE_TYPE (base); if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode) bftype = TREE_TYPE (exp); + else + { + temp = assign_stack_temp (DECL_MODE (base), + GET_MODE_SIZE (DECL_MODE (base)), + 0); + store_expr (base, temp, 0, false); + temp = adjust_address (temp, BLKmode, offset); + set_mem_size (temp, int_size_in_bytes (TREE_TYPE (exp))); + return temp; + } return expand_expr (build3 (BIT_FIELD_REF, bftype, base, TYPE_SIZE (TREE_TYPE (exp)), --- gcc/testsuite/g++.dg/opt/pr51895.C.jj 2012-01-19 13:20:27.808899825 +0100 +++ gcc/testsuite/g++.dg/opt/pr51895.C 2012-01-19 13:21:10.042655293 +0100 @@ -0,0 +1,25 @@ +// PR middle-end/51895 +// { dg-do compile } +// { dg-options "-O2" } + +struct S +{ + long a; + char b; + S () : a (0), b (0) {} + bool baz (); +}; + +__attribute__((noinline)) static bool +bar (S x, S y) +{ + y = x; + return y.baz (); +} + +bool +foo (S x) +{ + S y; + return bar (x, y); +}