diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 83f5e90172..bc9c06fa1d 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1237,6 +1237,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = else: scope = initScope(p.s(cpsStmts)) # we handled the error: + linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp]) expr(p, t[i][0], d) linefmt(p, cpsStmts, "#popCurrentException();$n", []) endBlockWith(p): diff --git a/tests/exception/treraise_typeless_except_finally.nim b/tests/exception/treraise_typeless_except_finally.nim new file mode 100644 index 0000000000..259863e4d4 --- /dev/null +++ b/tests/exception/treraise_typeless_except_finally.nim @@ -0,0 +1,30 @@ +discard """ + targets: "cpp" + matrix: "--mm:arc; --mm:orc; --mm:refc" + output: ''' +finally +after +''' +""" + +# Regression test: typeless `except:` followed by `finally:` must not +# trigger ReraiseDefect at the end of the proc. +# +# Previously, `genTryCpp` only emitted `T_ = nullptr;` in the *typed* +# except branches, leaving the typeless `except:` path with a still-set +# `T_`. After the handler body and `popCurrentException`, the trailing +# `if (T_) std::rethrow_exception(T_);` in the finally block would still +# fire — but with the Nim exception stack already popped, the rethrow +# bubbled up as a `ReraiseDefect: no exception to reraise`. + +proc test() = + try: + raise newException(CatchableError, "x") + except: + let e = getCurrentException() + discard e + finally: + echo "finally" + +test() +echo "after"