parent
50229293ae
commit
bcda71a8a7
3 changed files with 44 additions and 27 deletions
|
|
@ -37,6 +37,10 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} =
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
|
proc inExceptBlockLen(p: BProc): int =
|
||||||
|
for x in p.nestedTryStmts:
|
||||||
|
if x.inExcept: result.inc
|
||||||
|
|
||||||
proc genVarTuple(p: BProc, n: PNode) =
|
proc genVarTuple(p: BProc, n: PNode) =
|
||||||
var tup, field: TLoc
|
var tup, field: TLoc
|
||||||
if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
|
if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
|
||||||
|
|
@ -96,7 +100,7 @@ proc startBlock(p: BProc, start: FormatStr = "{$n",
|
||||||
setLen(p.blocks, result + 1)
|
setLen(p.blocks, result + 1)
|
||||||
p.blocks[result].id = p.labels
|
p.blocks[result].id = p.labels
|
||||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
|
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.} =
|
proc assignLabel(b: var TBlock): Rope {.inline.} =
|
||||||
b.label = "LA" & b.id.rope
|
b.label = "LA" & b.id.rope
|
||||||
|
|
@ -344,26 +348,22 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||||
# Called by return and break stmts.
|
# Called by return and break stmts.
|
||||||
# Deals with issues faced when jumping out of try/except/finally stmts,
|
# Deals with issues faced when jumping out of try/except/finally stmts,
|
||||||
|
|
||||||
var stack: seq[PNode]
|
var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
|
||||||
newSeq(stack, 0)
|
|
||||||
|
|
||||||
var alreadyPoppedCnt = p.inExceptBlock
|
|
||||||
for i in countup(1, howManyTrys):
|
for i in countup(1, howManyTrys):
|
||||||
|
let tryStmt = p.nestedTryStmts.pop
|
||||||
if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions:
|
if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions:
|
||||||
# Pop safe points generated by try
|
# Pop safe points generated by try
|
||||||
if alreadyPoppedCnt > 0:
|
if not tryStmt.inExcept:
|
||||||
dec alreadyPoppedCnt
|
|
||||||
else:
|
|
||||||
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
||||||
|
|
||||||
# Pop this try-stmt of the list of nested trys
|
# Pop this try-stmt of the list of nested trys
|
||||||
# so we don't infinite recurse on it in the next step.
|
# so we don't infinite recurse on it in the next step.
|
||||||
var tryStmt = p.nestedTryStmts.pop
|
|
||||||
stack.add(tryStmt)
|
stack.add(tryStmt)
|
||||||
|
|
||||||
# Find finally-stmt for this try-stmt
|
# Find finally-stmt for this try-stmt
|
||||||
# and generate a copy of its sons
|
# and generate a copy of its sons
|
||||||
var finallyStmt = lastSon(tryStmt)
|
var finallyStmt = lastSon(tryStmt.n)
|
||||||
if finallyStmt.kind == nkFinally:
|
if finallyStmt.kind == nkFinally:
|
||||||
genStmts(p, finallyStmt.sons[0])
|
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])
|
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
|
||||||
blockLeaveActions(p,
|
blockLeaveActions(p,
|
||||||
howManyTrys = p.nestedTryStmts.len,
|
howManyTrys = p.nestedTryStmts.len,
|
||||||
howManyExcepts = p.inExceptBlock)
|
howManyExcepts = p.inExceptBlockLen)
|
||||||
if (p.finallySafePoints.len > 0):
|
if (p.finallySafePoints.len > 0):
|
||||||
# If we're in a finally block, and we came here by exception
|
# If we're in a finally block, and we came here by exception
|
||||||
# consume it before we return.
|
# consume it before we return.
|
||||||
|
|
@ -567,15 +567,15 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||||
let label = assignLabel(p.blocks[idx])
|
let label = assignLabel(p.blocks[idx])
|
||||||
blockLeaveActions(p,
|
blockLeaveActions(p,
|
||||||
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
|
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
|
||||||
p.inExceptBlock - p.blocks[idx].nestedExceptStmts)
|
p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
lineF(p, cpsStmts, "goto $1;$n", [label])
|
lineF(p, cpsStmts, "goto $1;$n", [label])
|
||||||
|
|
||||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
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,
|
# if the current try stmt have a finally block,
|
||||||
# we must execute it before reraising
|
# 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:
|
if finallyBlock.kind == nkFinally:
|
||||||
genSimpleBlock(p, finallyBlock.sons[0])
|
genSimpleBlock(p, finallyBlock.sons[0])
|
||||||
if t.sons[0].kind != nkEmpty:
|
if t.sons[0].kind != nkEmpty:
|
||||||
|
|
@ -812,14 +812,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
|
|
||||||
let end_label = getLabel(p)
|
let end_label = getLabel(p)
|
||||||
discard cgsym(p.module, "Exception")
|
discard cgsym(p.module, "Exception")
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, (t, false))
|
||||||
startBlock(p, "try {$n")
|
startBlock(p, "try {$n")
|
||||||
expr(p, t[0], d)
|
expr(p, t[0], d)
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
var catchAllPresent = false
|
var catchAllPresent = false
|
||||||
|
|
||||||
inc p.inExceptBlock
|
p.nestedTryStmts[^1].inExcept = true
|
||||||
for i in 1..<t.len:
|
for i in 1..<t.len:
|
||||||
if t[i].kind != nkExceptBranch: break
|
if t[i].kind != nkExceptBranch: break
|
||||||
|
|
||||||
|
|
@ -839,6 +839,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
|
discard pop(p.nestedTryStmts)
|
||||||
|
|
||||||
if not catchAllPresent and t[^1].kind == nkFinally:
|
if not catchAllPresent and t[^1].kind == nkFinally:
|
||||||
# finally requires catch all presence
|
# finally requires catch all presence
|
||||||
startBlock(p, "catch (...) {$n")
|
startBlock(p, "catch (...) {$n")
|
||||||
|
|
@ -846,9 +848,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
line(p, cpsStmts, ~"throw;$n")
|
line(p, cpsStmts, ~"throw;$n")
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
dec p.inExceptBlock
|
|
||||||
discard pop(p.nestedTryStmts)
|
|
||||||
|
|
||||||
if t[^1].kind == nkFinally:
|
if t[^1].kind == nkFinally:
|
||||||
genSimpleBlock(p, t[^1][0])
|
genSimpleBlock(p, t[^1][0])
|
||||||
|
|
||||||
|
|
@ -902,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||||
var length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, (t, false))
|
||||||
expr(p, t.sons[0], d)
|
expr(p, t.sons[0], d)
|
||||||
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
@ -910,7 +909,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
||||||
if optStackTrace in p.options:
|
if optStackTrace in p.options:
|
||||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
||||||
inc p.inExceptBlock
|
p.nestedTryStmts[^1].inExcept = true
|
||||||
var i = 1
|
var i = 1
|
||||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||||
# bug #4230: avoid false sharing between branches:
|
# bug #4230: avoid false sharing between branches:
|
||||||
|
|
@ -941,7 +940,6 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "#popCurrentException();$n")
|
linefmt(p, cpsStmts, "#popCurrentException();$n")
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
inc(i)
|
inc(i)
|
||||||
dec p.inExceptBlock
|
|
||||||
discard pop(p.nestedTryStmts)
|
discard pop(p.nestedTryStmts)
|
||||||
endBlock(p) # end of else block
|
endBlock(p) # end of else block
|
||||||
if i < length and t.sons[i].kind == nkFinally:
|
if i < length and t.sons[i].kind == nkFinally:
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,10 @@ type
|
||||||
threadVarAccessed*: bool # true if the proc already accessed some threadvar
|
threadVarAccessed*: bool # true if the proc already accessed some threadvar
|
||||||
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
|
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
|
||||||
currLineInfo*: TLineInfo # AST codegen will make this superfluous
|
currLineInfo*: TLineInfo # AST codegen will make this superfluous
|
||||||
nestedTryStmts*: seq[PNode] # in how many nested try statements we are
|
nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]
|
||||||
# (the vars must be volatile then)
|
# in how many nested try statements we are
|
||||||
inExceptBlock*: int # are we currently inside an except block?
|
# (the vars must be volatile then)
|
||||||
# leaving such scopes by raise or by return must
|
# bool is true when are in the except part of a try block
|
||||||
# execute any applicable finally blocks
|
|
||||||
finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
|
finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
|
||||||
# using return in finally statements
|
# using return in finally statements
|
||||||
labels*: Natural # for generating unique labels in the C proc
|
labels*: Natural # for generating unique labels in the C proc
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ msg1
|
||||||
msg2
|
msg2
|
||||||
finally2
|
finally2
|
||||||
finally1
|
finally1
|
||||||
|
-----------
|
||||||
|
except1
|
||||||
|
finally1
|
||||||
|
except2
|
||||||
|
finally2
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
# Test return in try statement:
|
# Test return in try statement:
|
||||||
|
|
@ -39,4 +44,19 @@ proc nested_finally =
|
||||||
finally:
|
finally:
|
||||||
echo "finally1"
|
echo "finally1"
|
||||||
|
|
||||||
nested_finally()
|
nested_finally()
|
||||||
|
|
||||||
|
echo "-----------"
|
||||||
|
#bug 7414
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
raise newException(Exception, "Hello")
|
||||||
|
except:
|
||||||
|
echo "except1"
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
echo "finally1"
|
||||||
|
except:
|
||||||
|
echo "except2"
|
||||||
|
finally:
|
||||||
|
echo "finally2"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue