This commit is contained in:
Araq
2015-04-27 23:11:36 +02:00
parent b34bd3b163
commit c6398d408d
9 changed files with 107 additions and 81 deletions

View File

@@ -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

View File

@@ -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
View 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"

View File

@@ -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"

View File

@@ -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!

View File

@@ -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"

View File

@@ -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

View File

@@ -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!")

View File

@@ -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