diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-08-27 23:19:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-27 23:19:41 +0200 |
commit | eaebbfa785eeb8ba586fa43bcd5e240b5c9c4ad9 (patch) | |
tree | 4453e28332d2224a584f7de36c19ecbc588a2aa1 | |
parent | d564130a3b2596161847d695329ad009e693358a (diff) | |
parent | 329e169e964951b39cee863dd715277166497213 (diff) | |
download | Nim-eaebbfa785eeb8ba586fa43bcd5e240b5c9c4ad9.tar.gz |
Fix several float range issues (supersedes #11905) (#12067)
* Fix several float range issues * address the comments
-rw-r--r-- | compiler/sem.nim | 1 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 6 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 7 | ||||
-rw-r--r-- | tests/range/trange.nim | 11 |
6 files changed, 27 insertions, 3 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim index a13fd138b..7c47dac22 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -444,6 +444,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, const errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters" + errFloatToString = "cannot convert '$1' to '$2'" proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, flags: TExprFlags = {}): PNode = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 57d9aae4b..765110d56 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -513,6 +513,9 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) = if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType): localError(c.config, n.info, "cannot convert " & $value & " to " & typeToString(newType)) + of nkFloatLit..nkFloat64Lit: + if check and not floatRangeCheck(n.floatVal, newType): + localError(c.config, n.info, errFloatToString % [$n.floatVal, typeToString(newType)]) else: discard n.typ = newType diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 0d9d1af39..5a9c92647 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -292,6 +292,8 @@ proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode = result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal) result.info = n.info result.typ = typ + if not floatRangeCheck(result.floatVal, typ): + localError(c.config, n.info, errFloatToString % [$n.floatVal, typeToString(typ)]) else: changeType(c, r1, typ, check=true) result = r1 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 4d628e6ec..16cc89e13 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -10,6 +10,8 @@ # this module does the semantic checking of type declarations # included from sem.nim +import math + const errStringOrIdentNodeExpected = "string or ident node expected" errStringLiteralExpected = "string literal expected" @@ -236,6 +238,10 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = else: result.n.addSon semConstExpr(c, range[i]) + if (result.n[0].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[0].floatVal) == fcNan) or + (result.n[1].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[1].floatVal) == fcNan): + localError(c.config, n.info, "NaN is not a valid start or end for a range") + if weakLeValue(result.n[0], result.n[1]) == impNo: localError(c.config, n.info, "range is empty") diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e4bf13e60..cec3ecb28 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -414,9 +414,10 @@ proc isConvertibleToRange(f, a: PType): bool = of tyUInt16: result = a.kind in {tyUInt8, tyUInt16, tyUInt} of tyUInt32: result = a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt} else: result = false - elif f.kind in {tyFloat..tyFloat128} and - a.kind in {tyFloat..tyFloat128}: - result = true + elif f.kind in {tyFloat..tyFloat128}: + # `isIntLit` is correct and should be used above as well, see PR: + # https://github.com/nim-lang/Nim/pull/11197 + result = isIntLit(a) or a.kind in {tyFloat..tyFloat128} proc handleFloatRange(f, a: PType): TTypeRelation = if a.kind == f.kind: diff --git a/tests/range/trange.nim b/tests/range/trange.nim index 41804d0f2..9df0e6975 100644 --- a/tests/range/trange.nim +++ b/tests/range/trange.nim @@ -118,3 +118,14 @@ block: x3 = R32(4) doAssert $x1 & $x2 & $x3 == "444" + +block: + var x1: range[0'f..1'f] = 1 + const x2: range[0'f..1'f] = 1 + var x5: range[0'f32..1'f32] = 1'f64 + const x6: range[0'f32..1'f32] = 1'f64 + + reject: + const x: range[0'f..1'f] = 2'f + reject: + const x: range[0'f..1'f] = 2 |