summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-08-11 19:10:04 +0800
committerGitHub <noreply@github.com>2024-08-11 13:10:04 +0200
commitf0e1eef65ed08fb153b88615f07ea0fd91e4c258 (patch)
tree4b580b25b54f31d9fc89ef7347f0d6eb4e23e731
parent49544692598812a8306b8f9b4b437eac32ca804e (diff)
downloadNim-f0e1eef65ed08fb153b88615f07ea0fd91e4c258.tar.gz
fixes #14522 #22085 #12700 #23132; no range check for uints (#23930)
fixes #14522
fixes #22085
fixes #12700
fixes #23132
closes https://github.com/nim-lang/Nim/pull/22343 (succeeded by this PR)
completes https://github.com/nim-lang/RFCs/issues/175

follow up https://github.com/nim-lang/Nim/pull/12688
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semfold.nim11
-rw-r--r--doc/manual.md3
-rw-r--r--tests/int/t1.nim25
-rw-r--r--tests/range/tcompiletime_range_checks.nim4
5 files changed, 37 insertions, 9 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index c1e74b457..1c197c5e2 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -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
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index ca68bc2f3..69aaf2e90 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -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
@@ -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" %
diff --git a/doc/manual.md b/doc/manual.md
index e471658a4..045749450 100644
--- a/doc/manual.md
+++ b/doc/manual.md
@@ -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
diff --git a/tests/int/t1.nim b/tests/int/t1.nim
index 36402da07..d08f5f29b 100644
--- a/tests/int/t1.nim
+++ b/tests/int/t1.nim
@@ -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
@@ -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
+
diff --git a/tests/range/tcompiletime_range_checks.nim b/tests/range/tcompiletime_range_checks.nim
index 29e2c48a8..2d3f292ec 100644
--- a/tests/range/tcompiletime_range_checks.nim
+++ b/tests/range/tcompiletime_range_checks.nim
@@ -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