https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87951

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Vitali from comment #5)
> Jonathan, I think the defect report here does actually apply to this
> example.

I didn't say otherwise.

> I agree the argument could be made that if there's gaps in the enum
> values that it's arguable that the current GCC behaviour is standards
> compliant (clearly clang & GCC disagree on this for both C & C++ so unclear
> who's right or wrong in their interpretation of what's allowed).

No, it has nothing to do with "gaps" in the enum. This is a myth.

All that matters is the range of representable values, which (for an
enumeration without a fixed underlying type) depends on the number of bits
required to represent the minimum and maximum enumerator values. It doesn't
make any difference whatsoever whether there are "gaps" between those minimum
and maximum
values.

> However, in the example posted this is a "dense" enum.

What matters is that all the values of the enum can be represented in a single
bit, and so the only valid values are 0 and 1, which happen to have
enumerators. But the only valid values would still be 0 and 1 if your enum was
defined as
enum Enum { B=1 }; and so a switch that failed to handle the possibility of
Enum(0) would be wrong (even with -fstrict-enums)

The mental model of "dense" vs "gaps" is WRONG.

> There's no integer
> value possible that's not outside the range & yet GCC still continues to
> treat that as a possibility & thus missing optimization opportunities &
> generating false-positive warnings.

Yes, that's what -fstrict-enums is for.

The default (without -fstrict-enums) assumes most code is buggy and doesn't
follow the rules. If you do not use values outside the valid range of values
for the enumeration, use -fstrict-enums.

I can see some value in the suggestion to annotate a specific enumeration type
as strict, but that might not be the right solution. What matters is how the
enumeration type is used (whether invalid values are ever created) and that
isn't something you can guarantee when the enum is declared.

You *can* annotate the uses of a specific enum, but telling the compiler that
no other values will ever be used in the switch, by adding:

  default:
    __builtin_unreachable();

Reply via email to