summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/dfa.nim39
-rw-r--r--compiler/injectdestructors.nim10
-rw-r--r--tests/destructor/tobjfield_analysis.nim34
3 files changed, 60 insertions, 23 deletions
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index 0072c9410..45e1aaffe 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -567,19 +567,36 @@ proc genReturn(c: var Con; n: PNode) =
 
 const
   InterestingSyms = {skVar, skResult, skLet, skParam, skForVar, skTemp}
-  PathKinds* = {nkDotExpr, nkCheckedFieldExpr,
+  PathKinds0 = {nkDotExpr, nkCheckedFieldExpr,
                 nkBracketExpr, nkDerefExpr, nkHiddenDeref,
                 nkAddr, nkHiddenAddr,
-                nkHiddenStdConv, nkHiddenSubConv, nkObjDownConv, nkObjUpConv}
+                nkObjDownConv, nkObjUpConv}
+  PathKinds1 = {nkHiddenStdConv, nkHiddenSubConv}
+
+proc getRoot(n: PNode): PNode =
+  result = n
+  while true:
+    case result.kind
+    of PathKinds0:
+      result = result[0]
+    of PathKinds1:
+      result = result[1]
+    else: break
+
+proc skipConvDfa*(n: PNode): PNode =
+  result = n
+  while true:
+    case result.kind
+    of nkObjDownConv, nkObjUpConv:
+      result = result[0]
+    of PathKinds1:
+      result = result[1]
+    else: break
 
 proc genUse(c: var Con; orig: PNode) =
-  var n = orig
-  var iters = 0
-  while n.kind in PathKinds:
-    n = n[0]
-    inc iters
+  let n = dfa.getRoot(orig)
   if n.kind == nkSym and n.sym.kind in InterestingSyms:
-    c.code.add Instr(n: orig, kind: use, sym: if iters > 0: nil else: n.sym)
+    c.code.add Instr(n: orig, kind: use, sym: if orig != n: nil else: n.sym)
 
 proc aliases(obj, field: PNode): bool =
   var n = field
@@ -729,7 +746,7 @@ proc gen(c: var Con; n: PNode) =
     # "uses" 'i'. But we are only talking about builtin array indexing so
     # it doesn't matter and 'x = 34' is NOT a usage of 'x'.
     genDef(c, n[0])
-  of PathKinds:
+  of PathKinds0 - {nkHiddenStdConv, nkHiddenSubConv, nkObjDownConv, nkObjUpConv}:
     genUse(c, n)
   of nkIfStmt, nkIfExpr: genIf(c, n)
   of nkWhenStmt:
@@ -746,8 +763,8 @@ proc gen(c: var Con; n: PNode) =
      nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr:
     for x in n: gen(c, x)
   of nkPragmaBlock: gen(c, n.lastSon)
-  of nkDiscardStmt: gen(c, n.sons[0])
-  of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast:
+  of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n.sons[0])
+  of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast, nkHiddenSubConv, nkHiddenStdConv:
     gen(c, n.sons[1])
   of nkStringToCString, nkCStringToString: gen(c, n.sons[0])
   of nkVarSection, nkLetSection: genVarSection(c, n)
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index 4bcc38cb3..5958d89ae 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -195,15 +195,17 @@ proc isLastRead(n: PNode; c: var Con): bool =
   # first we need to search for the instruction that belongs to 'n':
   c.otherRead = nil
   var instr = -1
+  let m = dfa.skipConvDfa(n)
+
   for i in 0..<c.g.len:
     # This comparison is correct and MUST not be ``instrTargets``:
-    if c.g[i].kind == use and c.g[i].n == n:
+    if c.g[i].kind == use and c.g[i].n == m:
       if instr < 0:
         instr = i
         break
 
   dbg:
-    echo "starting point for ", n, " is ", instr
+    echo "starting point for ", n, " is ", instr, " ", n.kind
 
   if instr < 0: return false
   # we go through all paths beginning from 'instr+1' and need to
@@ -625,7 +627,9 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
       result = genCopy(c, dest.typ, dest, ri)
       result.add p(ri, c)
   of nkHiddenSubConv, nkHiddenStdConv:
-    if ri[1].kind in movableNodeKinds:
+    if sameType(ri.typ, ri[1].typ):
+      result = moveOrCopy(dest, ri[1], c)
+    elif ri[1].kind in movableNodeKinds:
       result = moveOrCopy(dest, ri[1], c)
       var b = newNodeIT(ri.kind, ri.info, ri.typ)
       b.add ri[0] # add empty node
diff --git a/tests/destructor/tobjfield_analysis.nim b/tests/destructor/tobjfield_analysis.nim
index 24cf02aee..83f394c3b 100644
--- a/tests/destructor/tobjfield_analysis.nim
+++ b/tests/destructor/tobjfield_analysis.nim
@@ -2,30 +2,46 @@ discard """
   output: '''works'''
 """
 
+#  bug #11095
+
 type
-  MyVal = object
-    f: ptr float
+  MyVal[T] = object
+    f: ptr T
 
-proc `=destroy`(x: var MyVal) =
+proc `=destroy`[T](x: var MyVal[T]) =
   if x.f != nil:
     dealloc(x.f)
 
-proc `=sink`(x1: var MyVal, x2: Myval) =
+proc `=sink`[T](x1: var MyVal[T], x2: MyVal[T]) =
   if x1.f != x2.f:
     `=destroy`(x1)
     x1.f = x2.f
 
-proc `=`(x1: var MyVal, x2: Myval) {.error.}
+proc `=`[T](x1: var MyVal[T], x2: MyVal[T]) {.error.}
 
-proc newVal(x: float): MyVal =
-  result.f = create(float)
+proc newVal[T](x: sink T): MyVal[T] =
+  result.f = create(T)
   result.f[] = x
 
-proc sinkMe(x: sink MyVal) =
+proc set[T](x: var MyVal[T], val: T) =
+  x.f[] = val
+
+proc sinkMe[T](x: sink MyVal[T]) =
   discard
 
+var flag = false
+
 proc main =
-  var y = (newVal(3.0), newVal(4.0))
+  var y = case flag
+    of true:
+      var x1 = newVal[float](1.0)
+      var x2 = newVal[float](2.0)
+      (newVal(x1), newVal(x2))
+
+    of false:
+      var x1 = newVal[float](1.0)
+      var x2 = newVal[float](2.0)
+      (newVal(x1), newVal(x2))
 
   sinkMe y[0]
   sinkMe y[1]