diff --git a/lib/system.nim b/lib/system.nim index 0f0349fba6..cb0e1c85c7 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3116,3 +3116,27 @@ proc arrayWithDefault*[T](size: static int): array[size, T] {.noinit, nodestroy, ## Creates a new array filled with `default(T)`. for i in 0..size-1: result[i] = default(T) + +when hostOS == "standalone": + # Include panicoverride.nim late so users can use the full extent of the + # language in their custom panic handlers (e.g. macros). + # Users define `proc panic(msg: string)` and `proc rawoutput(msg: string)`. + include "$projectpath/panicoverride" + + when not declared(panic): + {.error: + "a panic proc with the following signature must be provided " & + "when compiling with --os:standalone: " & + "`proc panic(msg: string) {.nimcall.}`".} + + when not declared(rawoutput): + {.error: + "a rawoutput proc with the following signature must be provided " & + "when compiling with --os:standalone: " & + "`proc rawoutput(msg: string) {.nimcall.}`".} + + # Wrappers with exportc that fatal.nim references via importc. + # This way panicoverride keeps old API and can still be included without + # ssymbols being duplicated. + proc nimPanic(s: string) {.exportc, noreturn.} = panic(s) + proc nimRawoutput(s: string) {.exportc.} = rawoutput(s) diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index 25c05e52d9..900ffa9400 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -14,14 +14,23 @@ const quirkyExceptions = compileOption("exceptions", "quirky") when hostOS == "standalone": - include "$projectpath/panicoverride" + # These procs are defined in panicoverride.nim, which gets included at end + # of system.nim with exportc. + proc nimPanic(msg: string) {.importc: "nimPanic", noreturn.} + proc nimRawoutput(msg: string) {.importc: "nimRawoutput".} - func sysFatal(exceptn: typedesc[Defect], message: string) {.inline.} = - panic(message) + proc sysFatal(exceptn: typedesc[Defect], message: string) {.inline, noreturn, raises: [], tags: [].} = + {.cast(noSideEffect).}: + {.cast(raises: []).}: + {.cast(tags: []).}: + nimPanic(message) - func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline.} = - rawoutput(message) - panic(arg) + proc sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline, noreturn, raises: [], tags: [].} = + {.cast(noSideEffect).}: + {.cast(raises: []).}: + {.cast(tags: []).}: + nimRawoutput(message) + nimPanic(arg) elif quirkyExceptions and not defined(nimscript): import ansi_c diff --git a/tests/assert/panicoverride.nim b/tests/assert/panicoverride.nim index 53ad64215b..573c23ea88 100644 --- a/tests/assert/panicoverride.nim +++ b/tests/assert/panicoverride.nim @@ -5,11 +5,11 @@ proc exit(code: cint) {.importc, header:"stdlib.h".} {.push stack_trace: off, profiler:off.} -proc rawoutput(s: cstring) = - printf("RAW: %s\n", s) - -proc panic(s: cstring) {.noreturn.} = - printf("PANIC: %s\n", s) +proc rawoutput(s: string) = + printf("RAW: %s\n", s.cstring) + +proc panic(s: string) {.noreturn.} = + printf("PANIC: %s\n", s.cstring) exit(0) {.pop.} \ No newline at end of file diff --git a/tests/avr/panicoverride.nim b/tests/avr/panicoverride.nim index 770933ddd4..3f2eb1d6eb 100644 --- a/tests/avr/panicoverride.nim +++ b/tests/avr/panicoverride.nim @@ -4,9 +4,9 @@ proc exit(code: int) {.importc, header: "", cdecl.} {.push stack_trace: off, profiler:off.} proc rawoutput(s: string) = - printf("%s\n", s) + printf("%s\n", s.cstring) -proc panic(s: string) = +proc panic(s: string) {.noreturn.} = rawoutput(s) exit(1) diff --git a/tests/errmsgs/t14444.nim b/tests/errmsgs/t14444.nim index 27365236ed..c9b9049323 100644 --- a/tests/errmsgs/t14444.nim +++ b/tests/errmsgs/t14444.nim @@ -3,7 +3,7 @@ discard """ exitcode: "1" output: ''' t14444.nim(13) t14444 -fatal.nim(53) sysFatal +fatal.nim(62) sysFatal Error: unhandled exception: index out of bounds, the container is empty [IndexDefect] ''' """ diff --git a/tests/errmsgs/t23536.nim b/tests/errmsgs/t23536.nim index d8f1433331..5dd0f6e0ce 100644 --- a/tests/errmsgs/t23536.nim +++ b/tests/errmsgs/t23536.nim @@ -8,7 +8,7 @@ t23536.nim(22) t23536 t23536.nim(17) foo assertions.nim(45) failedAssertImpl assertions.nim(40) raiseAssert -fatal.nim(53) sysFatal +fatal.nim(62) sysFatal """ diff --git a/tests/errmsgs/t24974.nim b/tests/errmsgs/t24974.nim index 39d473a89e..cfbb138c87 100644 --- a/tests/errmsgs/t24974.nim +++ b/tests/errmsgs/t24974.nim @@ -6,7 +6,7 @@ t24974.nim(19) d t24974.nim(16) s assertions.nim(45) failedAssertImpl assertions.nim(40) raiseAssert -fatal.nim(53) sysFatal +fatal.nim(62) sysFatal Error: unhandled exception: t24974.nim(16, 26) `false` [AssertionDefect] ''' """ diff --git a/tests/exception/t22469.nim b/tests/exception/t22469.nim index a76c749678..368890c208 100644 --- a/tests/exception/t22469.nim +++ b/tests/exception/t22469.nim @@ -3,7 +3,7 @@ discard """ output: ''' First top-level statement of ModuleB m22469.nim(3) m22469 -fatal.nim(53) sysFatal +fatal.nim(62) sysFatal Error: unhandled exception: over- or underflow [OverflowDefect] ''' """ diff --git a/tests/gc/panicoverride.nim b/tests/gc/panicoverride.nim index 0f28b0b72b..9e3b4785c8 100644 --- a/tests/gc/panicoverride.nim +++ b/tests/gc/panicoverride.nim @@ -5,7 +5,7 @@ proc exit(code: int) {.importc, header: "", cdecl.} {.push stack_trace: off, profiler:off.} proc rawoutput(s: string) = - printf("%s\n", s) + printf("%s\n", s.cstring) proc panic(s: string) {.noreturn.} = rawoutput(s) diff --git a/tests/manyloc/standalone/barebone.nim b/tests/manyloc/standalone/barebone.nim index 487f6da650..9fbebcba0a 100644 --- a/tests/manyloc/standalone/barebone.nim +++ b/tests/manyloc/standalone/barebone.nim @@ -1,7 +1,7 @@ discard """ ccodecheck: "\\i !@('systemInit')" ccodecheck: "\\i !@('systemDatInit')" -output: "hello" +output: "hi 4778" """ # bug #2041: Macros need to be available for os:standalone! import macros diff --git a/tests/manyloc/standalone/panicoverride.nim b/tests/manyloc/standalone/panicoverride.nim index c0b8bb030e..2b6b34d434 100644 --- a/tests/manyloc/standalone/panicoverride.nim +++ b/tests/manyloc/standalone/panicoverride.nim @@ -5,7 +5,7 @@ proc exit(code: int) {.importc, header: "", cdecl.} {.push stack_trace: off, profiler:off.} proc rawoutput(s: string) = - printf("%s\n", s) + printf("%s\n", s.cstring) proc panic(s: string) {.noreturn.} = rawoutput(s) diff --git a/tests/manyloc/standalone2/panicoverride.nim b/tests/manyloc/standalone2/panicoverride.nim index c0b8bb030e..2b6b34d434 100644 --- a/tests/manyloc/standalone2/panicoverride.nim +++ b/tests/manyloc/standalone2/panicoverride.nim @@ -5,7 +5,7 @@ proc exit(code: int) {.importc, header: "", cdecl.} {.push stack_trace: off, profiler:off.} proc rawoutput(s: string) = - printf("%s\n", s) + printf("%s\n", s.cstring) proc panic(s: string) {.noreturn.} = rawoutput(s)