From 1c82d40ab23b7b5e9108d26bbd2ecc740cdd708b Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Sat, 24 Oct 2026 20:51:12 +1100 Subject: [PATCH] fix(translate): diagnose out-of-range numeric literals Integer and float literals outside the i64/f64 range threw an uncaught std::out_of_range from std::stoll/std::stod and aborted the compiler. Parse integers with StringRef::getAsInteger and floats with llvm::to_float, and emit a located parser error when the value does not fit. Float literals that overflow to infinity are rejected; literals that underflow round to zero or a subnormal, as in C. --- lib/Translation/ForthToMLIR/ForthToMLIR.cpp | 11 +++++++++-- test/Translation/Forth/basic-literals.forth | 5 ++++- .../Forth/float-literal-overflow-error.forth | 4 ++++ test/Translation/Forth/float-literals.forth | 4 +++- .../Forth/integer-literal-overflow-error.forth | 4 ++++ .../Forth/integer-literal-underflow-error.forth | 4 ++++ 6 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 test/Translation/Forth/float-literal-overflow-error.forth create mode 100644 test/Translation/Forth/integer-literal-overflow-error.forth create mode 100644 test/Translation/Forth/integer-literal-underflow-error.forth diff --git a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp index 808e421..a31e661 100644 --- a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp +++ b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include +#include using namespace mlir; using namespace mlir::forth; @@ -958,7 +959,11 @@ LogicalResult ForthParser::parseBody(Value &stack) { if (currentToken.kind == Token::Kind::Number) { Location tokenLoc = getLoc(); - int64_t value = std::stoll(currentToken.text); + StringRef text = currentToken.text; + text.consume_front("+"); + int64_t value; + if (text.getAsInteger(10, value)) + return emitError("integer literal out of range for i64"); stack = builder .create(tokenLoc, stackType, stack, builder.getI64IntegerAttr(value)) @@ -966,7 +971,9 @@ LogicalResult ForthParser::parseBody(Value &stack) { consume(); } else if (currentToken.kind == Token::Kind::Float) { Location tokenLoc = getLoc(); - double value = std::stod(currentToken.text); + double value; + if (!llvm::to_float(currentToken.text, value) || std::isinf(value)) + return emitError("float literal out of range for f64"); stack = builder .create(tokenLoc, stackType, stack, builder.getF64FloatAttr(value)) diff --git a/test/Translation/Forth/basic-literals.forth b/test/Translation/Forth/basic-literals.forth index e739e93..829487a 100644 --- a/test/Translation/Forth/basic-literals.forth +++ b/test/Translation/Forth/basic-literals.forth @@ -4,5 +4,8 @@ \ CHECK-NEXT: forth.constant %{{.*}}(42 : i64) \ CHECK-NEXT: forth.constant %{{.*}}(-7 : i64) \ CHECK-NEXT: forth.constant %{{.*}}(0 : i64) +\ CHECK-NEXT: forth.constant %{{.*}}(5 : i64) +\ CHECK-NEXT: forth.constant %{{.*}}(9223372036854775807 : i64) +\ CHECK-NEXT: forth.constant %{{.*}}(-9223372036854775808 : i64) \! kernel main -42 -7 0 +42 -7 0 +5 9223372036854775807 -9223372036854775808 diff --git a/test/Translation/Forth/float-literal-overflow-error.forth b/test/Translation/Forth/float-literal-overflow-error.forth new file mode 100644 index 0000000..cf2df0f --- /dev/null +++ b/test/Translation/Forth/float-literal-overflow-error.forth @@ -0,0 +1,4 @@ +\ RUN: %not %warpforth-translate --forth-to-mlir %s 2>&1 | %FileCheck %s +\ CHECK: {{.*}}float-literal-overflow-error.forth:4:5: error: float literal out of range for f64 +\! kernel main +1.0 -1e999 diff --git a/test/Translation/Forth/float-literals.forth b/test/Translation/Forth/float-literals.forth index 26b4c8b..e52b23f 100644 --- a/test/Translation/Forth/float-literals.forth +++ b/test/Translation/Forth/float-literals.forth @@ -11,5 +11,7 @@ \ CHECK-NEXT: forth.constant %{{.*}}(5.000000e+00 : f64) \ CHECK-NEXT: forth.constant %{{.*}}(1.500000e+00 : f64) \ CHECK-NEXT: forth.constant %{{.*}}(2.500000e+02 : f64) +\ CHECK-NEXT: forth.constant %{{.*}}(1.7976931348623157E+308 : f64) +\ CHECK-NEXT: forth.constant %{{.*}}(0.000000e+00 : f64) \! kernel main -3.14 -2.0 1.0e-5 1e3 1E3 .5 -.5 5. +1.5 2.5e+2 +3.14 -2.0 1.0e-5 1e3 1E3 .5 -.5 5. +1.5 2.5e+2 1.7976931348623157e308 1e-400 diff --git a/test/Translation/Forth/integer-literal-overflow-error.forth b/test/Translation/Forth/integer-literal-overflow-error.forth new file mode 100644 index 0000000..99d7665 --- /dev/null +++ b/test/Translation/Forth/integer-literal-overflow-error.forth @@ -0,0 +1,4 @@ +\ RUN: %not %warpforth-translate --forth-to-mlir %s 2>&1 | %FileCheck %s +\ CHECK: {{.*}}integer-literal-overflow-error.forth:4:3: error: integer literal out of range for i64 +\! kernel main +1 9223372036854775808 diff --git a/test/Translation/Forth/integer-literal-underflow-error.forth b/test/Translation/Forth/integer-literal-underflow-error.forth new file mode 100644 index 0000000..fc16000 --- /dev/null +++ b/test/Translation/Forth/integer-literal-underflow-error.forth @@ -0,0 +1,4 @@ +\ RUN: %not %warpforth-translate --forth-to-mlir %s 2>&1 | %FileCheck %s +\ CHECK: {{.*}}integer-literal-underflow-error.forth:4:3: error: integer literal out of range for i64 +\! kernel main +1 -9223372036854775809