Subject: bug#75964: Switching the Emacs build to -Wswitch-enum in src/

From: Pip Cet <[email-masked]>
Date: Tue, 04 Feb 2025 17:30:34 +0000

"Stefan Monnier" <[email-masked]> writes:

>>> Yes, this part of C sucks and I had forgotten about it.
>> What sucks and why?
>
> That
>
>     switch ((enum Lisp_Type) 53) {
>     case Lisp_Symbol:
>     case Lisp_Type_Unused0:
>     case Lisp_Int0:
>     case Lisp_Int1:
>     case Lisp_String:
>     case Lisp_Vectorlike:
>     case Lisp_Cons:
>     case Lisp_Float:
>       return 1;
>     }
>     return 2;
>
> should return 2, because I'd prefer that it aborts and/or that the
> programmer have a way to say explicitly what should happen.  `default:`
> works for that in the case where you have listed *all* the enum's
> values, but then you get stiffed in the case where you add an enum value
> because the compiler won't tell you that you forgot to update this
> `switch` accordingly.

But... that's precisely what -Wswitch-enum does!  It warns about a
fargotten case even though there is also a default label!

So, yes, the compiler will warn you about that forgotten enumeration,
but it's not easy to turn this on and off on a per-switch basis.

(Also GCC misses a few cases where the enumeration type isn't the type
of the switch expression but is the type of the labels.  That one's
easiest to fix).

Paul's proposal to use switch (+x) when you mean "don't warn me about
new cases" and switch (x) when you mean "do warn me about new cases"
seems easy enough to add as a special case, but it is new and
non-obvious syntax.

And while it would be nice to

#define exhaustive_switch(x)  switch (x) { default: eassume (false); ELIDE_TOKEN("{")

I don't know how to write ELIDE_TOKEN in CPP, because someone decided
token streams form a free monoid rather than a free group...

Pip