summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2020-09-16 17:26:13 +0200
committerGitHub <noreply@github.com>2020-09-16 17:26:13 +0200
commitae4ede6b009632bd0d809c61066b240e8ee7719a (patch)
tree0850c2b3735a098a111c6f0513786a039deda3c2
parentde7f2372be770ca97f3f63dcc9447bdd2827f9d0 (diff)
downloadNim-ae4ede6b009632bd0d809c61066b240e8ee7719a.tar.gz
fixes #15325 (#15340)
-rw-r--r--compiler/commands.nim3
-rw-r--r--compiler/injectdestructors.nim3
-rw-r--r--compiler/options.nim3
-rw-r--r--compiler/varpartitions.nim13
-rw-r--r--tests/arc/tcursor_on_localvar.nim126
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
+
+