[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHk-=wiy=JOAWvSLwPq-jHPBfq8EX5NjVkEoh+RUMZbVn+GuOg@mail.gmail.com>
Date: Wed, 6 Sep 2023 16:16:52 -0700
From: Linus Torvalds <torvalds@...ux-foundation.org>
To: Arnaldo Carvalho de Melo <acme@...nel.org>
Cc: Kent Overstreet <kent.overstreet@...ux.dev>,
linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
linux-bcachefs@...r.kernel.org
Subject: Re: [GIT PULL] bcachefs
On Wed, 6 Sept 2023 at 14:55, Arnaldo Carvalho de Melo <acme@...nel.org> wrote:
>
> > I don't think gcc ever uses less than that (ie while a six_lock_type
> > could fit in two bits, it's still going to be considered at least a
> > 8-bit value in practice).
>
> There are some cases where people stuff the enum into a bitfield, but
> no, no simple type.
Note that I am talking about the types gcc uses natively.
To show what I'm talking about, build this (silly) code that has some
of the same enum types that bcachefs has:
#include <stdio.h>
enum enum1 {
val1 = 0,
val2 = 1,
val3 = 2,
};
enum enum2 {
num1 = -1,
num2 = 0,
num3 = 1,
num4 = 2,
};
int main(int argc, char **argv)
{
printf("%d %d (%zu %zu)\n",
(enum enum1) num1,
(enum enum1) num1 == num1,
sizeof(enum enum1),
sizeof(enum enum2));
return 0;
}
and run it. On x86 with no special options, you should get something like this:
-1 1 (4 4)
ie both types have a four-byte size, and casting 'num1' to 'enum
enum1' will in fact give you back -1, and will then compare equal to
num1 in the end.
Because both types are in practice just 'int'.
But now do the same with -fshort-enums, and you instead get
255 0 (1 1)
because both types are just a single byte, and casting 'num1' to 'enum
enum1' will in fact result in 255 (because it's an _unsigned_ type),
and then comparing with the original num1 value will no longer compare
equal.
(But casting it then further back to 'enum enum2' will in fact result
in -1 again, because you're effectively casting it back to 'signed
char', and then 255 and -1 are in fact the same in that type).
End result: you can get some really unexpected behavior if you cast
enums to other types.
Which is, of course, exactly why the compiler is warning about the
comparison and about passing in the wrong type of enum.
Sadly, the compiler doesn't warn about the cast, so you can hide all
of this by just adding casts. That doesn't make it *right*, of course.
Linus
Powered by blists - more mailing lists