From: Bruno Haible Date: Tue, 25 Aug 2020 23:45:49 +0000 (+0200) Subject: verify: Avoid warnings when assume(0) is used. X-Git-Tag: v1.0~3675 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=5667b92ddf0c830d612344aa20206c9000e931f8;p=gnulib.git verify: Avoid warnings when assume(0) is used. Reported by Mattias Engdegård via Paul Eggert in . * lib/verify.h (assume): Use __builtin_unreachable if the argument is the constant 0. * tests/test-verify.c (f): New function. (state): New type. (test_assume_expressions, test_assume_optimization, test_assume_noreturn): New functions. --- diff --git a/ChangeLog b/ChangeLog index 4ffa48fb1c..a97600d7f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2020-08-25 Bruno Haible + + verify: Avoid warnings when assume(0) is used. + Reported by Mattias EngdegÃ¥rd via Paul Eggert in + . + * lib/verify.h (assume): Use __builtin_unreachable if the argument is + the constant 0. + * tests/test-verify.c (f): New function. + (state): New type. + (test_assume_expressions, test_assume_optimization, + test_assume_noreturn): New functions. + 2020-08-25 Bruno Haible fstrcmp: Clarification regarding NOTE_ORDERED. diff --git a/lib/verify.h b/lib/verify.h index 6d7b961db7..ca2a154073 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -320,7 +320,9 @@ template based on __builtin_unreachable does not. (GCC so far has only __builtin_unreachable.) */ #if _GL_HAS_BUILTIN_ASSUME -/* Use a temporary variable, to avoid a clang warning +/* Use __builtin_constant_p to help clang's data-flow analysis for the case + assume (0). + Use a temporary variable, to avoid a clang warning "the argument to '__builtin_assume' has side effects that will be discarded" if R contains invocations of functions not marked as 'const'. The type of the temporary variable can't be __typeof__ (R), because that @@ -328,12 +330,16 @@ template instead. */ # if defined __cplusplus # define assume(R) \ - ((void) ({ bool _gl_verify_temp = (R); \ - __builtin_assume (_gl_verify_temp); })) + (__builtin_constant_p (R) && !(R) \ + ? (void) __builtin_unreachable () \ + : (void) ({ bool _gl_verify_temp = (R); \ + __builtin_assume (_gl_verify_temp); })) # else # define assume(R) \ - ((void) ({ _Bool _gl_verify_temp = (R); \ - __builtin_assume (_gl_verify_temp); })) + (__builtin_constant_p (R) && !(R) \ + ? (void) __builtin_unreachable () \ + : (void) ({ _Bool _gl_verify_temp = (R); \ + __builtin_assume (_gl_verify_temp); })) # endif #elif _GL_HAS_BUILTIN_UNREACHABLE # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) diff --git a/tests/test-verify.c b/tests/test-verify.c index 498dd2f6d4..7201ca1fff 100644 --- a/tests/test-verify.c +++ b/tests/test-verify.c @@ -25,6 +25,8 @@ # define EXP_FAIL 0 #endif +/* ======================= Test verify, verify_expr ======================= */ + int x; enum { a, b, c }; @@ -67,3 +69,43 @@ main (void) { return !(function (0) == 0 && function (1) == 8); } + +/* ============================== Test assume ============================== */ + +static int +f (int a) +{ + return a; +} + +typedef struct { unsigned int context : 4; unsigned int halt : 1; } state; + +void +test_assume_expressions (state *s) +{ + /* Check that 'assume' accepts a function call, even of a non-const + function. */ + assume (f (1)); + /* Check that 'assume' accepts a bit-field expression. */ + assume (s->halt); +} + +int +test_assume_optimization (int x) +{ + /* Check that the compiler uses 'assume' for optimization. + This function, when compiled with optimization, should have code + equivalent to + return x + 3; + Use 'objdump --disassemble test-verify.o' to verify this. */ + assume (x >= 4); + return (x > 1 ? x + 3 : 2 * x + 10); +} + +_Noreturn void +test_assume_noreturn (void) +{ + /* Check that the compiler's data-flow analysis recognizes 'assume (0)'. + This function should not elicit a warning. */ + assume (0); +}