Implemented a hint for optimizers to better detect unreachable code
Summary
I've added the macros DUNE_UNREACHABLE
and DUNE_UNREACHABLE_MSG
that wrap some compiler builtin functionality to mark code segments as unreachable.
Motivation
This might be useful to optimize switch-case statements over the values of an enum, where all enumeration values are handled. The compiler does not necessarily recognize this and implements additional checks and branches.
Also, the macro can be used to suppress compiler warnings about missing return statements in non-void functions, e.g.
int foo() {
switch (flag) {
case f1: return 1;
case f2: return 2;
}
}
If flag
in the example can only have the two values f1
or f2
all cases are handled, but the compiler throws the warning of a missing return statement, since there is not default:
case. But what to return on default? A std::abort()
could be fine, but the most optimal code is produced when the default:
case is marked unreachable. At least in clang >= 3.7 and gcc >= 8:
int foo() {
switch (flag) {
case f1: return 1;
case f2: return 2;
default: DUNE_UNREACHABLE;
}
}
Discussion
The macro is implemented so that in the unexpected case that the unreachable line is reached, the DUNE_THROW
is called, except if -DNDEBUG
is set. It maybe discussed, whether a std::abort()
call is better than an exception in the debug case.
A reached unreachable line causes undefined behaviour. Thus, the macro should be used only in cases where you are sure that this does not happen. The critical line can be found in debug mode, since an error is thrown, or (in case of unhandled enum values) by adding the warning flag -Wswitch-enum
.