Paul Eggert wrote:
> For situations like these I prefer "default: unreachable ();" to 
> "default: abort ();", as "unreachable ()" lets the builder decide 
> whether to abort or optimize; but it's no big deal.

If there's only the slightest chance of that 'default:' case being
reached (possibly through programmer mistake or heap corruption),
I prefer to call abort() rather than unreachable(), because

  1) ISO C 23 ยง 7.21.1.(3) is clear that it's undefined behaviour.
     This is also what gcc does with the usual optimization options:
     It produces no instruction at all, leaving the CPU to execute
     whatever instruction may follow.
     It's documented in
     <https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html>
     but you can see it directly: compile this code with "gcc -m32 -O2 -S":
     -----------------------------------------------------
     void foo (void) { __builtin_unreachable(); }
     -----------------------------------------------------

     Even with the option -funreachable-traps of GCC >= 13, documented in
     <https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html>,
     it produces zero instructions, not even a trap. (See:
     compile the code above with "gcc -m64 -funreachable-traps -S").

  2) Even if it were to generate a trap, that is a weird way to get the
     programmer's attention.
     This code
     -----------------------------------------------------
     #include <stdarg.h>
     unsigned char bar (va_list args) { return va_arg (args, unsigned char); }
     -----------------------------------------------------
     produces an illegal instruction ('ud2' with newer gcc, 'int $5' with older
     gcc). It's weird when you look at it in gdb and all you see is an
     illegal instruction.

  3) If the situation happens when a user runs my programs, I want them
     to report it, and furthermore to report it with as much debugging
     info as possible. abort() achieves this (via core dumps, stack traces,
     crash reporting daemons and whatever). unreachable() doesn't, regardless
     of compiler options.

So, IMO, the only purpose of unreachable() is to allow compiler optimizations.
It is NOT a way of verifying invariants or an equivalent of 'assert()'.

Bruno




Reply via email to