]> Savannah Git Hosting - gnulib.git/commitdiff
verify: Avoid warnings when assume(0) is used.
authorBruno Haible <bruno@clisp.org>
Tue, 25 Aug 2020 23:45:49 +0000 (01:45 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 26 Aug 2020 00:00:55 +0000 (02:00 +0200)
Reported by Mattias EngdegĂ„rd <mattiase@acm.org> via Paul Eggert in
<https://lists.gnu.org/archive/html/emacs-devel/2020-08/msg00838.html>.

* 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.

ChangeLog
lib/verify.h
tests/test-verify.c

index 4ffa48fb1cc2c9f01852f41984a3ebfb56c8c5c4..a97600d7f334af9115ff4a57876357f7d2b2a522 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2020-08-25  Bruno Haible  <bruno@clisp.org>
+
+       verify: Avoid warnings when assume(0) is used.
+       Reported by Mattias EngdegĂ„rd <mattiase@acm.org> via Paul Eggert in
+       <https://lists.gnu.org/archive/html/emacs-devel/2020-08/msg00838.html>.
+       * 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  <bruno@clisp.org>
 
        fstrcmp: Clarification regarding NOTE_ORDERED.
index 6d7b961db717679616ee12ecb3f61c28f9e48374..ca2a15407360a3600edfc3250652b4d0c4128664 100644 (file)
@@ -320,7 +320,9 @@ template <int w>
    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 <int w>
    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 ())
index 498dd2f6d4868e553fec1a5bd92415efbf8cf600..7201ca1fffaa3bf096dea86add0fa4e2d89947be 100644 (file)
@@ -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);
+}