Blob Blame History Raw
2012-01-19  Jakub Jelinek  <jakub@redhat.com>

	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);
+}