Bug 114775 - on mingw __attribute__ ((__format__ (__printf__, ...))) doesn't recognize C99 specifiers
Summary: on mingw __attribute__ ((__format__ (__printf__, ...))) doesn't recognize C99...
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 13.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 116232 (view as bug list)
Depends on:
Blocks:
 
Reported: 2024-04-18 20:48 UTC by Nikita Kniazev
Modified: 2024-08-07 07:28 UTC (History)
3 users (show)

See Also:
Host:
Target: *-w64-mingw32
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nikita Kniazev 2024-04-18 20:48:21 UTC
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)

void _bfd_error_handler (const char *fmt, ...) ATTRIBUTE_PRINTF_1;

void foo(void) { _bfd_error_handler("%zu\n", sizeof(0)); }

$ gcc -Wall -c bug.c -std=c99
bug.c: In function 'foo':
bug.c:6:39: warning: unknown conversion type character 'z' in format [-Wformat=]
    6 | void foo(void) { _bfd_error_handler("%zu\n", sizeof(0)); }
      |                                       ^
bug.c:6:37: warning: too many arguments for format [-Wformat-extra-args]
    6 | void foo(void) { _bfd_error_handler("%zu\n", sizeof(0)); }
      |                                     ^~~~~~~


From my understanding the warning should not happen when `__USE_MINGW_ANSI_STDIO=1`, the difficulty is that it's set in `_mingw.h`, not in GCC itself, and could be set by a user or by other headers.

Possible solutions:
1) Lookup real `printf` declaration, but it won't be there if the code doesn't include `stdio.h`. False positives.
2) Query `__USE_MINGW_ANSI_STDIO` and fall back to the used C mode. Code that sets `__USE_MINGW_ANSI_STDIO` different from default value could get false positives on C89 and false negatives on C99, the logic for default value of `__USE_MINGW_ANSI_STDIO` in `_mingw.h` is more complicated than just current C mode.
3) Make GCC always be fine with C99 specifiers for now.

Any of the solutions above would be better than `-Wno-format`.
Comment 1 Andrew Pinski 2024-04-18 20:57:35 UTC
So there is mingw_printf and gnu_printf attributes for mingw because at one point %ll didn't exist for mingw and nobody has updated it since then.
Comment 2 Andrew Pinski 2024-04-18 21:05:11 UTC
(In reply to Andrew Pinski from comment #1)
> So there is mingw_printf and gnu_printf attributes for mingw because at one
> point %ll didn't exist for mingw and nobody has updated it since then.

Sorry I mean ms_printf rather than mingw_printf.

Anyways this is all documented:
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Common-Function-Attributes.html#index-format-function-attribute
Comment 3 Andrew Pinski 2024-04-18 21:05:54 UTC
If anything gnu_printf should be used instead for _bfd_error_handler and that would be a binutils issue and reported there ...
Comment 4 Andrew Pinski 2024-04-18 21:13:25 UTC
This is documented this way. If you want to use C99 printf format, you need to use gnu_printf instead (note gnu_printf format is for all targets and not just mingw).
Comment 5 Nikita Kniazev 2024-04-18 21:15:41 UTC
> So there is mingw_printf and gnu_printf attributes for mingw because at one point %ll didn't exist for mingw and nobody has updated it since then.

Do you mean that binutils and [other code out there](https://github.com/search?q=%2F__attribute__%5Cs*%5C%28%5Cs*%5C%28%5Cs*_*format_*%5Cs*%5C%28%5Cs*_*printf%2F&type=code) should be updated to use gnu_printf in attributes? That would be a lot of work, clang doesn't know gnu_printf, and is wrong for actual printf wrappers.
Comment 6 Andrew Pinski 2024-04-18 21:19:27 UTC
(In reply to Nikita Kniazev from comment #5)
> > So there is mingw_printf and gnu_printf attributes for mingw because at one point %ll didn't exist for mingw and nobody has updated it since then.
> 
> Do you mean that binutils and [other code out
> there](https://github.com/
> search?q=%2F__attribute__%5Cs*%5C%28%5Cs*%5C%28%5Cs*_*format_*%5Cs*%5C%28%5Cs
> *_*printf%2F&type=code) should be updated to use gnu_printf in attributes?
> That would be a lot of work, clang doesn't know gnu_printf, and is wrong for
> actual printf wrappers.

This has been documented/implemented this way for ~16 years now (for GCC 4.4.0), r0-86297-g6590fc9fbd071d .

https://inbox.sourceware.org/gcc-patches/OF604F1098.0E3FE32A-ONC1257408.003BB78C-C1257408.003CE7F2@onevision.de/
Comment 7 Nikita Kniazev 2024-04-18 21:35:44 UTC
(In reply to Andrew Pinski from comment #6)
> (In reply to Nikita Kniazev from comment #5)
> > > So there is mingw_printf and gnu_printf attributes for mingw because at one point %ll didn't exist for mingw and nobody has updated it since then.
> > 
> > Do you mean that binutils and [other code out
> > there](https://github.com/
> > search?q=%2F__attribute__%5Cs*%5C%28%5Cs*%5C%28%5Cs*_*format_*%5Cs*%5C%28%5Cs
> > *_*printf%2F&type=code) should be updated to use gnu_printf in attributes?
> > That would be a lot of work, clang doesn't know gnu_printf, and is wrong for
> > actual printf wrappers.
> 
> This has been documented/implemented this way for ~16 years now (for GCC
> 4.4.0), r0-86297-g6590fc9fbd071d .
> 
> https://inbox.sourceware.org/gcc-patches/OF604F1098.0E3FE32A-ONC1257408.
> 003BB78C-C1257408.003CE7F2@onevision.de/

Which attributes should use for

void my_printf(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  printf(fmt, ap);
  va_end(ap);
}

so it will behave correctly with any combination of -std=c89, -std=c99, __USE_MINGW_ANSI_STDIO=0, __USE_MINGW_ANSI_STDIO=1, _UCRT
Comment 8 Andrew Pinski 2024-04-18 21:37:54 UTC
(In reply to Nikita Kniazev from comment #7)
> (In reply to Andrew Pinski from comment #6)
> > (In reply to Nikita Kniazev from comment #5)
> > > > So there is mingw_printf and gnu_printf attributes for mingw because at one point %ll didn't exist for mingw and nobody has updated it since then.
> > > 
> > > Do you mean that binutils and [other code out
> > > there](https://github.com/
> > > search?q=%2F__attribute__%5Cs*%5C%28%5Cs*%5C%28%5Cs*_*format_*%5Cs*%5C%28%5Cs
> > > *_*printf%2F&type=code) should be updated to use gnu_printf in attributes?
> > > That would be a lot of work, clang doesn't know gnu_printf, and is wrong for
> > > actual printf wrappers.
> > 
> > This has been documented/implemented this way for ~16 years now (for GCC
> > 4.4.0), r0-86297-g6590fc9fbd071d .
> > 
> > https://inbox.sourceware.org/gcc-patches/OF604F1098.0E3FE32A-ONC1257408.
> > 003BB78C-C1257408.003CE7F2@onevision.de/
> 
> Which attributes should use for
> 
> void my_printf(const char *fmt, ...)
> {
>   va_list ap;
> 
>   va_start(ap, fmt);
>   printf(fmt, ap);
>   va_end(ap);
> }
> 
> so it will behave correctly with any combination of -std=c89, -std=c99,
> __USE_MINGW_ANSI_STDIO=0, __USE_MINGW_ANSI_STDIO=1, _UCRT

that is a good question but that is a question for the mingw forums really rather than inside gcc bugzilla.
Comment 9 Nikita Kniazev 2024-04-18 22:31:36 UTC
Ok, is there at least an option to build GCC so it defaults __printf__ to gnu_printf? Defaulting __printf__ to ms_printf on UCRT is wrong (every OS without UCRT is already EOL).
Comment 10 Andrew Pinski 2024-04-18 22:36:27 UTC
(In reply to Nikita Kniazev from comment #9)
> Ok, is there at least an option to build GCC so it defaults __printf__ to
> gnu_printf? Defaulting __printf__ to ms_printf on UCRT is wrong (every OS
> without UCRT is already EOL).

There is none yet. But any fix won't happen until GCC 15 really ...
Comment 11 Nikita Kniazev 2024-04-19 02:43:37 UTC
-mcrtdll=ucrt should make __printf__ be gnu_printf instead of ms_printf. Should I file separate issue or this one can be reopened?
Comment 12 Andrew Pinski 2024-04-19 02:51:28 UTC
(In reply to Nikita Kniazev from comment #11)
> -mcrtdll=ucrt should make __printf__ be gnu_printf instead of ms_printf.
> Should I file separate issue or this one can be reopened?

The reality is ms_printf most likely should just include z and ll support instead since they are supported now:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170

They have been included since 2015. As I mentioned GCC mingw support is out of date really and should be fixed there .
Comment 13 Nikita Kniazev 2024-04-19 03:15:49 UTC
(In reply to Andrew Pinski from comment #12)
> The reality is ms_printf most likely should just include z and ll support
> instead since they are supported now:
> https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-
> syntax-printf-and-wprintf-functions?view=msvc-170

While it makes sense, if ms_printf and gnu_printf will behave the same - there is no point in having them then.

(In reply to Andrew Pinski from comment #12)
> As I mentioned GCC mingw support is out of date really and should be fixed there .

Fixed where? IIUC the machinery is in gcc/config/i386/msformat-c.cc
Comment 14 Andrew Pinski 2024-08-05 04:51:44 UTC
*** Bug 116232 has been marked as a duplicate of this bug. ***