Closed andrewrk closed 3 years ago
#include <stdio.h> #include <limits.h> #include <errno.h> #include <float.h> #include <math.h> #include <inttypes.h> static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) { uint32_t x = 0; long double y = 0; long double scale = 1; long double bias = 0; int gottail = 0, gotrad = 0, gotdig = 0; long long rp = 0; long long dc = 0; long long e2 = 0; int d; int c; c = shgetc(f); /* Skip leading zeros */ for (; c=='0'; c = shgetc(f)) gotdig = 1; if (c=='.') { gotrad = 1; c = shgetc(f); /* Count zeros after the radix point before significand */ for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; } for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { if (c=='.') { if (gotrad) break; rp = dc; gotrad = 1; } else { gotdig = 1; if (c > '9') d = (c|32)+10-'a'; else d = c-'0'; if (dc<8) { x = x*16 + d; } else if (dc < LDBL_MANT_DIG/4+1) { y += d*(scale/=16); } else if (d && !gottail) { y += 0.5*scale; gottail = 1; } dc++; } } if (!gotdig) { shunget(f); if (pok) { shunget(f); if (gotrad) shunget(f); } else { shlim(f, 0); } return sign * 0.0; } if (!gotrad) rp = dc; while (dc<8) x *= 16, dc++; if ((c|32)=='p') { e2 = scanexp(f, pok); if (e2 == LLONG_MIN) { if (pok) { shunget(f); } else { shlim(f, 0); return 0; } e2 = 0; } } else { shunget(f); } e2 += 4*rp - 32; if (!x) return sign * 0.0; if (e2 > -emin) { errno = ERANGE; return sign * LDBL_MAX * LDBL_MAX; } if (e2 < emin-2*LDBL_MANT_DIG) { errno = ERANGE; return sign * LDBL_MIN * LDBL_MIN; } while (x < 0x80000000) { if (y>=0.5) { x += x + 1; y += y - 1; } else { x += x; y += y; } e2--; } if (bits > 32+e2-emin) { bits = 32+e2-emin; if (bits<0) bits=0; } if (bits < LDBL_MANT_DIG) bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign); if (bits<32 && y && !(x&1)) x++, y=0; y = bias + sign*(long double)x + sign*y; y -= bias; if (!y) errno = ERANGE; return scalbnl(y, e2); }
[nix-shell:~/Downloads/zig/build]$ ./zig translate-c floatscan.c -lc -target x86_64-linux-musl thread 30059 panic: reached unreachable code /home/andy/Downloads/zig/lib/std/debug.zig:223:14: 0xb477d8 in std.debug.assert (zig1) if (!ok) unreachable; // assertion failure ^ /home/andy/Downloads/zig/lib/std/zig/ast.zig:114:15: 0xcc5b92 in std.zig.ast.Tree.tokenSlice (zig1) assert(token.tag == token_tag); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:2400:30: 0x115563f in std.zig.render.tokenSliceForRender (zig1) var ret = tree.tokenSlice(token_index); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:2205:39: 0x105525e in std.zig.render.renderToken (zig1) const lexeme = tokenSliceForRender(tree, token_index); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:192:30: 0x115b512 in std.zig.render.renderExpression (zig1) => return renderToken(ais, tree, main_tokens[node], space), ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:388:36: 0x1157255 in std.zig.render.renderExpression (zig1) return renderExpression(gpa, ais, tree, infix.rhs, space); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:533:33: 0x115ccec in std.zig.render.renderExpression (zig1) try renderExpression(gpa, ais, tree, datas[node].lhs, .none); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:378:33: 0x115c461 in std.zig.render.renderExpression (zig1) try renderExpression(gpa, ais, tree, infix.lhs, .space); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:524:37: 0x115cbe1 in std.zig.render.renderExpression (zig1) try renderExpression(gpa, ais, tree, datas[node].lhs, space); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:1525:45: 0x13366b7 in std.zig.render.renderBlock (zig1) else => try renderExpression(gpa, ais, tree, stmt, .semicolon), ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:235:31: 0x115bbc7 in std.zig.render.renderExpression (zig1) return renderBlock(gpa, ais, tree, node, statements, space); ^ /home/andy/Downloads/zig/lib/std/zig/render.zig:1107:33: 0x1344295 in std.zig.render.renderWhile (zig1) try renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); ^
The long double constants LDBL_MAX and LDBL_MIN are casted into double by translate-c and become inf, an invalid literal.
long double
LDBL_MAX
LDBL_MIN
double
inf
floatscan.c