diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-06-06 17:51:41 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-06 11:51:41 +0200 |
commit | 8f5ae28fab113c425d22e5abc230f456fa627744 (patch) | |
tree | f3a82b83cc0460d500b73530a4707dddfa5ded24 /compiler/ccgcalls.nim | |
parent | 69d0b73d667c4be9383f29cda3f70e411995d9af (diff) | |
download | Nim-8f5ae28fab113c425d22e5abc230f456fa627744.tar.gz |
fixes #22672; Destructor not called for result when exception is thrown (#23267)
fixes #22672
Diffstat (limited to 'compiler/ccgcalls.nim')
-rw-r--r-- | compiler/ccgcalls.nim | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 6b716f759..81c0fb555 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -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]) @@ -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") |