std-aux: make NM_BOOLEAN_EXPR() a constant expression for constant arguments

This allows the compiler to see that nm_assert(0) is unreachable code.
That is because nm_assert(0) calls NM_LIKELY(0), which calls
NM_BOOLEAN_EXPR(0). The latter was a statement expression, which
to the compiler was not a constant expression. Hence, this may trigger
compiler warnings about uninitialized variables.

Let NM_BOOLEAN_EXPR() to be constant, if the arguments are.

This can avoid compiler warnings in some cases.

Note that __builtin_choose_expr(__builtin_constant_p(...), ...) does
not properly work with gcc 4.8 ([1]). Hence only do macro shenanigans
with a newer gcc. Then entire point of NM_BOOLEAN_EXPR() is anyway
to preserve the "-Wparentheses" warning (while only evaluating the
argument once, being safe with nested invocations, propagate constness).
If we don't care about "-Wparentheses", it should be the same as
(!!(expr)). We can ignore that on non-recent gcc.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19449
This commit is contained in:
Thomas Haller
2022-11-30 09:52:10 +01:00
parent 7483dfd7c4
commit fffdb14887

View File

@@ -175,7 +175,15 @@ typedef uint64_t _nm_bitwise nm_be64_t;
NM_UNIQ_T(V, v) = 0; \
NM_UNIQ_T(V, v); \
})
#define NM_BOOLEAN_EXPR(expr) _NM_BOOLEAN_EXPR_IMPL(NM_UNIQ, expr)
#if defined(__GNUC__) && (__GNUC__ > 4)
#define NM_BOOLEAN_EXPR(expr) \
__builtin_choose_expr(__builtin_constant_p(expr), \
(!!(expr)), \
_NM_BOOLEAN_EXPR_IMPL(NM_UNIQ, expr))
#else
#define NM_BOOLEAN_EXPR(expr) (!!(expr))
#endif
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
#define NM_LIKELY(expr) __builtin_expect(NM_BOOLEAN_EXPR(expr), 1)