Skip to content

Commit

Permalink
fixes #22672; Destructor not called for result when exception is thrown
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout authored Jan 30, 2024
1 parent 857b35c commit 9351494
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
24 changes: 23 additions & 1 deletion compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
proc hasNoInit(call: PNode): bool {.inline.} =
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags

import renderer

proc isHarmlessStore(p: BProc; canRaise: bool; d: TLoc): bool =
if d.k in {locTemp, locNone} or not canRaise:
result = true
Expand Down Expand Up @@ -139,7 +141,27 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
var list = initLoc(locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, tmp, list, flags) # no need for deep copying
if canRaise: raiseExit(p)
if canRaise:
if hasDestructor(typ.returnType) and p.nestedTryStmts.len > 0:
var needRaiseExit = true
debug p.nestedTryStmts[^1].fin
var fin = p.nestedTryStmts[^1].fin
if fin.len == 1 and fin[0].kind in {nkStmtList, nkStmtListExpr}:
fin = fin[0]
for dtor in fin:
if dtor.kind == nkCall and dtor[0].kind == nkSym and
dtor[0].sym.name.s == "=destroy" and
sameType(dtor[1].typ, typ.returnType):
var op = initLocExpr(p, dtor[0])
var callee = rdLoc(op)
let destroy = callee & "(" & rdLoc(tmp) & ")"
raiseExitCleanup(p, destroy)
needRaiseExit = false
break
if needRaiseExit:
raiseExit(p)
else:
raiseExit(p)
genAssignment(p, d, tmp, {})
else:
pl.add(");\n")
Expand Down
6 changes: 6 additions & 0 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,12 @@ proc raiseExit(p: BProc) =
lineCg(p, cpsStmts, "if (NIM_UNLIKELY(*nimErr_)) goto LA$1_;$n",
[p.nestedTryStmts[^1].label])

proc raiseExitCleanup(p: BProc, destroy: string) =
assert p.config.exc == excGoto
if nimErrorFlagDisabled notin p.flags:
lineCg(p, cpsStmts, "if (NIM_UNLIKELY(*nimErr_)) {$2; goto LA$1_;}$n",
[p.nestedTryStmts[^1].label, destroy])

proc finallyActions(p: BProc) =
if p.config.exc != excGoto and p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept:
# if the current try stmt have a finally block,
Expand Down
1 change: 1 addition & 0 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ proc intLiteral(i: BiggestInt; result: var Rope)
proc genLiteral(p: BProc, n: PNode; result: var Rope)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
proc raiseExit(p: BProc)
proc raiseExitCleanup(p: BProc, destroy: string)

proc initLocExpr(p: BProc, e: PNode, flags: TLocFlags = {}): TLoc =
result = initLoc(locNone, e, OnUnknown, flags)
Expand Down

0 comments on commit 9351494

Please sign in to comment.