This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Bit-field patch, part 1


The following patch is the easy part of resurrecting the bit-field
patch: moving the validation of bit-field types and widths to a
separate function.  This fixes one of the underlying bug reports (PR
c/3347, bit-fields that are too wide should be hard errors), and as it
doesn't include the part giving bit-fields their correct types it
should be less problematic than the rest of the patch.  It should also
be sufficient for RTH's patch (always warning for enum bit-fields with
-pedantic) not to require additional complexity to save the pedantic
setting.

(Neil's original patch combined checking type and width with
generating the correct type for the bit-field.  I've found it
necessary to separate these - preserving the separate width and
original type until finish_struct - to get the correct layout in
various cases.)

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

2003-12-17  Neil Booth  <neil@daikokuya.co.uk>
            Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/3347
	* c-decl.c (enum_decl_context): Remove BITFIELD.
	(grokdeclarator): Take bit-field width as an input.
	Perform bit-field width validation with
	check_bitfield_type_and_width rather than waiting for
	finish_struct.
	(groktypename, groktypename_in_parm_context, start_decl,
	push_parm_decl, grokfield, start_function): Update calls to
	grokdeclarator.
	(check_bitfield_type_and_width): New function.
	(finish_struct): Move bit-field validation to grokdeclarator
	and check_bitfield_type_and_width.

2003-12-17  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/3347
	* gcc.dg/bitfld-8.c: New test.

diff -rupN GCC.orig/gcc/c-decl.c GCC-part1/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2003-11-26 13:49:04.000000000 +0000
+++ GCC-part1/gcc/c-decl.c	2003-12-16 10:17:33.000000000 +0000
@@ -61,7 +61,6 @@ enum decl_context
   FUNCDEF,			/* Function definition */
   PARM,				/* Declaration of parm before function body */
   FIELD,			/* Declaration inside struct or union */
-  BITFIELD,			/* Likewise but with specified width */
   TYPENAME};			/* Typename (inside cast or sizeof)  */
 
 
@@ -315,7 +314,7 @@ static void bind_label (tree, tree, stru
 static void implicit_decl_warning (tree);
 static tree lookup_tag (enum tree_code, tree, int);
 static tree lookup_name_current_level (tree);
-static tree grokdeclarator (tree, tree, enum decl_context, int);
+static tree grokdeclarator (tree, tree, enum decl_context, int, tree *);
 static tree grokparms (tree, int);
 static void layout_array_type (tree);
 static void store_parm_decls_newstyle (void);
@@ -325,6 +324,7 @@ static void c_expand_body_1 (tree, int);
 static tree any_external_decl (tree);
 static void record_external_decl (tree);
 static void warn_if_shadowing (tree, tree);
+static void check_bitfield_type_and_width (tree *, tree *, const char *);
 static void clone_underlying_type (tree);
 static bool flexible_array_type_p (tree);
 static hashval_t link_hash_hash	(const void *);
@@ -2527,7 +2527,8 @@ groktypename (tree typename)
 
   split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
 
-  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
+  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
+			     NULL);
 
   /* Apply attributes.  */
   decl_attributes (&typename, attrs, 0);
@@ -2544,7 +2545,7 @@ groktypename_in_parm_context (tree typen
     return typename;
   return grokdeclarator (TREE_VALUE (typename),
 			 TREE_PURPOSE (typename),
-			 PARM, 0);
+			 PARM, 0, NULL);
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
@@ -2574,7 +2575,7 @@ start_decl (tree declarator, tree declsp
     deprecated_state = DEPRECATED_SUPPRESS;
 
   decl = grokdeclarator (declarator, declspecs,
-			 NORMAL, initialized);
+			 NORMAL, initialized, NULL);
 
   deprecated_state = DEPRECATED_NORMAL;
 
@@ -3010,7 +3011,8 @@ push_parm_decl (tree parm)
   immediate_size_expand = 0;
 
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
-			 TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
+			 TREE_PURPOSE (TREE_PURPOSE (parm)),
+			 PARM, 0, NULL);
   decl_attributes (&decl, TREE_VALUE (parm), 0);
 
   decl = pushdecl (decl);
@@ -3205,6 +3207,80 @@ flexible_array_type_p (tree type)
   }
 }
 
+/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
+   replacing with appropriate values if they are invalid.  */
+static void
+check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
+{
+  tree type_mv;
+  unsigned int max_width;
+  unsigned HOST_WIDE_INT w;
+  const char *name = orig_name ? orig_name: _("<anonymous>");
+
+  /* Necessary?  */
+  STRIP_NOPS (*width);
+
+  /* Detect and ignore out of range field width and process valid
+     field widths.  */
+  if (TREE_CODE (*width) != INTEGER_CST)
+    {
+      error ("bit-field `%s' width not an integer constant", name);
+      *width = integer_one_node;
+    }
+  else
+    {
+      constant_expression_warning (*width);
+      if (tree_int_cst_sgn (*width) < 0)
+	{
+	  error ("negative width in bit-field `%s'", name);
+	  *width = integer_one_node;
+	}
+      else if (integer_zerop (*width) && orig_name)
+	{
+	  error ("zero width for bit-field `%s'", name);
+	  *width = integer_one_node;
+	}
+    }
+
+  /* Detect invalid bit-field type.  */
+  if (TREE_CODE (*type) != INTEGER_TYPE
+      && TREE_CODE (*type) != BOOLEAN_TYPE
+      && TREE_CODE (*type) != ENUMERAL_TYPE)
+    {
+      error ("bit-field `%s' has invalid type", name);
+      *type = unsigned_type_node;
+    }
+
+  type_mv = TYPE_MAIN_VARIANT (*type);
+  if (pedantic
+      && type_mv != integer_type_node
+      && type_mv != unsigned_type_node
+      && type_mv != boolean_type_node
+      /* Accept an enum that's equivalent to int or unsigned int.  */
+      && (TREE_CODE (*type) != ENUMERAL_TYPE
+	  || TYPE_PRECISION (*type) != TYPE_PRECISION (integer_type_node)))
+    pedwarn ("type of bit-field `%s' is a GCC extension", name);
+
+  if (type_mv == boolean_type_node)
+    max_width = CHAR_TYPE_SIZE;
+  else
+    max_width = TYPE_PRECISION (*type);
+
+  if (0 < compare_tree_int (*width, max_width))
+    {
+      error ("width of `%s' exceeds its type", name);
+      w = max_width;
+      *width = build_int_2 (w, 0);
+    }
+  else
+    w = tree_low_cst (*width, 1);
+
+  if (TREE_CODE (*type) == ENUMERAL_TYPE
+      && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type))
+	  || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type))))
+    warning ("`%s' is narrower than values of its type", name);
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -3224,8 +3300,9 @@ flexible_array_type_p (tree type)
      TYPENAME if for a typename (in a cast or sizeof).
       Don't make a DECL node; just return the ..._TYPE node.
      FIELD for a struct or union field; make a FIELD_DECL.
-     BITFIELD for a field with specified width.
    INITIALIZED is 1 if the decl has an initializer.
+   WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
+   representing the width of the bit-field.
 
    In the TYPENAME case, DECLARATOR is really an absolute declarator.
    It may also be so in the PARM case, for a prototype where the
@@ -3236,7 +3313,7 @@ flexible_array_type_p (tree type)
 
 static tree
 grokdeclarator (tree declarator, tree declspecs,
-		enum decl_context decl_context, int initialized)
+		enum decl_context decl_context, int initialized, tree *width)
 {
   int specbits = 0;
   tree spec;
@@ -3251,19 +3328,16 @@ grokdeclarator (tree declarator, tree de
   int explicit_char = 0;
   int defaulted_int = 0;
   tree typedef_decl = 0;
-  const char *name;
+  const char *name, *orig_name;
   tree typedef_type = 0;
   int funcdef_flag = 0;
   enum tree_code innermost_code = ERROR_MARK;
-  int bitfield = 0;
   int size_varies = 0;
   tree decl_attr = NULL_TREE;
   tree array_ptr_quals = NULL_TREE;
   int array_parm_static = 0;
   tree returned_attrs = NULL_TREE;
-
-  if (decl_context == BITFIELD)
-    bitfield = 1, decl_context = FIELD;
+  bool bitfield = width != NULL;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
@@ -3296,6 +3370,7 @@ grokdeclarator (tree declarator, tree de
 	default:
 	  abort ();
 	}
+    orig_name = name;
     if (name == 0)
       name = "type name";
   }
@@ -3528,7 +3603,7 @@ grokdeclarator (tree declarator, tree de
     }
 
   /* Decide whether an integer type is signed or not.
-     Optionally treat bitfields as signed by default.  */
+     Optionally treat bit-fields as signed by default.  */
   if (specbits & 1 << (int) RID_UNSIGNED
       || (bitfield && ! flag_signed_bitfields
 	  && (explicit_int || defaulted_int || explicit_char
@@ -3600,6 +3675,10 @@ grokdeclarator (tree declarator, tree de
 	}
     }
 
+  /* Check the type and width of a bit-field.  */
+  if (bitfield)
+    check_bitfield_type_and_width (&type, width, orig_name);
+
   /* Figure out the type qualifiers for the declaration.  There are
      two ways a declaration can become qualified.  One is something
      like `const int i' where the `const' is explicit.  Another is
@@ -4756,7 +4835,7 @@ start_struct (enum tree_code code, tree 
 
 /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
    of a structure component, returning a FIELD_DECL node.
-   WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.
+   WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
 
    This is done during the parsing of the struct declaration.
    The FIELD_DECL nodes are chained together and the lot of them
@@ -4811,7 +4890,8 @@ grokfield (tree declarator, tree declspe
 	}
     }
 
-  value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
+  value = grokdeclarator (declarator, declspecs, FIELD, 0,
+			  width ? &width : NULL);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
@@ -4958,72 +5038,12 @@ finish_struct (tree t, tree fieldlist, t
 	error ("nested redefinition of `%s'",
 	       IDENTIFIER_POINTER (TYPE_NAME (t)));
 
-      /* Detect invalid bit-field size.  */
-      if (DECL_INITIAL (x))
-	STRIP_NOPS (DECL_INITIAL (x));
       if (DECL_INITIAL (x))
 	{
-	  if (TREE_CODE (DECL_INITIAL (x)) == INTEGER_CST)
-	    constant_expression_warning (DECL_INITIAL (x));
-	  else
-	    {
-	      error ("%Jbit-field '%D' width not an integer constant", x, x);
-	      DECL_INITIAL (x) = NULL;
-	    }
-	}
-
-      /* Detect invalid bit-field type.  */
-      if (DECL_INITIAL (x)
-	  && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
-	  && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE
-	  && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
-	{
-	  error ("%Jbit-field '%D' has invalid type", x, x);
-	  DECL_INITIAL (x) = NULL;
-	}
-
-      if (DECL_INITIAL (x) && pedantic
-	  && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
-	  && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
-	  && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != boolean_type_node
-	  /* Accept an enum that's equivalent to int or unsigned int.  */
-	  && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
-	       && (TYPE_PRECISION (TREE_TYPE (x))
-		   == TYPE_PRECISION (integer_type_node))))
-	pedwarn ("%Jbit-field '%D' type invalid in ISO C", x, x);
-
-      /* Detect and ignore out of range field width and process valid
-	 field widths.  */
-      if (DECL_INITIAL (x))
-	{
-	  int max_width
-	    = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == boolean_type_node
-	       ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
-
-	  if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
-	    error ("%Jnegative width in bit-field '%D'", x, x);
-	  else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
-	    pedwarn ("%Jwidth of '%D' exceeds its type", x, x);
-	  else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
-	    error ("%Jzero width for bit-field '%D'", x, x);
-	  else
-	    {
-	      /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
-	      unsigned HOST_WIDE_INT width
-		= tree_low_cst (DECL_INITIAL (x), 1);
-
-	      if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
-		  && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
-					     TREE_UNSIGNED (TREE_TYPE (x)))
-		      || (width
-			  < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
-					   TREE_UNSIGNED (TREE_TYPE (x))))))
-		warning ("%J'%D' is narrower than values of its type", x, x);
-
-	      DECL_SIZE (x) = bitsize_int (width);
-	      DECL_BIT_FIELD (x) = 1;
-	      SET_DECL_C_BIT_FIELD (x);
-	    }
+	  unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
+	  DECL_SIZE (x) = bitsize_int (width);
+	  DECL_BIT_FIELD (x) = 1;
+	  SET_DECL_C_BIT_FIELD (x);
 	}
 
       DECL_INITIAL (x) = 0;
@@ -5448,7 +5468,7 @@ start_function (tree declspecs, tree dec
   /* Don't expand any sizes in the return type of the function.  */
   immediate_size_expand = 0;
 
-  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1);
+  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
 
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/bitfld-8.c GCC-part1/gcc/testsuite/gcc.dg/bitfld-8.c
--- GCC.orig/gcc/testsuite/gcc.dg/bitfld-8.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC-part1/gcc/testsuite/gcc.dg/bitfld-8.c	2003-12-16 10:21:01.000000000 +0000
@@ -0,0 +1,7 @@
+/* Test that too wide bit-fields are hard errors.  PR c/3347.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk>, from PR c/3347 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct { int i : 1999; } x; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "width" "bit-field too wide" { target *-*-* } 6 } */

-- 
Joseph S. Myers
jsm@polyomino.org.uk


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]