fixes #787
This commit is contained in:
parent
5d75ce2f2e
commit
eb1d23c0c7
2 changed files with 60 additions and 9 deletions
|
|
@ -2545,7 +2545,7 @@ proc raiseAssert*(msg: string) {.noinline.} =
|
||||||
sysFatal(EAssertionFailed, msg)
|
sysFatal(EAssertionFailed, msg)
|
||||||
|
|
||||||
when true:
|
when true:
|
||||||
proc hiddenRaiseAssert(msg: string) {.raises: [], tags: [].} =
|
proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
|
||||||
# trick the compiler to not list ``EAssertionFailed`` when called
|
# trick the compiler to not list ``EAssertionFailed`` when called
|
||||||
# by ``assert``.
|
# by ``assert``.
|
||||||
type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
|
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
|
## raises an ``EAssertionFailure`` exception. However, the compiler may
|
||||||
## not generate any code at all for ``assert`` if it is advised to do so.
|
## not generate any code at all for ``assert`` if it is advised to do so.
|
||||||
## Use ``assert`` for debugging purposes only.
|
## Use ``assert`` for debugging purposes only.
|
||||||
bind instantiationInfo, hiddenRaiseAssert
|
bind instantiationInfo
|
||||||
|
mixin failedAssertImpl
|
||||||
when compileOption("assertions"):
|
when compileOption("assertions"):
|
||||||
{.line.}:
|
{.line.}:
|
||||||
if not cond:
|
if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg)
|
||||||
hiddenRaiseAssert(astToStr(cond) & ' ' & msg)
|
|
||||||
|
|
||||||
template doAssert*(cond: bool, msg = "") =
|
template doAssert*(cond: bool, msg = "") =
|
||||||
## same as `assert` but is always turned on and not affected by the
|
## 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):
|
when not defined(nimhygiene):
|
||||||
{.pragma: inject.}
|
{.pragma: inject.}
|
||||||
|
|
||||||
template onFailedAssert*(msg: expr, code: stmt): stmt =
|
template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
|
||||||
## Sets an assertion failure handler that will intercept any assert statements
|
## Sets an assertion failure handler that will intercept any assert
|
||||||
## following `onFailedAssert` in the current lexical scope.
|
## statements following `onFailedAssert` in the current lexical scope.
|
||||||
## Can be defined multiple times in a single function.
|
## Can be defined multiple times in a single function.
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
|
|
@ -2594,8 +2594,8 @@ template onFailedAssert*(msg: expr, code: stmt): stmt =
|
||||||
##
|
##
|
||||||
## assert(...)
|
## assert(...)
|
||||||
##
|
##
|
||||||
template raiseAssert(msgIMPL: string): stmt =
|
template failedAssertImpl(msgIMPL: string): stmt {.dirty, immediate.} =
|
||||||
let msg {.inject.} = msgIMPL
|
let msg = msgIMPL
|
||||||
code
|
code
|
||||||
|
|
||||||
proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
||||||
|
|
|
||||||
51
tests/run/tfailedassert.nim
Normal file
51
tests/run/tfailedassert.nim
Normal file
|
|
@ -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
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue