From 6b332f91c82da6e19efad92b58ac1d9c1bc9eec0 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 09:35:19 +0000 Subject: feat(runtime): write runtime diagnostics to stderr Runtime check messages and the unhandled-exception message were printed to stdout by the generated program, so `cpsc x.cps -r >out.txt` captured them. They are now formatted with snprintf and written with write(2). Test expectations and docs are updated accordingly. Co-Authored-By: Claude Sonnet 5.5 --- AGENTS/ARCH.md | 4 ++-- AGENTS/CONVENTIONS.md | 4 ++-- AGENTS/EXTENDING.md | 2 +- AGENTS/PITFALLS.md | 2 +- AGENTS/SUBSYSTEMS.md | 2 +- doc/cpsc.1.md | 2 +- doc/language/function/cpsc-function-free.7.md | 2 +- doc/language/function/cpsc-function-malloc.7.md | 2 +- doc/language/function/cpsc-function-realloc.7.md | 2 +- doc/language/keyword/cpsc-keyword-try.7.md | 2 +- include/cps/RuntimeCheck.h | 10 ++++++-- lib/CodeGen/CodeGen.cc | 2 +- lib/CodeGen/FunctionGen.cc | 2 +- lib/CodeGen/RuntimeCheck.cc | 28 ++++++++++++++++++---- tests/i/caught-errors/expected-stderr.txt | 4 ++++ tests/i/caught-errors/expected.txt | 4 ---- .../i/class-delete-designators/expected-stderr.txt | 1 + tests/i/class-delete-designators/expected.txt | 1 - tests/i/class-delete/expected-stderr.txt | 2 ++ tests/i/class-delete/expected.txt | 2 -- tests/i/class-unwind/expected-stderr.txt | 1 + tests/i/class-unwind/expected.txt | 1 - tests/i/enum-range/expected-stderr.txt | 1 + tests/i/enum-range/expected.txt | 1 - .../i/function-call-statements/expected-stderr.txt | 1 + tests/i/function-call-statements/expected.txt | 1 - tests/i/input-targets/expected-stderr.txt | 2 ++ tests/i/input-targets/expected.txt | 2 -- tests/i/memory-allocation/expected-stderr.txt | 4 ++++ tests/i/memory-allocation/expected.txt | 4 ---- tests/i/memory-reallocation/expected-stderr.txt | 6 +++++ tests/i/memory-reallocation/expected.txt | 6 ----- tests/i/memory-uncaught/expected-stderr.txt | 2 ++ tests/i/memory-uncaught/expected.txt | 2 -- .../i/multifile-runtime-catch/expected-stderr.txt | 1 + tests/i/multifile-runtime-catch/expected.txt | 1 - tests/i/multifile-uncaught/expected-stderr.txt | 1 + tests/i/multifile-uncaught/expected.txt | 1 - tests/i/signed-zero-division/expected-stderr.txt | 1 + tests/i/signed-zero-division/expected.txt | 1 - tests/i/uncaught-error/expected-stderr.txt | 2 ++ tests/i/uncaught-error/expected.txt | 2 -- 42 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 tests/i/caught-errors/expected-stderr.txt create mode 100644 tests/i/class-delete-designators/expected-stderr.txt create mode 100644 tests/i/class-delete/expected-stderr.txt create mode 100644 tests/i/class-unwind/expected-stderr.txt create mode 100644 tests/i/enum-range/expected-stderr.txt create mode 100644 tests/i/function-call-statements/expected-stderr.txt create mode 100644 tests/i/input-targets/expected-stderr.txt create mode 100644 tests/i/memory-allocation/expected-stderr.txt create mode 100644 tests/i/memory-reallocation/expected-stderr.txt create mode 100644 tests/i/memory-uncaught/expected-stderr.txt create mode 100644 tests/i/multifile-runtime-catch/expected-stderr.txt create mode 100644 tests/i/multifile-uncaught/expected-stderr.txt create mode 100644 tests/i/signed-zero-division/expected-stderr.txt create mode 100644 tests/i/uncaught-error/expected-stderr.txt diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md index aef89ed..5ddddc1 100644 --- a/AGENTS/ARCH.md +++ b/AGENTS/ARCH.md @@ -75,9 +75,9 @@ Generated IR uses the C++ exception ABI; native compilation links its runtime automatically. Manually linking emitted `.ll` files still requires a C++ driver (use LLVM 23's `clang++`, or `clang++-23` on Debian/Ubuntu). TRY/CATCH/ENDTRY and bare THROW are compiler extensions. -Runtime checks print the source line and error reason to stdout before throwing +Runtime checks print the source line and error reason to stderr before throwing anonymous exceptions; the final handler in generated main -prints `Unhandled exception. Program terminated.` to stdout and returns 1. +prints `Unhandled exception. Program terminated.` to stderr and returns 1. Exception execution with the embedded ORC JIT is verified on Linux with LLVM 23; Windows/macOS await CI verification. diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md index 2686760..f912e79 100644 --- a/AGENTS/CONVENTIONS.md +++ b/AGENTS/CONVENTIONS.md @@ -176,9 +176,9 @@ Its handler stack and catch depth are keyed by LLVM function, so synthesizing fi helpers never inherits the caller's catches. User calls, file runtime calls and THROW must use `ExceptionHandler::emitCall`; ordinary nonthrowing libc calls stay plain calls. RETURN must finish all active catches after evaluating its value. -`RuntimeCheck::emitCheck` prints the source line and error reason to stdout before +`RuntimeCheck::emitCheck` prints the source line and error reason to stderr before throwing. Generated main catches anything unhandled, prints the generic termination -message to stdout, and returns 1. Explicit bare THROW prints no diagnostic itself. +message to stderr, and returns 1. Explicit bare THROW prints no diagnostic itself. Arrays in TRY and CATCH use separate block scopes; scalars retain existing function scope. **Compilation units and entry points.** SourceUnit borrows its AST list; it and the diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md index b3f481a..3161407 100644 --- a/AGENTS/EXTENDING.md +++ b/AGENTS/EXTENDING.md @@ -62,7 +62,7 @@ collapse to a legacy node. **New runtime check:** add `emitXxxCheck` in `RuntimeCheck` (build an i1 fail-condition and call `emitCheck` with a diagnostic format and arguments — it splits the block and leaves the builder at the continuation), then call it from -the emit site. Failure prints the source line and error reason to stdout before +the emit site. Failure prints the source line and error reason to stderr before throwing an anonymous exception; generated main supplies the uncaught message and status 1. Precedents: `emitIndexCheck`, `emitEnumRangeCheck`, `emitNullDerefCheck`, `emitArrayArgBoundsCheck` and FileHandler's direct `emitCheck` calls. diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index d811ea4..951a2f6 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -121,7 +121,7 @@ test programs. ENDTRY. Bare THROW raises a new anonymous exception even inside CATCH; there is no rethrow syntax, error object or what(). Runtime checks are catchable; compiler errors are not. Runtime checks print the source line and error reason - to stdout before throwing, even when caught. Uncaught exceptions also print the + to stderr before throwing, even when caught. Uncaught exceptions also print the generic termination message and return 1. Bare THROW prints no diagnostic itself. Native binaries must link the C++ runtime with LLVM 23's `clang++` (`clang++-23` on Debian/Ubuntu). diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index d21dfe8..bb59ebf 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -114,7 +114,7 @@ dereferences and array-parameter bounds contracts are checked at their emit site `ArithmeticHandler` calls `emitDivZeroCheck` before `/`, DIV and MOD; the check accepts integer and floating-point divisors, including both floating-point signed zeros. `emitCheck(Cond, Msg, Args)` splits the block, prints the source line and error -reason to stdout, and calls `ExceptionHandler::emitThrow` on failure. File helper +reason to stderr, and calls `ExceptionHandler::emitThrow` on failure. File helper checks receive the source line as a runtime argument. **Exceptions** (`ExceptionHandler`): holds Context/Builder/Module refs and a map of diff --git a/doc/cpsc.1.md b/doc/cpsc.1.md index 2bb1f1c..5b1369d 100644 --- a/doc/cpsc.1.md +++ b/doc/cpsc.1.md @@ -112,7 +112,7 @@ An uncaught program exception returns 1 after printing `Unhandled exception. Pro # NOTES -Compiler diagnostics go to stderr. With multiple input files, lexer, parser and code generation diagnostics include the source path after the line number. Failed source compilation does not write output; failed native linking does not replace an existing output file. Successful compilation overwrites an existing output file, but an output path that refers to any input source file (including a symbolic or hard link) is rejected. +Compiler diagnostics go to stderr. With multiple input files, lexer, parser and code generation diagnostics include the source path after the line number. Failed source compilation does not write output; failed native linking does not replace an existing output file. Successful compilation overwrites an existing output file, but an output path that refers to any input source file (including a symbolic or hard link) is rejected. Runtime diagnostics of the compiled program (for example `[Fatal] line N: ...` and `Unhandled exception. Program terminated.`) are also written to stderr, so `OUTPUT` text alone appears on stdout. Missing input, including invoking `cpsc` without arguments, reports `cpsc: fatal error: no input files`. Ordinary lexical, syntax and semantic errors use `error:`; failures that prevent compilation, such as file I/O errors, use `fatal error:`. Compilation and argument failures end with one `compilation terminated.` line. Execution-stage failures do not print that line. diff --git a/doc/language/function/cpsc-function-free.7.md b/doc/language/function/cpsc-function-free.7.md index 61a3558..366b317 100644 --- a/doc/language/function/cpsc-function-free.7.md +++ b/doc/language/function/cpsc-function-free.7.md @@ -12,7 +12,7 @@ FREE(pointer) # DESCRIPTION -FREE is a compiler extension. Its argument and return type are C `void*`. Explicitly cast other pointer types to a `void*` alias before passing them. A null pointer is accepted and returned. A non-null pointer must be the start of an active explicit MALLOC, REALLOC or keyword NEW allocation; internal STRING/ARRAY storage, stack addresses, interior addresses and already released allocations are rejected with a source-line diagnostic on stdout and an anonymous exception. +FREE is a compiler extension. Its argument and return type are C `void*`. Explicitly cast other pointer types to a `void*` alias before passing them. A null pointer is accepted and returned. A non-null pointer must be the start of an active explicit MALLOC, REALLOC or keyword NEW allocation; internal STRING/ARRAY storage, stack addresses, interior addresses and already released allocations are rejected with a source-line diagnostic on stderr and an anonymous exception. FREE returns its input address after releasing the allocation. It does not clear the caller's variable. The returned address and all aliases are invalid for memory access. Calling FREE again on that address throws unless a subsequent allocation has reused the address. Tracking cannot distinguish stale aliases once an address is reused. diff --git a/doc/language/function/cpsc-function-malloc.7.md b/doc/language/function/cpsc-function-malloc.7.md index 909903a..c0ca1a6 100644 --- a/doc/language/function/cpsc-function-malloc.7.md +++ b/doc/language/function/cpsc-function-malloc.7.md @@ -12,7 +12,7 @@ MALLOC(bytes) # DESCRIPTION -MALLOC is a compiler extension returning a C `void*` to the beginning of an uninitialized allocation. The size is in bytes and accepts INTEGER or a C integer, converted to the host size_t using C integer conversion rules. Negative values are not separately rejected. MALLOC(0) returns null without allocating. A nonzero allocation failure prints the source line and reason to stdout, then throws an anonymous exception catchable with TRY/CATCH. Allocation tracking failures behave the same way. +MALLOC is a compiler extension returning a C `void*` to the beginning of an uninitialized allocation. The size is in bytes and accepts INTEGER or a C integer, converted to the host size_t using C integer conversion rules. Negative values are not separately rejected. MALLOC(0) returns null without allocating. A nonzero allocation failure prints the source line and reason to stderr, then throws an anonymous exception catchable with TRY/CATCH. Allocation tracking failures behave the same way. Declare a `void*` alias with C_TYPE and explicitly cast the result to a C or pseudocode pointer before dereferencing. MALLOC does not initialize fields or call constructors; it is unrelated to the CIE class NEW construct. The caller must supply enough bytes and initialize values before reading them. User memory is not automatically released. diff --git a/doc/language/function/cpsc-function-realloc.7.md b/doc/language/function/cpsc-function-realloc.7.md index 19fcfdf..dc2d61f 100644 --- a/doc/language/function/cpsc-function-realloc.7.md +++ b/doc/language/function/cpsc-function-realloc.7.md @@ -14,7 +14,7 @@ REALLOC(pointer, bytes) REALLOC is a compiler extension returning C `void*`. The pointer argument must also be C `void*`; explicitly cast other pointer types. The size accepts INTEGER or a C integer and converts to host size_t, just as MALLOC does. -A null pointer behaves as MALLOC(bytes). A non-null pointer must start an active explicit MALLOC or REALLOC allocation, even when bytes is zero. Invalid addresses print the source line and reason to stdout and throw an anonymous exception before touching the memory or allocation record. +A null pointer behaves as MALLOC(bytes). A non-null pointer must start an active explicit MALLOC or REALLOC allocation, even when bytes is zero. Invalid addresses print the source line and reason to stderr and throw an anonymous exception before touching the memory or allocation record. For a valid pointer and zero bytes, REALLOC releases the block and returns null. This rule is independent of libc's zero-size behavior. For a nonzero size, successful resizing preserves the smaller of the old and new sizes; added bytes are uninitialized. The returned address may differ from the input. Use the returned pointer afterward; previous aliases must not be used. diff --git a/doc/language/keyword/cpsc-keyword-try.7.md b/doc/language/keyword/cpsc-keyword-try.7.md index 8ebe89d..eea0510 100644 --- a/doc/language/keyword/cpsc-keyword-try.7.md +++ b/doc/language/keyword/cpsc-keyword-try.7.md @@ -24,7 +24,7 @@ Normal execution skips CATCH. An exception stops the current operation, unwinds THROW takes no argument and always raises a new anonymous exception. An exception raised inside CATCH propagates to an enclosing TRY or a caller's handler; the same CATCH cannot catch it again. RETURN may leave either body, and leaving a handler finishes its catch state. -Runtime checks throw the same anonymous exceptions for division by zero, array index errors, null pointer dereferences, invalid enumeration values, array-parameter bounds mismatches, and file misuse. Before throwing, a runtime check prints the source line and error reason to standard output, even when CATCH handles the exception. Explicit THROW prints no diagnostic itself. Compiler errors cannot be caught. If no handler catches an exception, the program prints `Unhandled exception. Program terminated.` to standard output and returns status 1. +Runtime checks throw the same anonymous exceptions for division by zero, array index errors, null pointer dereferences, invalid enumeration values, array-parameter bounds mismatches, and file misuse. Before throwing, a runtime check prints the source line and error reason to standard error, even when CATCH handles the exception. Explicit THROW prints no diagnostic itself. Compiler errors cannot be caught. If no handler catches an exception, the program prints `Unhandled exception. Program terminated.` to standard error and returns status 1. Arrays declared inside either body remain local to that block. Stack unwinding does not automatically free heap strings or arrays, close files, or run user-defined destructors. Exception execution is verified on Linux with LLVM 23; Windows and macOS remain unverified. diff --git a/include/cps/RuntimeCheck.h b/include/cps/RuntimeCheck.h index f5a8aa7..8f33e99 100644 --- a/include/cps/RuntimeCheck.h +++ b/include/cps/RuntimeCheck.h @@ -14,7 +14,10 @@ class RuntimeCheck { llvm::LLVMContext &TheContext; llvm::IRBuilder<> &Builder; - llvm::FunctionCallee PrintfFunc; + llvm::FunctionCallee SnprintfFunc; + llvm::FunctionCallee WriteFunc; + llvm::FunctionCallee StrLenFunc; + llvm::GlobalVariable *ErrBuf; ExceptionHandler &Exceptions; llvm::Value *DivZeroMsg; llvm::Value *OutOfBoundsMsg; @@ -29,6 +32,9 @@ public: RuntimeCheck(llvm::Module &M, llvm::LLVMContext &C, llvm::IRBuilder<> &B, ExceptionHandler &EH); + // Format a runtime diagnostic (printf-style) and write it to stderr. + void emitStderr(llvm::Value *Msg, llvm::ArrayRef FmtArgs = {}); + void emitDivZeroCheck(llvm::Value *Divisor, int Line); void emitIndexCheck(llvm::Value *Index, llvm::Value *Lower, llvm::Value *Upper, int Line); @@ -44,7 +50,7 @@ public: void emitArrayArgBoundsCheck(llvm::Value *ActualLower, llvm::Value *ActualUpper, int64_t DeclaredLower, int64_t DeclaredUpper, int Line); - // Print the diagnostic, then throw an anonymous exception on failure. + // Print the diagnostic to stderr, then throw an anonymous exception on failure. // Runtime-computed variant: FmtArgs are the printf varargs after Msg // (e.g. {i32 line, ptr filename}). Needed when the failure site is inside // a synthesized helper function, where the line number is an argument diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index eba7d77..b81fe2b 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -340,7 +340,7 @@ void CodeGen::compile(const std::vector &Sources) { Exceptions->endCatch(); Value *Msg = Builder->CreateGlobalString("Unhandled exception. Program terminated.\n", "err_unhandled", 0, TheModule.get()); - Builder->CreateCall(PrintfFunc, {Msg}); + RuntimeChecker->emitStderr(Msg); Builder->CreateRet(ConstantInt::get(Type::getInt32Ty(*TheContext), 1)); if (verifyModule(*TheModule, &errs())) { diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc index 47971cf..4e70faf 100644 --- a/lib/CodeGen/FunctionGen.cc +++ b/lib/CodeGen/FunctionGen.cc @@ -14,7 +14,7 @@ static bool isReservedRuntimeName(const std::string &Name) { static const char *Reserved[] = { "__cps_main", "printf", "scanf", "malloc", "free", "strlen", "memcpy", "strcpy", "strcat", "toupper", "tolower", "sprintf", "snprintf", "strtol", "strtoll", - "strtod", "memset", "exit", + "strtod", "memset", "exit", "write", "fopen", "fclose", "fgetc", "ungetc", "fputs", "fputc", "realloc", "strcmp", "__cxa_allocate_exception", "__cxa_throw", "__cxa_begin_catch", "__cxa_end_catch", "__gxx_personality_v0", diff --git a/lib/CodeGen/RuntimeCheck.cc b/lib/CodeGen/RuntimeCheck.cc index 215702e..b1eb677 100644 --- a/lib/CodeGen/RuntimeCheck.cc +++ b/lib/CodeGen/RuntimeCheck.cc @@ -3,6 +3,7 @@ #include "cps/TypeSystem.h" // kEnumOrdinalBase #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Constants.h" using namespace llvm; @@ -14,10 +15,18 @@ RuntimeCheck::RuntimeCheck(Module &M, LLVMContext &C, IRBuilder<> &B, ExceptionH } void RuntimeCheck::setupExternalFunctions() { - std::vector PrintfArgs; - PrintfArgs.push_back(PointerType::getUnqual(TheContext)); - FunctionType *PrintfType = FunctionType::get(Type::getInt32Ty(TheContext), PrintfArgs, true); - PrintfFunc = TheModule.getOrInsertFunction("printf", PrintfType); + Type *PtrTy = PointerType::getUnqual(TheContext); + Type *I32 = Type::getInt32Ty(TheContext); + Type *I64 = Type::getInt64Ty(TheContext); + SnprintfFunc = TheModule.getOrInsertFunction( + "snprintf", FunctionType::get(I32, {PtrTy, I64, PtrTy}, true)); + WriteFunc = TheModule.getOrInsertFunction( + "write", FunctionType::get(I32, {I32, PtrTy, I64}, false)); + StrLenFunc = TheModule.getOrInsertFunction( + "strlen", FunctionType::get(I64, {PtrTy}, false)); + ArrayType *BufTy = ArrayType::get(Type::getInt8Ty(TheContext), 1024); + ErrBuf = new GlobalVariable(TheModule, BufTy, false, GlobalValue::InternalLinkage, + ConstantAggregateZero::get(BufTy), "__cps_errbuf"); DivZeroMsg = Builder.CreateGlobalString("[Fatal] line %d: Division by zero\n", "err_div_zero", 0, &TheModule); OutOfBoundsMsg = Builder.CreateGlobalString("[Fatal] line %d: Array index out of bounds\n", "err_bounds", 0, &TheModule); @@ -28,6 +37,15 @@ void RuntimeCheck::setupExternalFunctions() { "err_arr_arg_bounds", 0, &TheModule); } +void RuntimeCheck::emitStderr(Value *Msg, ArrayRef FmtArgs) { + // Format into a fixed buffer, then write(2) so diagnostics bypass stdout. + std::vector Args = {ErrBuf, ConstantInt::get(Type::getInt64Ty(TheContext), 1024), Msg}; + Args.insert(Args.end(), FmtArgs.begin(), FmtArgs.end()); + Builder.CreateCall(SnprintfFunc, Args); + Value *Len = Builder.CreateCall(StrLenFunc, {ErrBuf}); + Builder.CreateCall(WriteFunc, {ConstantInt::get(Type::getInt32Ty(TheContext), 2), ErrBuf, Len}); +} + void RuntimeCheck::emitCheck(Value *Condition, Value *Msg, int Line) { emitCheck(Condition, Msg, {ConstantInt::get(TheContext, APInt(32, Line))}); } @@ -44,7 +62,7 @@ void RuntimeCheck::emitCheck(Value *Condition, Value *Msg, ArrayRef Fmt std::vector PrintArgs; PrintArgs.push_back(Msg); PrintArgs.insert(PrintArgs.end(), FmtArgs.begin(), FmtArgs.end()); - Builder.CreateCall(PrintfFunc, PrintArgs); + emitStderr(Msg, ArrayRef(PrintArgs).drop_front()); Exceptions.emitThrow(); diff --git a/tests/i/caught-errors/expected-stderr.txt b/tests/i/caught-errors/expected-stderr.txt new file mode 100644 index 0000000..7c5bfd1 --- /dev/null +++ b/tests/i/caught-errors/expected-stderr.txt @@ -0,0 +1,4 @@ +[Fatal] line 7: Division by zero +[Fatal] line 12: Array index out of bounds +[Fatal] line 17: Dereference of an unset pointer +[Fatal] line 22: File 'closed.txt' is not open diff --git a/tests/i/caught-errors/expected.txt b/tests/i/caught-errors/expected.txt index ae32ca6..6a677de 100644 --- a/tests/i/caught-errors/expected.txt +++ b/tests/i/caught-errors/expected.txt @@ -1,10 +1,6 @@ -[Fatal] line 7: Division by zero division caught -[Fatal] line 12: Array index out of bounds bounds caught -[Fatal] line 17: Dereference of an unset pointer pointer caught -[Fatal] line 22: File 'closed.txt' is not open file caught throw caught alive diff --git a/tests/i/class-delete-designators/expected-stderr.txt b/tests/i/class-delete-designators/expected-stderr.txt new file mode 100644 index 0000000..268ec7f --- /dev/null +++ b/tests/i/class-delete-designators/expected-stderr.txt @@ -0,0 +1 @@ +[Fatal] line 27: Invalid memory address (not an active allocation) diff --git a/tests/i/class-delete-designators/expected.txt b/tests/i/class-delete-designators/expected.txt index 3a62de6..b63409e 100644 --- a/tests/i/class-delete-designators/expected.txt +++ b/tests/i/class-delete-designators/expected.txt @@ -1,7 +1,6 @@ item:1 item:1 item:2 -[Fatal] line 27: Invalid memory address (not an active allocation) array caught item:3 item:0 diff --git a/tests/i/class-delete/expected-stderr.txt b/tests/i/class-delete/expected-stderr.txt new file mode 100644 index 0000000..bbd6b69 --- /dev/null +++ b/tests/i/class-delete/expected-stderr.txt @@ -0,0 +1,2 @@ +[Fatal] line 24: Invalid memory address (not an active allocation) +[Fatal] line 30: Invalid memory address (not an active allocation) diff --git a/tests/i/class-delete/expected.txt b/tests/i/class-delete/expected.txt index c7e7246..bb2c73d 100644 --- a/tests/i/class-delete/expected.txt +++ b/tests/i/class-delete/expected.txt @@ -3,9 +3,7 @@ pair pair leaf:2 leaf:1 -[Fatal] line 24: Invalid memory address (not an active allocation) double caught -[Fatal] line 30: Invalid memory address (not an active allocation) stack caught leaf:2 pair diff --git a/tests/i/class-unwind/expected-stderr.txt b/tests/i/class-unwind/expected-stderr.txt new file mode 100644 index 0000000..e9431ec --- /dev/null +++ b/tests/i/class-unwind/expected-stderr.txt @@ -0,0 +1 @@ +Unhandled exception. Program terminated. diff --git a/tests/i/class-unwind/expected.txt b/tests/i/class-unwind/expected.txt index 3503cb5..e563d2c 100644 --- a/tests/i/class-unwind/expected.txt +++ b/tests/i/class-unwind/expected.txt @@ -11,4 +11,3 @@ uncaught next destroy:2 destroy:1 destroy:3 -Unhandled exception. Program terminated. diff --git a/tests/i/enum-range/expected-stderr.txt b/tests/i/enum-range/expected-stderr.txt new file mode 100644 index 0000000..b0c5ea2 --- /dev/null +++ b/tests/i/enum-range/expected-stderr.txt @@ -0,0 +1 @@ +[Fatal] line 5: Value out of range for enum Season diff --git a/tests/i/enum-range/expected.txt b/tests/i/enum-range/expected.txt index f91d556..e6e3e04 100644 --- a/tests/i/enum-range/expected.txt +++ b/tests/i/enum-range/expected.txt @@ -1,3 +1,2 @@ -[Fatal] line 5: Value out of range for enum Season enum caught TRUE diff --git a/tests/i/function-call-statements/expected-stderr.txt b/tests/i/function-call-statements/expected-stderr.txt new file mode 100644 index 0000000..1741571 --- /dev/null +++ b/tests/i/function-call-statements/expected-stderr.txt @@ -0,0 +1 @@ +[Fatal] line 33: Division by zero diff --git a/tests/i/function-call-statements/expected.txt b/tests/i/function-call-statements/expected.txt index d2576ac..b35d820 100644 --- a/tests/i/function-call-statements/expected.txt +++ b/tests/i/function-call-statements/expected.txt @@ -2,5 +2,4 @@ 23 7 19 -[Fatal] line 33: Division by zero caught diff --git a/tests/i/input-targets/expected-stderr.txt b/tests/i/input-targets/expected-stderr.txt new file mode 100644 index 0000000..a53ae1f --- /dev/null +++ b/tests/i/input-targets/expected-stderr.txt @@ -0,0 +1,2 @@ +[Fatal] line 45: Array index out of bounds +[Fatal] line 51: Dereference of an unset pointer diff --git a/tests/i/input-targets/expected.txt b/tests/i/input-targets/expected.txt index 75640cd..ba27972 100644 --- a/tests/i/input-targets/expected.txt +++ b/tests/i/input-targets/expected.txt @@ -4,8 +4,6 @@ TRUE:-7 60:70 index evaluated 90 -[Fatal] line 45: Array index out of bounds bounds caught -[Fatal] line 51: Dereference of an unset pointer pointer caught 100 diff --git a/tests/i/memory-allocation/expected-stderr.txt b/tests/i/memory-allocation/expected-stderr.txt new file mode 100644 index 0000000..72d9e66 --- /dev/null +++ b/tests/i/memory-allocation/expected-stderr.txt @@ -0,0 +1,4 @@ +[Fatal] line 34: Invalid memory address (not an active allocation) +[Fatal] line 40: Invalid memory address (not an active allocation) +[Fatal] line 48: Invalid memory address (not an active allocation) +[Fatal] line 54: Memory allocation failed diff --git a/tests/i/memory-allocation/expected.txt b/tests/i/memory-allocation/expected.txt index 330c9ba..e007979 100644 --- a/tests/i/memory-allocation/expected.txt +++ b/tests/i/memory-allocation/expected.txt @@ -3,12 +3,8 @@ TRUE 42 11:22 TRUE -[Fatal] line 34: Invalid memory address (not an active allocation) double free caught -[Fatal] line 40: Invalid memory address (not an active allocation) stack address caught -[Fatal] line 48: Invalid memory address (not an active allocation) interior address caught -[Fatal] line 54: Memory allocation failed allocation failure caught 99 diff --git a/tests/i/memory-reallocation/expected-stderr.txt b/tests/i/memory-reallocation/expected-stderr.txt new file mode 100644 index 0000000..5478518 --- /dev/null +++ b/tests/i/memory-reallocation/expected-stderr.txt @@ -0,0 +1,6 @@ +[Fatal] line 28: Memory allocation failed +[Fatal] line 40: Invalid memory address (not an active allocation) +[Fatal] line 47: Invalid memory address (not an active allocation) +[Fatal] line 63: Invalid memory address (not an active allocation) +[Fatal] line 69: Invalid memory address (not an active allocation) +[Fatal] line 77: Invalid memory address (not an active allocation) diff --git a/tests/i/memory-reallocation/expected.txt b/tests/i/memory-reallocation/expected.txt index 9e9ccc9..bb43f4f 100644 --- a/tests/i/memory-reallocation/expected.txt +++ b/tests/i/memory-reallocation/expected.txt @@ -1,17 +1,11 @@ TRUE 12:34 12 -[Fatal] line 28: Memory allocation failed preserved:12 56 TRUE -[Fatal] line 40: Invalid memory address (not an active allocation) released address caught -[Fatal] line 47: Invalid memory address (not an active allocation) invalid zero resize caught 71 -[Fatal] line 63: Invalid memory address (not an active allocation) -[Fatal] line 69: Invalid memory address (not an active allocation) nested catch -[Fatal] line 77: Invalid memory address (not an active allocation) internal buffer caught diff --git a/tests/i/memory-uncaught/expected-stderr.txt b/tests/i/memory-uncaught/expected-stderr.txt new file mode 100644 index 0000000..448a57b --- /dev/null +++ b/tests/i/memory-uncaught/expected-stderr.txt @@ -0,0 +1,2 @@ +[Fatal] line 5: Invalid memory address (not an active allocation) +Unhandled exception. Program terminated. diff --git a/tests/i/memory-uncaught/expected.txt b/tests/i/memory-uncaught/expected.txt index 448a57b..e69de29 100644 --- a/tests/i/memory-uncaught/expected.txt +++ b/tests/i/memory-uncaught/expected.txt @@ -1,2 +0,0 @@ -[Fatal] line 5: Invalid memory address (not an active allocation) -Unhandled exception. Program terminated. diff --git a/tests/i/multifile-runtime-catch/expected-stderr.txt b/tests/i/multifile-runtime-catch/expected-stderr.txt new file mode 100644 index 0000000..833ca4b --- /dev/null +++ b/tests/i/multifile-runtime-catch/expected-stderr.txt @@ -0,0 +1 @@ +[Fatal] line 2: Division by zero diff --git a/tests/i/multifile-runtime-catch/expected.txt b/tests/i/multifile-runtime-catch/expected.txt index 731df7f..6a0b8ed 100644 --- a/tests/i/multifile-runtime-catch/expected.txt +++ b/tests/i/multifile-runtime-catch/expected.txt @@ -1,3 +1,2 @@ -[Fatal] line 2: Division by zero runtime caught 5 diff --git a/tests/i/multifile-uncaught/expected-stderr.txt b/tests/i/multifile-uncaught/expected-stderr.txt new file mode 100644 index 0000000..e9431ec --- /dev/null +++ b/tests/i/multifile-uncaught/expected-stderr.txt @@ -0,0 +1 @@ +Unhandled exception. Program terminated. diff --git a/tests/i/multifile-uncaught/expected.txt b/tests/i/multifile-uncaught/expected.txt index e9431ec..e69de29 100644 --- a/tests/i/multifile-uncaught/expected.txt +++ b/tests/i/multifile-uncaught/expected.txt @@ -1 +0,0 @@ -Unhandled exception. Program terminated. diff --git a/tests/i/signed-zero-division/expected-stderr.txt b/tests/i/signed-zero-division/expected-stderr.txt new file mode 100644 index 0000000..77a3113 --- /dev/null +++ b/tests/i/signed-zero-division/expected-stderr.txt @@ -0,0 +1 @@ +[Fatal] line 4: Division by zero diff --git a/tests/i/signed-zero-division/expected.txt b/tests/i/signed-zero-division/expected.txt index 0376278..a0e6b3f 100644 --- a/tests/i/signed-zero-division/expected.txt +++ b/tests/i/signed-zero-division/expected.txt @@ -1,2 +1 @@ -[Fatal] line 4: Division by zero zero caught diff --git a/tests/i/uncaught-error/expected-stderr.txt b/tests/i/uncaught-error/expected-stderr.txt new file mode 100644 index 0000000..8b66756 --- /dev/null +++ b/tests/i/uncaught-error/expected-stderr.txt @@ -0,0 +1,2 @@ +[Fatal] line 3: Division by zero +Unhandled exception. Program terminated. diff --git a/tests/i/uncaught-error/expected.txt b/tests/i/uncaught-error/expected.txt index 8b66756..e69de29 100644 --- a/tests/i/uncaught-error/expected.txt +++ b/tests/i/uncaught-error/expected.txt @@ -1,2 +0,0 @@ -[Fatal] line 3: Division by zero -Unhandled exception. Program terminated. -- cgit v1.3.1-4-g156e