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.
This commit is contained in:
1 parent
c076463631
commit
9be66e9d22
1 file changed
+33
-11
+33
-11
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user