diff options
author | Araq <rumpf_a@web.de> | 2019-04-17 17:26:59 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2019-04-17 17:26:59 +0200 |
commit | 7640a230fc6166bb7fcc18bcab4251d7f6dc6caf (patch) | |
tree | f5ff43cfe6f85b46eb2f4a3eef3f3c4ecbb59295 | |
parent | 850e90ac303cf791369e5fe4827fa1ab2269bdad (diff) | |
download | Nim-7640a230fc6166bb7fcc18bcab4251d7f6dc6caf.tar.gz |
fixes #11050
-rw-r--r-- | compiler/sempass2.nim | 18 | ||||
-rw-r--r-- | compiler/transf.nim | 2 | ||||
-rw-r--r-- | tests/destructor/tgcdestructors.nim | 21 |
3 files changed, 34 insertions, 7 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index f2a6a7891..996735804 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -738,7 +738,7 @@ proc track(tracked: PEffects, n: PNode) = mergeTags(tracked, effectList.sons[tagEffects], n) gcsafeAndSideeffectCheck() if a.kind != nkSym or a.sym.magic != mNBindSym: - for i in 1 ..< len(n): trackOperand(tracked, n.sons[i], paramType(op, i), a) + for i in 1 ..< n.len: trackOperand(tracked, n.sons[i], paramType(op, i), a) if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}: # may not look like an assignment, but it is: let arg = n.sons[1] @@ -754,7 +754,7 @@ proc track(tracked: PEffects, n: PNode) = track(tracked, n.sons[i]) of nkDotExpr: guardDotAccess(tracked, n) - for i in 0 ..< len(n): track(tracked, n.sons[i]) + for i in 0 ..< n.len: track(tracked, n.sons[i]) of nkCheckedFieldExpr: track(tracked, n.sons[0]) if warnProveField in tracked.config.notes: @@ -821,7 +821,7 @@ proc track(tracked: PEffects, n: PNode) = of nkForStmt, nkParForStmt: # we are very conservative here and assume the loop is never executed: let oldState = tracked.init.len - for i in 0 .. len(n)-3: + for i in 0 .. n.len-3: let it = n[i] track(tracked, it) if tracked.owner.kind != skMacro: @@ -830,13 +830,19 @@ proc track(tracked: PEffects, n: PNode) = createTypeBoundOps(tracked.c, x.typ, x.info) else: createTypeBoundOps(tracked.c, it.typ, it.info) - for i in len(n)-2..len(n)-1: - track(tracked, n.sons[i]) + let iterCall = n[n.len-2] + let loopBody = n[n.len-1] + if tracked.owner.kind != skMacro and iterCall.len > 1: + # XXX this is a bit hacky: + if iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}: + createTypeBoundOps(tracked.c, iterCall[1].typ, iterCall[1].info) + track(tracked, iterCall) + track(tracked, loopBody) setLen(tracked.init, oldState) of nkObjConstr: when false: track(tracked, n.sons[0]) let oldFacts = tracked.guards.s.len - for i in 1 ..< len(n): + for i in 1 ..< n.len: let x = n.sons[i] track(tracked, x) if x.sons[0].kind == nkSym and sfDiscriminant in x.sons[0].sym.flags: diff --git a/compiler/transf.nim b/compiler/transf.nim index c455e3319..25a8bc5dd 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -651,6 +651,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var t = formal.typ if formal.ast != nil and formal.ast.typ.destructor != nil and t.destructor == nil: t = formal.ast.typ # better use the type that actually has a destructor. + elif t.destructor == nil and arg.typ.destructor != nil: + t = arg.typ # generate a temporary and produce an assignment statement: var temp = newTemp(c, t, formal.info) #temp.sym.flags.incl sfCursor diff --git a/tests/destructor/tgcdestructors.nim b/tests/destructor/tgcdestructors.nim index 620ba7d66..c0a88e650 100644 --- a/tests/destructor/tgcdestructors.nim +++ b/tests/destructor/tgcdestructors.nim @@ -4,7 +4,8 @@ discard """ ho ha @["arg", "asdfklasdfkl", "asdkfj", "dfasj", "klfjl"] -22 22''' +@[1, 2, 3] +25 25''' """ import allocators @@ -132,6 +133,24 @@ proc other = other() +# bug #11050 + +type + Obj* = object + f*: seq[int] + +method main(o: Obj) = + for newb in o.f: + discard + +# test that o.f was not moved! +proc testforNoMove = + var o = Obj(f: @[1, 2, 3]) + main(o) + echo o.f + +testforNoMove() + #echo s let (a, d) = allocCounters() discard cprintf("%ld %ld\n", a, d) |