bug-gnulib
[Top][All Lists]
Advanced

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

Re: Confusion about gnulib asprintf attribute annotation...


From: Bruno Haible
Subject: Re: Confusion about gnulib asprintf attribute annotation...
Date: Thu, 31 Mar 2011 01:58:55 +0100
User-agent: KMail/1.9.9

Eric Blake wrote:
> We only accept a subset of __gnu_printf__ in the gnulib replacement (for
> example, gnulib supports %Id on glibc, but not elsewhere, even though
> using attribute __gnu_printf__ would not warn about use of %Id).

GCC calls it "gnu_printf" but it actually denotes the C90 or C99 syntax
of printf format strings, depending on the -std option. And the syntax
checks are the same on glibc systems (which support the 'I' flag) and
on platforms other than glibc and mingw (which don't support the 'I' flag).
To demonstrate this: The program

==================================== foo.c ====================================
extern int pf (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 
2)));
extern int gpf (const char *, ...) __attribute__ ((__format__ (__gnu_printf__, 
1, 2)));

void foo (long long x)
{
  pf ("%Id", (int)x);
  gpf ("%Id", (int)x);
}
===============================================================================

yields the following warnings with GCC 4.4.5, both on a glibc system and on an
AIX 7.1 system:

$ gcc -Wall -S foo.c -std=gnu99
[no warning]
$ gcc -Wall -pedantic -S foo.c -std=gnu99
foo.c: In function 'foo':
foo.c:6: warning: ISO C does not support the 'I' printf flag
foo.c:7: warning: ISO C does not support the 'I' printf flag

Eric Blake wrote:
> sounds like we might really want an explicit __gnu_printf__ on
> asprintf, regardless of whether it was asprintf or asprintf-posix
> module

Yes, because our implementation of asprintf calls vasnprintf.

> whereas the printf declaration gets __printf__ for the printf 
> module and __gnu_printf__ for the printf-posix module.

Yes, except that when the printf and vfprintf-posix module is used,
we need __gnu_printf__ as well.

This patch should fix it all. I've committed it. Can you please report if
it doesn't work for you?


2011-03-30  Bruno Haible  <address@hidden>

        stdio: Avoid GCC >= 4.4 warnings when using %lld and similar on mingw.
        * lib/stdio.in.h (_GL_ATTRIBUTE_FORMAT_PRINTF): Use 'gnu_printf' format
        instead of 'printf' format for GCC >= 4.4.
        (_GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM): New macro.
        (fprintf, printf, vfprintf, vprintf): Declare with
        _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM when the function ends up calling
        the system's vfprintf() function.
        Reported by Daniel P. Berrange <address@hidden> via Eric Blake.

--- lib/stdio.in.h.orig Thu Mar 31 02:50:04 2011
+++ lib/stdio.in.h      Thu Mar 31 02:49:58 2011
@@ -67,7 +67,24 @@
 #else
 # define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
 #endif
-#define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
+
+/* _GL_ATTRIBUTE_FORMAT_PRINTF
+   indicates to GCC that the function takes a format string and arguments,
+   where the format string directives are the ones standardized by ISO C99
+   and POSIX.  */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
+   _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, 
first_argument))
+#else
+# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
+   _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
+#endif
+
+/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF,
+   except that it indicates to GCC that the supported format string directives
+   are the ones of the system printf(), rather than the ones standardized by
+   ISO C99 and POSIX.  */
+#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, 
first_argument) \
   _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
 
 /* Solaris 10 declares renameat in <unistd.h>, not in <stdio.h>.  */
@@ -191,9 +208,15 @@
 #   define fprintf rpl_fprintf
 #  endif
 #  define GNULIB_overrides_fprintf 1
+#  if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
 _GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...)
                                 _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
                                 _GL_ARG_NONNULL ((1, 2)));
+#  else
+_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...)
+                                _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3)
+                                _GL_ARG_NONNULL ((1, 2)));
+#  endif
 _GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...));
 # else
 _GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...));
@@ -694,12 +717,21 @@
 /* Don't break __attribute__((format(printf,M,N))).  */
 #    define printf __printf__
 #   endif
+#   if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
 _GL_FUNCDECL_RPL_1 (__printf__, int,
                     (const char *format, ...)
                     __asm__ (@ASM_SYMBOL_PREFIX@
                              _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf))
                     _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2)
                     _GL_ARG_NONNULL ((1)));
+#   else
+_GL_FUNCDECL_RPL_1 (__printf__, int,
+                    (const char *format, ...)
+                    __asm__ (@ASM_SYMBOL_PREFIX@
+                             _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf))
+                    _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2)
+                    _GL_ARG_NONNULL ((1)));
+#   endif
 _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...));
 #  else
 #   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -1004,9 +1036,15 @@
 #   define vfprintf rpl_vfprintf
 #  endif
 #  define GNULIB_overrides_vfprintf 1
+#  if @GNULIB_VFPRINTF_POSIX@
 _GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)
                                  _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
                                  _GL_ARG_NONNULL ((1, 2)));
+#  else
+_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)
+                                 _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0)
+                                 _GL_ARG_NONNULL ((1, 2)));
+#  endif
 _GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args));
 # else
 /* Need to cast, because on Solaris, the third parameter is
@@ -1034,9 +1072,15 @@
 #   define vprintf rpl_vprintf
 #  endif
 #  define GNULIB_overrides_vprintf 1
+#  if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
 _GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args)
                                 _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0)
                                 _GL_ARG_NONNULL ((1)));
+#  else
+_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args)
+                                _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0)
+                                _GL_ARG_NONNULL ((1)));
+#  endif
 _GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args));
 # else
 /* Need to cast, because on Solaris, the second parameter is

-- 
In memoriam Airey Neave <http://en.wikipedia.org/wiki/Airey_Neave>



reply via email to

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