diff options
| author | Vincent Mailhol <[email protected]> | 2024-11-13 17:18:32 +0000 |
|---|---|---|
| committer | Yury Norov <[email protected]> | 2024-12-30 18:29:25 +0000 |
| commit | 4f3d1be4c2f8a22470f3625cbc778ba2e2130def (patch) | |
| tree | 79ff73c0aea62deccdefea19e9554c603d293dd2 /lib/fault-inject.c | |
| parent | Linux 6.13-rc5 (diff) | |
| download | kernel-4f3d1be4c2f8a22470f3625cbc778ba2e2130def.tar.gz kernel-4f3d1be4c2f8a22470f3625cbc778ba2e2130def.zip | |
compiler.h: add const_true()
__builtin_constant_p() is known for not always being able to produce
constant expression [1] which led to the introduction of
__is_constexpr() [2]. Because of its dependency on
__builtin_constant_p(), statically_true() suffers from the same
issues.
For example:
void foo(int a)
{
/* fail on GCC */
BUILD_BUG_ON_ZERO(statically_true(a));
/* fail on both clang and GCC */
static char arr[statically_true(a) ? 1 : 2];
}
For the same reasons why __is_constexpr() was created to cover
__builtin_constant_p() edge cases, __is_constexpr() can be used to
resolve statically_true() limitations.
Note that, somehow, GCC is not always able to fold this:
__is_constexpr(x) && (x)
It is OK in BUILD_BUG_ON_ZERO() but not in array declarations nor in
static_assert():
void bar(int a)
{
/* success */
BUILD_BUG_ON_ZERO(__is_constexpr(a) && (a));
/* fail on GCC */
static char arr[__is_constexpr(a) && (a) ? 1 : 2];
/* fail on GCC */
static_assert(__is_constexpr(a) && (a));
}
Encapsulating the expression in a __builtin_choose_expr() switch
resolves all these failed tests.
Define a new const_true() macro which, by making use of the
__builtin_choose_expr() and __is_constexpr(x) combo, always produces a
constant expression.
It should be noted that statically_true() is the only one able to fold
tautological expressions in which at least one on the operands is not a
constant expression. For example:
statically_true(true || var)
statically_true(var == var)
statically_true(var * 0 + 1)
statically_true(!(var * 8 % 4))
always evaluates to true, whereas all of these would be false under
const_true() if var is not a constant expression [3].
For this reason, usage of const_true() should be the exception.
Reflect in the documentation that const_true() is less powerful and
that statically_true() is the overall preferred solution.
[1] __builtin_constant_p cannot resolve to const when optimizing
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19449
[2] commit 3c8ba0d61d04 ("kernel.h: Retain constant expression output for max()/min()")
Link: https://git.kernel.org/torvalds/c/3c8ba0d61d04
[3] https://godbolt.org/z/c61PMxqbK
CC: Linus Torvalds <[email protected]>
CC: Rasmus Villemoes <[email protected]>
CC: Luc Van Oostenryck <[email protected]>
Reviewed-by: Yury Norov <[email protected]>,
Signed-off-by: Vincent Mailhol <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Diffstat (limited to 'lib/fault-inject.c')
0 files changed, 0 insertions, 0 deletions
