Signed-off-by: Daniel Lehman dlehman25@gmail.com --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 37 ++++++++++++++++++- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 13 +++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 3 ++ 7 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 74d682b33bf..59b0c567216 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -89,7 +89,7 @@ @ cdecl exit(long) ucrtbase.exit @ stub feclearexcept @ cdecl fegetenv(ptr) ucrtbase.fegetenv -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) ucrtbase.fegetexceptflag @ cdecl fegetround() ucrtbase.fegetround @ stub feholdexcept @ cdecl fesetenv(ptr) ucrtbase.fesetenv diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 0e1c7705166..776d701e780 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2145,7 +2145,7 @@ @ cdecl fdiml(double double) fdim @ stub feclearexcept @ cdecl fegetenv(ptr) -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() @ stub feholdexcept @ cdecl feof(ptr) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index e8ef2be3520..d6e93b97629 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -182,6 +182,7 @@ static int (CDECL *p_fegetenv)(fenv_t*); static int (CDECL *p_fesetenv)(const fenv_t*); static int (CDECL *p_fegetround)(void); static int (CDECL *p_fesetround)(int); +static int (CDECL *p_fegetexceptflag)(fexcept_t*,int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -257,6 +258,7 @@ static BOOL init(void) SET(p_fesetenv, "fesetenv"); SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); + SET(p_fegetexceptflag, "fegetexceptflag");
SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); @@ -788,8 +790,25 @@ static void test_critical_section(void)
static void test_feenv(void) { + static const struct { + unsigned long set; + unsigned long get; + fexcept_t expect; + } tests[] = { + { 0, 0, 0 }, + { FE_INEXACT, 0, 0 }, + { FE_INEXACT, FE_ALL_EXCEPT, FE_INEXACT }, + { FE_INEXACT, FE_INEXACT, FE_INEXACT }, + { FE_INEXACT, FE_OVERFLOW, 0 }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT }, + { FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT }, + { FE_ALL_EXCEPT, 0, 0 }, + { FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, + { FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, + }; fenv_t env, env2; - int ret; + fexcept_t except; + int i, ret;
p__clearfp();
@@ -807,6 +826,22 @@ static void test_feenv(void) ok(!ret, "fesetenv returned %x\n", ret); ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); + + if(0) /* crashes on windows */ + p_fegetexceptflag(NULL, 0); + + for(i=0; i<ARRAY_SIZE(tests); i++) { + env._Fe_stat = tests[i].set; + ret = p_fesetenv(&env); + ok(!ret, "fesetenv returned %x\n", ret); + + except = ~0; + ret = p_fegetexceptflag(&except, tests[i].get); + ok(!ret, "fegetexceptflag returned %x.\n", ret); + ok(except == tests[i].expect, "expected %lx, got %lx\n", tests[i].expect, except); + } + + p__clearfp(); }
static void test__wcreate_locale(void) diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 05b8a97a084..a3be94e4a6c 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1811,7 +1811,7 @@ @ cdecl fdiml(double double) msvcr120.fdiml @ stub feclearexcept @ cdecl fegetenv(ptr) msvcr120.fegetenv -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) msvcr120.fegetexceptflag @ cdecl fegetround() msvcr120.fegetround @ stub feholdexcept @ cdecl feof(ptr) msvcr120.feof diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index d6b0d9422e7..996059cc036 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2214,6 +2214,19 @@ int CDECL fegetenv(fenv_t *env) env->_Fe_stat = _statusfp(); return 0; } + +/********************************************************************* + * fegetexceptflag (MSVCR120.@) + */ +int CDECL fegetexceptflag(fexcept_t *status, int excepts) +{ + fenv_t env; + int rc; + + rc = fegetenv(&env); + *status = env._Fe_stat & excepts & FE_ALL_EXCEPT; + return rc; +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 0a8d74521f5..41b1b79896d 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2288,7 +2288,7 @@ @ cdecl fdiml(double double) fdim @ stub feclearexcept @ cdecl fegetenv(ptr) -@ stub fegetexceptflag +@ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() @ stub feholdexcept @ cdecl feof(ptr) diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 92b341bd46b..56db8ea28b8 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -30,8 +30,11 @@ typedef struct __msvcrt_ulong _Fe_stat; } fenv_t;
+typedef __msvcrt_ulong fexcept_t; + _ACRTIMP int __cdecl fegetenv(fenv_t*); _ACRTIMP int __cdecl fesetenv(const fenv_t*); +_ACRTIMP int __cdecl fegetexceptflag(fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); _ACRTIMP int __cdecl fesetround(int);
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 5 +++++ dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 10 ++++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 59b0c567216..1d0b6e06b7c 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -95,7 +95,7 @@ @ cdecl fesetenv(ptr) ucrtbase.fesetenv @ stub fesetexceptflag @ cdecl fesetround(long) ucrtbase.fesetround -@ stub fetestexcept +@ cdecl fetestexcept(long) ucrtbase.fetestexcept @ cdecl perror(str) ucrtbase.perror @ cdecl quick_exit(long) ucrtbase.quick_exit @ cdecl raise(long) ucrtbase.raise diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 776d701e780..d9628883f34 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2154,7 +2154,7 @@ @ cdecl fesetenv(ptr) @ stub fesetexceptflag @ cdecl fesetround(long) -@ stub fetestexcept +@ cdecl fetestexcept(long) @ stub feupdateenv @ cdecl fflush(ptr) @ cdecl fgetc(ptr) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index d6e93b97629..a34c336d94d 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -183,6 +183,7 @@ static int (CDECL *p_fesetenv)(const fenv_t*); static int (CDECL *p_fegetround)(void); static int (CDECL *p_fesetround)(int); static int (CDECL *p_fegetexceptflag)(fexcept_t*,int); +static int (CDECL *p_fetestexcept)(int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -259,6 +260,7 @@ static BOOL init(void) SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); SET(p_fegetexceptflag, "fegetexceptflag"); + SET(p_fetestexcept, "fetestexcept");
SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); @@ -839,6 +841,9 @@ static void test_feenv(void) ret = p_fegetexceptflag(&except, tests[i].get); ok(!ret, "fegetexceptflag returned %x.\n", ret); ok(except == tests[i].expect, "expected %lx, got %lx\n", tests[i].expect, except); + + except = p_fetestexcept(tests[i].get); + ok(except == tests[i].expect, "expected %lx, got %lx\n", tests[i].expect, except); }
p__clearfp(); diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index a3be94e4a6c..152eda3be81 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1820,7 +1820,7 @@ @ cdecl fesetenv(ptr) msvcr120.fesetenv @ stub fesetexceptflag @ cdecl fesetround(long) msvcr120.fesetround -@ stub fetestexcept +@ cdecl fetestexcept(long) msvcr120.fetestexcept @ stub feupdateenv @ cdecl fflush(ptr) msvcr120.fflush @ cdecl fgetc(ptr) msvcr120.fgetc diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 996059cc036..5ae5f2e5d6c 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2227,6 +2227,16 @@ int CDECL fegetexceptflag(fexcept_t *status, int excepts) *status = env._Fe_stat & excepts & FE_ALL_EXCEPT; return rc; } + +/********************************************************************* + * fetestexcept (MSVCR120.@) + */ +int CDECL fetestexcept(int flags) +{ + fexcept_t except; + fegetexceptflag(&except, flags); + return except; +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 41b1b79896d..4f842c58d27 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2296,7 +2296,7 @@ @ cdecl fesetenv(ptr) @ stub fesetexceptflag @ cdecl fesetround(long) -@ stub fetestexcept +@ cdecl fetestexcept(long) @ cdecl fflush(ptr) @ cdecl fgetc(ptr) @ cdecl fgetpos(ptr ptr) diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 56db8ea28b8..0ddb6852368 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -37,6 +37,7 @@ _ACRTIMP int __cdecl fesetenv(const fenv_t*); _ACRTIMP int __cdecl fegetexceptflag(fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); _ACRTIMP int __cdecl fesetround(int); +_ACRTIMP int __cdecl fetestexcept(int);
#ifdef __cplusplus }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86255
Your paranoid android.
=== debiant2 (build log) ===
Task: WineTest did not produce the win32 report
=== debiant2 (build log) ===
Task: WineTest did not produce the wow32 report
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 50 ++++++++++++++++++- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 20 ++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 1d0b6e06b7c..610af8e436b 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -93,7 +93,7 @@ @ cdecl fegetround() ucrtbase.fegetround @ stub feholdexcept @ cdecl fesetenv(ptr) ucrtbase.fesetenv -@ stub fesetexceptflag +@ cdecl fesetexceptflag(ptr long) ucrtbase.fesetexceptflag @ cdecl fesetround(long) ucrtbase.fesetround @ cdecl fetestexcept(long) ucrtbase.fetestexcept @ cdecl perror(str) ucrtbase.perror diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index d9628883f34..430124740bb 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2152,7 +2152,7 @@ @ stub feraiseexcept @ cdecl ferror(ptr) @ cdecl fesetenv(ptr) -@ stub fesetexceptflag +@ cdecl fesetexceptflag(ptr long) @ cdecl fesetround(long) @ cdecl fetestexcept(long) @ stub feupdateenv diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index a34c336d94d..5266e73a3a0 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -183,6 +183,7 @@ static int (CDECL *p_fesetenv)(const fenv_t*); static int (CDECL *p_fegetround)(void); static int (CDECL *p_fesetround)(int); static int (CDECL *p_fegetexceptflag)(fexcept_t*,int); +static int (CDECL *p_fesetexceptflag)(const fexcept_t*,int); static int (CDECL *p_fetestexcept)(int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); @@ -260,6 +261,7 @@ static BOOL init(void) SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); SET(p_fegetexceptflag, "fegetexceptflag"); + SET(p_fesetexceptflag, "fesetexceptflag"); SET(p_fetestexcept, "fetestexcept");
SET(p__clearfp, "_clearfp"); @@ -808,6 +810,15 @@ static void test_feenv(void) { FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, { FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, }; + static const unsigned long tests2[] = { + 0, + FE_INEXACT, + FE_UNDERFLOW, + FE_OVERFLOW, + FE_DIVBYZERO, + FE_INVALID, + FE_ALL_EXCEPT, + }; fenv_t env, env2; fexcept_t except; int i, ret; @@ -829,8 +840,10 @@ static void test_feenv(void) ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret);
- if(0) /* crashes on windows */ + if(0) { /* crashes on windows */ p_fegetexceptflag(NULL, 0); + p_fesetexceptflag(NULL, FE_ALL_EXCEPT); + }
for(i=0; i<ARRAY_SIZE(tests); i++) { env._Fe_stat = tests[i].set; @@ -846,6 +859,41 @@ static void test_feenv(void) ok(except == tests[i].expect, "expected %lx, got %lx\n", tests[i].expect, except); }
+ ret = p_fesetexceptflag(NULL, 0); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + for(i=0; i<ARRAY_SIZE(tests2); i++) { + p__clearfp(); + + except = FE_ALL_EXCEPT; + ret = p_fesetexceptflag(&except, tests2[i]); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + except = p_fetestexcept(tests2[i]); + ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except); + + p__clearfp(); + + except = tests2[i]; + ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "fesetexceptflag returned %x\n", ret); + + except = p_fetestexcept(tests2[i]); + ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except); + } + + except = FE_ALL_EXCEPT; + ret = p_fesetexceptflag(&except, 0); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(except == FE_ALL_EXCEPT, "expected %x, got %lx\n", FE_ALL_EXCEPT, except); + + except = 0; + ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); + p__clearfp(); }
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 152eda3be81..2905f4d7b08 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1818,7 +1818,7 @@ @ stub feraiseexcept @ cdecl ferror(ptr) msvcr120.ferror @ cdecl fesetenv(ptr) msvcr120.fesetenv -@ stub fesetexceptflag +@ cdecl fesetexceptflag(ptr long) msvcr120.fesetexceptflag @ cdecl fesetround(long) msvcr120.fesetround @ cdecl fetestexcept(long) msvcr120.fetestexcept @ stub feupdateenv diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 5ae5f2e5d6c..8157e02f94a 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2237,6 +2237,26 @@ int CDECL fetestexcept(int flags) fegetexceptflag(&except, flags); return except; } + +/********************************************************************* + * fesetexceptflag (MSVCR120.@) + */ +int CDECL fesetexceptflag(const fexcept_t *status, int excepts) +{ + fenv_t env; + + if(!status) + return 0; + + if(!*status) { + _clearfp(); + return 0; + } + + fegetenv(&env); + env._Fe_stat |= (*status & excepts & FE_ALL_EXCEPT); + return fesetenv(&env); +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 4f842c58d27..e5fbc6b14b9 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2294,7 +2294,7 @@ @ cdecl feof(ptr) @ cdecl ferror(ptr) @ cdecl fesetenv(ptr) -@ stub fesetexceptflag +@ cdecl fesetexceptflag(ptr long) @ cdecl fesetround(long) @ cdecl fetestexcept(long) @ cdecl fflush(ptr) diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 0ddb6852368..45cd0b9e534 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -35,6 +35,7 @@ typedef __msvcrt_ulong fexcept_t; _ACRTIMP int __cdecl fegetenv(fenv_t*); _ACRTIMP int __cdecl fesetenv(const fenv_t*); _ACRTIMP int __cdecl fegetexceptflag(fexcept_t*, int); +_ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); _ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fetestexcept(int);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86256
Your paranoid android.
=== debiant2 (build log) ===
Task: WineTest did not produce the win32 report
=== debiant2 (build log) ===
Task: WineTest did not produce the wow32 report
Hi Daniel,
On 3/2/21 5:06 AM, Daniel Lehman wrote:
except = p_fetestexcept(tests2[i]);
ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except);
- }
- except = FE_ALL_EXCEPT;
- ret = p_fesetexceptflag(&except, 0);
- ok(!ret, "fesetexceptflag returned %x\n", ret);
- except = p_fetestexcept(FE_ALL_EXCEPT);
- ok(except == FE_ALL_EXCEPT, "expected %x, got %lx\n", FE_ALL_EXCEPT, except);
There's no fpclear call before this test, it probably doesn't test what you wanted.
+/*********************************************************************
fesetexceptflag (MSVCR120.@)
- */
+int CDECL fesetexceptflag(const fexcept_t *status, int excepts) +{
- fenv_t env;
- if(!status)
return 0;
You're adding a test that shows status == NULL crashes on Windows.
- if(!*status) {
_clearfp();
return 0;
- }
- fegetenv(&env);
- env._Fe_stat |= (*status & excepts & FE_ALL_EXCEPT);
- return fesetenv(&env);
I would expect the function to set all the fields specified by mask. Probably it should look like: excepts &= FE_ALL_EXCEPT; *status &= excepts; env._Fe_stat = (env._Fe_stat & ~excepts) | *status; Could you please add some tests that starts with non 0 status word? Also please test status on function exit, probably it should be set to new status word value.
Thanks, Piotr
Signed-off-by: Daniel Lehman dlehman25@gmail.com --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120/tests/msvcr120.c | 21 ++++++++++++++++--- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/math.c | 12 +++++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- include/msvcrt/fenv.h | 1 + 7 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 610af8e436b..3733a524382 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -87,7 +87,7 @@ @ cdecl _wsystem(wstr) ucrtbase._wsystem @ cdecl abort() ucrtbase.abort @ cdecl exit(long) ucrtbase.exit -@ stub feclearexcept +@ cdecl feclearexcept(long) ucrtbase.feclearexcept @ cdecl fegetenv(ptr) ucrtbase.fegetenv @ cdecl fegetexceptflag(ptr long) ucrtbase.fegetexceptflag @ cdecl fegetround() ucrtbase.fegetround diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 430124740bb..306bee5f50c 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2143,7 +2143,7 @@ @ cdecl fdim(double double) @ cdecl fdimf(float float) @ cdecl fdiml(double double) fdim -@ stub feclearexcept +@ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) @ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 5266e73a3a0..ceb06930b58 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -185,6 +185,7 @@ static int (CDECL *p_fesetround)(int); static int (CDECL *p_fegetexceptflag)(fexcept_t*,int); static int (CDECL *p_fesetexceptflag)(const fexcept_t*,int); static int (CDECL *p_fetestexcept)(int); +static int (CDECL *p_feclearexcept)(int); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -263,6 +264,7 @@ static BOOL init(void) SET(p_fegetexceptflag, "fegetexceptflag"); SET(p_fesetexceptflag, "fesetexceptflag"); SET(p_fetestexcept, "fetestexcept"); + SET(p_feclearexcept, "feclearexcept");
SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); @@ -861,10 +863,10 @@ static void test_feenv(void)
ret = p_fesetexceptflag(NULL, 0); ok(!ret, "fesetexceptflag returned %x\n", ret); + ret = p_feclearexcept(~FE_ALL_EXCEPT); + ok(!ret, "feclearexceptflag returned %x\n", ret);
for(i=0; i<ARRAY_SIZE(tests2); i++) { - p__clearfp(); - except = FE_ALL_EXCEPT; ret = p_fesetexceptflag(&except, tests2[i]); ok(!ret, "fesetexceptflag returned %x\n", ret); @@ -872,7 +874,10 @@ static void test_feenv(void) except = p_fetestexcept(tests2[i]); ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except);
- p__clearfp(); + ret = p_feclearexcept(tests2[i]); + ok(!ret, "feclearexceptflag returned %x\n", ret); + except = p_fetestexcept(tests2[i]); + ok(!except, "expected 0, got %lx\n", except);
except = tests2[i]; ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT); @@ -880,9 +885,19 @@ static void test_feenv(void)
except = p_fetestexcept(tests2[i]); ok(except == tests2[i], "expected %lx, got %lx\n", tests2[i], except); + + ret = p_feclearexcept(tests2[i]); + ok(!ret, "feclearexceptflag returned %x\n", ret); + except = p_fetestexcept(tests2[i]); + ok(!except, "expected 0, got %lx\n", except); }
except = FE_ALL_EXCEPT; + ret = p_fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = p_fetestexcept(FE_ALL_EXCEPT); + ok(except == FE_ALL_EXCEPT, "expected %x, got %lx\n", FE_ALL_EXCEPT, except); + ret = p_fesetexceptflag(&except, 0); ok(!ret, "fesetexceptflag returned %x\n", ret); except = p_fetestexcept(FE_ALL_EXCEPT); diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 2905f4d7b08..b16d1a5b3f0 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1809,7 +1809,7 @@ @ cdecl fdim(double double) msvcr120.fdim @ cdecl fdimf(float float) msvcr120.fdimf @ cdecl fdiml(double double) msvcr120.fdiml -@ stub feclearexcept +@ cdecl feclearexcept(long) msvcr120.feclearexcept @ cdecl fegetenv(ptr) msvcr120.fegetenv @ cdecl fegetexceptflag(ptr long) msvcr120.fegetexceptflag @ cdecl fegetround() msvcr120.fegetround diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 8157e02f94a..1d1f5a2d182 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2257,6 +2257,18 @@ int CDECL fesetexceptflag(const fexcept_t *status, int excepts) env._Fe_stat |= (*status & excepts & FE_ALL_EXCEPT); return fesetenv(&env); } + +/********************************************************************* + * feclearexcept (MSVCR120.@) + */ +int CDECL feclearexcept(int flags) +{ + fenv_t env; + + fegetenv(&env); + env._Fe_stat &= (~flags & FE_ALL_EXCEPT); + return fesetenv(&env); +} #endif
#if _MSVCR_VER>=140 diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index e5fbc6b14b9..8f331825fc4 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2286,7 +2286,7 @@ @ cdecl fdim(double double) @ cdecl fdimf(float float) @ cdecl fdiml(double double) fdim -@ stub feclearexcept +@ cdecl feclearexcept(long) @ cdecl fegetenv(ptr) @ cdecl fegetexceptflag(ptr long) @ cdecl fegetround() diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index 45cd0b9e534..88f9ebd1b4f 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -39,6 +39,7 @@ _ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); _ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fetestexcept(int); +_ACRTIMP int __cdecl feclearexcept(int);
#ifdef __cplusplus }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86257
Your paranoid android.
=== debiant2 (build log) ===
Task: WineTest did not produce the win32 report
=== debiant2 (build log) ===
Task: WineTest did not produce the wow32 report
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86254
Your paranoid android.
=== debiant2 (build log) ===
Task: WineTest did not produce the win32 report
=== debiant2 (build log) ===
Task: WineTest did not produce the wow32 report
Hi Daniel,
On 3/2/21 5:06 AM, Daniel Lehman wrote:
+/*********************************************************************
fegetexceptflag (MSVCR120.@)
- */
+int CDECL fegetexceptflag(fexcept_t *status, int excepts) +{
- fenv_t env;
- int rc;
- rc = fegetenv(&env);
- *status = env._Fe_stat & excepts & FE_ALL_EXCEPT;
- return rc;
+}
Is there a reason of not using _statusfp() instead of fegetenv here?
Thanks, Piotr