bug-gnulib
[Top][All Lists]
Advanced

[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);






reply via email to

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