diff options
-rw-r--r-- | compiler/cgen.nim | 21 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | tests/errmsgs/tproper_stacktrace.nim | 124 |
3 files changed, 129 insertions, 19 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim index ee60e62d2..cd344f096 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -204,27 +204,22 @@ proc freshLineInfo(p: BProc; info: TLineInfo): bool = result = true proc genLineDir(p: BProc, t: PNode) = - var tt = t - #while tt.kind in {nkStmtListExpr}+nkCallKinds: - # tt = tt.lastSon - if tt.kind in nkCallKinds and tt.len > 1: - tt = tt.sons[1] - let line = tt.info.safeLineNm + let line = t.info.safeLineNm if optEmbedOrigSrc in p.config.globalOptions: - add(p.s(cpsStmts), ~"//" & sourceLine(p.config, tt.info) & "\L") - genCLineDir(p.s(cpsStmts), toFullPath(p.config, tt.info), line, p.config) + add(p.s(cpsStmts), ~"//" & sourceLine(p.config, t.info) & "\L") + genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config) if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and (p.prc == nil or sfPure notin p.prc.flags): - if freshLineInfo(p, tt.info): + if freshLineInfo(p, t.info): linefmt(p, cpsStmts, "#endb($1, $2);$N", - line.rope, makeCString(toFilename(p.config, tt.info))) + line.rope, makeCString(toFilename(p.config, t.info))) elif ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and - (p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex != InvalidFileIDX: - if freshLineInfo(p, tt.info): + (p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIDX: + if freshLineInfo(p, t.info): linefmt(p, cpsStmts, "nimln_($1, $2);$n", - line.rope, quotedFilename(p.config, tt.info)) + line.rope, quotedFilename(p.config, t.info)) proc postStmtActions(p: BProc) {.inline.} = add(p.s(cpsStmts), p.module.injectStmt) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 64c145e51..135c1b32c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -31,6 +31,9 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags) popInfoContext(c.config) + # XXX: A more elaborate line info rewrite might be needed + result.info = n.info + proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = diff --git a/tests/errmsgs/tproper_stacktrace.nim b/tests/errmsgs/tproper_stacktrace.nim index 57e65fa6f..4e5c5fbf8 100644 --- a/tests/errmsgs/tproper_stacktrace.nim +++ b/tests/errmsgs/tproper_stacktrace.nim @@ -1,11 +1,123 @@ discard """ - outputsub: '''tproper_stacktrace.nim(7) tproper_stacktrace''' - exitcode: 1 + output: '''ok''' """ +import strscans, strutils -template fuzzy(x) = - echo x[] != 9 +proc raiseTestException*() = + raise newException(Exception, "test") -var p: ptr int -fuzzy p +proc matchStackTrace(actualEntries: openarray[StackTraceEntry], expected: string) = + var expectedEntries = newSeq[StackTraceEntry]() + var i = 0 + template checkEqual(actual, expected: typed, subject: string) = + if actual != expected: + echo "Unexpected ", subject, " on line ", i + echo "Actual: ", actual + echo "Expected: ", expected + doAssert(false) + + for l in splitLines(expected.strip): + var procname, filename: string + var line: int + if not scanf(l, "$s$w.nim($i) $w", filename, line, procname): + doAssert(false, "Wrong expected stack trace") + checkEqual($actualEntries[i].filename, filename & ".nim", "file name") + if line != 0: + checkEqual(actualEntries[i].line, line, "line number") + checkEqual($actualEntries[i].procname, procname, "proc name") + inc i + + doAssert(i == actualEntries.len, "Unexpected number of lines in stack trace") + +template verifyStackTrace*(expectedStackTrace: string, body: untyped) = + var verified = false + try: + body + except Exception as e: + verified = true + # echo "Stack trace:" + # echo e.getStackTrace + matchStackTrace(e.getStackTraceEntries(), expectedStackTrace) + + doAssert(verified, "No exception was raised") + + + + + + + + + + + + + + + + + + + + + + + + + +when isMainModule: +# <-- Align with line 70 in the text editor + block: + proc bar() = + raiseTestException() + + proc foo() = + bar() + + const expectedStackTrace = """ + tproper_stacktrace.nim(86) tproper_stacktrace + tproper_stacktrace.nim(76) foo + tproper_stacktrace.nim(73) bar + tproper_stacktrace.nim(7) raiseTestException + """ + + verifyStackTrace expectedStackTrace: + foo() + + block: + proc bar(x: int) = + raiseTestException() + + template foo(x: int) = + bar(x) + + const expectedStackTrace = """ + tproper_stacktrace.nim(103) tproper_stacktrace + tproper_stacktrace.nim(90) bar + tproper_stacktrace.nim(7) raiseTestException + """ + + verifyStackTrace expectedStackTrace: + var x: int + foo(x) + + block: #6803 + proc bar(x = 500) = + raiseTestException() + + proc foo() = + bar() + + const expectedStackTrace = """ + tproper_stacktrace.nim(120) tproper_stacktrace + tproper_stacktrace.nim(110) foo + tproper_stacktrace.nim(107) bar + tproper_stacktrace.nim(7) raiseTestException + """ + + verifyStackTrace expectedStackTrace: + foo() + + + echo "ok" |