diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-11-20 17:08:43 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-20 17:08:43 +0100 |
commit | c98e0e22ad7bf7772eb0ef3f50b7f67f33ec8905 (patch) | |
tree | 6ec8ee4149105307bfabb42444e979be890e7edc | |
parent | 85ffcd80c05ae1bbf853121059c39a215a29ae54 (diff) | |
download | Nim-c98e0e22ad7bf7772eb0ef3f50b7f67f33ec8905.tar.gz |
conversions to unsigned numbers are not checked anymore; implements /… (#12688) [backport]
* conversions to unsigned numbers are not checked anymore; implements / fixes https://github.com/nim-lang/RFCs/issues/175 * change the spec yet again to be less consistent but to make more sense; updated the changelog
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 3 | ||||
-rw-r--r-- | compiler/jsgen.nim | 5 | ||||
-rw-r--r-- | compiler/options.nim | 4 | ||||
-rw-r--r-- | compiler/semfold.nim | 6 | ||||
-rw-r--r-- | doc/manual.rst | 14 |
6 files changed, 29 insertions, 6 deletions
diff --git a/changelog.md b/changelog.md index 4aeb51141..caead21b4 100644 --- a/changelog.md +++ b/changelog.md @@ -64,6 +64,9 @@ ## Language changes - Unsigned integer operators have been fixed to allow promotion of the first operand. +- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim + versions. The documentation was improved to acknowledge this special case. + See https://github.com/nim-lang/RFCs/issues/175 for more details. ### Tool changes diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 1d9d0aca6..009ee7221 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1929,7 +1929,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) = proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) = var a: TLoc var dest = skipTypes(n.typ, abstractVar) - if optRangeCheck notin p.options: + if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and + checkUnsignedConversions notin p.config.legacyFeatures): initLocExpr(p, n.sons[0], a) putIntoDest(p, d, n, "(($1) ($2))" % [getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 4b3862cff..f4d43ce0c 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2155,7 +2155,10 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) = proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) = var a, b: TCompRes gen(p, n.sons[0], r) - if optRangeCheck in p.options: + if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and + checkUnsignedConversions notin p.config.legacyFeatures): + discard "XXX maybe emit masking instructions here" + else: gen(p, n.sons[1], a) gen(p, n.sons[2], b) useMagic(p, "chckRange") diff --git a/compiler/options.nim b/compiler/options.nim index 50bae9557..52ba8254a 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -146,6 +146,10 @@ type ## Allows to modify a NimNode where the type has already been ## flagged with nfSem. If you actually do this, it will cause ## bugs. + checkUnsignedConversions + ## Historically and especially in version 1.0.0 of the language + ## conversions to unsigned numbers were checked. In 1.0.4 they + ## are not anymore. SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/compiler/semfold.nim b/compiler/semfold.nim index ec3ebd65b..ec2d646c8 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -434,15 +434,12 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc}) let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc}) - # if srcTyp.kind == tyUInt64 and "FFFFFF" in $n: # echo "n: ", n, " a: ", a # echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check # echo getInt(a) # echo high(int64) # writeStackTrace() - - # XXX range checks? case dstTyp.kind of tyInt..tyInt64, tyUInt..tyUInt64: case srcTyp.kind @@ -450,9 +447,10 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = result = newIntNodeT(toInt128(getFloat(a)), n, g) of tyChar, tyUInt..tyUInt64, tyInt..tyInt64: var val = a.getOrdValue + if check: rangeCheck(n, val, g) result = newIntNodeT(val, n, g) - if dstTyp.kind in {tyUInt .. tyUInt64}: + if dstTyp.kind in {tyUInt..tyUInt64}: result.kind = nkUIntLit else: result = a diff --git a/doc/manual.rst b/doc/manual.rst index c869b391f..82487a385 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -3188,6 +3188,7 @@ has lots of advantages: Type conversions ---------------- + Syntactically a `type conversion` is like a procedure call, but a type name replaces the procedure name. A type conversion is always safe in the sense that a failure to convert a type to another @@ -3207,6 +3208,19 @@ A type conversion can also be used to disambiguate overloaded routines: let procVar = (proc(x: string))(p) procVar("a") +Since operations on unsigned numbers wrap around and are unchecked so are +type conversion 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 +conversions too are now *always unchecked*. + Type casts ---------- |