diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-12-28 23:53:48 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-12-28 23:53:48 +0200 |
commit | eb1d23c0c745c64225e8db22f62d8ebf596f4448 (patch) | |
tree | 2cb9a88374d255c38c94409bf7e13ad1879033dd | |
parent | 5d75ce2f2eec8d4ec6f152105a144abcf73e4a37 (diff) | |
download | Nim-eb1d23c0c745c64225e8db22f62d8ebf596f4448.tar.gz |
fixes #787
-rw-r--r-- | lib/system.nim | 18 | ||||
-rw-r--r-- | tests/run/tfailedassert.nim | 51 |
2 files changed, 60 insertions, 9 deletions
diff --git a/lib/system.nim b/lib/system.nim index d45137b9e..e9719c7e1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2545,7 +2545,7 @@ proc raiseAssert*(msg: string) {.noinline.} = sysFatal(EAssertionFailed, msg) when true: - proc hiddenRaiseAssert(msg: string) {.raises: [], tags: [].} = + proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} = # trick the compiler to not list ``EAssertionFailed`` when called # by ``assert``. type THide = proc (msg: string) {.noinline, raises: [], noSideEffect, @@ -2558,11 +2558,11 @@ template assert*(cond: bool, msg = "") = ## raises an ``EAssertionFailure`` exception. However, the compiler may ## not generate any code at all for ``assert`` if it is advised to do so. ## Use ``assert`` for debugging purposes only. - bind instantiationInfo, hiddenRaiseAssert + bind instantiationInfo + mixin failedAssertImpl when compileOption("assertions"): {.line.}: - if not cond: - hiddenRaiseAssert(astToStr(cond) & ' ' & msg) + if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg) template doAssert*(cond: bool, msg = "") = ## same as `assert` but is always turned on and not affected by the @@ -2575,9 +2575,9 @@ template doAssert*(cond: bool, msg = "") = when not defined(nimhygiene): {.pragma: inject.} -template onFailedAssert*(msg: expr, code: stmt): stmt = - ## Sets an assertion failure handler that will intercept any assert statements - ## following `onFailedAssert` in the current lexical scope. +template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} = + ## Sets an assertion failure handler that will intercept any assert + ## statements following `onFailedAssert` in the current lexical scope. ## Can be defined multiple times in a single function. ## ## .. code-block:: nimrod @@ -2594,8 +2594,8 @@ template onFailedAssert*(msg: expr, code: stmt): stmt = ## ## assert(...) ## - template raiseAssert(msgIMPL: string): stmt = - let msg {.inject.} = msgIMPL + template failedAssertImpl(msgIMPL: string): stmt {.dirty, immediate.} = + let msg = msgIMPL code proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} = diff --git a/tests/run/tfailedassert.nim b/tests/run/tfailedassert.nim new file mode 100644 index 000000000..0e536cffd --- /dev/null +++ b/tests/run/tfailedassert.nim @@ -0,0 +1,51 @@ +discard """ + output: ''' +WARNING: false first asseertion from bar +ERROR: false second assertion from bar +-1 +tests/run/tfailedassert.nim:40 false assertion from foo +''' +""" + +type + TLineInfo = tuple[filename: string, line: int] + + TMyError = object of E_Base + lineinfo: TLineInfo + + EMyError = ref TMyError + +# module-wide policy to change the failed assert +# exception type in order to include a lineinfo +onFailedAssert(msg): + var e = new(TMyError) + e.msg = msg + e.lineinfo = instantiationInfo(-2) + raise e + +proc foo = + assert(false, "assertion from foo") + +proc bar: int = + # local overrides that are active only + # in this proc + onFailedAssert(msg): echo "WARNING: " & msg + + assert(false, "first asseertion from bar") + + onFailedAssert(msg): + echo "ERROR: " & msg + return -1 + + assert(false, "second assertion from bar") + return 10 + +echo("") +echo(bar()) + +try: + foo() +except: + let e = EMyError(getCurrentException()) + echo e.lineinfo.filename, ":", e.lineinfo.line, " ", e.msg + |