From 9be66e9d22257ab008e1da58d2af3c3b9e0cacec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 14 Oct 2022 13:21:08 +0300 Subject: [PATCH] crt-test: Fix the macros for avoiding compiler optimizations The macros F() and L() etc were meant for providing constants for the tests, without the compiler seeing them as constants, to avoid optimizing out the entire functions that are to be tested. However in practice, the compiler is also able to optimize out e.g. a call to strtol("42", NULL, 0), so this didn't have the intended effect. Instead make the macros wrap through a no-op function, but which is indirected via a global function pointer. The compiler can't reason about global variables keeping their values (they could be modified by e.g. a constructor in a different object file, before running the main function). This avoids needing to pass all values through strtod/strtol etc. Change some constants like 123456789012345, which are seen by the compiler as integer constants (which aren't exactly representable in floating point form) into 123456789012345.0, which the compiler won't complain about being inexact. --- test/crt-test.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/test/crt-test.c b/test/crt-test.c index 86d3aea..a4cea0d 100644 --- a/test/crt-test.c +++ b/test/crt-test.c @@ -138,11 +138,33 @@ const char *context = ""; } \ } while (0) -#define F(x) strtod(#x, NULL) -#define L(x) strtol(#x, NULL, 0) -#define UL(x) strtoul(#x, NULL, 0) -#define LL(x) strtoll(#x, NULL, 0) -#define ULL(x) strtoull(#x, NULL, 0) +double double_wrap_impl(double f) { + return f; +} +long long_wrap_impl(long l) { + return l; +} +unsigned long ulong_wrap_impl(unsigned long u) { + return u; +} +long long longlong_wrap_impl(long long l) { + return l; +} +unsigned long long ulonglong_wrap_impl(unsigned long long u) { + return u; +} + +double (*double_wrap)(double f) = double_wrap_impl; +long (*long_wrap)(long l) = long_wrap_impl; +unsigned long (*ulong_wrap)(unsigned long u) = ulong_wrap_impl; +long long (*longlong_wrap)(long long l) = longlong_wrap_impl; +unsigned long long (*ulonglong_wrap)(unsigned long long l) = ulonglong_wrap_impl; + +#define F(x) double_wrap(x) +#define L(x) long_wrap(x) +#define UL(x) ulong_wrap(x) +#define LL(x) longlong_wrap(x) +#define ULL(x) ulonglong_wrap(x ## ULL) int vsscanf_wrap(const char* str, const char* fmt, ...) { va_list ap; @@ -1762,9 +1784,9 @@ int main(int argc, char* argv[]) { TEST_INT((unsigned long long)F(4.2), 4); TEST_INT((signed long long)F(4.2), 4); - TEST_INT((unsigned long long)F(123456789012345678), 123456789012345680ULL); - TEST_INT((signed long long)F(123456789012345678), 123456789012345680ULL); - TEST_INT((signed long long)F(-123456789012345), -123456789012345LL); + TEST_INT((unsigned long long)F(123456789012345678.0), 123456789012345680ULL); + TEST_INT((signed long long)F(123456789012345678.0), 123456789012345680ULL); + TEST_INT((signed long long)F(-123456789012345.0), -123456789012345LL); TEST_INT((unsigned long long)(float)F(4.2), 4); TEST_INT((signed long long)(float)F(4.2), 4); @@ -1798,9 +1820,9 @@ int main(int argc, char* argv[]) { #ifdef __SIZEOF_INT128__ TEST_INT((__uint128_t)F(4.2), 4); TEST_INT((__int128_t)F(4.2), 4); - TEST_INT((__uint128_t)F(123456789012345678), 123456789012345680ULL); - TEST_INT((__int128_t)F(123456789012345678), 123456789012345680ULL); - TEST_INT((__int128_t)F(-123456789012345), -123456789012345LL); + TEST_INT((__uint128_t)F(123456789012345678.0), 123456789012345680ULL); + TEST_INT((__int128_t)F(123456789012345678.0), 123456789012345680ULL); + TEST_INT((__int128_t)F(-123456789012345.0), -123456789012345LL); TEST_INT((__uint128_t)(float)F(4.2), 4); TEST_INT((__int128_t)(float)F(4.2), 4);