--- gcc/expr.c	2013-07-13 08:18:40.000000000 +0200
+++ gcc/expr.c	2013-07-20 04:12:26.000000000 +0200
@@ -4616,6 +4616,49 @@ addr_expr_of_non_mem_decl_p (tree op)
   return addr_expr_of_non_mem_decl_p_1 (op, true);
 }
 
+/* Warn about code which accesses volatile bit-fields
+   which may be dependent on whether -fstrict-volatile-bitfields
+   is used or not.
+   OP0, EXP, BITSIZE, BITNUM refer to the bit-field.  */
+
+static void
+warn_portable_volatility_p (rtx op0, tree exp,
+			    unsigned HOST_WIDE_INT bitsize,
+			    unsigned HOST_WIDE_INT bitnum)
+{
+  unsigned HOST_WIDE_INT modesize = 0;
+
+  /* -Wportable-volatility must be enabled and we must have a volatile MEM.  */
+  if (!MEM_P (op0)
+      || !MEM_VOLATILE_P (op0)
+      || 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 (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 > 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,
+	      "the code to accesses this volatile member is dependent on"
+	      " whether -fstrict-volatile-bitfields is used;"
+	      " accessing device registers may depend on this option"
+	      " however it contradicts the C11/C++11 memory model");
+  return;
+}
+
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
    is true, try generating a nontemporal store.  */
 
@@ -4862,6 +4905,8 @@ expand_assignment (tree to, tree from, b
 		MEM_VOLATILE_P (to_rtx) = 1;
 	    }
 
+	  warn_portable_volatility_p (to_rtx, to, bitsize, bitpos);
+
 	  if (optimize_bitfield_assignment_op (bitsize, bitpos,
 					       bitregion_start, bitregion_end,
 					       mode1,
@@ -10025,6 +10070,8 @@ expand_expr_real_1 (tree exp, rtx target
 	    MEM_VOLATILE_P (op0) = 1;
 	  }
 
+	warn_portable_volatility_p (op0, exp, bitsize, bitpos);
+
 	/* In cases where an aligned union has an unaligned object
 	   as a field, we might be extracting a BLKmode value from
 	   an integer-mode (e.g., SImode) object.  Handle this case
--- gcc/fold-const.c	2013-07-06 11:34:17.000000000 +0200
+++ gcc/fold-const.c	2013-07-20 05:32:45.000000000 +0200
@@ -3470,6 +3470,11 @@ optimize_bit_field_compare (location_t l
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
     return 0;
 
+  /* If the COMPONENT_REF is replaced by a BIT_FIELD_REF the warning can
+     not be generated correctly.  Do not try to optimize on volatiles.  */
+  if (warn_portable_volatility && lvolatilep)
+    return 0;
+
  if (!const_p)
    {
      /* If this is not a constant, we can only do something if bit positions,
@@ -3481,6 +3486,11 @@ optimize_bit_field_compare (location_t l
 	 || lunsignedp != runsignedp || offset != 0
 	 || TREE_CODE (rinner) == PLACEHOLDER_EXPR)
        return 0;
+
+     /* If the COMPONENT_REF is replaced by a BIT_FIELD_REF the warning can
+        not be generated correctly.  Do not try to optimize on volatiles.  */
+     if (warn_portable_volatility && rvolatilep)
+       return 0;
    }
 
   /* See if we can find a mode to refer to this field.  We should be able to,
--- gcc/stor-layout.c	2013-05-10 13:15:14.000000000 +0200
+++ gcc/stor-layout.c	2013-07-20 01:27:13.000000000 +0200
@@ -613,7 +613,8 @@ layout_decl (tree decl, unsigned int kno
 	  if (TYPE_SIZE (type) != 0
 	      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 	      && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
-	      && flag_strict_volatile_bitfields <= 0)
+	      && flag_strict_volatile_bitfields <= 0
+	      && warn_portable_volatility == 0)
 	    {
 	      enum machine_mode xmode
 		= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
--- gcc/c-family/c.opt	2013-05-28 21:55:10.000000000 +0200
+++ gcc/c-family/c.opt	2013-07-13 11:02:38.000000000 +0200
@@ -629,6 +629,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 code for which separate incompatible definitions exist even within gcc
+
 Wpragmas
 C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
 Warn about misuses of pragmas
--- gcc/doc/invoke.texi	2013-07-13 08:19:28.000000000 +0200
+++ gcc/doc/invoke.texi	2013-07-17 20:26:08.000000000 +0200
@@ -258,7 +258,7 @@
 -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
@@ -4817,6 +4817,23 @@
 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 which accesses volatile structure members for
+which different ABI specifications may exist whether in some
+language standard or in a target-specific ABI document.
+
+For instance on the ARM architecture AAPCS specifies how to
+access volatile bit-fields. But for C/C++ there exists a
+language standard, the C11/C++11 memory model. GCC tries to
+follow the latter by default unless -fstrict-volatile-bitfields
+is used.
+
+As an example this option will warn about code which accesses
+packed volatile structure members which may be dependent on
+whether -fstrict-volatile-bitfields is used or not.
+
 @item -Winvalid-pch
 @opindex Winvalid-pch
 @opindex Wno-invalid-pch
--- gcc/testsuite/c-c++-common/Wportable-volatility-1.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/c-c++-common/Wportable-volatility-1.c	2013-07-20 19:29:00.000000000 +0200
@@ -0,0 +1,91 @@
+/* { 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;
+
+int
+f2 (void)
+{
+  n.a = 1;
+  if (n.a == 1)
+    return n.a;
+  n.b = 2;
+  if (n.b == 2)
+    return n.b;
+  n.c = 3;
+  if (n.c == 3)
+    return n.c;
+  n.d = 4;
+  if (n.d == 4)
+    return n.d;
+  n.e = 5;
+  if (n.e == 5)
+    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 = 3;
+  if (x.c == 3)
+    return x.c;
+  x.d = 4; /* { dg-warning "volatility" } */
+  if (x.d == 4) /* { dg-warning "volatility" } */
+    return x.d; /* { dg-warning "volatility" } */
+  x.e = 5;
+  if (x.e == 5)
+    return x.e;
+  return 0 == x.a;
+}
--- gcc/testsuite/c-c++-common/Wportable-volatility-2.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/c-c++-common/Wportable-volatility-2.c	2013-07-20 19:30:33.000000000 +0200
@@ -0,0 +1,91 @@
+/* { 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;
+
+int
+f2 (void)
+{
+  n.a = 1;
+  if (n.a == 1)
+    return n.a;
+  n.b = 2;
+  if (n.b == 2)
+    return n.b;
+  n.c = 3;
+  if (n.c == 3)
+    return n.c;
+  n.d = 4;
+  if (n.d == 4)
+    return n.d;
+  n.e = 5;
+  if (n.e == 5)
+    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 = 3;
+  if (x.c == 3)
+    return x.c;
+  x.d = 4; /* { dg-warning "volatility" } */
+  if (x.d == 4) /* { dg-warning "volatility" } */
+    return x.d; /* { dg-warning "volatility" } */
+  x.e = 5;
+  if (x.e == 5)
+    return x.e;
+  return 0 == x.a;
+}
