Skip to content

Commit

Permalink
fixes #22672; Destructor not called for result when exception is thro…
Browse files Browse the repository at this point in the history
…wn (#23267)

fixes #22672
  • Loading branch information
ringabout committed Jun 6, 2024
1 parent 69d0b73 commit 8f5ae28
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 5 deletions.
30 changes: 27 additions & 3 deletions compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ proc isHarmlessStore(p: BProc; canRaise: bool; d: TLoc): bool =
else:
result = false

proc cleanupTemp(p: BProc; returnType: PType, tmp: TLoc): bool =
if returnType.kind in {tyVar, tyLent}:
# we don't need to worry about var/lent return types
result = false
elif hasDestructor(returnType) and getAttachedOp(p.module.g.graph, returnType, attachedDestructor) != nil:
let dtor = getAttachedOp(p.module.g.graph, returnType, attachedDestructor)
var op = initLocExpr(p, newSymNode(dtor))
var callee = rdLoc(op)
let destroy = if dtor.typ.firstParamType.kind == tyVar:
callee & "(&" & rdLoc(tmp) & ")"
else:
callee & "(" & rdLoc(tmp) & ")"
raiseExitCleanup(p, destroy)
result = true
else:
result = false

proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
callee, params: Rope) =
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
Expand Down Expand Up @@ -128,18 +145,25 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
if canRaise: raiseExit(p)

elif isHarmlessStore(p, canRaise, d):
if d.k == locNone: d = getTemp(p, typ.returnType)
var useTemp = false
if d.k == locNone:
useTemp = true
d = getTemp(p, typ.returnType)
assert(d.t != nil) # generate an assignment to d:
var list = initLoc(locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, flags) # no need for deep copying
if canRaise: raiseExit(p)
if canRaise:
if not (useTemp and cleanupTemp(p, typ.returnType, d)):
raiseExit(p)
else:
var tmp: TLoc = getTemp(p, typ.returnType, needsInit=true)
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 not cleanupTemp(p, typ.returnType, tmp):
raiseExit(p)
genAssignment(p, d, tmp, {})
else:
pl.add(");\n")
Expand Down
12 changes: 12 additions & 0 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,18 @@ 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:
p.flags.incl nimErrorFlagAccessed
if p.nestedTryStmts.len == 0:
p.flags.incl beforeRetNeeded
# easy case, simply goto 'ret':
lineCg(p, cpsStmts, "if (NIM_UNLIKELY(*nimErr_)) {$1; goto BeforeRet_;}$n", [destroy])
else:
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 @@ -752,6 +752,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
9 changes: 9 additions & 0 deletions tests/errmsgs/t22852.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
discard """
exitcode: 1
outputsub: '''
Error: unhandled exception: value out of range: -2 notin 0 .. 9223372036854775807 [RangeDefect]
'''
"""

# bug #22852
echo [0][2..^2]
4 changes: 2 additions & 2 deletions tests/stdlib/tjson.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --backend:cpp --mm:refc; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
matrix: "; --backend:cpp; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
"""


Expand Down Expand Up @@ -51,7 +51,7 @@ for i in 0 .. 10000:
except:
discard
# memory diff should less than 4M
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024) # todo fixme doesn;t work for ORC
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)


# test `$`
Expand Down

0 comments on commit 8f5ae28

Please sign in to comment.