re PR c/2511 (-pedantic not warning about bitfield overflow)
authorJoseph Myers <jsm@polyomino.org.uk>
Thu, 8 Jul 2004 08:45:05 +0000 (09:45 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Thu, 8 Jul 2004 08:45:05 +0000 (09:45 +0100)
2004-07-08  Joseph S. Myers  <jsm@polyomino.org.uk>
            Neil Booth  <neil@daikokuya.co.uk>

PR c/2511
PR c/3325
* c-decl.c (finish_struct): Ensure bit-fields are given the
correct type.
* c-common.c (c_common_signed_or_unsigned_type): For C, require
the precision to match as well as the mode.
* expr.c (reduce_to_bit_field_precision): New function.
(expand_expr_real_1): Reduce expressions of bit-field type to
proper precision.
* langhooks.h (reduce_bit_field_operations): New hook.
* langhooks-def.h (LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS):
Define.
* c-lang.c, objc/objc-lang.c
(LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS): Define.
* objc/objc-act.c (check_ivars): Convert types to bit-field types
before checking.
* tree.c (build_nonstandard_integer_type): New function.
* tree.h (build_nonstandard_integer_type): New prototype.
* tree-ssa.c (tree_ssa_useless_type_conversion_1): Don't treat
conversions between integer and boolean types as useless.

testsuite:
* gcc.c-torture/execute/bitfld-1.x: Remove.
* gcc.c-torture/execute/bitfld-3.c: New test.
* gcc.dg/bitfld-2.c: Remove XFAILs.

Co-Authored-By: Neil Booth <neil@daikokuya.co.uk>
From-SVN: r84279

16 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-decl.c
gcc/c-lang.c
gcc/expr.c
gcc/langhooks-def.h
gcc/langhooks.h
gcc/objc/objc-act.c
gcc/objc/objc-lang.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/bitfld-1.x [deleted file]
gcc/testsuite/gcc.c-torture/execute/bitfld-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/bitfld-2.c
gcc/tree-ssa.c
gcc/tree.c
gcc/tree.h

index b6b96781d2fda74a03780214ac93650609b3e659..fa0aefcc4695edc05ddadcc4f33f993eb7eec2de 100644 (file)
@@ -1,3 +1,27 @@
+2004-07-08  Joseph S. Myers  <jsm@polyomino.org.uk>
+            Neil Booth  <neil@daikokuya.co.uk>
+
+       PR c/2511
+       PR c/3325
+       * c-decl.c (finish_struct): Ensure bit-fields are given the
+       correct type.
+       * c-common.c (c_common_signed_or_unsigned_type): For C, require
+       the precision to match as well as the mode.
+       * expr.c (reduce_to_bit_field_precision): New function.
+       (expand_expr_real_1): Reduce expressions of bit-field type to
+       proper precision.
+       * langhooks.h (reduce_bit_field_operations): New hook.
+       * langhooks-def.h (LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS):
+       Define.
+       * c-lang.c, objc/objc-lang.c
+       (LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS): Define.
+       * objc/objc-act.c (check_ivars): Convert types to bit-field types
+       before checking.
+       * tree.c (build_nonstandard_integer_type): New function.
+       * tree.h (build_nonstandard_integer_type): New prototype.
+       * tree-ssa.c (tree_ssa_useless_type_conversion_1): Don't treat
+       conversions between integer and boolean types as useless.
+
 2004-07-08  Paolo Bonzini  <bonzini@gnu.org>
 
        * c-common.c (c_common_nodes_and_builtins): Do not
index 9a8039b943144daad410e839322965449762dfc7..ebb5e65e404a0aa1fba3b85e8fcddf8ef3e7befb 100644 (file)
@@ -1636,40 +1636,51 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
       || TYPE_UNSIGNED (type) == unsignedp)
     return type;
 
-  /* Must check the mode of the types, not the precision.  Enumeral types
-     in C++ have precision set to match their range, but may use a wider
-     mode to match an ABI.  If we change modes, we may wind up with bad
-     conversions.  */
-
-  if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
+  /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
+     the precision; they have precision set to match their range, but
+     may use a wider mode to match an ABI.  If we change modes, we may
+     wind up with bad conversions.  For INTEGER_TYPEs in C, must check
+     the precision as well, so as to yield correct results for
+     bit-field types.  C++ does not have these separate bit-field
+     types, and producing a signed or unsigned variant of an
+     ENUMERAL_TYPE may cause other problems as well.  */
+
+#define TYPE_OK(node)                                                      \
+  (TYPE_MODE (type) == TYPE_MODE (node)                                            \
+   && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+  if (TYPE_OK (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
+  if (TYPE_OK (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
+  if (TYPE_OK (short_integer_type_node))
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
+  if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
+  if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
            : long_long_integer_type_node);
-  if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
+  if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
            : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
-  if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
+  if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
-  if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
+  if (TYPE_OK (intDI_type_node))
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
+  if (TYPE_OK (intSI_type_node))
     return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
+  if (TYPE_OK (intHI_type_node))
     return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
-  if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
+  if (TYPE_OK (intQI_type_node))
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+#undef TYPE_OK
 
-  return type;
+  if (c_dialect_cxx ())
+    return type;
+  else
+    return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
index 3f6be35d91a7eb6b4efa09685f7b67d2f9e243a8..2a236aa51cf3c993f9339e59ec13e4b9e3e61e7c 100644 (file)
@@ -5162,9 +5162,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes,m which is found in the DECL_INITIAL.
-     Store 0 there, except for ": 0" fields (so we can find them
-     and delete them, below).  */
+     Also process specified field sizes, found in the DECL_INITIAL,
+     storing 0 there after the type has been changed to precision equal
+     to its width, rather than the precision of the specified standard
+     type.  (Correct layout requires the original type to have been preserved
+     until now.)  */
 
   saw_named_field = 0;
   for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5208,8 +5210,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          SET_DECL_C_BIT_FIELD (x);
        }
 
-      DECL_INITIAL (x) = 0;
-
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -5250,12 +5250,21 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
   layout_type (t);
 
-  /* Delete all zero-width bit-fields from the fieldlist.  */
+  /* Give bit-fields their proper types.  */
   {
     tree *fieldlistp = &fieldlist;
     while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
-       *fieldlistp = TREE_CHAIN (*fieldlistp);
+      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+         && TREE_TYPE (*fieldlistp) != error_mark_node)
+       {
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+         tree type = TREE_TYPE (*fieldlistp);
+         if (width != TYPE_PRECISION (type))
+           TREE_TYPE (*fieldlistp)
+             = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+         DECL_INITIAL (*fieldlistp) = 0;
+       }
       else
        fieldlistp = &TREE_CHAIN (*fieldlistp);
   }
index f58a89905876ecbd575c168c3dbde7cfb63eb597..8166698f7e742f1e4a04e216767b39c64c09a4ff 100644 (file)
@@ -74,6 +74,8 @@ enum c_language_kind c_language = clk_c;
 #define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
 #undef LANG_HOOKS_UNSAFE_FOR_REEVAL
 #define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
+#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
+#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
 #undef LANG_HOOKS_STATICP
 #define LANG_HOOKS_STATICP c_staticp
 #undef LANG_HOOKS_NO_BODY_BLOCKS
index b2e25c751148df132867d23112490bb47e0b4fba..3be412dd56f09ac00f81fd1603b48e6ba7c429b6 100644 (file)
@@ -154,6 +154,7 @@ static int is_aligning_offset (tree, tree);
 static rtx expand_increment (tree, int, int);
 static void expand_operands (tree, tree, rtx, rtx*, rtx*,
                             enum expand_modifier);
+static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
 static rtx do_store_flag (tree, rtx, enum machine_mode, int);
 #ifdef PUSH_ROUNDING
 static void emit_single_push_insn (enum machine_mode, rtx, tree);
@@ -6430,9 +6431,26 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
   rtx subtarget, original_target;
   int ignore;
   tree context;
+  bool reduce_bit_field = false;
+#define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore              \
+                                ? reduce_to_bit_field_precision ((expr), \
+                                                                 target, \
+                                                                 type)   \
+                                : (expr))
 
   mode = TYPE_MODE (type);
   unsignedp = TYPE_UNSIGNED (type);
+  if (lang_hooks.reduce_bit_field_operations
+      && TREE_CODE (type) == INTEGER_TYPE
+      && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type))
+    {
+      /* An operation in what may be a bit-field type needs the
+        result to be reduced to the precision of the bit-field type,
+        which is narrower than that of the type's mode.  */
+      reduce_bit_field = true;
+      if (modifier == EXPAND_STACK_PARM)
+       target = 0;
+    }
 
   /* Use subtarget as the target for operand 0 of a binary operation.  */
   subtarget = get_subtarget (target);
@@ -7423,10 +7441,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              && GET_CODE (op0) == SUBREG)
            SUBREG_PROMOTED_VAR_P (op0) = 0;
 
-         return op0;
+         return REDUCE_BIT_FIELD (op0);
        }
 
       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
+      op0 = REDUCE_BIT_FIELD (op0);
       if (GET_MODE (op0) == mode)
        return op0;
 
@@ -7594,7 +7613,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              op1 = plus_constant (op1, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op1 = force_operand (op1, target);
-             return op1;
+             return REDUCE_BIT_FIELD (op1);
            }
 
          else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
@@ -7627,7 +7646,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              op0 = plus_constant (op0, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op0 = force_operand (op0, target);
-             return op0;
+             return REDUCE_BIT_FIELD (op0);
            }
        }
 
@@ -7649,7 +7668,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
                       subtarget, &op0, &op1, modifier);
-      return simplify_gen_binary (PLUS, mode, op0, op1);
+      return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
 
     case MINUS_EXPR:
       /* For initializers, we are allowed to return a MINUS of two
@@ -7667,9 +7686,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          /* If the last operand is a CONST_INT, use plus_constant of
             the negated constant.  Else make the MINUS.  */
          if (GET_CODE (op1) == CONST_INT)
-           return plus_constant (op0, - INTVAL (op1));
+           return REDUCE_BIT_FIELD (plus_constant (op0, - INTVAL (op1)));
          else
-           return gen_rtx_MINUS (mode, op0, op1);
+           return REDUCE_BIT_FIELD (gen_rtx_MINUS (mode, op0, op1));
        }
 
       this_optab = ! unsignedp && flag_trapv
@@ -7691,7 +7710,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (GET_CODE (op1) == CONST_INT)
        {
          op1 = negate_rtx (mode, op1);
-         return simplify_gen_binary (PLUS, mode, op0, op1);
+         return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
        }
 
       goto binop2;
@@ -7723,9 +7742,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          if (!REG_P (op0))
            op0 = copy_to_mode_reg (mode, op0);
 
-         return gen_rtx_MULT (mode, op0,
+         return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
                               gen_int_mode (tree_low_cst (exp1, 0),
-                                            TYPE_MODE (TREE_TYPE (exp1))));
+                                            TYPE_MODE (TREE_TYPE (exp1)))));
        }
 
       if (modifier == EXPAND_STACK_PARM)
@@ -7803,13 +7822,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                                                      zextend_p);
                  if (htem != hipart)
                    emit_move_insn (hipart, htem);
-                 return temp;
+                 return REDUCE_BIT_FIELD (temp);
                }
            }
        }
       expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
                       subtarget, &op0, &op1, 0);
-      return expand_mult (mode, op0, op1, target, unsignedp);
+      return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
 
     case TRUNC_DIV_EXPR:
     case FLOOR_DIV_EXPR:
@@ -7885,7 +7904,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                          ? negv_optab : neg_optab, op0, target, 0);
       if (temp == 0)
        abort ();
-      return temp;
+      return REDUCE_BIT_FIELD (temp);
 
     case ABS_EXPR:
       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
@@ -8550,12 +8569,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
-      return expand_increment (exp, 0, ignore);
+      return REDUCE_BIT_FIELD (expand_increment (exp, 0, ignore));
 
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
       /* Faster to treat as pre-increment if result is not used.  */
-      return expand_increment (exp, ! ignore, ignore);
+      return REDUCE_BIT_FIELD (expand_increment (exp, ! ignore, ignore));
 
     case ADDR_EXPR:
       if (modifier == EXPAND_STACK_PARM)
@@ -8915,7 +8934,37 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                       unsignedp, OPTAB_LIB_WIDEN);
   if (temp == 0)
     abort ();
-  return temp;
+  return REDUCE_BIT_FIELD (temp);
+}
+#undef REDUCE_BIT_FIELD
+\f
+/* Subroutine of above: reduce EXP to the precision of TYPE (in the
+   signedness of TYPE), possibly returning the result in TARGET.  */
+static rtx
+reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
+{
+  HOST_WIDE_INT prec = TYPE_PRECISION (type);
+  if (target && GET_MODE (target) != GET_MODE (exp))
+    target = 0;
+  if (TYPE_UNSIGNED (type))
+    {
+      rtx mask;
+      if (prec < HOST_BITS_PER_WIDE_INT)
+       mask = immed_double_const (((unsigned HOST_WIDE_INT) 1 << prec) - 1, 0,
+                                  GET_MODE (exp));
+      else
+       mask = immed_double_const ((unsigned HOST_WIDE_INT) -1,
+                                  ((unsigned HOST_WIDE_INT) 1
+                                   << (prec - HOST_BITS_PER_WIDE_INT)) - 1,
+                                  GET_MODE (exp));
+      return expand_and (GET_MODE (exp), exp, mask, target);
+    }
+  else
+    {
+      tree count = build_int_2 (GET_MODE_BITSIZE (GET_MODE (exp)) - prec, 0);
+      exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
+      return expand_shift (RSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
+    }
 }
 \f
 /* Subroutine of above: returns 1 if OFFSET corresponds to an offset that
index 1cd44f5565eb2c90c1ec6be76eb7156367efcbb0..85c77e585f184bc2b22e30c33e207630f7ddd4aa 100644 (file)
@@ -116,6 +116,7 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
 #define LANG_HOOKS_MAYBE_BUILD_CLEANUP lhd_return_null_tree
 #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name
 #define LANG_HOOKS_CAN_USE_BIT_FIELDS_P lhd_can_use_bit_fields_p
+#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS false
 #define LANG_HOOKS_HONOR_READONLY      false
 #define LANG_HOOKS_NO_BODY_BLOCKS      false
 #define LANG_HOOKS_PRINT_STATISTICS    lhd_do_nothing
@@ -294,6 +295,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_MAYBE_BUILD_CLEANUP, \
   LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, \
   LANG_HOOKS_CAN_USE_BIT_FIELDS_P, \
+  LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS, \
   LANG_HOOKS_HONOR_READONLY, \
   LANG_HOOKS_NO_BODY_BLOCKS, \
   LANG_HOOKS_PRINT_STATISTICS, \
index fb36a144b84b2b36e79121e31ea1f54076dcd6ed..4400aa3dc6f53d33a9348ea110384e5cd74c212b 100644 (file)
@@ -347,6 +347,10 @@ struct lang_hooks
      optimizations, for instance in fold_truthop().  */
   bool (*can_use_bit_fields_p) (void);
 
+  /* Nonzero if operations on types narrower than their mode should
+     have their results reduced to the precision of the type.  */
+  bool reduce_bit_field_operations;
+
   /* Nonzero if TYPE_READONLY and TREE_READONLY should always be honored.  */
   bool honor_readonly;
 
index 4526e1845ce0cc1a5af9d1173bd0d1871dbaf103..308f2aca988b7f3893266bb3511e6ce59a817538 100644 (file)
@@ -4257,6 +4257,16 @@ check_ivars (tree inter, tree imp)
 
       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
 
+      if (TREE_VALUE (TREE_VALUE (rawimpdecls)))
+       {
+         /* t1 is the bit-field type, so t2 must be converted to the
+            bit-field type for comparison as well.  */
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (TREE_VALUE (TREE_VALUE (rawimpdecls)), 1);
+         if (width != TYPE_PRECISION (t2))
+           t2 = build_nonstandard_integer_type (width, TYPE_UNSIGNED (t2));
+       }
+
       if (!comptypes (t1, t2)
          || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
                                  TREE_VALUE (TREE_VALUE (rawimpdecls))))
index fde6cbd0907385f919a13be6f1f9163d44176d20..c5d099b63d3d34d89675e449fc8801c9ae237be2 100644 (file)
@@ -71,6 +71,8 @@ enum c_language_kind c_language = clk_objc;
 #define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
 #undef LANG_HOOKS_UNSAFE_FOR_REEVAL
 #define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
+#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
+#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
 #undef LANG_HOOKS_STATICP
 #define LANG_HOOKS_STATICP c_staticp
 #undef LANG_HOOKS_NO_BODY_BLOCKS
index 244498efc224381208b3fdf58ebced625be686c0..54be7f9605d4f0ff3efef45ab0a90bbeccb184a7 100644 (file)
@@ -1,3 +1,9 @@
+2004-07-08  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * gcc.c-torture/execute/bitfld-1.x: Remove.
+       * gcc.c-torture/execute/bitfld-3.c: New test.
+       * gcc.dg/bitfld-2.c: Remove XFAILs.
+
 2004-07-07  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR c++/16276
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-1.x b/gcc/testsuite/gcc.c-torture/execute/bitfld-1.x
deleted file mode 100644 (file)
index 2f397b9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-set torture_execute_xfail "*-*-*"
-return 0
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-3.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-3.c
new file mode 100644 (file)
index 0000000..52a4147
--- /dev/null
@@ -0,0 +1,54 @@
+/* Test that operations on bit-fields yield results reduced to bit-field
+   type.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+
+extern void exit (int);
+extern void abort (void);
+
+struct s {
+  unsigned long long u33: 33;
+  unsigned long long u40: 40;
+  unsigned long long u41: 41;
+};
+
+struct s a = { 0x100000, 0x100000, 0x100000 };
+struct s b = { 0x100000000ULL, 0x100000000ULL, 0x100000000ULL };
+struct s c = { 0x1FFFFFFFFULL, 0, 0 };
+
+int 
+main (void)
+{
+  if (a.u33 * a.u33 != 0 || a.u33 * a.u40 != 0 || a.u40 * a.u33 != 0
+      || a.u40 * a.u40 != 0)
+    abort ();
+  if (a.u33 * a.u41 != 0x10000000000ULL
+      || a.u40 * a.u41 != 0x10000000000ULL
+      || a.u41 * a.u33 != 0x10000000000ULL
+      || a.u41 * a.u40 != 0x10000000000ULL
+      || a.u41 * a.u41 != 0x10000000000ULL)
+    abort ();
+  if (b.u33 + b.u33 != 0)
+    abort ();
+  if (b.u33 + b.u40 != 0x200000000ULL
+      || b.u33 + b.u41 != 0x200000000ULL
+      || b.u40 + b.u33 != 0x200000000ULL
+      || b.u40 + b.u40 != 0x200000000ULL
+      || b.u40 + b.u41 != 0x200000000ULL
+      || b.u41 + b.u33 != 0x200000000ULL
+      || b.u41 + b.u40 != 0x200000000ULL
+      || b.u41 + b.u41 != 0x200000000ULL)
+    abort ();
+  if (a.u33 - b.u33 != 0x100100000ULL
+      || a.u33 - b.u40 != 0xFF00100000ULL
+      || a.u33 - b.u41 != 0x1FF00100000ULL
+      || a.u40 - b.u33 != 0xFF00100000ULL
+      || a.u40 - b.u40 != 0xFF00100000ULL
+      || a.u40 - b.u41 != 0x1FF00100000ULL
+      || a.u41 - b.u33 != 0x1FF00100000ULL
+      || a.u41 - b.u40 != 0x1FF00100000ULL
+      || a.u41 - b.u41 != 0x1FF00100000ULL)
+    abort ();
+  if (++c.u33 != 0 || --c.u40 != 0xFFFFFFFFFFULL || c.u41-- != 0)
+    abort ();
+  exit (0);
+}
index d3096a7caa8656f63161f61c4d1366b6a4bb716d..b61fec6084192271aa01d3051215ca5d550f2063 100644 (file)
@@ -11,13 +11,13 @@ struct bf
   int b: 2;
 };
 
-struct bf p = {4, 0};          /* { dg-warning "truncated" "" { xfail *-*-* } } */
-struct bf q = {0, 2};          /* { dg-warning "overflow" "" { xfail *-*-* } } */
+struct bf p = {4, 0};          /* { dg-warning "truncated" "" } */
+struct bf q = {0, 2};          /* { dg-warning "overflow" "" } */
 struct bf r = {3, -2};         /* { dg-bogus "(truncated|overflow)" } */
 
 void foo ()
 {
-  p.a = 4, p.b = 0;            /* { dg-warning "truncated" "" { xfail *-*-* } } */
-  q.a = 0, q.b = 2;            /* { dg-warning "overflow" "" { xfail *-*-* } } */
+  p.a = 4, p.b = 0;            /* { dg-warning "truncated" "" } */
+  q.a = 0, q.b = 2;            /* { dg-warning "overflow" "" } */
   r.a = 3, r.b = -2;           /* { dg-bogus "(truncated|overflow)" } */
 }
index 3ab7ac206bbf9cba7dfda1120f69f281c73a870f..ad1c1745c145626b0b91ea5e9a3ae2bdb3494e2b 100644 (file)
@@ -572,17 +572,22 @@ tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
 
   /* If both the inner and outer types are integral types, then the
      conversion is not necessary if they have the same mode and
-     signedness and precision.  Note that type _Bool can have size of
-     4 (only happens on powerpc-darwin right now but can happen on any
-     target that defines BOOL_TYPE_SIZE to be INT_TYPE_SIZE) and a
-     precision of 1 while unsigned int is the same expect for a
-     precision of 4 so testing of precision is necessary.  */
+     signedness and precision, and both or neither are boolean.  Some
+     code assumes an invariant that boolean types stay boolean and do
+     not become 1-bit bit-field types.  Note that types with precision
+     not using all bits of the mode (such as bit-field types in C)
+     mean that testing of precision is necessary.  */
   else if (INTEGRAL_TYPE_P (inner_type)
            && INTEGRAL_TYPE_P (outer_type)
           && TYPE_MODE (inner_type) == TYPE_MODE (outer_type)
           && TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type)
           && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
-    return true;
+    {
+      bool first_boolean = (TREE_CODE (inner_type) == BOOLEAN_TYPE);
+      bool second_boolean = (TREE_CODE (outer_type) == BOOLEAN_TYPE);
+      if (first_boolean == second_boolean)
+       return true;
+    }
 
   /* Recurse for complex types.  */
   else if (TREE_CODE (inner_type) == COMPLEX_TYPE
index 009888a5b21099ec2749d22625bd4545e06e62c6..3804d37cb44d7330878e81f3ca9ace04f4182511 100644 (file)
@@ -4133,6 +4133,28 @@ build_index_type (tree maxval)
     return itype;
 }
 
+/* Builds a signed or unsigned integer type of precision PRECISION.
+   Used for C bitfields whose precision does not match that of
+   built-in target types.  */
+tree
+build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
+                               int unsignedp)
+{
+  tree itype = make_node (INTEGER_TYPE);
+
+  TYPE_PRECISION (itype) = precision;
+
+  if (unsignedp)
+    fixup_unsigned_type (itype);
+  else
+    fixup_signed_type (itype);
+
+  if (host_integerp (TYPE_MAX_VALUE (itype), 1))
+    return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
+
+  return itype;
+}
+
 /* Create a range of some discrete type TYPE (an INTEGER_TYPE,
    ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
    low bound LOWVAL and high bound HIGHVAL.
index 28582dd7ec4bfc58441bc65da98fd95bb96b43f3..74cf79e6cbc436434f553450a6d91cf965474d7f 100644 (file)
@@ -3472,6 +3472,7 @@ extern int real_minus_onep (tree);
 extern void init_ttree (void);
 extern void build_common_tree_nodes (int);
 extern void build_common_tree_nodes_2 (int);
+extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
 extern tree build_range_type (tree, tree, tree);
 
 /* In function.c */