https://bugs.winehq.org/show_bug.cgi?id=48160
Bug ID: 48160 Summary: cl.exe (visual studio 2017) fails to compile c++ due to error C2177: constant too big Product: Wine Version: 4.20 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: luca.cunegondi@ocme.com Distribution: ---
when compiling c++ filles with options /TP /EHsc /std:c++17 cl.exe fails with the error described above, even for a single line program like:
#include <iostream> int main() { return 1;}
The error message is:
... include\limits(1153): error C2177: constant too big ... include\limits(1216): error C2177: constant too big
and is relative to DBL_MAX and LDBL_MAX constants Values of such constants are correct if compiling with preprocessing option only
There's no problem compiling C programs or using previous versions of Wine
thanks in advance
luca cunegondi
https://bugs.winehq.org/show_bug.cgi?id=48160
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |regression
--- Comment #1 from Austin English austinenglish@gmail.com --- So C++ worked in previous wine versions? Can you run a regression test? https://wiki.winehq.org/RegressionTesting
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #2 from luca.cunegondi@ocme.com --- (In reply to Austin English from comment #1)
So C++ worked in previous wine versions? Can you run a regression test? https://wiki.winehq.org/RegressionTesting
ran a regression test with the following final output:
0e183cc3c0d3b6f89f79047cdd71c389afc75073 is the first bad commit commit 0e183cc3c0d3b6f89f79047cdd71c389afc75073 Author: Alexandre Julliard julliard@winehq.org Date: Sat Nov 2 14:35:52 2019 +0100
msvcrt: Don't change FPU control word in _control87() on x86-64.
Signed-off-by: Alexandre Julliard julliard@winehq.org
dlls/msvcrt/math.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
the bug occurs in 64bit wine and wine-staging (don't know for 32bit)
the last working version is 4.19
thank you very much
https://bugs.winehq.org/show_bug.cgi?id=48160
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Regression SHA1| |0e183cc3c0d3b6f89f79047cdd7 | |1c389afc75073 CC| |julliard@winehq.org
https://bugs.winehq.org/show_bug.cgi?id=48160
Roman Pišl rpisl@seznam.cz changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |rpisl@seznam.cz
https://bugs.winehq.org/show_bug.cgi?id=48160
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |erich.e.hoover@gmail.com
--- Comment #3 from Alexandre Julliard julliard@winehq.org --- *** Bug 48263 has been marked as a duplicate of this bug. ***
https://bugs.winehq.org/show_bug.cgi?id=48160
Aaron Simmons paleozogt@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |paleozogt@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #4 from Erich E. Hoover erich.e.hoover@gmail.com --- Created attachment 65950 --> https://bugs.winehq.org/attachment.cgi?id=65950 override the x87 FPU control word in strtod_helper (even on x86-64)
Sorry for the duplicate :/
I've been investigating this a bit and this one is very tricky... 1) this is not a "real" regression, the patch is doing the exact correct behavior (lots of testbot results here) 2) there is no special undocumented flag that the application is sending to request different behavior 3) none of the fp*/fe* functions appear to touch the x87 FPU 4) the application itself does not appear to change the x87 FPU control word 5) the small number of x87 FPU instructions within Wine are not codepaths that the application is exercising 6) there are no relevant stubs being called (just __telemetry_main_return_trigger) 7) ignoring x87 FPU errors in _statusfp does not help
So, I started looking for routines that flag MSVCRT_ERANGE and discovered that the problem is occurring in msvcrt:string.c:strtod_helper because of our use of "long double". Apparently, this causes gcc to generate x87 FPU instructions instead of SSE2 instructions so our now-correct x87 precision is coming back to bite us. There are a couple ways to work around this: 1) override the x87 FPU settings within the context of this calculation 2) try to change the routine to be able to work with regular doubles 3) write our own SSE2 assembly to handle this case
I've attached a patch that takes approach #1 and would appreciate some feedback on whether this looks suitable.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #5 from Alexandre Julliard julliard@winehq.org --- We'll need to rewrite that function to not use long double, because the goal is to support building it with Mingw.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #6 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Alexandre Julliard from comment #5)
We'll need to rewrite that function to not use long double, because the goal is to support building it with Mingw.
I can confirm that plopping a minimal version of this routine into one of the tests (so that it compiles with mingw) also produces x87 instructions. I don't think that anything that I did in attachment 65950 would break in mingw (it just adjusts the x87 FPU precision temporarily and then sets it back), but I'll take a stab at figuring out how to do this operation without long double.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #7 from Erich E. Hoover erich.e.hoover@gmail.com --- Created attachment 65961 --> https://bugs.winehq.org/attachment.cgi?id=65961 implement strtod without using 'long double'
I've attached a patch that implements strtod without requiring "long double". I did have to add a bit of a hack to get a couple tests to work though, but the reason is a little odd so I would appreciate your thoughts. Without the hack this test: === strcpy(num, "1e-309"); ret = p__atodbl_l(&d, num, NULL); ok(ret == _UNDERFLOW, "_atodbl_l(&d, "1e-309", NULL) returned %d, expected _UNDERFLOW\n", ret); ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x); ==== throws an underflow error (passes) and returns _exactly_ zero (fails). Since this test is looking for zero I am wondering what the best thing to do here is: 1) return an almost zero value (the hack I currently have) 2) change the test to allow a return of exactly zero 3) look for another way to implement this operation that doesn't return exactly zero when the underflow occurs
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #8 from Alexandre Julliard julliard@winehq.org --- I don't think we want to return exactly 0 if Windows doesn't. But it doesn't really matter how we achieve that.
https://bugs.winehq.org/show_bug.cgi?id=48160
Erich E. Hoover erich.e.hoover@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #65961|0 |1 is obsolete| |
--- Comment #9 from Erich E. Hoover erich.e.hoover@gmail.com --- Created attachment 66005 --> https://bugs.winehq.org/attachment.cgi?id=66005 implement strtod without using 'long double'
(In reply to Alexandre Julliard from comment #8)
I don't think we want to return exactly 0 if Windows doesn't. But it doesn't really matter how we achieve that.
I looked into this a bit more and that may not actually be the case. It looks like what happens in this case is that Windows switches over to denormal values (1e-309 is represented as 0.1e-308). So, returning any old value under DBL_MIN is likely to break something. I have attached an updated patch that takes this into account (and updates the tests to demonstrate this behavior). Is this something that you would be receptive to having submitted during code freeze?
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #10 from Alexandre Julliard julliard@winehq.org --- It's a regression, so yes, if the patch doesn't get too large it could go in during code freeze (maybe with a few more tests).
https://bugs.winehq.org/show_bug.cgi?id=48160
Martin Storsjö martin@martin.st changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |martin@martin.st
--- Comment #11 from Martin Storsjö martin@martin.st --- (In reply to Alexandre Julliard from comment #5)
We'll need to rewrite that function to not use long double, because the goal is to support building it with Mingw.
FWIW, in Mingw (both gcc and clang) on x86, long doubles actually are the x87 80 bit extended precision floats, contrary to MSVC. So anything in Mingw that uses long doubles is ABI incompatible with MSVC.
In Mingw on arm and aarch64 (which only are supported by clang), long doubles are the same as regular doubles though.
In any case, not relying on long double here would be great, as I've run into range issues with the current implementation on 32 bit arm, where long doubles in linux also are the same as regular ones.
https://bugs.winehq.org/show_bug.cgi?id=48160
Nocifer apmichalopoulos@outlook.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |apmichalopoulos@outlook.com
--- Comment #12 from Nocifer apmichalopoulos@outlook.com --- As I am the OP of https://bugs.winehq.org/show_bug.cgi?id=48180, which has been marked as a duplicate of this one, I will report here that unfortunately this patch fails to resolve the issue reported in that other thread. I applied the patch to the most recent git sources and ran the .exe in a new, clean prefix.
As previously suggested, I also ran a WINEDEBUG=+d3d11,d3d,d3dshader but it exploded into a 6,5GB file, so I ran it again with only warn+d3d11,warn+d3d,warn+d3dshader. The resulting log provides nothing other than some d3d shader warnings which are probably due to wine not having full support for d3d11. To confirm this, I ran the WINEDEBUG in a clean 4.19 prefix and the resulting debug log is identical to that produced by running it in a 5.0-rc1 prefix with the patch applied.
I can provide any tracelogs or whatever else you may require.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #13 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Alexander Milos from comment #12)
... I can provide any tracelogs or whatever else you may require.
The most likely place the problem would be is in one of the other routines that use "long double". I see (after my patch): 1) dlls/msvcrt/scanf.h:325 (the whole family of scanf functions) 2) dlls/msvcrt/wcs.c:396/491 (MSVCRT__wcstod_l) 3) dlls/ntdll/string.c:999 (NTDLL_vsscanf) So, a WINEDEBUG="+msvcrt,+ntdll" looking for these functions might help narrow it down.
However, the x87 FPU is also used by d3d - so there are some other possibilities if it's not one of these routines.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #14 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Martin Storsjö from comment #11)
... In any case, not relying on long double here would be great, as I've run into range issues with the current implementation on 32 bit arm, where long doubles in linux also are the same as regular ones.
Would you mind testing my patch where you have encountered a problem? The latest version is here (fixes a problem with the tests failing on the 32-bit Debian VM): https://source.winehq.org/patches/data/176017
https://bugs.winehq.org/show_bug.cgi?id=48160
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |c22af971c287933a137c9fbecc8 | |1823812e12b7a Resolution|--- |FIXED Status|UNCONFIRMED |RESOLVED
--- Comment #15 from Alexandre Julliard julliard@winehq.org --- It should be fixed by c22af971c287933a137c9fbecc81823812e12b7a. Thanks Erich!
https://bugs.winehq.org/show_bug.cgi?id=48160
Nikolay Sivov bunglehead@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |msvcrt
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #16 from Martin Storsjö martin@martin.st --- (In reply to Erich E. Hoover from comment #14)
(In reply to Martin Storsjö from comment #11)
... In any case, not relying on long double here would be great, as I've run into range issues with the current implementation on 32 bit arm, where long doubles in linux also are the same as regular ones.
Would you mind testing my patch where you have encountered a problem? The latest version is here (fixes a problem with the tests failing on the 32-bit Debian VM): https://source.winehq.org/patches/data/176017
I tested the one pushed to master yesterday, and it seems like it fixes the issue for me. Thanks!
For reference, the issue was strtod("9.8813e-324"), which is a denormal for 64 bit doubles - the previous strtod implementation that relied on long doubles being larger than 64 bit would return this as a plain zero.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #17 from Alexander Milos apmichalopoulos@outlook.com --- Since this bug has been marked as fixed, I will continue posting my reports & traces in the bug thread I'd originally created (see previous post for link) so as to not pollute this one with irrelevant info. Hopefully that bug will get fixed soon-ish as well!
https://bugs.winehq.org/show_bug.cgi?id=48160
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #18 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.0-rc2.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #19 from Roman Pišl rpisl@seznam.cz --- I've found that there is still a minor difference between Windows and Wine. This compiles on Windows:
#include <stdio.h> void main() { printf("%f\n", 3.4028234663852886E38f); }
and shows: 340282346638528859811704183484516925440.000000
3.4028234663852887E38f is also OK and shows the same, 3.4028234663852888E38f fails: error C2177: constant too big
On Wine 5.0-r2 3.4028234663852886E38f fails, 3.4028234663852885E38f is OK.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #20 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Roman Pišl from comment #19)
I've found that there is still a minor difference between Windows and Wine. This compiles on Windows:
#include <stdio.h> void main() { printf("%f\n", 3.4028234663852886E38f); } ...
Since that's a float instead of a double, this is almost certainly a different issue. Would you mind opening a separate bug for it? It would be very useful to know what routine is being called by the compiler here (strtof?), if you get the chance to figure that out.
https://bugs.winehq.org/show_bug.cgi?id=48160
--- Comment #21 from Roman Pišl rpisl@seznam.cz --- Sure. See https://bugs.winehq.org/show_bug.cgi?id=48324.
Thank you for working on this.