Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#1162 GCC 4.3.0 alpha printf has a weird behavior

OTHER
closed
nobody
gcc (462)
out-of-date
Unknown
2013-02-05
2008-05-13
Paulo Lopes
No

printf has emits a warning on the following code which prevents to build some software that enable warnings as errors such as GDB 6.8.

here is one example:

#include <stdio.h>

int
main(int argc, char **argv)
{
long long int tick = 1;
printf("sizoef(tick): %d\n", sizeof(tick));
tick <<= 62;
printf("Big number: %lld\n", tick);
printf("Big number: %I64d\n", tick);

return 0;
}

this code builds without warnings and errors with GCC 4.2.1. and 3.4.5 with:

gcc -Wall -ansi test.c

With 4.3.0 it emits:

test.c: In function 'main':
test.c:10: warning: format '%I64d' expects type 'int', but argument 2 has type 'long long int'

And GDB fails to build.

Since this is not a GDB bug I think that warning should not be emitted from GCC 4.3.0 as before.

Discussion

  • FX
    FX
    2008-06-06

    Logged In: YES
    user_id=865300
    Originator: NO

    With current 4.4 (that is: gcc version 4.4.0 20080606 (experimental) [trunk revision 136436]), the behaviour observed is:

    $ gcc a.c -Wall -ansi
    a.c: In function 'main':
    a.c:9: warning: unknown conversion type character 'l' in format
    a.c:9: warning: too many arguments for format

    That is, the I64 warning has been taken care of, but you're apparently not supposed to use %lld format then.

     
  • Paulo Lopes
    Paulo Lopes
    2008-06-06

    Logged In: YES
    user_id=242158
    Originator: YES

    I'm ok with that since GDB would build without problems.

     
  • Keith Marshall
    Keith Marshall
    2008-06-07

    Logged In: YES
    user_id=823908
    Originator: NO

    > That is, the I64 warning has been taken care of, but you're
    > apparently not supposed to use %lld format then.

    Which is completely asinine!

    IMO, gcc is just trying to be too @~!&%$ clever for its own good here. "%I64d" may well be Microsoft convention for where the rest of the world uses "%lld", (as mandated by C99/POSIX), but we don't have to use Microsoft's crazy implementation. Anyone is free to replace any part of the MSVCRT runtime support, with enhanced functions of their own; indeed, we do exactly that with __mingw_snprintf(), (which IIRC was inspired by a requirement of gcc, for gfortran).

    __mingw_snprintf() goes out of its way to support *both* the standard C99/POSIX format specifications, *and* the Microsoft alternatives, so for gcc to now turn around and say that "%lld" is invalid is nothing short of biting the hand which feeds it. Agreed, __mingw_snprintf() only gives us snprintf() and vsnprintf() at present, but I am looking into extending its coverage to *all* of the printf() family of functions; when that is complete, MinGW *will* consider "%I64d" and "%lld" to be synonymous.

    FX, I know you are closely involved with gcc development; please take appropriate steps to ensure that this rejection of what should be perfectly valid syntax is sensibly resolved.

     
  • FX
    FX
    2008-06-07

    Logged In: YES
    user_id=865300
    Originator: NO

    Danny Smith was involved in the design and approval of the patch, so I reckon it's not a case of "GCC vs mingw" disagreement... you can probably discuss it directly with him. It seems consensus is hard to reach on that issue, so I'm not willing to step in :)

     
  • Paulo Lopes
    Paulo Lopes
    2008-06-07

    Logged In: YES
    user_id=242158
    Originator: YES

    Well I'm always in favor of using standards and l64d is not the standard but was accepted before, I guess then mingw/gcc should agree on what to use and then gdb people should be notified in order to change their macro definition to use the correct format string.

     
  • Keith Marshall
    Keith Marshall
    2008-06-07

    Logged In: YES
    user_id=823908
    Originator: NO

    "%lld" is the "standard", as defined by C99/POSIX, but since when have Microsoft respected any standard other than those they create for themselves; in this case *their* standard is "%I64d", and the MSVCRT implementation of printf() and friends will simply ignore "%lld", and consume a plain `int' argument.

    The "correct" solution, for *all* projects, is to use the macros defined in `inttypes.h'; that makes the code portable to any platform which provides an implementation specific `inttypes.h'.

    However, I'm surprised that Danny would be party to this nonsense of declaring "%lld" invalid for MinGW; it was he who provided the original mingw_snprintf.c implementation, and that very much does the right thing for "%lld".

    While I applaud the intentions of the GCC developers, in attempting to validate printf arguments against the format string, I would suggest that ultimately, this is doomed to fail; the GCC developers *cannot* second guess what format specifiers will be supported by any implementation of printf that a user may choose to install, in place of the compiler vendor's default, and rejecting forms mandatated by an ISO standard is ultimately likely to produce a deluge of bug reports.

    IMO, this *IS* a GCC bug; please report it upstream.

     
  • Danny Smith
    Danny Smith
    2008-06-07

    Logged In: YES
    user_id=11494
    Originator: NO

    Here is the gcc 4.4.0 documentation of the __attribute__((format ( printf, ..)

    `format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)'
    The `format' attribute specifies that a function takes `printf',
    `scanf', `strftime' or `strfmon' style arguments which should be
    type-checked against a format string. For example, the
    declaration:

    extern in
    my_printf (void *my_object, const char *my_format, ...)
    __attribute__ ((format (printf, 2, 3)));

    causes the compiler to check the arguments in calls to `my_printf'
    for consistency with the `printf' style format string argument
    `my_format'.

    The parameter ARCHETYPE determines how the format string is
    interpreted, and should be `printf', `scanf', `strftime',
    `gnu_printf', `gnu_scanf', `gnu_strftime' or `strfmon'. (You can
    also use `__printf__', `__scanf__', `__strftime__' or
    `__strfmon__'.) On MinGW targets, `ms_printf', `ms_scanf', and
    `ms_strftime' are also present. ARCHTYPE values such as `printf'
    refer to the formats accepted by the system's C run-time library,
    while `gnu_' values always refer to the formats accepted by the
    GNU C Library. On Microsoft Windows targets, `ms_' values refer
    to the formats accepted by the `msvcrt.dll' library. The
    parameter STRING-INDEX specifies which argument is the format
    string argument (starting from 1), while FIRST-TO-CHECK is the
    number of the first argument to check against the format string.
    For functions where the arguments are not available to be checked
    (such as `vprintf'), specify the third parameter as zero. In this
    case the compiler only checks the format string for consistency.
    For `strftime' formats, the third parameter is required to be zero.
    Since non-static C++ methods have an implicit `this' argument, the
    arguments of such methods should be counted from two, not one, when
    giving values for STRING-INDEX and FIRST-TO-CHECK.

    In the example above, the format string (`my_format') is the second
    argument of the function `my_print', and the arguments to check
    start with the third argument, so the correct parameters for the
    format attribute are 2 and 3.

    The `format' attribute allows you to identify your own functions
    which take format strings as arguments, so that GCC can check the
    calls to these functions for errors. The compiler always (unless
    `-ffreestanding' or `-fno-builtin' is used) checks formats for the
    standard library functions `printf', `fprintf', `sprintf',
    `scanf', `fscanf', `sscanf', `strftime', `vprintf', `vfprintf' and
    `vsprintf' whenever such warnings are requested (using
    `-Wformat'), so there is no need to modify the header file
    `stdio.h'. In C99 mode, the functions `snprintf', `vsnprintf',
    `vscanf', `vfscanf' and `vsscanf' are also checked. Except in
    strictly conforming C standard modes, the X/Open function
    `strfmon' is also checked as are `printf_unlocked' and
    `fprintf_unlocked'. *Note Options Controlling C Dialect: C
    Dialect Options.

    Now, the default for mingw (32 and 64 bit OS) is "ms_printf".
    Using "%lld" raises a warning (with -Wformat) that the "ll" length modifier is not supported. That is a useful warning for all of the ms_printf family.

    To override and be GNULY_CORRECT, add attribute ({format (gnu_printf, ...) to eg mingw_snprintf.

    When we have a thread-safe [w]printf family (ideally one that can stay in sync with IO streams in third party libs that use msvcrt.dll printf), than we can add a new archetype to GCC'S FORMAT WARNING for 'mingw_printf' and 'mingw_scanf'.

    Danny

     
  • David Brownell
    David Brownell
    2009-10-15

    I'm told the problem comes up even when "-std=gnu99" is given on the command line. It's hard for me to accept this behavior as anything other than a bug in that context. The intent of such -std specifiers is portability, but this "kowtow to Microsoft" line is an obstacle to portable code.

    I'm also told the same general issue shows up with "%zd" and "%jd" style printf formats, where the standard size-agnostic printf format specifiers do not work.

     
  • Earnie Boyd
    Earnie Boyd
    2013-02-05

    • labels: --> gcc
    • status: open --> closed
    • resolution: --> out-of-date
    • category: --> Unknown
    • milestone: --> OTHER
     
  • Earnie Boyd
    Earnie Boyd
    2013-02-05

    I believe this to be corrected with a command line option to suppress the warnings for Microsoft enabled formats.