MINOR: bug: make BUG_ON() fall back to ASSUME

When the strict level is zero and BUG_ON() is not implemented, some
possible null-deref warnings are emitted again because some were
covering for these cases. Let's make it fall back to ASSUME() so that
the compiler continues to know that the tested expression never happens.
It also allows to further optimize certain functions by helping the
compiler eliminate certain tests for impossible values. However it
requires that the expression is really evaluated before passing the
result through ASSUME() otherwise it was shown that gcc-11 and above
will fail to evaluate its implications and will continue to emit the
null-deref warnings in case the expression is non-trivial (e.g. it
has multiple terms).

We don't do it for BUG_ON_HOT() however because the extra cost of
evaluating the condition is generally not welcome in fast paths,
particularly when that BUG_ON_HOT() was kept disabled for
performance reasons.
This commit is contained in:
Willy Tarreau 2024-11-07 11:12:40 +01:00
parent 63798088b3
commit 7b6acb6a51

View File

@ -348,7 +348,13 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S
# define COUNT_IF(cond, ...) _COUNT_IF (cond, __FILE__, __LINE__, __VA_ARGS__)
# endif
#else
# define BUG_ON(cond, ...) do { (void)sizeof(cond); } while (0)
/* We want BUG_ON() to evaluate the expression sufficiently for next lines
* of codes not to complain about suspicious dereferences for example.
* GCC-11 tends to fail to validate that in combined expressions such as
* "BUG_ON(!a || !b)", but it works fine when using a temporary assignment
* like below, without hurting the generated code.
*/
# define BUG_ON(cond, ...) ({ typeof(cond) __cond = (cond); ASSUME(!__cond); })
# define WARN_ON(cond, ...) do { (void)sizeof(cond); } while (0)
# define CHECK_IF(cond, ...) do { (void)sizeof(cond); } while (0)
# define COUNT_IF(cond, ...) DISGUISE(cond)
@ -376,6 +382,10 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S
# define COUNT_IF_HOT(cond, ...) _COUNT_IF (cond, __FILE__, __LINE__, __VA_ARGS__)
# endif
#else
/* Contrary to BUG_ON(), we do *NOT* want BUG_ON_HOT() to evaluate the
* expression unless explicitly enabled, since it is located in hot code paths.
* We just validate that the expression results in a valid type.
*/
# define BUG_ON_HOT(cond, ...) do { (void)sizeof(cond) ; } while (0)
# define CHECK_IF_HOT(cond, ...) do { (void)sizeof(cond) ; } while (0)
# define COUNT_IF_HOT(cond, ...) DISGUISE(cond)