bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ./lib/error.h:410:8: warning: ISO C forbids braced-groups within exp


From: Bruno Haible
Subject: Re: ./lib/error.h:410:8: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
Date: Mon, 04 Sep 2023 21:55:21 +0200

Eric Blake wrote:
> We could, however, add use of the __extension__ keyword anywhere we
> use ({...}) in public macros

That's a good suggestion, thanks. Implemented through the patch below.

In fact, use of the __extension__ keyword not only silences the -Wpedantic
warning. It also allows to use the statement-as-expression extension when
__STRICT_ANSI__ is defined, i.e. when a -std option is used that denotes
a C standard without GNU extensions [1]. See:

$ cat foo.c
int foo (int x) { return __extension__ ({ int y = x * x; y * y; }); }
$ gcc -std=c90 -Wpedantic -S foo.c
$ gcc -std=c99 -Wpedantic -S foo.c
$ gcc -std=c11 -Wpedantic -S foo.c
$ gcc -std=c17 -Wpedantic -S foo.c
$ gcc -std=c2x -Wpedantic -S foo.c

This works in the same way with clang, even in such old versions as 2.8:

$ clang -std=c90 -S foo.c
$ clang -std=c99 -S foo.c

as well as in new versions, e.g. 16.0.0:

$ clang -std=c90 -S -Wall -Wpedantic foo.c
$ clang -std=c99 -S -Wall -Wpedantic foo.c
$ clang -std=c11 -S -Wall -Wpedantic foo.c
$ clang -std=c17 -S -Wall -Wpedantic foo.c
$ clang -std=c2x -S -Wall -Wpedantic foo.c

> along with suitable magic to #define
> __extension__ to empty on non-gcc compilers

This is not needed. We use ({...}) only with GNU C (>= 2.8) and clang.
These compilers support __extension__.

Note also that the compiler built-ins __builtin_constant_p and
__builtin_mul_overflow are available in strict ISO C mode [2].

[1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/cpp/Common-Predefined-Macros.html
[2] https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html


2023-09-04  Bruno Haible  <bruno@clisp.org>

        Use statement-expressions without warnings, even in strict ISO C mode.
        Suggested by Eric Blake <eblake@redhat.com> in
        <https://lists.gnu.org/archive/html/bug-gnulib/2023-09/msg00025.html>.
        * lib/error.in.h (__gl_error_call): Use the variant with obvious control
        flow also with clang. Use '__extension__' to avoid -Wpedantic warnings.
        * lib/math.in.h (gl_signbitf, gl_signbitd, gl_signbitl): Define as
        macros even when __STRICT_ANSI__ is defined. But use '__extension__' to
        avoid -Wpedantic warnings.
        * lib/setenv.c (KNOWN_VALUE): Use '__extension__' to avoid -Wpedantic
        warnings.
        * lib/xalloc-oversized.h (xalloc_oversized): Use optimized variant even
        when __STRICT_ANSI__ is defined. But use '__extension__' to avoid
        -Wpedantic warnings.

diff --git a/lib/error.in.h b/lib/error.in.h
index 94477fde08..61f98c5216 100644
--- a/lib/error.in.h
+++ b/lib/error.in.h
@@ -53,7 +53,7 @@
 /* Helper macro for supporting the compiler's control flow analysis better.
    It evaluates its arguments only once.
    Test case: Compile copy-file.c with "gcc -Wimplicit-fallthrough".  */
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __clang__
 /* Use 'unreachable' to tell the compiler when the function call does not
    return.  */
 # define __gl_error_call1(function, status, ...) \
@@ -66,11 +66,12 @@
    would trigger a -Wimplicit-fallthrough warning even when STATUS is != 0,
    when not optimizing.  This causes STATUS to be evaluated twice, but
    that's OK since it does not have side effects.  */
-# define __gl_error_call(function, status, ...) \
-    (__builtin_constant_p (status) \
-     ? __gl_error_call1 (function, status, __VA_ARGS__) \
-     : ({ \
-         int const __errstatus = status; \
+# define __gl_error_call(function, status, ...)                 \
+    (__builtin_constant_p (status)                              \
+     ? __gl_error_call1 (function, status, __VA_ARGS__)         \
+     : __extension__                                            \
+       ({                                                       \
+         int const __errstatus = status;                        \
          __gl_error_call1 (function, __errstatus, __VA_ARGS__); \
        }))
 #else
diff --git a/lib/math.in.h b/lib/math.in.h
index 117bc993b5..75d5013cf1 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2695,12 +2695,13 @@ _GL_WARN_REAL_FLOATING_DECL (isnan);
 _GL_EXTERN_C int gl_signbitf (float arg);
 _GL_EXTERN_C int gl_signbitd (double arg);
 _GL_EXTERN_C int gl_signbitl (long double arg);
-#  if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__
+#  if __GNUC__ >= 2 || defined __clang__
 #   define _GL_NUM_UINT_WORDS(type) \
       ((sizeof (type) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
 #   if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT && !defined 
gl_signbitf
 #    define gl_signbitf_OPTIMIZED_MACRO
 #    define gl_signbitf(arg) \
+       __extension__                                                    \
        ({ union { float _value;                                         \
                   unsigned int _word[_GL_NUM_UINT_WORDS (float)];       \
                 } _m;                                                   \
@@ -2711,6 +2712,7 @@ _GL_EXTERN_C int gl_signbitl (long double arg);
 #   if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT && !defined 
gl_signbitd
 #    define gl_signbitd_OPTIMIZED_MACRO
 #    define gl_signbitd(arg) \
+       __extension__                                                    \
        ({ union { double _value;                                        \
                   unsigned int _word[_GL_NUM_UINT_WORDS (double)];      \
                 } _m;                                                   \
@@ -2721,6 +2723,7 @@ _GL_EXTERN_C int gl_signbitl (long double arg);
 #   if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT && !defined 
gl_signbitl
 #    define gl_signbitl_OPTIMIZED_MACRO
 #    define gl_signbitl(arg) \
+       __extension__                                                    \
        ({ union { long double _value;                                   \
                   unsigned int _word[_GL_NUM_UINT_WORDS (long double)]; \
                 } _m;                                                   \
diff --git a/lib/setenv.c b/lib/setenv.c
index 22b12fd018..706a032a49 100644
--- a/lib/setenv.c
+++ b/lib/setenv.c
@@ -82,6 +82,7 @@ typedef int (*compar_fn_t) (const void *, const void *);
 static void *known_values;
 
 # define KNOWN_VALUE(Str) \
+  __extension__                                                               \
   ({                                                                          \
     void *value = tfind (Str, &known_values, (compar_fn_t) strcmp);           \
     value != NULL ? *(char **) value : NULL;                                  \
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 5dbdfb5506..483bd11796 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -48,13 +48,13 @@
 #if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX
 # define xalloc_oversized(n, s) \
    __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1)
-#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \
-       && PTRDIFF_MAX < SIZE_MAX)
+#elif 5 <= __GNUC__ && !defined __ICC && PTRDIFF_MAX < SIZE_MAX
 # define xalloc_oversized(n, s) \
    (__builtin_constant_p (n) && __builtin_constant_p (s) \
     ? __xalloc_oversized (n, s) \
-    : ({ ptrdiff_t __xalloc_count; \
-         __builtin_mul_overflow (n, s, &__xalloc_count); }))
+    : __extension__ \
+        ({ ptrdiff_t __xalloc_count; \
+           __builtin_mul_overflow (n, s, &__xalloc_count); }))
 
 /* Other compilers use integer division; this may be slower but is
    more portable.  */






reply via email to

[Prev in Thread] Current Thread [Next in Thread]