From bcda71a8a7c05566d729cf83f051dbc51649f6d5 Mon Sep 17 00:00:00 2001 From: cooldome Date: Thu, 29 Mar 2018 08:19:03 +0100 Subject: [PATCH] fixes #7414 (#7434) --- compiler/ccgstmts.nim | 40 +++++++++++++++++------------------- compiler/cgendata.nim | 9 ++++---- tests/exception/tfinally.nim | 22 +++++++++++++++++++- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 8a54708eee..f6c4204e87 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -37,6 +37,10 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} = return false result = true +proc inExceptBlockLen(p: BProc): int = + for x in p.nestedTryStmts: + if x.inExcept: result.inc + proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") @@ -96,7 +100,7 @@ proc startBlock(p: BProc, start: FormatStr = "{$n", setLen(p.blocks, result + 1) p.blocks[result].id = p.labels p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 - p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16 + p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16 proc assignLabel(b: var TBlock): Rope {.inline.} = b.label = "LA" & b.id.rope @@ -344,26 +348,22 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Called by return and break stmts. # Deals with issues faced when jumping out of try/except/finally stmts, - var stack: seq[PNode] - newSeq(stack, 0) + var stack = newSeq[tuple[n: PNode, inExcept: bool]](0) - var alreadyPoppedCnt = p.inExceptBlock for i in countup(1, howManyTrys): + let tryStmt = p.nestedTryStmts.pop if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions: # Pop safe points generated by try - if alreadyPoppedCnt > 0: - dec alreadyPoppedCnt - else: + if not tryStmt.inExcept: linefmt(p, cpsStmts, "#popSafePoint();$n") # Pop this try-stmt of the list of nested trys # so we don't infinite recurse on it in the next step. - var tryStmt = p.nestedTryStmts.pop stack.add(tryStmt) # Find finally-stmt for this try-stmt # and generate a copy of its sons - var finallyStmt = lastSon(tryStmt) + var finallyStmt = lastSon(tryStmt.n) if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) @@ -384,7 +384,7 @@ proc genReturnStmt(p: BProc, t: PNode) = if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) blockLeaveActions(p, howManyTrys = p.nestedTryStmts.len, - howManyExcepts = p.inExceptBlock) + howManyExcepts = p.inExceptBlockLen) if (p.finallySafePoints.len > 0): # If we're in a finally block, and we came here by exception # consume it before we return. @@ -567,15 +567,15 @@ proc genBreakStmt(p: BProc, t: PNode) = let label = assignLabel(p.blocks[idx]) blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts, - p.inExceptBlock - p.blocks[idx].nestedExceptStmts) + p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts) genLineDir(p, t) lineF(p, cpsStmts, "goto $1;$n", [label]) proc genRaiseStmt(p: BProc, t: PNode) = - if p.inExceptBlock > 0 and p.inExceptBlock == p.nestedTryStmts.len: + if p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept: # if the current try stmt have a finally block, # we must execute it before reraising - var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon + var finallyBlock = p.nestedTryStmts[^1].n[^1] if finallyBlock.kind == nkFinally: genSimpleBlock(p, finallyBlock.sons[0]) if t.sons[0].kind != nkEmpty: @@ -812,14 +812,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = let end_label = getLabel(p) discard cgsym(p.module, "Exception") - add(p.nestedTryStmts, t) + add(p.nestedTryStmts, (t, false)) startBlock(p, "try {$n") expr(p, t[0], d) endBlock(p) var catchAllPresent = false - inc p.inExceptBlock + p.nestedTryStmts[^1].inExcept = true for i in 1..