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