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]

Re: pedantic use of enum bitfields


On Tue, 2 Dec 2003, Richard Henderson wrote:

> > I'm currently working on resurrecting Neil's bit-field patch (for PRs
> > 2511, 3325 (and duplicates), 3347), which should remove the need for this
> > by moving the checks on bit-field types earlier than finish_struct.
> 
> Also good.  Do you expect this to be done soonish, or should I go
> ahead with my relatively localized hack?

I don't know.  The patch now bootstraps and passes the tests included with
Neil's original patch and the test added for ABI breakage caused by the
original patch, but it has problems with other existing tests such as
bf64-1.c.  The problematic test can be somewhat simplified to

struct tmp
{
  long long int pad : 12;
  long long int field : 52;
};

main()
{
  struct tmp tmp = {0x123, 0xFFF000FFF000FLL};

  if (tmp.field != 0xFFFFFF000FFF000FLL)
    abort();

  exit (0);
}

where the comparison gets simplified to comparing field (signed 52-bit,
converted to unsigned 52-bit) to a 52-bit unsigned constant.  field is
duly expanded in (signed) DImode (64-bit); expand_expr supposes that
nothing needs to be done for the conversion to unsigned as both 52-bit
types have mode DImode.  Thus the 64-bit signed value is compared against
an unsigned constant that was reduced to 52 bits, which fails.

This problem doesn't depend on the comparison getting narrowed to 52 bits, 
as both sides of the comparison could be bit-fields anyway.  It might be 
logical to have separate machine modes for these bit-field types, but 
having so many modes would probably cause other problems.  So in general 
the middle-end code doesn't seem prepared for computations in these 
bit-field types (there are other problems, e.g. in

struct s {unsigned long long x: 40; };
struct s a = { 0x100000 };
int
main(void) 
{ 
printf("%llu\n", (unsigned long long) (a.x * a.x)); 
}

the multiplication in a 40-bit unsigned type should yield 0).  I don't
know what the correct solution is (or why this problem didn't arise with
the original patch) though I suspect the simplest one is for expand_expr
to check for results being of these bit-field types and explicitly reduce
to the required number of bits in every case.

-- 
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]