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