From a562de2d9189706a9b7b9045c8abf9b821549692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 21 Aug 2019 19:15:15 +0200 Subject: [PATCH] squashed and merged with devel --- compiler/astalgo.nim | 6 ++-- compiler/lexer.nim | 2 +- compiler/semexprs.nim | 2 +- compiler/semtypes.nim | 2 +- compiler/types.nim | 11 +++---- lib/system.nim | 2 +- tests/arithm/tarithm.nim | 1 + tests/converter/tstatic_range_checks.nim | 42 ++++++++++++++++++++++++ 8 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 tests/converter/tstatic_range_checks.nim diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 4100c3629..632f00f4d 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -117,7 +117,7 @@ proc sameValue*(a, b: PNode): bool = result = false case a.kind of nkCharLit..nkUInt64Lit: - if b.kind in {nkCharLit..nkUInt64Lit}: result = a.intVal == b.intVal + if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) == getInt(b) of nkFloatLit..nkFloat64Lit: if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: @@ -131,8 +131,8 @@ proc leValue*(a, b: PNode): bool = # a <= b? result = false case a.kind - of nkCharLit..nkUInt32Lit: - if b.kind in {nkCharLit..nkUInt32Lit}: result = a.intVal <= b.intVal + of nkCharLit..nkUInt64Lit: + if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) <= getInt(b) of nkFloatLit..nkFloat64Lit: if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal of nkStrLit..nkTripleStrLit: diff --git a/compiler/lexer.nim b/compiler/lexer.nim index c2b95c481..d1e75d314 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -565,7 +565,7 @@ proc getNumber(L: var TLexer, result: var TToken) = case result.tokType of floatTypes: result.fNumber = parseFloat(result.literal) - of tkUInt64Lit: + of tkUInt64Lit, tkUIntLit: var iNumber: uint64 var len: int try: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index b80c4c8cb..5a4811770 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -341,7 +341,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = n.typ = getSysType(c.graph, n.info, tyInt) of tyArray: n.typ = typ.sons[0] # indextype - of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32, tyFloat..tyFloat64: + of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt..tyUInt64, tyFloat..tyFloat64: n.typ = n.sons[1].typ.skipTypes({tyTypeDesc}) of tyGenericParam: # prepare this for resolving in semtypinst: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 3038a1a6b..33285e6f4 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -223,7 +223,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = if not hasUnknownTypes: if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})): localError(c.config, n.info, "type mismatch") - elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128 or + elif not rangeT[0].isOrdinalType(allowUint=true) and rangeT[0].kind notin tyFloat..tyFloat128 or rangeT[0].kind == tyBool: localError(c.config, n.info, "ordinal or float type expected") elif enumHasHoles(rangeT[0]): diff --git a/compiler/types.nim b/compiler/types.nim index 61fbffd60..671ee622c 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -155,14 +155,13 @@ proc enumHasHoles*(t: PType): bool = var b = t.skipTypes({tyRange, tyGenericInst, tyAlias, tySink}) result = b.kind == tyEnum and tfEnumHasHoles in b.flags -proc isOrdinalType*(t: PType, allowEnumWithHoles = false): bool = +proc isOrdinalType*(t: PType, allowEnumWithHoles: bool = false): bool = assert(t != nil) const - # caution: uint, uint64 are no ordinal types! - baseKinds = {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum} + baseKinds = {tyChar,tyInt..tyUInt64,tyBool,tyEnum} parentKinds = {tyRange, tyOrdinal, tyGenericInst, tyAlias, tySink, tyDistinct} - (t.kind in baseKinds and not (t.enumHasHoles and not allowEnumWithHoles)) or - (t.kind in parentKinds and isOrdinalType(t.lastSon)) + result = (t.kind in baseKinds and not (t.enumHasHoles and not allowEnumWithHoles)) or + (t.kind in parentKinds and isOrdinalType(t.lastSon, allowEnumWithHoles)) proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, closure: RootRef): bool @@ -1284,7 +1283,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = typeAllowedAux(marker, lastSon(t), kind, flags) of tyRange: if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin - {tyChar, tyEnum, tyInt..tyFloat128, tyUInt8..tyUInt32}: result = t + {tyChar, tyEnum, tyInt..tyFloat128, tyInt..tyUInt64}: result = t of tyOpenArray, tyVarargs, tySink: if kind != skParam: result = t diff --git a/lib/system.nim b/lib/system.nim index 7e23b5188..61c9ee57f 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -97,7 +97,7 @@ type SomeInteger* = SomeSignedInt|SomeUnsignedInt ## Type class matching all integer types. - SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint8|uint16|uint32 + SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint|uint8|uint16|uint32|uint64 ## Type class matching all ordinal types; however this includes enums with ## holes. diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim index 1150af951..e20b159f8 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/arithm/tarithm.nim @@ -54,6 +54,7 @@ block tcast: crossCheck(uint16, uint16.high + 5'u16) crossCheck(uint32, uint32.high + 5'u32) crossCheck(uint64, 0xFFFFFFFFFFFFFFFF'u64 + 5'u64) + crossCheck(uint64, uint64.high + 5'u64) doAssert $sub1(0'u8) == "255" doAssert $sub1(0'u16) == "65535" diff --git a/tests/converter/tstatic_range_checks.nim b/tests/converter/tstatic_range_checks.nim new file mode 100644 index 000000000..ea61fd88d --- /dev/null +++ b/tests/converter/tstatic_range_checks.nim @@ -0,0 +1,42 @@ +template reject(e) = + static: assert(not compiles(e)) + +template accept(e) = + static: assert(compiles(e)) + +type + UnsignedRange = 0'u64 .. 100'u64 + SemiOutOfBounds = 0x7ffffffffffffe00'u64 .. 0x8000000000000100'u64 + FullOutOfBounds = 0x8000000000000000'u64 .. 0x8000000000000200'u64 + + FullNegativeRange = -200 .. -100 + HalfNegativeRange = -50 .. 50 + FullPositiveRange = 100 .. 200 + +reject(int32(0x80000000'i64)) +accept(int32(0x7fffffff'i64)) + +reject(uint64(-1'i64)) +accept(uint64(0'i64)) + +reject(FullNegativeRange(0xff'u32)) +reject(HalfNegativeRange(0xffffffffffffffff'u64)) # internal `intVal` is `-1` which would be in range. +accept(HalfNegativeRange(25'u64)) +reject(FullPositiveRange(300'u64)) + +accept(UnsignedRange(50'u64)) +reject(UnsignedRange(101'u64)) + +accept(SemiOutOfBounds(0x7ffffffffffffe00'i64)) +reject(SemiOutOfBounds(0x8000000000000000'i64)) # +accept(SemiOutOfBounds(0x8000000000000000'u64)) # the last two literals have internally the same `intVal`. + +reject(int32(NaN)) +reject(int64(1e100)) +reject(uint64(1e100)) + +# removed cross checks from tarithm.nim +reject(int64(0xFFFFFFFFFFFFFFFF'u64)) +reject(int32(0xFFFFFFFFFFFFFFFF'u64)) +reject(int16(0xFFFFFFFFFFFFFFFF'u64)) +reject( int8(0xFFFFFFFFFFFFFFFF'u64))