Another hex float fix
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled

Hex floating point number did fail when a lot of digits are present.
See testcase 70.
This commit is contained in:
herman ten brugge 2025-05-28 21:33:30 +02:00
parent c6792dac03
commit 59aecdb539
3 changed files with 17 additions and 9 deletions

20
tccpp.c
View File

@ -2240,15 +2240,18 @@ static void parse_string(const char *s, int len)
#endif #endif
/* bn = (bn << shift) | or_val */ /* bn = (bn << shift) | or_val */
static void bn_lshift(unsigned int *bn, int shift, int or_val) static int bn_lshift(unsigned int *bn, int shift, int or_val)
{ {
int i; int i;
unsigned int v; unsigned int v;
if (bn[BN_SIZE - 1] >> (32 - shift))
return shift;
for(i=0;i<BN_SIZE;i++) { for(i=0;i<BN_SIZE;i++) {
v = bn[i]; v = bn[i];
bn[i] = (v << shift) | or_val; bn[i] = (v << shift) | or_val;
or_val = v >> (32 - shift); or_val = v >> (32 - shift);
} }
return 0;
} }
static void bn_zero(unsigned int *bn) static void bn_zero(unsigned int *bn)
@ -2321,6 +2324,7 @@ static void parse_number(const char *p)
it by hand */ it by hand */
/* hexadecimal or binary floats */ /* hexadecimal or binary floats */
/* XXX: handle overflows */ /* XXX: handle overflows */
frac_bits = 0;
*q = '\0'; *q = '\0';
if (b == 16) if (b == 16)
shift = 4; shift = 4;
@ -2339,9 +2343,8 @@ static void parse_number(const char *p)
} else { } else {
t = t - '0'; t = t - '0';
} }
bn_lshift(bn, shift, t); frac_bits -= bn_lshift(bn, shift, t);
} }
frac_bits = 0;
if (ch == '.') { if (ch == '.') {
ch = *p++; ch = *p++;
while (1) { while (1) {
@ -2357,7 +2360,7 @@ static void parse_number(const char *p)
} }
if (t >= b) if (t >= b)
tcc_error("invalid digit"); tcc_error("invalid digit");
bn_lshift(bn, shift, t); frac_bits -= bn_lshift(bn, shift, t);
frac_bits += shift; frac_bits += shift;
ch = *p++; ch = *p++;
} }
@ -2376,7 +2379,9 @@ static void parse_number(const char *p)
if (ch < '0' || ch > '9') if (ch < '0' || ch > '9')
expect("exponent digits"); expect("exponent digits");
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
exp_val = exp_val * 10 + ch - '0'; /* If exp_val is this large ldexp will return HUGE_VAL */
if (exp_val < 100000000)
exp_val = exp_val * 10 + ch - '0';
ch = *p++; ch = *p++;
} }
exp_val = exp_val * s; exp_val = exp_val * s;
@ -2405,12 +2410,11 @@ static void parse_number(const char *p)
#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE #ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
tokc.d = d; tokc.d = d;
#else #else
/* XXX: not large enough */ tokc.ld = d;
tokc.ld = (long double)d;
#endif #endif
} else { } else {
tok = TOK_CDOUBLE; tok = TOK_CDOUBLE;
tokc.d = d; tokc.d = (double)d;
} }
} else { } else {
/* decimal floats */ /* decimal floats */

View File

@ -31,7 +31,9 @@ int main()
double da0 = 0X.1ACP12; double da0 = 0X.1ACP12;
double da1 = 0x.1acp-12; double da1 = 0x.1acp-12;
double da2 = 0x.1acp+12; double da2 = 0x.1acp+12;
printf("%f\n%f\n%f\n\n", da0, da1, da2); double da3 = 0x1.00000000000000000000000000000000000000000000p+12;
double da4 = 0x1000000000000000000000000000000000000000000000p-140;
printf("%f\n%f\n%f\n%f\n%f\n\n", da0, da1, da2, da3, da4);
double db0 = 0X1AC.BDP12; double db0 = 0X1AC.BDP12;
double db1 = 0x1ac.bdp-12; double db1 = 0x1ac.bdp-12;

View File

@ -21,6 +21,8 @@
428.000000 428.000000
0.000026 0.000026
428.000000 428.000000
4096.000000
1099511627776.000000
1756112.000000 1756112.000000
0.104672 0.104672