[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: error: Support the compiler's control flow analysis better (was: cop
From: |
Bruno Haible |
Subject: |
Re: error: Support the compiler's control flow analysis better (was: copy-file: Silence gcc warnings) |
Date: |
Sun, 04 Jun 2023 19:56:08 +0200 |
I did:
> (error): Define as a macro that explicitly invokes exit().
> (error_at_line): Likewise.
Oops. That patch broke the library namespacing via config.h. Namely,
when a package uses a config.h definition such as
#define error libgettextpo_error
the intent is that the Gnulib module defines a function named
'libgettextpo_error', not 'error'.
With the error.in.h change, I now get redefinition warnings and compilation
errors (on platforms other than glibc and cygwin) such as
./error.h:458:11: warning: 'error' macro redefined [-Wmacro-redefined]
# define error(status, ...) \
^
./config.h:51:9: note: previous definition is here
#define error libgettextpo_error
^
...
../../../gettext-tools/libgettextpo/gettext-po.c:1326:5: error: use of
undeclared identifier 'error'
error (EXIT_FAILURE, 0, _("memory exhausted"));
^
./error.h:459:23: note: expanded from macro 'error'
__gl_error_call (error, status, __VA_ARGS__)
^
The fix is:
1) Capture the name of the error function through an static function.
2) Since this static function is a varargs function and needs to call a
varargs function, it needs to invoke __builtin_va_arg_pack().
(The alternative would be to add a dependency from 'error' to the
'verror' module. Which is not really better...)
3) Since __builtin_va_arg_pack is only allowed in always-inline function,
we need to mark it as _GL_ATTRIBUTE_ALWAYS_INLINE.
4) The compiler then warns that the inlining may fail. To silence this
warning, we need a '#pragma GCC diagnostic ignored "-Wattributes"'.
That's more involved than what I had expected.
2023-06-04 Bruno Haible <bruno@clisp.org>
error: Fix support for library namespacing (regression 2023-05-27).
* lib/error.in.h (error): If error is defined as a macro, define a
static inline function _gl_inline_error that invokes it, and let the
new error macro invoke that function.
(error_at_line): If error_at_line is defined as a macro, define a static
inline function _gl_inline_error_at_line that invokes it, and let the
new error_at_line macro invoke that function.
diff --git a/lib/error.in.h b/lib/error.in.h
index ef4b3c3815..94477fde08 100644
--- a/lib/error.in.h
+++ b/lib/error.in.h
@@ -30,7 +30,8 @@
#ifndef _@GUARD_PREFIX@_ERROR_H
#define _@GUARD_PREFIX@_ERROR_H
-/* This file uses _GL_ATTRIBUTE_FORMAT. */
+/* This file uses _GL_ATTRIBUTE_ALWAYS_INLINE, _GL_ATTRIBUTE_FORMAT,
+ _GL_ATTRIBUTE_MAYBE_UNUSED. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
@@ -108,8 +109,28 @@ _GL_FUNCDECL_SYS (error, void,
_GL_CXXALIAS_SYS (error, void,
(int __status, int __errnum, const char *__format, ...));
# ifndef _GL_NO_INLINE_ERROR
-# define error(status, ...) \
- __gl_error_call (error, status, __VA_ARGS__)
+# ifdef error
+/* Only gcc ≥ 4.7 has __builtin_va_arg_pack. */
+# if _GL_GNUC_PREREQ (4, 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wattributes"
+_GL_ATTRIBUTE_MAYBE_UNUSED
+static void
+_GL_ATTRIBUTE_ALWAYS_INLINE
+_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 3, 4))
+_gl_inline_error (int __status, int __errnum, const char *__format, ...)
+{
+ return error (__status, __errnum, __format, __builtin_va_arg_pack ());
+}
+# pragma GCC diagnostic pop
+# undef error
+# define error(status, ...) \
+ __gl_error_call (_gl_inline_error, status, __VA_ARGS__)
+# endif
+# else
+# define error(status, ...) \
+ __gl_error_call (error, status, __VA_ARGS__)
+# endif
# endif
#endif
#if __GLIBC__ >= 2
@@ -146,8 +167,30 @@ _GL_CXXALIAS_SYS (error_at_line, void,
(int __status, int __errnum, const char *__filename,
unsigned int __lineno, const char *__format, ...));
# ifndef _GL_NO_INLINE_ERROR
-# define error_at_line(status, ...) \
- __gl_error_call (error_at_line, status, __VA_ARGS__)
+# ifdef error_at_line
+/* Only gcc ≥ 4.7 has __builtin_va_arg_pack. */
+# if _GL_GNUC_PREREQ (4, 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wattributes"
+_GL_ATTRIBUTE_MAYBE_UNUSED
+static void
+_GL_ATTRIBUTE_ALWAYS_INLINE
+_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 5, 6))
+_gl_inline_error_at_line (int __status, int __errnum, const char *__filename,
+ unsigned int __lineno, const char *__format, ...)
+{
+ return error_at_line (__status, __errnum, __filename, __lineno, __format,
+ __builtin_va_arg_pack ());
+}
+# pragma GCC diagnostic pop
+# undef error_at_line
+# define error_at_line(status, ...) \
+ __gl_error_call (_gl_inline_error_at_line, status, __VA_ARGS__)
+# endif
+# else
+# define error_at_line(status, ...) \
+ __gl_error_call (error_at_line, status, __VA_ARGS__)
+# endif
# endif
#endif
_GL_CXXALIASWARN (error_at_line);