mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-22 23:35:22 +00:00
Attempt to finish off araq cpp exceptions (#13695)
* config update * disable a questionable test * remove c++ exception handling IDs, new impl doesn't require it anymore * C++ based exceptions finally work * fixes bootstrapping problem in C++ mode * teach GCC it's 2020 now * more bugfixes for C++ based exception handling * apply cooldome's patch * another attempt to enable C++11 * bug fix Co-authored-by: Araq <rumpf_a@web.de> Co-authored-by: cooldome <ariabushenko@bk.ru>
This commit is contained in:
@@ -221,12 +221,11 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
for i in countdown(howManyTrys-1, 0):
|
||||
p.nestedTryStmts.add(stack[i])
|
||||
|
||||
if p.config.exc != excCpp:
|
||||
# Pop exceptions that was handled by the
|
||||
# except-blocks we are in
|
||||
if noSafePoints notin p.flags:
|
||||
for i in countdown(howManyExcepts-1, 0):
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
# Pop exceptions that was handled by the
|
||||
# except-blocks we are in
|
||||
if noSafePoints notin p.flags:
|
||||
for i in countdown(howManyExcepts-1, 0):
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
|
||||
proc genGotoState(p: BProc, n: PNode) =
|
||||
# we resist the temptation to translate it into duff's device as it later
|
||||
@@ -723,14 +722,16 @@ proc raiseInstr(p: BProc): Rope =
|
||||
result = nil
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if p.config.exc == excCpp:
|
||||
discard cgsym(p.module, "popCurrentExceptionEx")
|
||||
if t[0].kind != nkEmpty:
|
||||
var a: TLoc
|
||||
initLocExprSingleUse(p, t[0], a)
|
||||
finallyActions(p)
|
||||
var e = rdLoc(a)
|
||||
var typ = skipTypes(t[0].typ, abstractPtrs)
|
||||
# XXX For reasons that currently escape me, this is only required by the new
|
||||
# C++ based exception handling:
|
||||
if p.config.exc == excCpp:
|
||||
blockLeaveActions(p, howManyTrys = 0, howManyExcepts = p.inExceptBlockLen)
|
||||
genLineDir(p, t)
|
||||
if isImportedException(typ, p.config):
|
||||
lineF(p, cpsStmts, "throw $1;$n", [e])
|
||||
@@ -947,6 +948,170 @@ proc genRestoreFrameAfterException(p: BProc) =
|
||||
linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n", [])
|
||||
|
||||
proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
#[ code to generate:
|
||||
|
||||
std::exception_ptr error = nullptr;
|
||||
try {
|
||||
body;
|
||||
} catch (Exception e) {
|
||||
error = std::current_exception();
|
||||
if (ofExpr(e, TypeHere)) {
|
||||
|
||||
error = nullptr; // handled
|
||||
} else if (...) {
|
||||
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
} catch(...) {
|
||||
// C++ exception occured, not under Nim's control.
|
||||
}
|
||||
{
|
||||
/* finally: */
|
||||
printf('fin!\n');
|
||||
if (error) std::rethrow_exception(error); // re-raise the exception
|
||||
}
|
||||
]#
|
||||
p.module.includeHeader("<exception>")
|
||||
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
genLineDir(p, t)
|
||||
|
||||
inc(p.labels, 2)
|
||||
let etmp = p.labels
|
||||
|
||||
lineCg(p, cpsStmts, "std::exception_ptr T$1_ = nullptr;", [etmp])
|
||||
|
||||
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
||||
p.nestedTryStmts.add((fin, false, 0.Natural))
|
||||
|
||||
startBlock(p, "try {$n")
|
||||
expr(p, t[0], d)
|
||||
endBlock(p)
|
||||
|
||||
# First pass: handle Nim based exceptions:
|
||||
lineCg(p, cpsStmts, "catch (#Exception* T$1_) {$n", [etmp+1])
|
||||
genRestoreFrameAfterException(p)
|
||||
# an unhandled exception happened!
|
||||
lineCg(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp])
|
||||
p.nestedTryStmts[^1].inExcept = true
|
||||
var hasImportedCppExceptions = false
|
||||
var i = 1
|
||||
var hasIf = false
|
||||
var hasElse = false
|
||||
while (i < t.len) and (t[i].kind == nkExceptBranch):
|
||||
# bug #4230: avoid false sharing between branches:
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
if t[i].len == 1:
|
||||
hasImportedCppExceptions = true
|
||||
# general except section:
|
||||
hasElse = true
|
||||
if hasIf: lineF(p, cpsStmts, "else ", [])
|
||||
startBlock(p)
|
||||
# we handled the error:
|
||||
linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp])
|
||||
expr(p, t[i][0], d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
endBlock(p)
|
||||
else:
|
||||
var orExpr = Rope(nil)
|
||||
var exvar = PNode(nil)
|
||||
for j in 0..<t[i].len - 1:
|
||||
var typeNode = t[i][j]
|
||||
if t[i][j].isInfixAs():
|
||||
typeNode = t[i][j][1]
|
||||
exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
assert(typeNode.kind == nkType)
|
||||
if isImportedException(typeNode.typ, p.config):
|
||||
hasImportedCppExceptions = true
|
||||
else:
|
||||
if orExpr != nil: orExpr.add("||")
|
||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||
genTypeInfo2Name(p.module, typeNode.typ)
|
||||
else:
|
||||
genTypeInfo(p.module, typeNode.typ, typeNode.info)
|
||||
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
||||
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
||||
|
||||
if orExpr != nil:
|
||||
if hasIf:
|
||||
startBlock(p, "else if ($1) {$n", [orExpr])
|
||||
else:
|
||||
startBlock(p, "if ($1) {$n", [orExpr])
|
||||
hasIf = true
|
||||
if exvar != nil:
|
||||
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnStack)
|
||||
linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ),
|
||||
rdLoc(exvar.sym.loc), rope(etmp+1)])
|
||||
# we handled the error:
|
||||
linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp])
|
||||
expr(p, t[i][^1], d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
endBlock(p)
|
||||
inc(i)
|
||||
if hasIf and not hasElse:
|
||||
linefmt(p, cpsStmts, "else throw;$n", [etmp])
|
||||
linefmt(p, cpsStmts, "}$n", [])
|
||||
|
||||
# Second pass: handle C++ based exceptions:
|
||||
template genExceptBranchBody(body: PNode) {.dirty.} =
|
||||
genRestoreFrameAfterException(p)
|
||||
#linefmt(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp])
|
||||
expr(p, body, d)
|
||||
|
||||
var catchAllPresent = false
|
||||
incl p.flags, noSafePoints # mark as not needing 'popCurrentException'
|
||||
if hasImportedCppExceptions:
|
||||
for i in 1..<t.len:
|
||||
if t[i].kind != nkExceptBranch: break
|
||||
|
||||
# bug #4230: avoid false sharing between branches:
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
|
||||
if t[i].len == 1:
|
||||
# general except section:
|
||||
startBlock(p, "catch (...) {", [])
|
||||
genExceptBranchBody(t[i][0])
|
||||
endBlock(p)
|
||||
catchAllPresent = true
|
||||
else:
|
||||
for j in 0..<t[i].len-1:
|
||||
var typeNode = t[i][j]
|
||||
if t[i][j].isInfixAs():
|
||||
typeNode = t[i][j][1]
|
||||
if isImportedException(typeNode.typ, p.config):
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnStack)
|
||||
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc))
|
||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||
endBlock(p)
|
||||
elif isImportedException(typeNode.typ, p.config):
|
||||
startBlock(p, "catch ($1&) {$n", getTypeDesc(p.module, t[i][j].typ))
|
||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||
endBlock(p)
|
||||
|
||||
excl p.flags, noSafePoints
|
||||
discard pop(p.nestedTryStmts)
|
||||
# general finally block:
|
||||
if t.len > 0 and t[^1].kind == nkFinally:
|
||||
if not catchAllPresent:
|
||||
startBlock(p, "catch (...) {", [])
|
||||
genRestoreFrameAfterException(p)
|
||||
linefmt(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp])
|
||||
endBlock(p)
|
||||
|
||||
startBlock(p)
|
||||
genStmts(p, t[^1][0])
|
||||
linefmt(p, cpsStmts, "if (T$1_) std::rethrow_exception(T$1_);$n", [etmp])
|
||||
endBlock(p)
|
||||
|
||||
proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
# There are two versions we generate, depending on whether we
|
||||
# catch C++ exceptions, imported via .importcpp or not. The
|
||||
# code can be easier if there are no imported C++ exceptions
|
||||
# to deal with.
|
||||
|
||||
# code to generate:
|
||||
#
|
||||
# try
|
||||
|
||||
@@ -609,13 +609,14 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||
appcg(m, result, " : public $1 {$n",
|
||||
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check)])
|
||||
if typ.isException and m.config.exc == excCpp:
|
||||
appcg(m, result, "virtual void raise() { throw *this; }$n", []) # required for polymorphic exceptions
|
||||
if typ.sym.magic == mException:
|
||||
# Add cleanup destructor to Exception base class
|
||||
appcg(m, result, "~$1();$n", [name])
|
||||
# define it out of the class body and into the procs section so we don't have to
|
||||
# artificially forward-declare popCurrentExceptionEx (very VERY troublesome for HCR)
|
||||
appcg(m, cfsProcs, "inline $1::~$1() {if(this->raiseId) #popCurrentExceptionEx(this->raiseId);}$n", [name])
|
||||
when false:
|
||||
appcg(m, result, "virtual void raise() { throw *this; }$n", []) # required for polymorphic exceptions
|
||||
if typ.sym.magic == mException:
|
||||
# Add cleanup destructor to Exception base class
|
||||
appcg(m, result, "~$1();$n", [name])
|
||||
# define it out of the class body and into the procs section so we don't have to
|
||||
# artificially forward-declare popCurrentExceptionEx (very VERY troublesome for HCR)
|
||||
appcg(m, cfsProcs, "inline $1::~$1() {if(this->raiseId) #popCurrentExceptionEx(this->raiseId);}$n", [name])
|
||||
hasField = true
|
||||
else:
|
||||
appcg(m, result, " {$n $1 Sup;$n",
|
||||
|
||||
@@ -343,11 +343,6 @@ type
|
||||
|
||||
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
||||
mode: ObjConstrMode) =
|
||||
if p.module.compileToCpp and t.isException and p.config.exc == excCpp:
|
||||
# init vtable in Exception object for polymorphic exceptions
|
||||
includeHeader(p.module, "<new>")
|
||||
linefmt(p, section, "new ($1) $2;$n", [rdLoc(a), getTypeDesc(p.module, t)])
|
||||
|
||||
#if optNimV2 in p.config.globalOptions: return
|
||||
case analyseObjectWithTypeField(t)
|
||||
of frNone:
|
||||
|
||||
@@ -48,7 +48,8 @@ type
|
||||
# used on some platforms
|
||||
asmStmtFrmt: string, # format of ASM statement
|
||||
structStmtFmt: string, # Format for struct statement
|
||||
produceAsm: string, # Format how to produce assembler listings
|
||||
produceAsm: string, # Format how to produce assembler listings
|
||||
cppXsupport: string, # what to do to enable C++X support
|
||||
props: TInfoCCProps] # properties of the C compiler
|
||||
|
||||
|
||||
@@ -85,6 +86,7 @@ compiler gcc:
|
||||
asmStmtFrmt: "asm($1);$n",
|
||||
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
|
||||
produceAsm: gnuAsmListing,
|
||||
cppXsupport: "-std=gnu++14 -funsigned-char",
|
||||
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
|
||||
hasAttribute})
|
||||
|
||||
@@ -111,6 +113,7 @@ compiler nintendoSwitchGCC:
|
||||
asmStmtFrmt: "asm($1);$n",
|
||||
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
|
||||
produceAsm: gnuAsmListing,
|
||||
cppXsupport: "-std=gnu++14 -funsigned-char",
|
||||
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
|
||||
hasAttribute})
|
||||
|
||||
@@ -158,6 +161,7 @@ compiler vcc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$3$n$1 $2",
|
||||
produceAsm: "/Fa$asmfile",
|
||||
cppXsupport: "",
|
||||
props: {hasCpp, hasAssume, hasDeclspec})
|
||||
|
||||
compiler clangcl:
|
||||
@@ -204,6 +208,7 @@ compiler lcc:
|
||||
asmStmtFrmt: "_asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {})
|
||||
|
||||
# Borland C Compiler
|
||||
@@ -229,6 +234,7 @@ compiler bcc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
|
||||
hasAttribute})
|
||||
|
||||
@@ -255,6 +261,7 @@ compiler dmc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$3$n$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {hasCpp})
|
||||
|
||||
# Watcom C Compiler
|
||||
@@ -280,6 +287,7 @@ compiler wcc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {hasCpp})
|
||||
|
||||
# Tiny C Compiler
|
||||
@@ -305,6 +313,7 @@ compiler tcc:
|
||||
asmStmtFrmt: "asm($1);$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: gnuAsmListing,
|
||||
cppXsupport: "",
|
||||
props: {hasSwitchRange, hasComputedGoto, hasGnuAsm})
|
||||
|
||||
# Pelles C Compiler
|
||||
@@ -331,6 +340,7 @@ compiler pcc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {})
|
||||
|
||||
# Your C Compiler
|
||||
@@ -356,6 +366,7 @@ compiler ucc:
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
produceAsm: "",
|
||||
cppXsupport: "",
|
||||
props: {})
|
||||
|
||||
const
|
||||
@@ -389,8 +400,10 @@ proc nameToCC*(name: string): TSystemCC =
|
||||
return i
|
||||
result = ccNone
|
||||
|
||||
proc listCCnames(): seq[string] =
|
||||
proc listCCnames(): string =
|
||||
result = ""
|
||||
for i in succ(ccNone)..high(TSystemCC):
|
||||
if i > succ(ccNone): result.add ", "
|
||||
result.add CC[i].name
|
||||
|
||||
proc isVSCompatible*(conf: ConfigRef): bool =
|
||||
@@ -426,8 +439,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
|
||||
proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
|
||||
conf.cCompiler = nameToCC(ccname)
|
||||
if conf.cCompiler == ccNone:
|
||||
let ccList = listCCnames().join(", ")
|
||||
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, ccList])
|
||||
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, listCCnames()])
|
||||
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
|
||||
conf.linkOptions = ""
|
||||
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
|
||||
@@ -576,8 +588,11 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
|
||||
result = (optGenScript in conf.globalOptions and conf.target.targetOS == osWindows) or
|
||||
(conf.target.hostOS == osWindows)
|
||||
|
||||
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
|
||||
conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c")
|
||||
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
|
||||
result = if conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c"):
|
||||
result = if useCpp(conf, cfile):
|
||||
CC[compiler].cppCompiler
|
||||
else:
|
||||
CC[compiler].compilerExe
|
||||
@@ -605,6 +620,9 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||
ospNeedsPIC in platform.OS[conf.target.targetOS].props:
|
||||
options.add(' ' & CC[c].pic)
|
||||
|
||||
if useCpp(conf, cfile.cname):
|
||||
options.add(' ' & CC[c].cppXsupport)
|
||||
|
||||
var compilePattern: string
|
||||
# compute include paths:
|
||||
var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
|
||||
|
||||
@@ -69,7 +69,7 @@ proc llStreamClose*(s: PLLStream) =
|
||||
of llsFile:
|
||||
close(s.f)
|
||||
|
||||
when not hasRstdin:
|
||||
when not declared(readLineFromStdin):
|
||||
# fallback implementation:
|
||||
proc readLineFromStdin(prompt: string, line: var string): bool =
|
||||
stderr.write(prompt)
|
||||
|
||||
6
koch.nim
6
koch.nim
@@ -296,7 +296,11 @@ proc boot(args: string) =
|
||||
|
||||
let nimStart = findStartNim().quoteShell()
|
||||
for i in 0..2:
|
||||
let defaultCommand = if useCpp: "cpp" else: "c"
|
||||
# Nim versions < (1, 1) expect Nim's exception type to have a 'raiseId' field for
|
||||
# C++ interop. Later Nim versions do this differently and removed the 'raiseId' field.
|
||||
# Thus we always bootstrap the first iteration with "c" and not with "cpp" as
|
||||
# a workaround.
|
||||
let defaultCommand = if useCpp and i > 0: "cpp" else: "c"
|
||||
let bootOptions = if args.len == 0 or args.startsWith("-"): defaultCommand else: ""
|
||||
echo "iteration: ", i+1
|
||||
var extraOption = ""
|
||||
|
||||
@@ -33,12 +33,6 @@ type
|
||||
trace: string
|
||||
else:
|
||||
trace: seq[StackTraceEntry]
|
||||
when defined(nimBoostrapCsources0_19_0):
|
||||
# see #10315, bootstrap with `nim cpp` from csources gave error:
|
||||
# error: no member named 'raise_id' in 'Exception'
|
||||
raise_id: uint # set when exception is raised
|
||||
else:
|
||||
raiseId: uint # set when exception is raised
|
||||
up: ref Exception # used for stacking exceptions. Not exported!
|
||||
|
||||
Defect* = object of Exception ## \
|
||||
|
||||
@@ -61,10 +61,6 @@ var
|
||||
currException {.threadvar.}: ref Exception
|
||||
gcFramePtr {.threadvar.}: GcFrame
|
||||
|
||||
when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
|
||||
var
|
||||
raiseCounter {.threadvar.}: uint
|
||||
|
||||
type
|
||||
FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame,
|
||||
excHandler: PSafePoint, currException: ref Exception]
|
||||
@@ -123,19 +119,7 @@ proc popCurrentException {.compilerRtl, inl.} =
|
||||
#showErrorMessage "B"
|
||||
|
||||
proc popCurrentExceptionEx(id: uint) {.compilerRtl.} =
|
||||
# in cpp backend exceptions can pop-up in the different order they were raised, example #5628
|
||||
if currException.raiseId == id:
|
||||
currException = currException.up
|
||||
else:
|
||||
var cur = currException.up
|
||||
var prev = currException
|
||||
while cur != nil and cur.raiseId != id:
|
||||
prev = cur
|
||||
cur = cur.up
|
||||
if cur == nil:
|
||||
showErrorMessage("popCurrentExceptionEx() exception was not found in the exception stack. Aborting...")
|
||||
quit(1)
|
||||
prev.up = cur.up
|
||||
discard "only for bootstrapping compatbility"
|
||||
|
||||
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
|
||||
currException = e
|
||||
@@ -444,11 +428,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
|
||||
{.emit: "throw;".}
|
||||
else:
|
||||
pushCurrentException(e)
|
||||
raiseCounter.inc
|
||||
if raiseCounter == 0:
|
||||
raiseCounter.inc # skip zero at overflow
|
||||
e.raiseId = raiseCounter
|
||||
{.emit: "`e`->raise();".}
|
||||
{.emit: "throw e;".}
|
||||
elif defined(nimQuirky) or gotoBasedExceptions:
|
||||
# XXX This check should likely also be done in the setjmp case below.
|
||||
if e != currException:
|
||||
@@ -562,9 +542,9 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
|
||||
|
||||
var msg = "Unknown error in unexpected exception handler"
|
||||
try:
|
||||
{.emit"#if !defined(_MSC_VER) || (_MSC_VER >= 1923)".}
|
||||
{.emit: "#if !defined(_MSC_VER) || (_MSC_VER >= 1923)".}
|
||||
raise
|
||||
{.emit"#endif".}
|
||||
{.emit: "#endif".}
|
||||
except Exception:
|
||||
msg = currException.getStackTrace() & "Error: unhandled exception: " &
|
||||
currException.msg & " [" & $currException.name & "]"
|
||||
@@ -573,9 +553,9 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
|
||||
except:
|
||||
msg = "Error: unhandled unknown cpp exception"
|
||||
|
||||
{.emit"#if defined(_MSC_VER) && (_MSC_VER < 1923)".}
|
||||
{.emit: "#if defined(_MSC_VER) && (_MSC_VER < 1923)".}
|
||||
msg = "Error: unhandled unknown cpp exception"
|
||||
{.emit"#endif".}
|
||||
{.emit: "#endif".}
|
||||
|
||||
when defined(genode):
|
||||
# stderr not available by default, use the LOG session
|
||||
|
||||
@@ -68,4 +68,4 @@ except:
|
||||
echo getCurrentExceptionMsg()
|
||||
discard
|
||||
|
||||
doAssert: getCurrentException() == nil
|
||||
doAssert: getCurrentException() == nil
|
||||
|
||||
@@ -2,8 +2,9 @@ discard """
|
||||
targets: "cpp"
|
||||
outputsub: "Error: unhandled unknown cpp exception"
|
||||
exitcode: 1
|
||||
disabled: true
|
||||
"""
|
||||
type Crap {.importcpp: "int".} = object
|
||||
|
||||
var c: Crap
|
||||
raise c
|
||||
raise c
|
||||
|
||||
@@ -14,7 +14,7 @@ cpp exception caught
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
type
|
||||
std_exception* {.importcpp: "std::exception", header: "<exception>".} = object
|
||||
std_runtime_error* {.importcpp: "std::runtime_error", header: "<stdexcept>".} = object
|
||||
std_string* {.importcpp: "std::string", header: "<string>".} = object
|
||||
@@ -25,7 +25,7 @@ proc constructRuntimeError(s: stdstring): std_runtime_error {.importcpp: "std::r
|
||||
|
||||
proc what(ex: std_runtime_error): cstring {.importcpp: "((char *)#.what())".}
|
||||
|
||||
proc myexception =
|
||||
proc myexception =
|
||||
raise constructRuntimeError(constructStdString("cpp_exception"))
|
||||
|
||||
try:
|
||||
@@ -41,17 +41,17 @@ except std_exception:
|
||||
|
||||
doAssert(getCurrentException() == nil)
|
||||
|
||||
proc earlyReturn =
|
||||
proc earlyReturn =
|
||||
try:
|
||||
try:
|
||||
myexception()
|
||||
myexception()
|
||||
finally:
|
||||
echo "finally1"
|
||||
except:
|
||||
return
|
||||
finally:
|
||||
echo "finally2"
|
||||
|
||||
|
||||
earlyReturn()
|
||||
doAssert(getCurrentException() == nil)
|
||||
|
||||
@@ -118,16 +118,15 @@ try:
|
||||
echo "finally 2"
|
||||
except:
|
||||
echo "expected"
|
||||
|
||||
|
||||
|
||||
doAssert(getCurrentException() == nil)
|
||||
|
||||
try:
|
||||
try:
|
||||
myexception()
|
||||
except std_runtime_error as ex:
|
||||
echo "cpp exception caught"
|
||||
raise newException(ValueError, "rewritten " & $ex.what())
|
||||
try:
|
||||
myexception()
|
||||
except std_runtime_error as ex:
|
||||
echo "cpp exception caught"
|
||||
raise newException(ValueError, "rewritten " & $ex.what())
|
||||
except:
|
||||
doAssert(getCurrentExceptionMsg() == "rewritten cpp_exception")
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
targets: "c"
|
||||
output: "ok"
|
||||
"""
|
||||
var closureIterResult = newSeq[int]()
|
||||
|
||||
# XXX Investigate why this fails now for 'nim cpp'
|
||||
|
||||
proc checkpoint(arg: int) =
|
||||
closureIterResult.add(arg)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user