diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-09-16 17:26:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-16 17:26:13 +0200 |
commit | ae4ede6b009632bd0d809c61066b240e8ee7719a (patch) | |
tree | 0850c2b3735a098a111c6f0513786a039deda3c2 | |
parent | de7f2372be770ca97f3f63dcc9447bdd2827f9d0 (diff) | |
download | Nim-ae4ede6b009632bd0d809c61066b240e8ee7719a.tar.gz |
fixes #15325 (#15340)
-rw-r--r-- | compiler/commands.nim | 3 | ||||
-rw-r--r-- | compiler/injectdestructors.nim | 3 | ||||
-rw-r--r-- | compiler/options.nim | 3 | ||||
-rw-r--r-- | compiler/varpartitions.nim | 13 | ||||
-rw-r--r-- | tests/arc/tcursor_on_localvar.nim | 126 |
5 files changed, 144 insertions, 4 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index 0af31b2c7..a76a5be73 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -891,6 +891,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; processOnOffSwitchG(conf, {optProfileVM}, arg, pass, info) of "sinkinference": processOnOffSwitch(conf, {optSinkInference}, arg, pass, info) + of "cursorinference": + # undocumented, for debugging purposes only: + processOnOffSwitch(conf, {optCursorInference}, arg, pass, info) of "panics": processOnOffSwitchG(conf, {optPanics}, arg, pass, info) if optPanics in conf.globalOptions: diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index b8b8e776e..9d1f43595 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -1006,7 +1006,8 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = echoCfg(c.g) echo n - computeCursors(owner, n, g.config) + if optCursorInference in g.config.options: + computeCursors(owner, n, g.config) var scope: Scope let body = p(n, c, scope, normal) diff --git a/compiler/options.nim b/compiler/options.nim index 03418d953..226f13c73 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -41,6 +41,7 @@ type # please make sure we have under 32 options optMemTracker, optNilSeqs, optSinkInference # 'sink T' inference + optCursorInference TOptions* = set[TOption] @@ -372,7 +373,7 @@ const DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck, optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs` - optTrMacros, optStyleCheck} + optTrMacros, optStyleCheck, optCursorInference} DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace, optListFullPaths} diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index 87424c4be..743c4d55d 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -392,9 +392,18 @@ proc deps(c: var Partitions; dest, src: PNode) = analyseAsgn(c, c.s[vid], src) # do not borrow from a different local variable, this is easier # than tracking reassignments, consider 'var cursor = local; local = newNode()' - if src.kind == nkSym and (src.sym.kind in {skVar, skResult, skTemp} or + if src.kind == nkSym: + if (src.sym.kind in {skVar, skResult, skTemp} or (src.sym.kind in {skLet, skParam, skForVar} and hasDisabledAsgn(src.sym.typ))): - c.s[vid].flags.incl preventCursor + c.s[vid].flags.incl preventCursor + elif src.sym.kind in {skVar, skResult, skTemp, skLet, skForVar}: + # XXX: we need to compute variable alive ranges before doing anything else: + let srcid = variableId(c, src.sym) + if srcid >= 0 and preventCursor in c.s[srcid].flags: + # you cannot borrow from a local that lives shorter than 'vid': + if c.s[srcid].aliveStart > c.s[vid].aliveStart or + c.s[srcid].aliveEnd < c.s[vid].aliveEnd: + c.s[vid].flags.incl preventCursor if src.kind == nkSym and hasDestructor(src.typ): rhsIsSink(c, src) diff --git a/tests/arc/tcursor_on_localvar.nim b/tests/arc/tcursor_on_localvar.nim new file mode 100644 index 000000000..81b48271f --- /dev/null +++ b/tests/arc/tcursor_on_localvar.nim @@ -0,0 +1,126 @@ +discard """ + output: '''Section: common + Param: Floats1 +Section: local + Param: Str + Param: Bool + Param: Floats2''' + cmd: '''nim c --gc:arc $file''' +""" + +# bug #15325 + +import tables +import strutils + +const defaultSection = "***" + +type + Config* = ref object + table: OrderedTableRef[string, OrderedTable[string, string]] + +# ---------------------------------------------------------------------------------------------------------------------- +proc newConfig*(): Config = + result = new(Config) + result.table = newOrderedTable[string, OrderedTable[string, string]]() + +# ---------------------------------------------------------------------------------------------------------------------- +proc add*(self: Config, param, value, section: string) {.nosinks.} = + let s = if section == "": defaultSection else: section + + if not self.table.contains(s): + self.table[s] = initOrderedTable[string, string]() + + self.table[s][param] = value + +# ---------------------------------------------------------------------------------------------------------------------- +proc sections*(self: Config): seq[string] = + for i in self.table.keys: + let s = if i == defaultSection: "" else: i + result.add(s) + +# ---------------------------------------------------------------------------------------------------------------------- +proc params*(self: Config, section: string): seq[string] = + let s = if section == "": defaultSection else: section + + if self.table.contains(s): + for i in self.table[s].keys: + result.add(i) + +# ---------------------------------------------------------------------------------------------------------------------- +proc extract*(str, start, finish: string): string = + let startPos = str.find(start) + + if startPos < 0: + return "" + + let endPos = str.find(finish, startPos) + + if endPos < 0: + return "" + + return str[startPos + start.len() ..< endPos] + +# ---------------------------------------------------------------------------------------------------------------------- +proc loadString*(self: Config, text: string): tuple[valid: bool, errorInLine: int] {.discardable.} = + self.table.clear() + + var data = "" + + data = text + + var + actualSection = "" + lineCount = 0 + + for i in splitLines(data): + lineCount += 1 + + var line = strip(i) + + if line.len() == 0: + continue + + if line[0] == '#' or line[0] == ';': + continue + + if line[0] == '[': + let section = strip(extract(line, "[", "]")) + + if section.len() != 0: + actualSection = section + else: + self.table.clear() + return (false, lineCount) + else: + let equal = find(line, '=') + + if equal <= 0: + self.table.clear() + return (false, lineCount) + else: + let + param = strip(line[0 .. equal - 1]) + value = strip(line[equal + 1 .. ^1]) + + if param.len() == 0: + self.table.clear() + return (false, lineCount) + else: + self.add(param, value, actualSection) + + return (true, 0) + +# ---------------------------------------------------------------------------------------------------------------------- +when isMainModule: + var cfg = newConfig() + + cfg.loadString("[common]\nFloats1 = 1,2,3\n[local]\nStr = \"String...\"\nBool = true\nFloats2 = 4, 5, 6\n") + + for s in cfg.sections(): + echo "Section: " & s + + for p in cfg.params(s): + echo " Param: " & p + + |