This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Help with bit-field semantics in C and C++
- From: Richard Earnshaw <rearnsha at gcc dot gnu dot org>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: Joe Buck <Joe dot Buck at synopsys dot com>, Mark Mitchell <mark at codesourcery dot com>, gcc at gcc dot gnu dot org
- Date: Tue, 24 Aug 2004 18:54:45 +0100
- Subject: Re: Help with bit-field semantics in C and C++
- Organization: GNU
- References: <Pine.LNX.4.44.0408241047350.14511-100000@www.eyesopen.com>
On Tue, 2004-08-24 at 18:05, Roger Sayle wrote:
> On Tue, 24 Aug 2004, Joe Buck wrote:
> > [ issues connected with limited range of C++ enums ]
> > On Tue, Aug 24, 2004 at 10:32:39AM -0600, Roger Sayle wrote:
> > > I'm happy with the explanations so far. The next question is, if
> > > the middle-end is supposed to treat loads, stores and comparisons
> > > of these types identically to the underlying integer type for the
> > > enumeration, is there a benefit for setting TYPE_PRECISION lower
> > > than GET_MODE_BITSIZE for C++'s enumerated types?
> >
> > I think that the middle end should, at least by default, try to generate
> > the best code possible for conformant programs that use C++ enums. In
> > most cases, that probably means treating them as belonging to the
> > underlying integer type; the exception would be where the limited range
> > allows for, say, more efficient switch statements, or to determine that
> > some code is unreachable.
> >
> > It's possible to have the compiler generate enum range-checking code, but
> > doing so would seem inconsistent with how we do everything else. It would
> > only make sense in the context of a bounds-checking compiler that would
> > also handle array bounds and the like.
>
> The problem here is that a C++ enum can hold values outside the range
> of it's type.
>
> enum E { zero = 0x00, one = 0x01 };
>
> void test(int n)
> {
> enum E x;
>
> x = (E)n;
> switch (x)
> {
> case zero: foo(); break;
> case one: bar(); break;
> }
> }
>
> int main()
> {
> test(255);
> return 0;
> }
>
> In the above code, the enumeration makes "x" is a single bit
> wide, and all possible values of the width are handled in the switch.
> If we were to omit the range tests, and use a table jump, the above
> code would probably core dump for values of x such as 255.
>
In this case the application could call either foo, or bar or both or
neither.
A perfectly reasonable compilation of this could reduce the switch to a
simple 'if (x == 0) foo() else bar();' so you'd end up with bar being
called for any value of x that wasn't zero. Equally viable would be 'if
(x == 1) bar () else foo();'
> To paraphrase Mike Stump, "undefined" allows us to "rm -rf ~/" or
> core dump, I'm not sure if "unspecified" also allows us to seg fault
> in the case above?
>
foo or bar might indeed do that; in general we shouldn't magic up
malicious code, but if we happen to execute an unintended code path when
out-of-domain values are passed then so be it.
R.