diff options
author | Araq <rumpf_a@web.de> | 2020-07-07 23:59:13 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2020-07-08 10:48:12 +0200 |
commit | cdce245a235f3a8c255d0f782bc088546343b6ed (patch) | |
tree | 8aafea73122a127b4f61ecf967d3a1fc22ce1f83 /compiler | |
parent | b17e1efc67a64ce6acd2ddf4f432879f3bf739e2 (diff) | |
download | Nim-cdce245a235f3a8c255d0f782bc088546343b6ed.tar.gz |
fixes #14899
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/injectdestructors.nim | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index e57898ae8..291cd36aa 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -37,6 +37,9 @@ type final: seq[PNode] # finally section needsTry: bool parent: ptr Scope + escapingSyms: IntSet # a construct like (block: let x = f(); x) + # means that 'x' escapes. We then destroy it + # in the parent's scope (and also allocate it there). proc nestedScope(parent: var Scope): Scope = Scope(vars: @[], wasMoved: @[], final: @[], needsTry: false, parent: addr(parent)) @@ -400,8 +403,11 @@ proc genCopy(c: var Con; dest, ri: PNode): PNode = checkForErrorPragma(c, t, ri, "=") result = genCopyNoCheck(c, dest, ri) -proc addTopVar(c: var Con; s: var Scope; v: PNode) = - s.vars.add v.sym +proc addTopVar(c: var Con; s: var Scope; v: PNode): ptr Scope = + result = addr(s) + while v.sym.id in result.escapingSyms and result.parent != nil: + result = result.parent + result[].vars.add v.sym proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode = let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) @@ -584,9 +590,31 @@ proc cycleCheck(n: PNode; c: var Con) = message(c.graph.config, n.info, warnCycleCreated, msg) break +proc markEscapingVars(n: PNode; s: var Scope) = + case n.kind + of nkSym: + s.escapingSyms.incl n.sym.id + of nkDotExpr, nkBracketExpr, nkCheckedFieldExpr, nkDerefExpr, nkHiddenDeref, + nkAddr, nkHiddenAddr, nkStringToCString, nkCStringToString, nkObjDownConv, + nkObjUpConv: + markEscapingVars(n[0], s) + of nkCast, nkHiddenSubConv, nkHiddenStdConv, nkConv: + markEscapingVars(n[1], s) + of nkTupleConstr, nkBracket, nkPar, nkClosure: + for i in 0 ..< n.len: + markEscapingVars(n[i], s) + of nkObjConstr: + for i in 1 ..< n.len: + markEscapingVars(n[i], s) + of nkStmtList, nkStmtListExpr: + if n.len > 0: + markEscapingVars(n[^1], s) + else: + discard "no arbitrary tree traversal here" + proc pVarTopLevel(v: PNode; c: var Con; s: var Scope; ri, res: PNode) = # move the variable declaration to the top of the frame: - c.addTopVar s, v + let owningScope = c.addTopVar(s, v) if isUnpackedTuple(v): if c.inLoop > 0: # unpacked tuple needs reset at every loop iteration @@ -596,7 +624,7 @@ proc pVarTopLevel(v: PNode; c: var Con; s: var Scope; ri, res: PNode) = if sfGlobal in v.sym.flags and s.parent == nil: c.graph.globalDestructors.add genDestroy(c, v) else: - s.final.add genDestroy(c, v) + owningScope[].final.add genDestroy(c, v) if ri.kind == nkEmpty and c.inLoop > 0: res.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, isDecl = true) elif ri.kind != nkEmpty: @@ -617,6 +645,7 @@ template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = for i in 0..<n.len-1: result.add p(n[i], c, s, normal) result.add maybeVoid(n[^1], s) + markEscapingVars(n[^1], s) of nkCaseStmt: result = copyNode(n) @@ -630,6 +659,7 @@ template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = for j in 0 ..< it.len-1: branch[j] = copyTree(it[j]) var ofScope = nestedScope(s) + markEscapingVars(it[^1], ofScope) let ofResult = maybeVoid(it[^1], ofScope) branch[^1] = toTree(ofScope, ofResult, treeFlags) result.add branch @@ -650,6 +680,7 @@ template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = if alwaysStmt: result.typ = nil result.add n[0] var bodyScope = nestedScope(s) + markEscapingVars(n[1], bodyScope) let bodyResult = processCall(n[1], bodyScope) result.add toTree(bodyScope, bodyResult, treeFlags) rememberParent(s, bodyScope) @@ -667,6 +698,7 @@ template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = branch[0] = toTree(branchScope, cond, {producesValue, onlyCareAboutVars}) branchScope.parent = addr(s) + markEscapingVars(it[^1], branchScope) var branchResult = processCall(it[^1], branchScope) branch[^1] = toTree(branchScope, branchResult, treeFlags) result.add branch @@ -676,6 +708,7 @@ template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = result = copyNode(n) if alwaysStmt: result.typ = nil var tryScope = nestedScope(s) + markEscapingVars(n[0], tryScope) var tryResult = maybeVoid(n[0], tryScope) result.add toTree(tryScope, tryResult, treeFlags) rememberParent(s, tryScope) |