mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-06 11:54:11 +00:00
fixes #1888
This commit is contained in:
@@ -551,12 +551,7 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||
lineF(p, cpsStmts, "goto $1;$n", [label])
|
||||
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
if p.module.compileToCpp:
|
||||
result = "throw NimException($1, $2);$n"
|
||||
elif getCompilerProc("Exception") != nil:
|
||||
result = "#raiseException((#Exception*)$1, $2);$n"
|
||||
else:
|
||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||
result = "#raiseException((#Exception*)$1, $2);$n"
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if p.inExceptBlock > 0:
|
||||
@@ -797,11 +792,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
# finallyPart();
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
var
|
||||
exc: Rope
|
||||
i, length, blen: int
|
||||
genLineDir(p, t)
|
||||
exc = getTempName()
|
||||
let exc = getTempName()
|
||||
if getCompilerProc("Exception") != nil:
|
||||
discard cgsym(p.module, "Exception")
|
||||
else:
|
||||
@@ -809,20 +801,23 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
add(p.nestedTryStmts, t)
|
||||
startBlock(p, "try {$n")
|
||||
expr(p, t.sons[0], d)
|
||||
length = sonsLen(t)
|
||||
let length = sonsLen(t)
|
||||
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
|
||||
if optStackTrace in p.options:
|
||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR);$n")
|
||||
inc p.inExceptBlock
|
||||
i = 1
|
||||
var i = 1
|
||||
var catchAllPresent = false
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
blen = sonsLen(t.sons[i])
|
||||
let blen = sonsLen(t.sons[i])
|
||||
if i > 1: addf(p.s(cpsStmts), "else ", [])
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
catchAllPresent = true
|
||||
exprBlock(p, t.sons[i].sons[0], d)
|
||||
startBlock(p)
|
||||
expr(p, t.sons[i].sons[0], d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n")
|
||||
endBlock(p)
|
||||
else:
|
||||
var orExpr: Rope = nil
|
||||
for j in countup(0, blen - 2):
|
||||
@@ -832,7 +827,10 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
"#isObj($1.exp->m_type, $2)",
|
||||
[exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||
lineF(p, cpsStmts, "if ($1) ", [orExpr])
|
||||
exprBlock(p, t.sons[i].sons[blen-1], d)
|
||||
startBlock(p)
|
||||
expr(p, t.sons[i].sons[blen-1], d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n")
|
||||
endBlock(p)
|
||||
inc(i)
|
||||
|
||||
# reraise the exception if there was no catch all
|
||||
|
||||
@@ -58,7 +58,7 @@ proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||
proc popSafePoint {.compilerRtl, inl.} =
|
||||
excHandler = excHandler.prev
|
||||
|
||||
proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
|
||||
proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
|
||||
e.parent = currException
|
||||
currException = e
|
||||
|
||||
@@ -69,12 +69,12 @@ proc popCurrentException {.compilerRtl, inl.} =
|
||||
const
|
||||
nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
|
||||
not NimStackTrace
|
||||
hasSomeStackTrace = NimStackTrace or
|
||||
hasSomeStackTrace = NimStackTrace or
|
||||
defined(nativeStackTrace) and nativeStackTraceSupported
|
||||
|
||||
when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||
type
|
||||
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
|
||||
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
|
||||
final, pure.} = object
|
||||
dli_fname: cstring
|
||||
dli_fbase: pointer
|
||||
@@ -98,7 +98,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||
tempDlInfo: TDl_info
|
||||
# This is allowed to be expensive since it only happens during crashes
|
||||
# (but this way you don't need manual stack tracing)
|
||||
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
|
||||
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
|
||||
len(tempAddresses))
|
||||
var enabled = false
|
||||
for i in 0..size-1:
|
||||
@@ -123,7 +123,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||
when not hasThreadSupport:
|
||||
var
|
||||
tempFrames: array [0..127, PFrame] # should not be alloc'd on stack
|
||||
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
when hasThreadSupport:
|
||||
var
|
||||
@@ -160,7 +160,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
inc(i)
|
||||
b = b.prev
|
||||
for j in countdown(i-1, 0):
|
||||
if tempFrames[j] == nil:
|
||||
if tempFrames[j] == nil:
|
||||
add(s, "(")
|
||||
add(s, $skipped)
|
||||
add(s, " calls omitted) ...")
|
||||
@@ -214,41 +214,49 @@ proc raiseExceptionAux(e: ref Exception) =
|
||||
if not localRaiseHook(e): return
|
||||
if globalRaiseHook != nil:
|
||||
if not globalRaiseHook(e): return
|
||||
if excHandler != nil:
|
||||
if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
|
||||
pushCurrentException(e)
|
||||
c_longjmp(excHandler.context, 1)
|
||||
elif e[] of OutOfMemError:
|
||||
showErrorMessage(e.name)
|
||||
quitOrDebug()
|
||||
else:
|
||||
when hasSomeStackTrace:
|
||||
var buf = newStringOfCap(2000)
|
||||
if isNil(e.trace): rawWriteStackTrace(buf)
|
||||
else: add(buf, e.trace)
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
if not isNil(e.msg): add(buf, e.msg)
|
||||
add(buf, " [")
|
||||
add(buf, $e.name)
|
||||
add(buf, "]\n")
|
||||
showErrorMessage(buf)
|
||||
when defined(cpp):
|
||||
if e[] of OutOfMemError:
|
||||
showErrorMessage(e.name)
|
||||
quitOrDebug()
|
||||
else:
|
||||
# ugly, but avoids heap allocations :-)
|
||||
template xadd(buf, s, slen: expr) =
|
||||
if L + slen < high(buf):
|
||||
copyMem(addr(buf[L]), cstring(s), slen)
|
||||
inc L, slen
|
||||
template add(buf, s: expr) =
|
||||
xadd(buf, s, s.len)
|
||||
var buf: array [0..2000, char]
|
||||
var L = 0
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
if not isNil(e.msg): add(buf, e.msg)
|
||||
add(buf, " [")
|
||||
xadd(buf, e.name, c_strlen(e.name))
|
||||
add(buf, "]\n")
|
||||
showErrorMessage(buf)
|
||||
quitOrDebug()
|
||||
pushCurrentException(e)
|
||||
{.emit: "throw NimException(`e`, `e`->name);".}
|
||||
else:
|
||||
if excHandler != nil:
|
||||
if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
|
||||
pushCurrentException(e)
|
||||
c_longjmp(excHandler.context, 1)
|
||||
elif e[] of OutOfMemError:
|
||||
showErrorMessage(e.name)
|
||||
quitOrDebug()
|
||||
else:
|
||||
when hasSomeStackTrace:
|
||||
var buf = newStringOfCap(2000)
|
||||
if isNil(e.trace): rawWriteStackTrace(buf)
|
||||
else: add(buf, e.trace)
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
if not isNil(e.msg): add(buf, e.msg)
|
||||
add(buf, " [")
|
||||
add(buf, $e.name)
|
||||
add(buf, "]\n")
|
||||
showErrorMessage(buf)
|
||||
else:
|
||||
# ugly, but avoids heap allocations :-)
|
||||
template xadd(buf, s, slen: expr) =
|
||||
if L + slen < high(buf):
|
||||
copyMem(addr(buf[L]), cstring(s), slen)
|
||||
inc L, slen
|
||||
template add(buf, s: expr) =
|
||||
xadd(buf, s, s.len)
|
||||
var buf: array [0..2000, char]
|
||||
var L = 0
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
if not isNil(e.msg): add(buf, e.msg)
|
||||
add(buf, " [")
|
||||
xadd(buf, e.name, c_strlen(e.name))
|
||||
add(buf, "]\n")
|
||||
showErrorMessage(buf)
|
||||
quitOrDebug()
|
||||
|
||||
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
|
||||
e.name = ename
|
||||
@@ -309,7 +317,7 @@ when not defined(noSignalHandler):
|
||||
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
||||
template processSignal(s, action: expr) {.immediate, dirty.} =
|
||||
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
|
||||
elif s == SIGSEGV:
|
||||
elif s == SIGSEGV:
|
||||
action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
elif s == SIGABRT:
|
||||
when defined(endb):
|
||||
|
||||
17
tests/cpp/tcppraise.nim
Normal file
17
tests/cpp/tcppraise.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
discard """
|
||||
cmd: "nim cpp $file"
|
||||
output: '''foo
|
||||
bar
|
||||
Need odd and >= 3 digits##
|
||||
baz'''
|
||||
"""
|
||||
|
||||
# bug #1888
|
||||
echo "foo"
|
||||
try:
|
||||
echo "bar"
|
||||
raise newException(ValueError, "Need odd and >= 3 digits")
|
||||
# echo "baz"
|
||||
except ValueError:
|
||||
echo getCurrentExceptionMsg(), "##"
|
||||
echo "baz"
|
||||
@@ -5,20 +5,20 @@ discard """
|
||||
|
||||
# First variety
|
||||
try:
|
||||
raise newException(EOS, "Problem")
|
||||
except EOS:
|
||||
raise newException(OSError, "Problem")
|
||||
except OSError:
|
||||
for y in [1, 2, 3]:
|
||||
discard
|
||||
try:
|
||||
discard
|
||||
except EOS:
|
||||
except OSError:
|
||||
discard
|
||||
echo "1"
|
||||
|
||||
# Second Variety
|
||||
try:
|
||||
raise newException(EOS, "Problem")
|
||||
except EOS:
|
||||
raise newException(OSError, "Problem")
|
||||
except OSError:
|
||||
for y in [1, 2, 3]:
|
||||
discard
|
||||
for y in [1, 2, 3]:
|
||||
@@ -28,8 +28,8 @@ echo "2"
|
||||
|
||||
# Third Variety
|
||||
try:
|
||||
raise newException(EOS, "Problem")
|
||||
except EOS:
|
||||
raise newException(OSError, "Problem")
|
||||
except OSError:
|
||||
block:
|
||||
break
|
||||
|
||||
@@ -38,8 +38,8 @@ echo "3"
|
||||
# Fourth Variety
|
||||
block:
|
||||
try:
|
||||
raise newException(EOS, "Problem")
|
||||
except EOS:
|
||||
raise newException(OSError, "Problem")
|
||||
except OSError:
|
||||
break
|
||||
|
||||
echo "4"
|
||||
echo "4"
|
||||
|
||||
@@ -5,12 +5,12 @@ discard """
|
||||
# Test inheritance for exception matching:
|
||||
|
||||
try:
|
||||
raise newException(EOS, "dummy message")
|
||||
except E_Base:
|
||||
raise newException(OSError, "dummy message")
|
||||
except Exception:
|
||||
echo "caught!"
|
||||
except:
|
||||
except:
|
||||
echo "wtf!?"
|
||||
|
||||
|
||||
#OUT caught!
|
||||
|
||||
|
||||
|
||||
@@ -8,19 +8,19 @@ discard """
|
||||
var raiseEx = true
|
||||
var returnA = true
|
||||
var returnB = false
|
||||
|
||||
proc main: int =
|
||||
|
||||
proc main: int =
|
||||
try: #A
|
||||
try: #B
|
||||
if raiseEx:
|
||||
raise newException(EOS, "")
|
||||
raise newException(OSError, "")
|
||||
return 3
|
||||
finally: #B
|
||||
echo "B1"
|
||||
if returnB:
|
||||
return 2
|
||||
echo "B2"
|
||||
except EOS: #A
|
||||
except OSError: #A
|
||||
echo "catch"
|
||||
finally: #A
|
||||
echo "A1"
|
||||
|
||||
@@ -7,7 +7,7 @@ discard """
|
||||
|
||||
proc test1() =
|
||||
|
||||
finally: echo "A"
|
||||
defer: echo "A"
|
||||
|
||||
try:
|
||||
raise newException(OSError, "Problem")
|
||||
@@ -19,7 +19,7 @@ test1()
|
||||
|
||||
proc test2() =
|
||||
|
||||
finally: echo "B"
|
||||
defer: echo "B"
|
||||
|
||||
try:
|
||||
return
|
||||
|
||||
@@ -4,8 +4,8 @@ success'''
|
||||
"""
|
||||
|
||||
type
|
||||
ESomething = object of E_Base
|
||||
ESomeOtherErr = object of E_Base
|
||||
ESomething = object of Exception
|
||||
ESomeOtherErr = object of Exception
|
||||
|
||||
proc genErrors(s: string) =
|
||||
if s == "error!":
|
||||
@@ -17,14 +17,14 @@ proc foo() =
|
||||
var i = 0
|
||||
try:
|
||||
inc i
|
||||
onRaise(proc (e: ref E_Base): bool =
|
||||
onRaise(proc (e: ref Exception): bool =
|
||||
echo "i: ", i)
|
||||
genErrors("errssor!")
|
||||
except ESomething:
|
||||
echo("ESomething happened")
|
||||
except:
|
||||
echo("Some other error happened")
|
||||
|
||||
|
||||
# test that raise handler is gone:
|
||||
try:
|
||||
genErrors("error!")
|
||||
|
||||
@@ -3,7 +3,7 @@ News
|
||||
====
|
||||
|
||||
..
|
||||
2015-03-01 Version 0.10.4 released
|
||||
2015-03-01 Version 0.11.0 released
|
||||
==================================
|
||||
|
||||
|
||||
@@ -131,6 +131,9 @@ News
|
||||
|
||||
- A single underscore can now be used to discard values when unpacking tuples.
|
||||
- ``marshal.$$`` and ``marshal.to`` can be executed at compile-time.
|
||||
- Interoperability with C++ improved tremendously; C++'s templates and
|
||||
operators can be wrapped directly. See `this <nimc.html#ImportCpp-pragma>`_
|
||||
for more information.
|
||||
|
||||
|
||||
Library additions
|
||||
|
||||
Reference in New Issue
Block a user