diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 67b7469cb0..236f0f86e5 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -309,7 +309,7 @@ proc addAbiCheck(m: BModule; t: PType, name: Rope) = proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) = - ensureMutable param.sym + backendEnsureMutable param.sym fillLoc(param.sym.locImpl, locParam, param, "Result", OnStack) let t = param.sym.typ @@ -542,7 +542,7 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params var types, names, args: seq[string] = @[] if not isCtor: var this = t.n[1].sym - ensureMutable this + backendEnsureMutable this fillParamName(m, this) fillLoc(this.locImpl, locParam, t.n[1], this.paramStorageLoc) @@ -564,7 +564,7 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params else: descKind = dkRefParam var typ, name: string - ensureMutable param + backendEnsureMutable param fillParamName(m, param) fillLoc(param.locImpl, locParam, t.n[i], param.paramStorageLoc) @@ -1183,7 +1183,7 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Builder; asPtr: bool let isCtor = sfConstructor in prc.flags var check = initIntSet() fillBackendName(m, prc) - ensureMutable prc + backendEnsureMutable prc fillLoc(prc.locImpl, locProc, prc.ast[namePos], OnUnknown) var memberOp = "#." #only virtual var typ: PType diff --git a/compiler/commands.nim b/compiler/commands.nim index 3d2aabdc03..be5a8abd27 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -951,7 +951,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectArg(conf, switch, arg, pass, info) var value: int = 10_000_000 discard parseSaturatedNatural(arg, value) - if not value > 0: localError(conf, info, "maxLoopIterationsVM must be a positive integer greater than zero") + if value <= 0: localError(conf, info, "maxLoopIterationsVM must be a positive integer greater than zero") conf.maxLoopIterationsVM = value of "maxcalldepthvm": expectArg(conf, switch, arg, pass, info) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 307761409c..71af95a5f2 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -148,7 +148,7 @@ proc cmpDecimalsIgnoreCase(a, b: string): int = limitB = iB while limitA < aLen and isDigit(a[limitA]): inc limitA while limitB < bLen and isDigit(b[limitB]): inc limitB - var pos = max(limitA-iA, limitB-iA) + var pos = max(limitA-iA, limitB-iB) while pos > 0: if limitA-pos < iA: # digit in `a` is 0 effectively result = ord('0') - ord(b[limitB-pos]) diff --git a/compiler/nifbackend.nim b/compiler/nifbackend.nim index fa293bbfe3..181a3dc040 100644 --- a/compiler/nifbackend.nim +++ b/compiler/nifbackend.nim @@ -44,14 +44,16 @@ proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[Precomp let suffix = stack.pop() if not visited.containsOrIncl(suffix.string): - let nifFile = toGeneratedFile(g.config, AbsoluteFile(suffix.string), ".nif") - let fileIdx = msgs.fileInfoIdx(g.config, nifFile) + var isKnownFile = false + let fileIdx = g.config.registerNifSuffix(suffix.string, isKnownFile) let precomp = moduleFromNifFile(g, fileIdx, {LoadFullAst}) if precomp.module != nil: result.add precomp for dep in precomp.deps: if not visited.contains(dep.string): stack.add dep + else: + assert false, "Recompiling module is not implemented." if mainModule.module != nil: result.add mainModule diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index da7576ca4a..e2f91587ff 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -2234,6 +2234,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semAnyRef(c, n, tyPtr, prev) elif op.id == ord(wRef): result = semAnyRef(c, n, tyRef, prev) + elif op.id == ord(wStatic): + checkSonsLen(n, 2, c.config) + result = semStaticType(c, n[1], prev) elif op.id == ord(wType): checkSonsLen(n, 2, c.config) result = semTypeOf(c, n[1], prev) diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index 80b532371c..05584341b6 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -99,12 +99,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, if isInlineIterator(typ) and kind in {skVar, skLet, skConst, skParam, skResult}: # only closure iterators may be assigned to anything. result = t - let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags + let innerFlags = flags - {taObjField, taTupField, taIsOpenArray} + let f = if kind in {skProc, skFunc}: innerFlags+{taNoUntyped} else: innerFlags for _, a in t.paramTypes: if result != nil: break - result = typeAllowedAux(marker, a, skParam, c, f-{taIsOpenArray}) + result = typeAllowedAux(marker, a, skParam, c, f) if result.isNil and t.returnType != nil: - result = typeAllowedAux(marker, t.returnType, skResult, c, flags) + result = typeAllowedAux(marker, t.returnType, skResult, c, innerFlags) of tyTypeDesc: if kind in {skVar, skLet, skConst} and taProcContextIsNotMacro in flags: result = t diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index c5e71c0179..af5a661cf6 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -556,7 +556,7 @@ proc replace(s: string): string = while i < s.len(): if s[i] == '\\': d.add(r"\\") - elif s[i] == '\c' and s[i+1] == '\l': + elif s[i] == '\c' and i+1 < s.len() and s[i+1] == '\l': d.add(r"\c\l") inc(i) elif s[i] == '\c': diff --git a/lib/system.nim b/lib/system.nim index 306818ffa0..03164b4f32 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1469,7 +1469,7 @@ when defined(nimHasTopDownInference): ## This is not as efficient as turning a fixed length array into a sequence ## as it always copies every element of `a`. let sz = a.len - when supportsCopyMem(T) and not defined(js): + when supportsCopyMem(T) and not defined(js) and not defined(nimscript): result = newSeqUninit[T](sz) when nimvm: for i in 0..sz-1: result[i] = a[i] diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim index 5711004822..b2e4e41720 100644 --- a/lib/system/arithmetics.nim +++ b/lib/system/arithmetics.nim @@ -306,15 +306,15 @@ proc `mod`*(x, y: uint32): uint32 {.magic: "ModU", noSideEffect.} proc `mod`*(x, y: uint64): uint64 {.magic: "ModU", noSideEffect.} proc `+=`*[T: SomeInteger](x: var T, y: T) {. - magic: "Inc", noSideEffect.} + magic: "Inc", noSideEffect, systemRaisesDefect.} ## Increments an integer. proc `-=`*[T: SomeInteger](x: var T, y: T) {. - magic: "Dec", noSideEffect.} + magic: "Dec", noSideEffect, systemRaisesDefect.} ## Decrements an integer. proc `*=`*[T: SomeInteger](x: var T, y: T) {. - inline, noSideEffect.} = + inline, noSideEffect, systemRaisesDefect.} = ## Binary `*=` operator for integers. x = x * y @@ -339,20 +339,22 @@ proc `+=`*[T: float|float32|float64] (x: var T, y: T) {. x = x + y proc `-=`*[T: float|float32|float64] (x: var T, y: T) {. - inline, noSideEffect.} = + inline, noSideEffect, systemRaisesDefect.} = ## Decrements in place a floating point number. x = x - y proc `*=`*[T: float|float32|float64] (x: var T, y: T) {. - inline, noSideEffect.} = + inline, noSideEffect, systemRaisesDefect.} = ## Multiplies in place a floating point number. x = x * y -proc `/=`*(x: var float64, y: float64) {.inline, noSideEffect.} = +proc `/=`*(x: var float64, y: float64) {. + inline, noSideEffect, systemRaisesDefect.} = ## Divides in place a floating point number. x = x / y -proc `/=`*[T: float|float32](x: var T, y: T) {.inline, noSideEffect.} = +proc `/=`*[T: float|float32](x: var T, y: T) {. + inline, noSideEffect, systemRaisesDefect.} = ## Divides in place a floating point number. x = x / y diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim index 76e9cd8d51..db749a38d3 100644 --- a/tests/generics/tgeneric0.nim +++ b/tests/generics/tgeneric0.nim @@ -219,3 +219,6 @@ block: # bug #19531 x.cb() y.cb() + +block: + proc r(_: typedesc, _: static uint | static int) = discard; r(uint, 0) diff --git a/tests/ic/tmiscs.nim b/tests/ic/tmiscs.nim index 72407afcc4..34cd79fe99 100644 --- a/tests/ic/tmiscs.nim +++ b/tests/ic/tmiscs.nim @@ -4,6 +4,8 @@ discard """ 5 3 2 +1.0 +2.0 ''' """ @@ -42,4 +44,26 @@ proc divmod(a, b: int): (int, int) = let (q, r) = divmod(17, 5) echo q -echo r \ No newline at end of file +echo r + + +# Shallow object with seq (trigger GC interaction) +type + Matrix = object + rows, cols: int + data: seq[float] + +proc newMatrix(r, c: int): Matrix = + Matrix(rows: r, cols: c, data: newSeq[float](r * c)) + +proc `[]`(m: Matrix, r, c: int): float = + m.data[r * m.cols + c] + +proc `[]=`(m: var Matrix, r, c: int, v: float) = + m.data[r * m.cols + c] = v + +var m = newMatrix(2, 2) +m[0, 0] = 1.0 +m[1, 1] = 2.0 +echo m[0, 0] +echo m[1, 1] diff --git a/tests/lent/tlents.nim b/tests/lent/tlents.nim index 28fe0602ed..1b14972239 100644 --- a/tests/lent/tlents.nim +++ b/tests/lent/tlents.nim @@ -23,3 +23,25 @@ block: doAssert x(a) == 1 doAssert y(a) == 1 + +import std/tables + +block: + type + R = proc(): lent O {.nimcall.} + F = object + schema: R + O = object + fields: Table[string, F] + + func f(o: O, key: string): R = + if key in o.fields: o.fields[key].schema + else: nil + +block: + type + R = proc(): lent O + O = object + r: R + + func f(o: O): int = 42 diff --git a/tests/stdlib/tmisc_issues.nim b/tests/stdlib/tmisc_issues.nim index 4f7707d976..18dea064cf 100644 --- a/tests/stdlib/tmisc_issues.nim +++ b/tests/stdlib/tmisc_issues.nim @@ -64,3 +64,120 @@ block: # bug #24683 cast[ptr int](addr x)[] = 10 doAssert x == @[1, 2, 3, 4, 45, 56, 67, 999, 88, 777] + +when not defined(js): + block: + var x = high int + var result = x + + # assert that multiplying highest int by highest int overflows + + doAssertRaises(OverflowDefect): + x *= x + + doAssertRaises(OverflowDefect): + result *= x + + # overflow via compound assignment on int + var a = high(int) + doAssertRaises(OverflowDefect): + a += 1 + + var b = low(int) + doAssertRaises(OverflowDefect): + b -= 1 + + var c = high(int) + doAssertRaises(OverflowDefect): + c *= 2 + + # add smaller signed types too + var a8 = high(int8) + doAssertRaises(OverflowDefect): + a8 += 1 + + var b8 = low(int8) + doAssertRaises(OverflowDefect): + b8 -= 1 + + var c8 = high(int8) + doAssertRaises(OverflowDefect): + c8 *= 2 + + var a16 = high(int16) + doAssertRaises(OverflowDefect): + a16 += 1 + + var b16 = low(int16) + doAssertRaises(OverflowDefect): + b16 -= 1 + + # arithmetic operations that can overflow (non-compound direct ops) + doAssertRaises(OverflowDefect): + discard high(int) + 1 + + doAssertRaises(OverflowDefect): + discard low(int) - 1 + + doAssertRaises(OverflowDefect): + discard high(int) * 2 + + doAssertRaises(OverflowDefect): + discard low(int) div -1 + + # int8 overflow for signed operations + doAssertRaises(OverflowDefect): + discard high(int8) + 1'i8 + + doAssertRaises(OverflowDefect): + discard low(int8) - 1'i8 + + doAssertRaises(OverflowDefect): + discard high(int8) * 2'i8 + + # enum overflow, from arithmetics.succ/pred + type E = enum eA, eB + doAssertRaises(OverflowDefect): + discard eB.succ + doAssertRaises(OverflowDefect): + discard eA.pred + + # floating-point compound divide should produce inf (not raise by defect) + var f = 1.0 + f /= 0.0 + # 1.0/0.0 is inf, check not finite + #doAssert not f.isFinite # `isFinite` not in this context, but avoid crash + # simple check ensures it mutated to a very large value + # (in Nim, `inf` is represented as 1e300*1e300; this compares as true) + doAssert f == 1.0 / 0.0 + + # Additional overflow cases across various integer widths + doAssertRaises(OverflowDefect): + discard high(int32) + 1'i32 + + doAssertRaises(OverflowDefect): + discard low(int32) - 1'i32 + + doAssertRaises(OverflowDefect): + discard high(int64) + 1'i64 + + doAssertRaises(OverflowDefect): + discard low(int64) - 1'i64 + + doAssertRaises(OverflowDefect): + discard -low(int64) + + doAssertRaises(OverflowDefect): + discard abs(low(int8)) + + doAssertRaises(OverflowDefect): + discard high(int32) * 2'i32 + + doAssertRaises(OverflowDefect): + discard high(int64) * 2'i64 + + doAssertRaises(OverflowDefect): + discard low(int32) div -1'i32 + + doAssertRaises(OverflowDefect): + discard low(int64) div -1'i64 diff --git a/tests/stdlib/tparsecfg.nim b/tests/stdlib/tparsecfg.nim index 2600d6f663..693ea5c86a 100644 --- a/tests/stdlib/tparsecfg.nim +++ b/tests/stdlib/tparsecfg.nim @@ -130,3 +130,9 @@ block: doAssert dict.getSectionValue(section4, "can_values_be_as_well") == "True" doAssert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False" doAssert dict.getSectionValue(section4, "purpose") == "formatting for readability" + +block: # bug #25674 + var dict = newConfig() + dict.setSectionKey("", "key", "value\c") + var s = newStringStream() + dict.writeConfig(s) diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims index 15e9d878d8..02572cb5ac 100644 --- a/tests/test_nimscript.nims +++ b/tests/test_nimscript.nims @@ -143,3 +143,7 @@ proc discardableCall(cmd: string): int {.discardable.} = result = 123 discardableCall "echo hi" + +block: + let a = "abc" + doAssert @a == @['a', 'b', 'c']