From mboxrd@z Thu Jan 1 00:00:00 1970 From: ben@666.com To: gcc-gnats@gcc.gnu.org Cc: martin@xemacs.org, ben@666.com Subject: c++/4588: bogus warning concerning bit field limits Date: Wed, 17 Oct 2001 00:56:00 -0000 Message-id: <20011017075346.10920.qmail@sourceware.cygnus.com> X-SW-Source: 2001-10/msg00343.html List-Id: >Number: 4588 >Category: c++ >Synopsis: bogus warning concerning bit field limits >Confidential: no >Severity: non-critical >Priority: medium >Responsible: unassigned >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Wed Oct 17 00:56:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: ben@666.com >Release: 2.95.3-5 >Organization: >Environment: Cygwin >Description: i get the following warnings: /src/xemacs/mule/src/alloc.c: In function `void sledgehammer_check_ascii_begin(L isp_Object)': /src/xemacs/mule/src/alloc.c:1846: warning: comparison is always 0 due to width of bitfield but this is bogus, as the code shows. here is the function mentioned: [line 1846 is second from bottom, and indicated with an arrow like <=========== ] void sledgehammer_check_ascii_begin (Lisp_Object str) { int i; for (i = 0; i < XSTRING_LENGTH (str); i++) { if (!BYTE_ASCII_P (XSTRING_BYTE (str, i))) break; } assert (i == (int) XSTRING_ASCII_BEGIN (str) || (i > MAX_STRING_ASCII_BEGIN && XSTRING_ASCII_BEGIN (str) == MAX_STRING_ASCII_BEGIN)); <========== } the various structures and macros look like this: struct Lisp_String { union { struct lrecord_header lheader; struct { /* WARNING: Everything before ascii_begin must agree exactly with struct lrecord_header */ unsigned int type :8; unsigned int mark :1; unsigned int c_readonly :1; unsigned int lisp_readonly :1; /* Number of chars at beginning of string that are one byte in length (BYTE_ASCII_P) */ unsigned int ascii_begin :21; } v; } u; Bytecount size; Bufbyte *data; Lisp_Object plist; }; typedef struct Lisp_String Lisp_String; typedef EMACS_INT Bytecount; [see below] typedef unsigned char Bufbyte; see below for Lisp_Object struct lrecord_header { /* index into lrecord_implementations_table[] */ unsigned int type :8; /* If `mark' is 0 after the GC mark phase, the object will be freed during the GC sweep phase. There are 2 ways that `mark' can be 1: - by being referenced from other objects during the GC mark phase - because it is permanently on, for c_readonly objects */ unsigned int mark :1; /* 1 if the object resides in logically read-only space, and does not reference other non-c_readonly objects. Invariant: if (c_readonly == 1), then (mark == 1 && lisp_readonly == 1) */ unsigned int c_readonly :1; /* 1 if the object is readonly from lisp */ unsigned int lisp_readonly :1; unsigned int unused :21; }; #define MAX_STRING_ASCII_BEGIN ((2 << 21) - 1) #define XSTRING_ASCII_BEGIN(s) string_ascii_begin (XSTRING (s)) #define string_ascii_begin(s) ((s)->u.v.ascii_begin + 0) #define XSTRING(x) XRECORD (x, string, Lisp_String) # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) #define XPNTR(x) ((void *) XPNTRVAL(x)) NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Basically, a Lisp_Object is a [usually] 32-bit "tagged" integral type that can hold either a pointer, a 31-bit integer, or a few other things. XPNTR(x) just extracts the pointer. Most of the time we use `int' as the base type of Lisp_Object, and XPNTRVAL is just a no-op. However, we also have a version where the Lisp_Object is represented as a union, which allows for better type checking, so we use it for tests. This time, I was using this version, so I duly report the actual structures. But I seriously doubt it matters whether union or int is used, since the problem occurs after the string structure has been extracted from the Lisp_Object, and at that point we have nothing more to do with the Lisp_Object. Here is the int version for easy testing: typedef EMACS_INT Lisp_Object; #define XPNTRVAL(x) (x) /* This depends on Lisp_Type_Record == 0 */ #define EMACS_INT long Here is the grody union version that was actually used: typedef union Lisp_Object { /* if non-valbits are at lower addresses */ #ifdef WORDS_BIGENDIAN struct { EMACS_UINT val : VALBITS; enum_field (Lisp_Type) type : GCTYPEBITS; } gu; struct { signed EMACS_INT val : INT_VALBITS; unsigned int bits : INT_GCBITS; } s; struct { EMACS_UINT val : INT_VALBITS; unsigned int bits : INT_GCBITS; } u; #else /* non-valbits are at higher addresses */ struct { enum_field (Lisp_Type) type : GCTYPEBITS; EMACS_UINT val : VALBITS; } gu; struct { unsigned int bits : INT_GCBITS; signed EMACS_INT val : INT_VALBITS; } s; struct { unsigned int bits : INT_GCBITS; EMACS_UINT val : INT_VALBITS; } u; #endif /* non-valbits are at higher addresses */ EMACS_UINT ui; signed EMACS_INT i; /* This was formerly declared 'void *v' etc. but that causes GCC to accept any (yes, any) pointer as the argument of a function declared to accept a Lisp_Object. */ struct nosuchstruct *v; const struct nosuchstruct *cv; } Lisp_Object; # define XPNTRVAL(x) ((x).ui) #define GCMARKBITS 0 #define GCTYPEBITS 2 #define GCBITS 2 #define INT_GCBITS 1 #define INT_VALBITS (BITS_PER_EMACS_INT - INT_GCBITS) #define VALBITS (BITS_PER_EMACS_INT - GCBITS) #define EMACS_UINT unsigned long #define EMACS_INT is long #define BITS_PER_EMACS_INT 32 WORDS_BIGENDIAN not defined. So anyway, as you can see, ascii_begin in struct Lisp_String should be an unsigned int bitfield of 21 bits; therefore, its range is 0 .. 2^21 - 1. MAX_STRING_ASCII_BEGIN is 2^21 - 1, so it should be perfectly okay to compare a bitfield value to MAX_STRING_ASCII_BEGIN. >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted: