error: do not evaluate status twice
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 3 Jun 2023 05:30:52 +0000 (22:30 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 3 Jun 2023 06:07:07 +0000 (23:07 -0700)
Do this in a different way, so that the status is evaluated
once even when not optimizing and when using GCC.
* lib/error.in.h (__gl_error_call1) [__GNUC__]: New macro.
(__gl_error_call) [__GNUC__]: Use it.

ChangeLog
lib/error.in.h

index 3187128c1f25c17c31b8122a6f383a283e3942fe..fda2ed0e3f6dbca99ee09c215a096c930e54ad86 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2023-06-02  Paul Eggert  <eggert@cs.ucla.edu>
+
+       error: do not evaluate status twice
+       Do this in a different way, so that the status is evaluated
+       once even when not optimizing and when using GCC.
+       * lib/error.in.h (__gl_error_call1) [__GNUC__]: New macro.
+       (__gl_error_call) [__GNUC__]: Use it.
+
 2023-06-02  Bruno Haible  <bruno@clisp.org>
 
        warnings: Add ability to inhibit all warnings.
index f37dba170c8ec90139bf2d783c816fa12234b3de..279258f63e977f2af564bd11aad43f7172f2bad0 100644 (file)
 #endif
 
 /* Helper macro for supporting the compiler's control flow analysis better.
+   It evaluates its arguments only once.  It uses __builtin_constant_p
+   and comma expressions to work around GCC false positives.
    Test case: Compile copy-file.c with "gcc -Wimplicit-fallthrough".  */
 #ifdef __GNUC__
-/* Avoid evaluating STATUS twice, if this is possible without making the
-   "warning: this statement may fall through" reappear.  */
-# if __OPTIMIZE__
-#  define __gl_error_call(function, status, ...) \
-     ({ \
-        int const __errstatus = (status); \
-        (function) (__errstatus, __VA_ARGS__); \
-        __errstatus != 0 ? unreachable () : (void) 0; \
-     })
-# else
-#  define __gl_error_call(function, status, ...) \
-     ((function) (status, __VA_ARGS__), \
-      (status) != 0 ? unreachable () : (void)0 \
-     )
-# endif
+# define __gl_error_call1(function, status, ...) \
+    ((function) (status, __VA_ARGS__), \
+     (status) != 0 ? unreachable () : (void) 0)
+# define __gl_error_call(function, status, ...) \
+    (__builtin_constant_p (status) \
+     ? __gl_error_call1 (function, status, __VA_ARGS__) \
+     : ({ \
+         int const __errstatus = status; \
+         __gl_error_call1 (function, __errstatus, __VA_ARGS__); \
+       }))
 #else
 # define __gl_error_call(function, status, ...) \
     (function) (status, __VA_ARGS__)