mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 19:33:42 +00:00
Fix 26144; exception propagation for non-raising virtual methods (#26145)
ref #26144 The C backend must not use `sfNeverRaises` to remove exception checks from virtual method calls. The flag describes only the selected base method body, while a vtable override may raise a catchable exception. This change makes `canRaiseDisp` conservative for `skMethod` symbols and adds a regression test covering an exception raised by a child method invoked through a base reference.
This commit is contained in:
@@ -11,7 +11,11 @@
|
||||
|
||||
proc canRaiseDisp(p: BProc; n: PNode): bool =
|
||||
# we assume things like sysFatal cannot raise themselves
|
||||
if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
|
||||
if n.kind == nkSym and n.sym.kind == skMethod:
|
||||
# A base method may be overridden by a branch with a wider exception set.
|
||||
# Its inferred effects describe only the base body, not every vtable target.
|
||||
result = true
|
||||
elif n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
|
||||
result = false
|
||||
elif optPanics in p.config.globalOptions or
|
||||
(n.kind == nkSym and sfSystemModule in getModule(n.sym).flags and
|
||||
|
||||
20
tests/method/tmethod_virtual_raise.nim
Normal file
20
tests/method/tmethod_virtual_raise.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
output: '''caught'''
|
||||
"""
|
||||
|
||||
type
|
||||
Base = ref object of RootObj
|
||||
Child = ref object of Base
|
||||
|
||||
method run(value: Base): string {.base.} =
|
||||
result = "base"
|
||||
|
||||
method run(value: Child): string =
|
||||
raise newException(ValueError, "child")
|
||||
|
||||
let value: Base = Child()
|
||||
try:
|
||||
discard value.run()
|
||||
quit "virtual method did not raise"
|
||||
except ValueError:
|
||||
echo "caught"
|
||||
Reference in New Issue
Block a user