GCCのバグを直した

GCCで8bit長・16bit長のビットフィールドが正しく扱われない(STRICT_ALGINMENTな環境でもアライン無視する、volatile付けると領域破壊を起こす)問題を修正した。
BTSには投げたけれど、多分無視されるのでここにパッチを置いておく(gcc-4_6-branch/trunkにて動作確認)。

I fixed the problem around handling bit-field (GCC generates wrong code when using 8bit or 16bit width of bit-field.)
Patch is here (also posted to BTS.)

diff --git a/gcc/expr.c b/gcc/expr.c
index a4cfee0..a2823a2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4689,7 +4689,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
 	 use BLKmode for it instead.  */
       if (MEM_P (to_rtx))
 	{
-	  if (volatilep && flag_strict_volatile_bitfields > 0)
+	  if (STRICT_ALIGNMENT || (volatilep && flag_strict_volatile_bitfields > 0))
 	    to_rtx = adjust_address (to_rtx, mode1, 0);
 	  else if (GET_MODE (to_rtx) == VOIDmode)
 	    to_rtx = adjust_address (to_rtx, BLKmode, 0);
@@ -6345,7 +6345,9 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
 	 store it as a bit field.  */
       || (mode != BLKmode
 	  && ((((MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode))
-		|| bitpos % GET_MODE_ALIGNMENT (mode))
+		|| bitpos % GET_MODE_ALIGNMENT (mode)
+		|| (TREE_THIS_VOLATILE (type)
+		   && flag_strict_volatile_bitfields > 0))
 	       && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target)))
 	      || (bitpos % BITS_PER_UNIT != 0)))
       /* If the RHS and field are a constant size and the size of the
@@ -6510,8 +6512,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 	mode = DECL_MODE (field);
       else if (DECL_MODE (field) == BLKmode)
 	blkmode_bitfield = true;
-      else if (TREE_THIS_VOLATILE (exp)
-	       && flag_strict_volatile_bitfields > 0)
+      else if (STRICT_ALIGNMENT || (TREE_THIS_VOLATILE (exp)
+	       && flag_strict_volatile_bitfields > 0))
 	/* Volatile bitfields should be accessed in the mode of the
 	     field's type, not the mode computed based on the bit
 	     size.  */
@@ -9624,7 +9626,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 	   use BLKmode for it instead.  */
 	if (MEM_P (op0))
 	  {
-	    if (volatilep && flag_strict_volatile_bitfields > 0)
+	    if (STRICT_ALIGNMENT || (volatilep && flag_strict_volatile_bitfields > 0))
 	      op0 = adjust_address (op0, mode1, 0);
 	    else if (GET_MODE (op0) == VOIDmode)
 	      op0 = adjust_address (op0, BLKmode, 0);
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 359541e..7ebba2f 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -626,6 +626,7 @@ layout_decl (tree decl, unsigned int known_align)
 	  if (TYPE_SIZE (type) != 0
 	      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 	      && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+	      && !STRICT_ALIGNMENT
 	      && !(TREE_THIS_VOLATILE (decl)
 		   && flag_strict_volatile_bitfields > 0))
 	    {