[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