Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 203898)
+++ gcc/expmed.c	(working copy)
@@ -871,6 +871,18 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_I
 		 enum machine_mode fieldmode,
 		 rtx value)
 {
+  /* Treat unaligned fields like bit regions otherwise we might
+     touch bits outside the field.  */
+  if (MEM_P (str_rtx) && bitregion_start == 0 && bitregion_end == 0
+      && bitsize > 0 && bitsize % BITS_PER_UNIT == 0
+      && bitnum % BITS_PER_UNIT == 0
+      && (bitsize % MIN (MEM_ALIGN (str_rtx), BITS_PER_WORD) > 0
+	|| bitnum % MIN (MEM_ALIGN (str_rtx), BITS_PER_WORD) > 0))
+    {
+      bitregion_start = bitnum;
+      bitregion_end = bitnum + bitsize - 1;
+    }
+
   /* Under the C++0x memory model, we must not touch bits outside the
      bit region.  Adjust the address to start at the beginning of the
      bit region.  */
--- gcc/testsuite/gcc.dg/pr56997-4.c	(working copy)
+++ gcc/testsuite/gcc.dg/pr56997-4.c	(working copy)
@@ -0,0 +1,23 @@
+/* Test volatile access to unaligned field.  */
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-volatile-bitfields -fdump-rtl-final" } */
+
+#define test_type unsigned short
+
+typedef struct s{
+ unsigned char Prefix[1];
+ volatile test_type Type;
+}__attribute((__packed__,__aligned__(4))) ss;
+
+extern volatile ss v;
+
+void
+foo (test_type u)
+{
+  v.Type = u;
+}
+
+/* The C++ memory model forbids data store race conditions outside the
+   unaligned data member, therefore only QI or HI access is allowed, no SI.  */
+/* { dg-final { scan-rtl-dump-not "mem/v(/.)*:SI" "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */
