Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 203572)
+++ gcc/doc/invoke.texi	(working copy)
@@ -260,7 +260,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wno-multichar  -Wnonnull  -Wno-overflow @gol
 -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
 -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
--Wpointer-arith  -Wno-pointer-to-int-cast @gol
+-Wpointer-arith  -Wno-pointer-to-int-cast  -Wportable-volatility @gol
 -Wredundant-decls  -Wno-return-local-addr @gol
 -Wreturn-type  -Wsequence-point  -Wshadow @gol
 -Wsign-compare  -Wsign-conversion  -Wsizeof-pointer-memaccess @gol
@@ -4911,6 +4911,18 @@ an error. @option{Wint-to-pointer-cast} is enabled
 Suppress warnings from casts from a pointer to an integer type of a
 different size.
 
+@item -Wportable-volatility
+@opindex Wportable-volatility
+@opindex Wno-portable-volatility
+Warn about code that accesses volatile structure members for
+which different ABI specifications may exist whether in some
+language standard or in a target-specific ABI document.
+
+In particular, this option causes GCC to warn about volatile memory
+accesses for which use of the @option{-fstrict-volatile-bitfields}
+option causes code to be generated that does not conform to the
+C11/C++11 memory model.
+
 @item -Winvalid-pch
 @opindex Winvalid-pch
 @opindex Wno-invalid-pch
@@ -21704,6 +21716,10 @@ the one being updated.
 The default value of this option is determined by the application binary
 interface for the target processor.
 
+You can use @option{-Wportable-volatility} to make GCC issue warnings
+about volatile structure accesses affected by
+@option{-fstrict-volatile-bitfields}.
+
 @item -fsync-libcalls
 @opindex fsync-libcalls
 This option controls whether any out-of-line instance of the @code{__sync}
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 203572)
+++ gcc/c-family/c.opt	(working copy)
@@ -637,6 +637,10 @@ Wpointer-to-int-cast
 C ObjC Var(warn_pointer_to_int_cast) Init(1) Warning
 Warn when a pointer is cast to an integer of a different size
 
+Wportable-volatility
+C ObjC C++ ObjC++ Var(warn_portable_volatility) Warning
+Warn about potentially nonportable volatile memory accesses
+
 Wpragmas
 C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
 Warn about misuses of pragmas
Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 203572)
+++ gcc/expr.h	(working copy)
@@ -730,7 +730,10 @@ extern tree build_libfunc_function (const char *);
 /* Get the personality libfunc for a function decl.  */
 rtx get_personality_function (tree);
 
+/* Optionally emit a warning for unportable volatile structure accesses.  */
+void check_portable_volatility (tree, HOST_WIDE_INT, HOST_WIDE_INT);
 
+
 /* In stmt.c */
 
 /* Expand a GIMPLE_SWITCH statement.  */
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 203572)
+++ gcc/expr.c	(working copy)
@@ -4634,6 +4634,48 @@ addr_expr_of_non_mem_decl_p (tree op)
   return addr_expr_of_non_mem_decl_p_1 (op, true);
 }
 
+/* Warn about code that accesses volatile structure members for
+   which different ABI specifications may exist whether in some
+   language standard or in a target-specific ABI document.
+   There may be even cases where the code generation is different
+   depending on the used compile flags.
+   At present this function only covers -fstrict-volatile-bitfields.
+   EXP, BITSIZE, BITNUM refer to the bit-field.  */
+
+void
+check_portable_volatility (tree exp,
+			   HOST_WIDE_INT bitsize,
+			   HOST_WIDE_INT bitnum)
+{
+  HOST_WIDE_INT modesize = 0;
+
+  /* -Wportable-volatility must be enabled.  */
+  if (warn_portable_volatility == 0)
+    return;
+
+  /* Get the bit size of the declaration type of the bit-field.  */
+  if (TREE_CODE (exp) == COMPONENT_REF)
+  {
+    tree field = TREE_OPERAND (exp, 1);
+    if (DECL_BIT_FIELD_TYPE (field))
+      modesize = GET_MODE_BITSIZE (TYPE_MODE (DECL_BIT_FIELD_TYPE (field)));
+  }
+
+  /* The bit size must not be larger than the field mode, and
+     the field mode must not be larger than a word.  */
+  if (bitsize <= 0 || bitsize > modesize || modesize > BITS_PER_WORD)
+    return;
+
+  /* Check for cases of unaligned fields that must be split.  */
+  if (bitnum % BITS_PER_UNIT + bitsize > modesize)
+    return;
+
+  warning_at (input_location, OPT_Wportable_volatility,
+	      "access to volatile member may not conform to the C11/C++11"
+	      " memory model if -fstrict-volatile-bitfields is in effect");
+  return;
+}
+
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
    is true, try generating a nontemporal store.  */
 
@@ -4714,6 +4756,9 @@ expand_assignment (tree to, tree from, bool nontem
       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
 				 &unsignedp, &volatilep, true);
 
+      if (volatilep)
+	  check_portable_volatility (to, bitsize, bitpos);
+
       if (TREE_CODE (to) == COMPONENT_REF
 	  && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
 	get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
@@ -9867,6 +9912,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	rtx orig_op0, memloc;
 	bool mem_attrs_from_type = false;
 
+	if (volatilep)
+	  check_portable_volatility (exp, bitsize, bitpos);
+
 	/* If we got back the original object, something is wrong.  Perhaps
 	   we are evaluating an expression too early.  In any event, don't
 	   infinitely recurse.  */
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 203572)
+++ gcc/fold-const.c	(working copy)
@@ -3503,16 +3503,11 @@ optimize_bit_field_compare (location_t loc, enum t
 
   /* See if we can find a mode to refer to this field.  We should be able to,
      but fail if we can't.  */
-  if (lvolatilep
-      && GET_MODE_BITSIZE (lmode) > 0
-      && flag_strict_volatile_bitfields > 0)
-    nmode = lmode;
-  else
-    nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
-			   const_p ? TYPE_ALIGN (TREE_TYPE (linner))
-			   : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
-				  TYPE_ALIGN (TREE_TYPE (rinner))),
-			   word_mode, lvolatilep || rvolatilep);
+  nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
+			 const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+			 : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+				TYPE_ALIGN (TREE_TYPE (rinner))),
+			 word_mode, lvolatilep || rvolatilep);
   if (nmode == VOIDmode)
     return 0;
 
@@ -3526,10 +3521,20 @@ optimize_bit_field_compare (location_t loc, enum t
      won't optimize anything, so return zero.  */
   nbitsize = GET_MODE_BITSIZE (nmode);
   nbitpos = lbitpos & ~ (nbitsize - 1);
-  lbitpos -= nbitpos;
   if (nbitsize == lbitsize)
     return 0;
 
+  /* At this point the COMPONENT_REF will be replaced by a BIT_FIELD_REF which
+     does no longer have the necessary information for the portable volatility
+     warning.  So, emit the warning now or never.  */
+  if (lvolatilep)
+    check_portable_volatility (lhs, lbitsize, lbitpos);
+
+  if (rvolatilep)
+    check_portable_volatility (rhs, lbitsize, lbitpos);
+
+  lbitpos -= nbitpos;
+
   if (BYTES_BIG_ENDIAN)
     lbitpos = nbitsize - lbitsize - lbitpos;
 
Index: gcc/testsuite/c-c++-common/Wportable-volatility-1.c
===================================================================
--- gcc/testsuite/c-c++-common/Wportable-volatility-1.c	(revision 0)
+++ gcc/testsuite/c-c++-common/Wportable-volatility-1.c	(revision 0)
@@ -0,0 +1,92 @@
+/* { dg-do compile } */
+/* { dg-options "-Wportable-volatility -fno-strict-volatile-bitfields" } */
+
+struct s1
+{
+  int a:2;
+  int b:14;
+  int c:16;
+  int :0;
+  int d:8;
+  int e:16;
+};
+
+volatile struct s1 v;
+
+int
+f1 (void)
+{
+  v.a = 1; /* { dg-warning "volatility" } */
+  if (v.a == 1) /* { dg-warning "volatility" } */
+    return v.a; /* { dg-warning "volatility" } */
+  v.b = 2; /* { dg-warning "volatility" } */
+  if (v.b == 2) /* { dg-warning "volatility" } */
+    return v.b; /* { dg-warning "volatility" } */
+  v.c = 3; /* { dg-warning "volatility" } */
+  if (v.c == 3) /* { dg-warning "volatility" } */
+    return v.c; /* { dg-warning "volatility" } */
+  v.d = 4; /* { dg-warning "volatility" } */
+  if (v.d == 4) /* { dg-warning "volatility" } */
+    return v.d; /* { dg-warning "volatility" } */
+  v.e = 5; /* { dg-warning "volatility" } */
+  if (v.e == 5) /* { dg-warning "volatility" } */
+    return v.e; /* { dg-warning "volatility" } */
+  return 0 == v.a; /* { dg-warning "volatility" } */
+}
+
+struct s1 n;
+volatile int i;
+
+int
+f2 (void)
+{
+  n.a = i;
+  if (n.a == i)
+    return n.a;
+  n.b = i;
+  if (n.b == i)
+    return n.b;
+  n.c = i;
+  if (n.c == i)
+    return n.c;
+  n.d = i;
+  if (n.d == i)
+    return n.d;
+  n.e = i;
+  if (n.e == i)
+    return n.e;
+  return 0 == n.a;
+}
+
+struct s2
+{
+  volatile char a;
+  volatile int b:8;
+  int c:16;
+  int :0;
+  volatile int d:4;
+  int e:4;
+};
+
+struct s2 x;
+
+int
+f3 (void)
+{
+  x.a = 1;
+  if (x.a == 1)
+    return x.a;
+  x.b = 2; /* { dg-warning "volatility" } */
+  if (x.b == 2) /* { dg-warning "volatility" } */
+    return x.b; /* { dg-warning "volatility" } */
+  x.c = i;
+  if (x.c == i)
+    return x.c;
+  x.d = 4; /* { dg-warning "volatility" } */
+  if (x.d == 4) /* { dg-warning "volatility" } */
+    return x.d; /* { dg-warning "volatility" } */
+  x.e = i;
+  if (x.e == i)
+    return x.e;
+  return 0 == x.a;
+}
Index: gcc/testsuite/c-c++-common/Wportable-volatility-2.c
===================================================================
--- gcc/testsuite/c-c++-common/Wportable-volatility-2.c	(revision 0)
+++ gcc/testsuite/c-c++-common/Wportable-volatility-2.c	(revision 0)
@@ -0,0 +1,92 @@
+/* { dg-do compile } */
+/* { dg-options "-Wportable-volatility -fstrict-volatile-bitfields" } */
+
+struct s1
+{
+  int a:2;
+  int b:14;
+  int c:16;
+  int :0;
+  int d:8;
+  int e:16;
+};
+
+volatile struct s1 v;
+
+int
+f1 (void)
+{
+  v.a = 1; /* { dg-warning "volatility" } */
+  if (v.a == 1) /* { dg-warning "volatility" } */
+    return v.a; /* { dg-warning "volatility" } */
+  v.b = 2; /* { dg-warning "volatility" } */
+  if (v.b == 2) /* { dg-warning "volatility" } */
+    return v.b; /* { dg-warning "volatility" } */
+  v.c = 3; /* { dg-warning "volatility" } */
+  if (v.c == 3) /* { dg-warning "volatility" } */
+    return v.c; /* { dg-warning "volatility" } */
+  v.d = 4; /* { dg-warning "volatility" } */
+  if (v.d == 4) /* { dg-warning "volatility" } */
+    return v.d; /* { dg-warning "volatility" } */
+  v.e = 5; /* { dg-warning "volatility" } */
+  if (v.e == 5) /* { dg-warning "volatility" } */
+    return v.e; /* { dg-warning "volatility" } */
+  return 0 == v.a; /* { dg-warning "volatility" } */
+}
+
+struct s1 n;
+volatile int i;
+
+int
+f2 (void)
+{
+  n.a = i;
+  if (n.a == i)
+    return n.a;
+  n.b = i;
+  if (n.b == i)
+    return n.b;
+  n.c = i;
+  if (n.c == i)
+    return n.c;
+  n.d = i;
+  if (n.d == i)
+    return n.d;
+  n.e = i;
+  if (n.e == i)
+    return n.e;
+  return 0 == n.a;
+}
+
+struct s2
+{
+  volatile char a;
+  volatile int b:8;
+  int c:16;
+  int :0;
+  volatile int d:4;
+  int e:4;
+};
+
+struct s2 x;
+
+int
+f3 (void)
+{
+  x.a = 1;
+  if (x.a == 1)
+    return x.a;
+  x.b = 2; /* { dg-warning "volatility" } */
+  if (x.b == 2) /* { dg-warning "volatility" } */
+    return x.b; /* { dg-warning "volatility" } */
+  x.c = i;
+  if (x.c == i)
+    return x.c;
+  x.d = 4; /* { dg-warning "volatility" } */
+  if (x.d == 4) /* { dg-warning "volatility" } */
+    return x.d; /* { dg-warning "volatility" } */
+  x.e = i;
+  if (x.e == i)
+    return x.e;
+  return 0 == x.a;
+}
