[PATCH] [RFC] Fix bitfield behaviour

Christian Ehrhardt ehrhardt@mathematik.uni-ulm.de
Mon Apr 14 17:16:00 GMT 2003


Hi,

bit-fields currently have several issues including some where wrong
code is generated. Neil proposed a patch for these some time ago but
it had to be reverted. This problem is the reason for at least the following
PRs: 9620, 7696, 6515, 6346, 3326, 3325 and 2511. There are also XFAILing
testcases for this problem in the testsuite.

This patch fixes these PRs. Bootstrapped and regtested on x86 with
c, c++, objc, fortran and java and on sparc-sun-solaris2.9 with c and c++.

The patch uncovered a few bugs where bit-fields of width one were
declared as int instead of unsigned int. This results in a bit-field
with range [-1, 0] and comparisions with 1 will fail. This behaviour is
unchanged with the patch, but with the patch we get a (justified) overflow
warning for things like this:

struct X {
	int a : 1;
} x = { 1 };

This in turn caused bootstrapping failures with -Werror. Otherwise the
hunks that affect predict.c and java/* wouldn't be necessary. Note that
these hunks should probably be applied no matter what people think of
the rest of this patch.

     regards  Christian


	* c-decl.c (finish_struct): Use build_type_precision_variant
	for bit-field types.
	* c-typeck.c (default_conversion): Use TYPE_PRECISION for
	bitfield promotion test.
	* tree.c (build_type_precision_variant): Define.
	* tree.h (TYPE_SYMTAB): Define.
	* predict.c (struct block_info_def, struct edge_info_def):
	Convert int bit-fields to unsigned int.
	* java/jcf.h (struct JCF): Likewise.
	* java/lex.h (struct java_lexer): Likewise.
	* java/parse.h (struct _jdep): Likewise.

Index: c-decl.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.375
diff -u -r1.375 c-decl.c
--- c-decl.c	3 Apr 2003 18:23:01 -0000	1.375
+++ c-decl.c	13 Apr 2003 23:00:23 -0000
@@ -5250,6 +5250,8 @@
 	      DECL_SIZE (x) = bitsize_int (width);
 	      DECL_BIT_FIELD (x) = 1;
 	      SET_DECL_C_BIT_FIELD (x);
+	      TREE_TYPE (x) = build_type_precision_variant (TREE_TYPE (x),
+							    width);
 	    }
 	}
 
Index: c-typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.228
diff -u -r1.228 c-typeck.c
--- c-typeck.c	1 Apr 2003 13:40:09 -0000	1.228
+++ c-typeck.c	13 Apr 2003 23:04:39 -0000
@@ -977,8 +977,8 @@
       && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
       /* If it's thinner than an int, promote it like a
 	 c_promoting_integer_type_p, otherwise leave it alone.  */
-      && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
-			       TYPE_PRECISION (integer_type_node)))
+      && (TYPE_PRECISION (TREE_TYPE (exp))
+	  < TYPE_PRECISION (integer_type_node)))
     return convert (integer_type_node, exp);
 
   if (c_promoting_integer_type_p (type))
Index: predict.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/predict.c,v
retrieving revision 1.87
diff -u -r1.87 predict.c
--- predict.c	1 Mar 2003 15:11:59 -0000	1.87
+++ predict.c	13 Apr 2003 23:09:53 -0000
@@ -918,7 +918,7 @@
   basic_block next;
 
   /* True if block needs to be visited in prop_freqency.  */
-  int tovisit:1;
+  unsigned int tovisit:1;
 
   /* Number of predecessors we need to visit first.  */
   int npredecessors;
@@ -932,7 +932,7 @@
      then computed as 1 / (1 - back_edge_prob).  */
   sreal back_edge_prob;
   /* True if the edge is an loopback edge in the natural loop.  */
-  int back_edge:1;
+  unsigned int back_edge:1;
 } *edge_info;
 
 #define BLOCK_INFO(B)	((block_info) (B)->aux)
Index: tree.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree.c,v
retrieving revision 1.291
diff -u -r1.291 tree.c
--- tree.c	19 Mar 2003 20:20:57 -0000	1.291
+++ tree.c	13 Apr 2003 23:11:07 -0000
@@ -2489,6 +2489,80 @@
   return ddecl;
 }
 
+/* Return a type like TTYPE except that its TYPE_PRECISION
+   is PREC. Also adjust TYPE_MIN_VALUE and TYPE_MAX_VALUE
+   accordingly.
+
+   Record such modified types already made so we don't make duplicates.  */
+
+tree
+build_type_precision_variant (ttype, prec)
+    tree ttype;
+    int prec;
+{
+  if ((TREE_CODE (ttype) == INTEGER_TYPE || TREE_CODE (ttype) == ENUMERAL_TYPE
+       || TREE_CODE (ttype) == BOOLEAN_TYPE) && TYPE_PRECISION (ttype) != prec)
+    {
+      unsigned int hashcode;
+      tree ntype;
+
+      ntype = copy_node (ttype);
+
+      TYPE_POINTER_TO (ntype) = 0;
+      TYPE_REFERENCE_TO (ntype) = 0;
+
+      /* Create a new main variant of TYPE.  */
+      TYPE_MAIN_VARIANT (ntype) = ntype;
+      TYPE_NEXT_VARIANT (ntype) = 0;
+      set_type_quals (ntype, TYPE_UNQUALIFIED);
+
+      hashcode = (TYPE_HASH (TREE_CODE (ntype))
+		  + TYPE_HASH (TREE_TYPE (ntype))
+		  + attribute_hash_list (TYPE_ATTRIBUTES (ntype)));
+      if (TREE_UNSIGNED (ntype))
+	{
+	  TYPE_MIN_VALUE (ntype) = build_int_2 (0, 0);
+	  TYPE_MAX_VALUE (ntype)
+	    = build_int_2 (prec - HOST_BITS_PER_WIDE_INT >= 0
+			   ? -1 : ((HOST_WIDE_INT) 1 << prec) - 1,
+			   prec - HOST_BITS_PER_WIDE_INT > 0
+			   ? ((unsigned HOST_WIDE_INT) ~0
+			      >> (HOST_BITS_PER_WIDE_INT
+				  - (prec - HOST_BITS_PER_WIDE_INT)))
+			   :0);
+	}
+      else
+	{
+	  TYPE_MIN_VALUE (ntype)
+	    = build_int_2 ((prec - HOST_BITS_PER_WIDE_INT > 0
+			    ? 0 : (HOST_WIDE_INT) (-1) << (prec - 1)),
+			   (((HOST_WIDE_INT) (-1)
+			     << (prec - HOST_BITS_PER_WIDE_INT - 1 > 0
+				 ? prec - HOST_BITS_PER_WIDE_INT - 1
+				 : 0))));
+	  TYPE_MAX_VALUE (ntype)
+	    = build_int_2 ((prec - HOST_BITS_PER_WIDE_INT > 0
+			    ? -1 : ((HOST_WIDE_INT) 1 << (prec - 1)) - 1),
+			   (prec - HOST_BITS_PER_WIDE_INT - 1 > 0
+			    ? (((HOST_WIDE_INT) 1
+				<< (prec - HOST_BITS_PER_WIDE_INT - 1))) - 1
+			    : 0));
+	}
+      TYPE_PRECISION (ntype) = prec;
+      TREE_TYPE (TYPE_MIN_VALUE (ntype)) = ntype;
+      TREE_TYPE (TYPE_MAX_VALUE (ntype)) = ntype;
+      if (TREE_CODE (ntype) == INTEGER_TYPE)
+	hashcode += TYPE_HASH (TYPE_MAX_VALUE (ntype));
+      /* Make sure the debugging info is that of the original type.  */
+      TYPE_SYMTAB(ntype) = TYPE_SYMTAB(ttype);
+
+      ntype = type_hash_canon (hashcode, ntype);
+      ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
+    }
+
+  return ttype;
+}
+
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
 
Index: tree.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree.h,v
retrieving revision 1.388
diff -u -r1.388 tree.h
--- tree.h	3 Apr 2003 18:23:00 -0000	1.388
+++ tree.h	13 Apr 2003 23:12:09 -0000
@@ -978,6 +978,7 @@
 #define TYPE_MIN_VALUE(NODE) (TYPE_CHECK (NODE)->type.minval)
 #define TYPE_MAX_VALUE(NODE) (TYPE_CHECK (NODE)->type.maxval)
 #define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type.precision)
+#define TYPE_SYMTAB(NODE) (TYPE_CHECK (NODE)->type.symtab)
 #define TYPE_SYMTAB_ADDRESS(NODE) (TYPE_CHECK (NODE)->type.symtab.address)
 #define TYPE_SYMTAB_POINTER(NODE) (TYPE_CHECK (NODE)->type.symtab.pointer)
 #define TYPE_SYMTAB_DIE(NODE) (TYPE_CHECK (NODE)->type.symtab.die)
@@ -2285,6 +2286,7 @@
    are not made.  */
 
 extern tree build_type_attribute_variant PARAMS ((tree, tree));
+extern tree build_type_precision_variant PARAMS ((tree, int));
 extern tree build_decl_attribute_variant PARAMS ((tree, tree));
 
 /* Structure describing an attribute and a function to handle it.  */
Index: java/jcf.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/java/jcf.h,v
retrieving revision 1.36
diff -u -r1.36 jcf.h
--- java/jcf.h	7 Mar 2003 04:40:08 -0000	1.36
+++ java/jcf.h	13 Apr 2003 23:12:21 -0000
@@ -97,9 +97,9 @@
   unsigned char * GTY ((skip (""))) buffer_end;
   unsigned char * GTY ((skip (""))) read_ptr;
   unsigned char * GTY ((skip (""))) read_end;
-  int java_source : 1;
-  int right_zip : 1;
-  int finished : 1;
+  unsigned int java_source : 1;
+  unsigned int right_zip : 1;
+  unsigned int finished : 1;
   jcf_filbuf_t filbuf;
   PTR GTY ((skip (""))) read_state;
   const char *filename;
Index: java/lex.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/java/lex.h,v
retrieving revision 1.32
diff -u -r1.32 lex.h
--- java/lex.h	10 Jan 2003 02:22:26 -0000	1.32
+++ java/lex.h	13 Apr 2003 23:12:26 -0000
@@ -114,18 +114,18 @@
   unicode_t unget_value;
 
   /* If nonzero, we've hit EOF.  Used only by java_get_unicode().  */
-  int hit_eof : 1;
+  unsigned int hit_eof : 1;
 
 #ifdef HAVE_ICONV
   /* Nonzero if we've read any bytes.  We only recognize the
      byte-order-marker (BOM) as the first word.  */
-  int read_anything : 1;
+  unsigned int read_anything : 1;
 
   /* Nonzero if we have to byte swap.  */
-  int byte_swap : 1;
+  unsigned int byte_swap : 1;
 
   /* Nonzero if we're using the fallback decoder.  */
-  int use_fallback : 1;
+  unsigned int use_fallback : 1;
 
   /* The handle for the iconv converter we're using.  */
   iconv_t handle;
Index: java/parse.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/java/parse.h,v
retrieving revision 1.89
diff -u -r1.89 parse.h
--- java/parse.h	24 Feb 2003 02:14:49 -0000	1.89
+++ java/parse.h	13 Apr 2003 23:17:34 -0000
@@ -479,7 +479,7 @@
 typedef struct _jdep {
   ENUM_BITFIELD(jdep_code) kind : 8; /* Type of patch */
 
-  int  flag0 : 1;		/* Some flags */
+  unsigned int  flag0 : 1;	/* Some flags */
   tree decl;			/* Tied decl/or WFL */
   tree solv;			/* What to solve */
   tree wfl;			/* Where thing to resolve where found */



More information about the Gcc-patches mailing list