[Bug c/95130] GCC ignoring attribute(format(gnu_printf)) on printf in mingw

2024-04-19 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95130

--- Comment #25 from Martin Storsjö  ---
(In reply to Andrew Pinski from comment #23)
> Note since MSVC 2015 runtime, printf has support %ll so ms_printf should be
> fixed to incldue that.
> 
> https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-
> syntax-printf-and-wprintf-functions?view=msvc-140
> 
> I think for GCC 15, we should just update ms_printf to the 2015 version of
> what is supported ...

As long as GCC links against msvcrt.dll, distributed with the OS, the time
since it's supported in MSVC doesn't affect things much though.

But as Liu Hao noted, we already do support %lld in ms_printf since
c51f1e7427e6a5ae2a6d82b5a790df77a3adc99a, since it apparently was supported in
the OS provided msvcrt.dll since a number of versions anyway.

(In reply to LIU Hao from comment #24)
> `%L` (for floating-point specifiers) is not compatible between `ms_printf`
> and `gnu_printf`.

We do use gnu_printf for the UCRT printf functions (which is what MSVC ships
since 2015) though, see e.g.
https://github.com/mingw-w64/mingw-w64/commit/8565cdb729b96f1122b1e9c490a7baba7b788f18.

But since the change in c51f1e7427e6a5ae2a6d82b5a790df77a3adc99a (released in
GCC 12 already), we probably don't need this any longer. So I think it might be
more correct to revert to ms_printf for UCRT, at least for GCC >= 12 - what do
you think?

[Bug c/95130] GCC ignoring attribute(format(gnu_printf)) on printf in mingw

2022-10-25 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95130

--- Comment #8 from Martin Storsjö  ---
(In reply to Tomas Kalibera from comment #7)
> I sent an updated version for the trunk, 12, 11 and 10 to the gcc-patches
> mailing list in May:
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2022-May/594960.html
> 
> The patches still apply to current 10,11,12 and trunk. Please see the email
> linked above for more information.

Did you notice the review comment in July,
https://gcc.gnu.org/pipermail/gcc-patches/2022-July/59.html?

[Bug target/105506] Error building GCC 12.1.0 against MinGW-w64: fatal error: cannot execute 'cc1': CreateProcess: No such file or directory

2022-06-06 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105506

--- Comment #8 from Martin Storsjö  ---
(In reply to Brecht Sanders from comment #7)
> So I guess the question that remains is: Where is -D__USE_MINGW_ACCES
> missing in the configuration of GCC 12?
> 
> It would seem to me the answer lies in code added since GCC 11 that contains
> access()/X_OK.

I bisected, and it seems like a build system adjustment makes it lose the flags
that are added in config/mh-mingw (where they are added to CFLAGS, CXXFLAGS and
a bunch of other *_CXXFLAGS). The built GCC reproduces the issue since this
commit:

https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4a5e71f2348adcc49939804889d9f1a64d97005a

Unfortunately, the build system changes here are slightly complex, so it's not
entirely obvious to me where the flags that are added to CFLAGS/CXXFLAGS are
lost.

(Due to other commits around it, cross compiling GCC from linux to windows
fails entirely, until a couple commits later though -
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ab18659afc054434cef4d4757a3519f1100adc52
- but I tested the commit above with this one cherrypicked on top.)

[Bug target/105506] Error building GCC 12.1.0 against MinGW-w64: fatal error: cannot execute 'cc1': CreateProcess: No such file or directory

2022-06-05 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105506

Martin Storsjö  changed:

   What|Removed |Added

 CC||martin at martin dot st

--- Comment #6 from Martin Storsjö  ---
This is an old longstanding issue that seems to have reappeared, but which has
been fixed differently recently in the very latest mingw-w64 git. But first a
brief history of the issue:

GCC uses the access() function for checking whether a binary exists and is
executable (with the X_OK flag as parameter). On Windows, there's no separate
"execute" permission bit, but the X_OK bit (which isn't a documented parameter
from Microsoft's side) used to be ignored.

In Vista, msvcrt.dll's access() function suddenly stopped ignoring the bit that
was used for X_OK (which mingw had decided to use for that purpose), and
started erroring out when this bit was set. This was dealt with in 2007 in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33281, by adding a
reimplementation of the access() function in mingw. By defining
__USE_MINGW_ACCESS, the access() function is redirected to the __mingw_access()
function. GCC set -D__USE_MINGW_ACCESS when building on mingw to include this
workaround.

After some time, it seems like Microsoft reverted this behaviour in
msvcrt.dll's access() function, because now it no longer seems like this
behaviour is present, not on modern Windows 10, but not even on "modern"
installations of Vista either. So the need for -D__USE_MINGW_ACCESS has
vanished (and bitrotted in GCC somewhat).

UCRT's access() function does have the same issue though - if passed the
undocumented, mingw-invented X_OK bit, it errors out. As GCC did try to define
__USE_MINGW_ACCESS, the workaround should have been picked up though, but as
GCC's codebase had evolved, the define wasn't being set in all the cases where
it might have been needed. This was fixed for GCC 11 in
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=89e95ad2e7679322b2f5ee9070ff2721d5ca1d6d
(and later backported to GCC 9 and 10 in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101238).

But apparently something has changed further in GCC 12, so that this define
doesn't end up set in all the places where it needs to. (It'd be interesting to
know why/where/when!) In mingw-w64, we decided to enable this workaround
unconditionally for UCRT (as a more general fix for other audiences, although
GCC is the only one I've heard of needing it) - skipping the UCRT provided
access() function and always using the mingw reimplementation, see
https://github.com/mingw-w64/mingw-w64/commit/bceadc54d8f32b3f14c69074892e2718eac08e3b.

So to successfully build GCC 12 running on UCRT, you'd need to use another GCC
install, with the very latest mingw-w64 (or an older release with that fix
cherry-picked, plus the following Makefile.in update from
https://github.com/mingw-w64/mingw-w64/commit/89bacd2be60fa92dd74d3b5f2074b06a32d8c784),
to build GCC 12. Alternatively, see if you can manually pass
-D__USE_MINGW_ACCESS to the GCC 12 build, if it'd end up in all the places
where it's needed.

[Bug c/103956] New: [10 Regression] -Wstringop-overflow= false positive on -O3 for writes to array

2022-01-09 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103956

Bug ID: 103956
   Summary: [10 Regression] -Wstringop-overflow= false positive on
-O3 for writes to array
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: martin at martin dot st
  Target Milestone: ---

Since GCC 10.0, the following snippet produces warnings (various numbers of
warnings with the same issue) for this reduced snippet:

$ cat repro.c
struct data {
  unsigned char array[10];
};
void copy(struct data *data, unsigned char *src, int n) {
  int i;
  for (i = 0; i < n; i++)
data->array[i] = src[i];
}
$ gcc -c -O3 repro.c
repro.c: In function 'copy':
repro.c:7:20: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
7 | data->array[i] = src[i];
  | ~~~^~~~
repro.c:2:17: note: at offset 10 into destination object 'array' of size 10
2 |   unsigned char array[10];
  | ^


It doesn't reproduce at -O2.

The issue is also testable on Compiler Explorer:
https://godbolt.org/z/xsc3K37jK

[Bug target/103274] [10/11/12 regression] remaining -freorder-blocks-and-partition/ glitch with Windows SEH

2021-11-30 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103274

--- Comment #11 from Martin Storsjö  ---
(In reply to Eric Botcazou from comment #10)
> Thanks for reporting the problem.

Thanks for the fix! I can confirm that the version of the patch backported on
the gcc-10 branch fixes the testcase at least. Let's hope that it manages to
fix all the instances of the issue in real-world use too.

[Bug target/103274] Remaining -freorder-blocks-and-partition/ glitch with Windows SEH

2021-11-16 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103274

--- Comment #4 from Martin Storsjö  ---
Also for additional context; with GCC 9.x, this testcase had the needed nop
instruction between "call" and ".seh_endproc".

In GCC 10.x (regressed in
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=095f78c62157124ad479a3f98b6995ced090b807),
-freorder-blocks-and-partition applies on this function and it gets split into
a hot and cold part, and the needed "nop" instruction disappeared.

If building with -fno-reorder-blocks-and-partition, the issue disappears and
you get roughly the same output as in GCC 9.x

This seems like the same issue as was fixed in
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=15278fb2877184c75a6ee3a6def09efbb191968b;hp=9d3b9a3e70e634c7c48bb12bb35ec8219024f98b
- but that fix doesn't seem to help here, as builds of GCC that include that
commit still are missing the nop between "call" and ".seh_endproc".

[Bug target/103274] Remaining -freorder-blocks-and-partition/ glitch with Windows SEH

2021-11-16 Thread martin at martin dot st via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103274

Martin Storsjö  changed:

   What|Removed |Added

 CC||martin at martin dot st

--- Comment #3 from Martin Storsjö  ---
(In reply to Eric Botcazou from comment #1)
> > -freorder-blocks-and-partition sometimes causes a function to end right in a
> > (non-returning) call, but SEH needs at least one more instruction on x86_64.
> > Seen in GCC 10.3, 11.2 and git master. Maybe [1] did not cover all the 
> > cases?
> 
> SEH means "Structured Exception Handling" but there is no exception handling
> in this chunk of program since it's written in C and compiled without
> -fexceptions, so I'm not quite sure what you're expecting here.

Even if it doesn't have explicit exception handling, there's still unwind
information generated, and the needed "nop" instruction between the trailing
"call" instruction and ".seh_endproc" is missing.

[Bug c/95130] New: GCC ignoring attribute(format(gnu_printf)) on printf in mingw

2020-05-14 Thread martin at martin dot st
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95130

Bug ID: 95130
   Summary: GCC ignoring attribute(format(gnu_printf)) on printf
in mingw
   Product: gcc
   Version: 9.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: martin at martin dot st
  Target Milestone: ---

Since a long time (GCC 4.4?) GCC does support annotating functions with either
the format attribute "gnu_printf" or "ms_printf" to distinguish between
different format string interpretations.

However, it seems like the attribute is ignored for the "printf" symbol;
regardless what the function declaration says, GCC treats it as "ms_printf".
This has become an issue now that mingw-w64 supports using the UCRT instead of
msvcrt.dll, and in this case the stdio functions are declared with the
gnu_printf attribute, and inttypes.h uses the same format specifiers as in GNU
mode.

A reproducible example of the problem:

$ cat format.c
__attribute__((__format__ (gnu_printf, 1, 2))) int printf (const char
*__format, ...);
__attribute__((__format__ (gnu_printf, 1, 2))) int othername (const char
*__format, ...); 

void function(void) {
long long unsigned x = 42;
othername("%llu\n", x);
printf("%llu\n", x);
}
$ x86_64-w64-mingw32-gcc -c -Wformat format.c 
format.c: In function 'function':
format.c:7:15: warning: unknown conversion type character 'l' in format
[-Wformat=] 
7 | printf("%llu\n", x); 
  |   ^
format.c:7:12: warning: too many arguments for format [-Wformat-extra-args]
7 | printf("%llu\n", x);
  |^~~~


Note how both functions, printf and othername, are declare with identical
gnu_printf format attributes - GCC does take this into account for "othername"
and doesn't produce a warning, but GCC seems to disregard the attribute in the
printf declaration and behave as if it was declared as ms_printf.

If the printf function declaration is changed into a static inline function,
the actual attribute used is honored though.

[Bug c++/89088] Dllexport for explicit template instantiation missing inline methods

2019-04-26 Thread martin at martin dot st
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89088

--- Comment #1 from Martin Storsjö  ---
FWIW, Clang (when operating in MinGW mode, where it tries to follow what GCC
does) also had the same issue. There this issue was fixed by making dllexport
export inline methods as well, for template instantiations:
https://github.com/llvm-project/clang/commit/2061b0cab0002c264af632bf5e6ba5306c589c94

[Bug c++/89087] Dllexport for explicit template instantiation with nested classes loses nested class

2019-04-26 Thread martin at martin dot st
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89087

--- Comment #1 from Martin Storsjö  ---
FWIW, Clang (when operating in MinGW mode, where it tries to follow what GCC
does) also had the same issue. There this issue was fixed by emitting
definitions for nested classes even if a template instantiation has been
declared, like this:
https://github.com/llvm-project/clang/commit/7331c3301af9628719664c9a4feea576df3994a9

[Bug c++/89088] New: Dllexport for explicit template instantiation missing inline methods

2019-01-28 Thread martin at martin dot st
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89088

Bug ID: 89088
   Summary: Dllexport for explicit template instantiation missing
inline methods
   Product: gcc
   Version: 8.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: martin at martin dot st
  Target Milestone: ---

Created attachment 45538
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45538=edit
Sample code showing the issue

With dllexported explicit template instantiation, inline methods aren't
exported, but callers still create undefined references to the inline methods,
which fail due to the missing export. (This can be remedied by applying
-Wl,--export-all-symbols to export all generated symbols, regardless of
dllexport attributes.)

Example:

header.h:
template  struct C {
  void f();
  void g() {}
};

template  void C::f() {}

extern template class
#ifdef DLLEXPORT
__declspec(dllexport)
#elif defined(DLLIMPORT)
__declspec(dllimport)
#endif
C;

lib.cpp:
#define DLLEXPORT
#include "header.h"

template class C;

caller.cpp:
#define DLLIMPORT
#include "header.h"

int main(int argc, char* argv[]) {
  C a;
  a.g();
  return 0;
}

Building of this fails in this way:
$ make
x86_64-w64-mingw32-g++-c -o caller.o caller.cpp
x86_64-w64-mingw32-g++-c -o lib.o lib.cpp
x86_64-w64-mingw32-g++ -shared -o lib.dll lib.o -Wl,--out-implib,liblib.dll.a
x86_64-w64-mingw32-g++ -o caller.exe caller.o -L. -llib
caller.o:caller.cpp:(.text+0x1c): undefined reference to `C::g()'
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'caller.exe' failed
make: *** [caller.exe] Error 1


The instantiation definition in lib.cpp emitted both methods, but only export
the non-inline method:
$ x86_64-w64-mingw32-nm lib.o 

 T _ZN1CIcE1fEv
 T _ZN1CIcE1gEv
$ x86_64-w64-mingw32-objdump -s lib.o

Contents of section .drectve:
  202d6578 706f7274 3a225f5a 4e314349   -export:"_ZN1CI
 0010 63453166 45762200cE1fEv".

However, despite this, the caller creates an undefined reference to the inline
method:
$ x86_64-w64-mingw32-nm caller.o 

 T main
 U _ZN1CIcE1gEv

[Bug c++/89087] New: Dllexport for explicit template instantiation with nested classes loses nested class

2019-01-28 Thread martin at martin dot st
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89087

Bug ID: 89087
   Summary: Dllexport for explicit template instantiation with
nested classes loses nested class
   Product: gcc
   Version: 8.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: martin at martin dot st
  Target Milestone: ---

Created attachment 45537
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45537=edit
Sample code showing the issue

When an explicit template instantiation of a template class with a nested class
is declared with the dllexport attribute, only members from the outer class
actually gets the embedded export directive.

A caller that sees the explicit template instantiation declaration won't emit
those symbols but produce undefined references to them (both for the outer and
inner class), relying on the template instantiation in a different translation
unit.

If relying on the dllexport attribute for exporting the relevant symbols, only
the outer class' members are exported, and linking to the dll fais.


To showcase the problem:

header.h:
template  struct outer {
  void f();
  struct inner {
void f();
  };
};

template  void outer::f() {}
template  void outer::inner::f() {}

extern template class
#ifdef DLLEXPORT
__declspec(dllexport)
#elif defined(DLLIMPORT)
__declspec(dllimport)
#endif
outer;


lib.cpp:
#define DLLEXPORT
#include "header.h"

template class outer;

caller.cpp:
#define DLLIMPORT
#include "header.h"

int main(int argc, char* argv[]) {
  outer a;
  a.f();
  outer::inner b;
  b.f();
  return 0;
}


Building this fails in this way:
$ make
x86_64-w64-mingw32-g++-c -o caller.o caller.cpp
x86_64-w64-mingw32-g++-c -o lib.o lib.cpp
x86_64-w64-mingw32-g++ -shared -o lib.dll lib.o -Wl,--out-implib,liblib.dll.a
x86_64-w64-mingw32-g++ -o caller.exe caller.o -L. -llib
caller.o:caller.cpp:(.text+0x28): undefined reference to
`outer::inner::f()'
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'caller.exe' failed
make: *** [caller.exe] Error 1


The template instantiation in lib.cpp does get both outer and inner function
definitions:
$ x86_64-w64-mingw32-nm lib.o

 T _ZN5outerIcE1fEv
 T _ZN5outerIcE5inner1fEv

And the caller gets undefined references to the same:
$ x86_64-w64-mingw32-nm caller.o 

 T main
 U _ZN5outerIcE1fEv
 U _ZN5outerIcE5inner1fEv

But only the outer function actually ended up exported from the DLL:
$ x86_64-w64-mingw32-objdump -s lib.o

Contents of section .drectve:
  202d6578 706f7274 3a225f5a 4e356f75   -export:"_ZN5ou
 0010 74657249 63453166 45762200   terIcE1fEv".


If the DLL is linked with -Wl,--export-all-symbols, both functions are exported
from the DLL and linking succeeds.


This is contrary to MSVC (which admittedly has got an entirely different C++
ABI). In MSVC, the caller emits the inner class' methods despite the explicit
template instantiation (both when the template instantiation was marked
dllimport, but also if dllimport is omitted):

With dllimport:
$ cl -nologo -c caller.cpp 
caller.cpp
$ x86_64-w64-mingw32-nm caller.obj 

 T ?f@inner@?$outer@D@@QEAAXXZ
 U __imp_?f@?$outer@D@@QEAAXXZ
 T main

Without dllimport:
$ cat caller.cpp | sed 's/^#def.*//' > caller-nodllimport.cpp
$ ~/msvc2017/bin64/cl -nologo -c caller-nodllimport.cpp 
caller-nodllimport.cpp
$ x86_64-w64-mingw32-nm caller-nodllimport.obj 

 T ?f@inner@?$outer@D@@QEAAXXZ
 U ?f@?$outer@D@@QEAAXXZ
 T main



To solve this (short of requiring using -Wl,--export-all-symbols on any library
that uses explicit template instantiation with nested classes), the dllexport
either needs to cover the nested class, or an explicit template instantiation
should only be considered to cover the outer class.