Skip to content

Commit

Permalink
fixes #14522 #22085 #12700 #23132; no range check for uints (#23930)
Browse files Browse the repository at this point in the history
fixes #14522
fixes #22085
fixes #12700
fixes #23132
closes #22343 (succeeded by this PR)
completes nim-lang/RFCs#175

follow up #12688
  • Loading branch information
ringabout authored Aug 11, 2024
1 parent 4954469 commit f0e1eef
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 9 deletions.
3 changes: 2 additions & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
discard "convOk"
elif targetTyp.isOrdinalType:
if src.kind in nkCharLit..nkUInt64Lit and
src.getInt notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp):
src.getInt notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp) and
targetTyp.kind notin {tyUInt..tyUInt64}:
result = convNotInRange
elif src.kind in nkFloatLit..nkFloat64Lit and
(classify(src.floatVal) in {fcNan, fcNegInf, fcInf} or
Expand Down
11 changes: 8 additions & 3 deletions compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,17 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
result = newIntNodeT(toInt128(getFloat(a)), n, idgen, g)
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
var val = a.getOrdValue
if check: rangeCheck(n, val, g)
result = newIntNodeT(val, n, idgen, g)
if dstTyp.kind in {tyUInt..tyUInt64}:
result = newIntNodeT(val, n, idgen, g)
result.transitionIntKind(nkUIntLit)
else:
if check: rangeCheck(n, val, g)
result = newIntNodeT(val, n, idgen, g)
else:
result = a
result.typ = n.typ
if check and result.kind in {nkCharLit..nkUInt64Lit}:
if check and result.kind in {nkCharLit..nkUInt64Lit} and
dstTyp.kind notin {tyUInt..tyUInt64}:
rangeCheck(n, getInt(result), g)
of tyFloat..tyFloat64:
case srcTyp.kind
Expand Down Expand Up @@ -747,6 +750,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
if leValueConv(n[1], a) and leValueConv(a, n[2]):
result = a # a <= x and x <= b
result.typ = n.typ
elif n.typ.kind in {tyUInt..tyUInt64}:
discard "don't check uints"
else:
localError(g.config, n.info,
"conversion from $1 to $2 is invalid" %
Expand Down
3 changes: 0 additions & 3 deletions doc/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -3788,9 +3788,6 @@ type conversions to unsigned integers and between unsigned integers. The
rationale for this is mostly better interoperability with the C Programming
language when algorithms are ported from C to Nim.

Exception: Values that are converted to an unsigned type at compile time
are checked so that code like `byte(-1)` does not compile.

**Note**: Historically the operations
were unchecked and the conversions were sometimes checked but starting with
the revision 1.0.4 of this document and the language implementation the
Expand Down
25 changes: 25 additions & 0 deletions tests/int/t1.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
discard """
targets: "c cpp"
"""

doAssert typeOf(1.int64 + 1.int) is int64
doAssert typeOf(1.uint64 + 1.uint) is uint64
doAssert int64 is SomeNumber
Expand All @@ -12,3 +16,24 @@ doAssert typeOf(myInt16 + myInt) is int # of type `int`
doAssert typeOf(myInt16 + 2i32) is int32 # of type `int32`
doAssert int32 isnot int64
doAssert int32 isnot int

block:
# bug #22085
const
x = uint32(uint64.high) # vm error
u = uint64.high
v = uint32(u) # vm error

let
z = uint64.high
y = uint32(z) # runtime ok

let
w = uint32(uint64.high) # semfold error

doAssert x == w
doAssert v == y

# bug #14522
doAssert 0xFF000000_00000000.uint64 == 18374686479671623680'u64

4 changes: 2 additions & 2 deletions tests/range/tcompiletime_range_checks.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
discard """
cmd: "nim check --hint:Processing:off --hint:Conf:off $file"
errormsg: "18446744073709551615 can't be converted to int8"
nimout: '''tcompiletime_range_checks.nim(36, 21) Error: 2147483648 can't be converted to int32
tcompiletime_range_checks.nim(37, 23) Error: -1 can't be converted to uint64
nimout: '''
tcompiletime_range_checks.nim(36, 21) Error: 2147483648 can't be converted to int32
tcompiletime_range_checks.nim(38, 34) Error: 255 can't be converted to FullNegativeRange
tcompiletime_range_checks.nim(39, 34) Error: 18446744073709551615 can't be converted to HalfNegativeRange
tcompiletime_range_checks.nim(40, 34) Error: 300 can't be converted to FullPositiveRange
Expand Down

0 comments on commit f0e1eef

Please sign in to comment.