The defect
A float literal whose value is outside its type's range transpiles with exit 0 on every target. The generated C then fails the -Werror compile that every fixture cell uses, or holds a different value from the one written.
Measured on main at 0cd96994b with npx tsx src/cli/index.ts <file> --target host, then gcc -c -O3 -Wall -Wextra -Werror (the // test-no-warnings flags). g++ -x c++ with the same flags gives the same errors.
| program |
C-Next |
emitted |
gcc -Werror |
f32 a <- 1e39f32; |
exit 0 |
float a = 1e39f; |
error: floating constant exceeds range of 'float' [-Werror=overflow] |
f32 c <- 1e-50f32; |
exit 0 |
float c = 1e-50f; |
error: floating constant truncated to zero [-Werror=overflow] |
f64 d <- 1e309; |
exit 0 |
double d = 1e309; |
error: floating constant exceeds range of 'double' [-Werror=overflow] |
f32 b <- 1e39; |
exit 0 |
float b = 1e39; |
no diagnostic; b holds inf |
Without -Werror, the first three only warn, and the program holds inf or 0.0f where it wrote 1e39, 1e-50 or 1e309. The fourth is an f64 literal converted to float. C11 6.3.1.5p1 leaves the conversion of a value outside the destination's range undefined, and Annex F gives inf.
Controls (in range, must stay accepted): f32 ok1 <- 3.4e38f32; and f32 ok2 <- 1e-38f32; transpile with exit 0 and compile cleanly under the same flags.
Reproduction
suffixed.cnx:
f32 a <- 1e39f32;
u32 main() {
if (a < 1.0f32) { return 1; }
return 0;
}
npx tsx src/cli/index.ts suffixed.cnx --target host # exit 0
gcc -c -O3 -Wall -Wextra -Werror suffixed.c # error: floating constant exceeds range of 'float'
What needs deciding
No ADR decides this. E0868 (ADR-024) rejects an integer literal that does not fit its target's range. ADR-044 "Floating Point Literals" says only that an unsuffixed literal is f64 and that narrowing it to f32 "loses precision". It says nothing about a value outside the type's range, or one that rounds to zero.
Related
Definition of done
The defect
A float literal whose value is outside its type's range transpiles with exit 0 on every target. The generated C then fails the
-Werrorcompile that every fixture cell uses, or holds a different value from the one written.Measured on
mainat0cd96994bwithnpx tsx src/cli/index.ts <file> --target host, thengcc -c -O3 -Wall -Wextra -Werror(the// test-no-warningsflags).g++ -x c++with the same flags gives the same errors.-Werrorf32 a <- 1e39f32;float a = 1e39f;error: floating constant exceeds range of 'float' [-Werror=overflow]f32 c <- 1e-50f32;float c = 1e-50f;error: floating constant truncated to zero [-Werror=overflow]f64 d <- 1e309;double d = 1e309;error: floating constant exceeds range of 'double' [-Werror=overflow]f32 b <- 1e39;float b = 1e39;bholds infWithout
-Werror, the first three only warn, and the program holds inf or0.0fwhere it wrote1e39,1e-50or1e309. The fourth is anf64literal converted tofloat. C11 6.3.1.5p1 leaves the conversion of a value outside the destination's range undefined, and Annex F gives inf.Controls (in range, must stay accepted):
f32 ok1 <- 3.4e38f32;andf32 ok2 <- 1e-38f32;transpile with exit 0 and compile cleanly under the same flags.Reproduction
suffixed.cnx:What needs deciding
No ADR decides this. E0868 (ADR-024) rejects an integer literal that does not fit its target's range. ADR-044 "Floating Point Literals" says only that an unsuffixed literal is
f64and that narrowing it tof32"loses precision". It says nothing about a value outside the type's range, or one that rounds to zero.Related
f64literal on AVR, whosedoubleis 32 bits, so that case depends on the target. These rows fail on every target, becausef32's range is the same on every catalog row.f64value narrows tof32silently at every conversion site. Row 4 is the literal case of that narrowing.f32literals, sok / 1e-50f32reports E0800 there, which matches C's0.0f.Definition of done
f32.test-errorfixture that keeps the in-range controls beside it, or has a reason recorded here for leaving it to the C compiler.