mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
compiler: yet more panic handler changes
* `std.builtin.Panic` -> `std.builtin.panic`, because it is a namespace. * `root.Panic` -> `root.panic` for the same reason. There are type checks so that we still allow the legacy `pub fn panic` strategy in the 0.14.0 release. * `std.debug.SimplePanic` -> `std.debug.simple_panic`, same reason. * `std.debug.NoPanic` -> `std.debug.no_panic`, same reason. * `std.debug.FormattedPanic` is now a function `std.debug.FullPanic` which takes as input a `panicFn` and returns a namespace with all the panic functions. This handles the incredibly common case of just wanting to override how the message is printed, whilst keeping nice formatted panics. * Remove `std.builtin.panic.messages`; now, every safety panic has its own function. This reduces binary bloat, as calls to these functions no longer need to prepare any arguments (aside from the error return trace). * Remove some legacy declarations, since a zig1.wasm update has happened. Most of these were related to the panic handler, but a quick grep for "zig1" brought up a couple more results too. Also, add some missing type checks to Sema. Resolves: #22584 formatted -> full
This commit is contained in:
parent
b3d9b0e3f6
commit
83991efe10
19 changed files with 792 additions and 410 deletions
|
|
@ -370,7 +370,7 @@ pub const Os = struct {
|
|||
range: std.SemanticVersion.Range,
|
||||
glibc: std.SemanticVersion,
|
||||
/// Android API level.
|
||||
android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated.
|
||||
android: u32,
|
||||
|
||||
pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
|
||||
return range.range.includesVersion(ver);
|
||||
|
|
|
|||
|
|
@ -1110,45 +1110,28 @@ pub const TestFn = struct {
|
|||
/// Deprecated, use the `Panic` namespace instead.
|
||||
/// To be deleted after 0.14.0 is released.
|
||||
pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn;
|
||||
/// Deprecated, use the `Panic` namespace instead.
|
||||
/// To be deleted after 0.14.0 is released.
|
||||
pub const panic: PanicFn = Panic.call;
|
||||
|
||||
/// This namespace is used by the Zig compiler to emit various kinds of safety
|
||||
/// panics. These can be overridden by making a public `Panic` namespace in the
|
||||
/// panics. These can be overridden by making a public `panic` namespace in the
|
||||
/// root source file.
|
||||
pub const Panic: type = if (@hasDecl(root, "Panic"))
|
||||
root.Panic
|
||||
else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead.
|
||||
DeprecatedPanic
|
||||
else if (builtin.zig_backend == .stage2_riscv64)
|
||||
std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519
|
||||
else
|
||||
std.debug.FormattedPanic;
|
||||
|
||||
/// To be deleted after 0.14.0 is released.
|
||||
const DeprecatedPanic = struct {
|
||||
pub const call = root.panic;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
pub const panic: type = p: {
|
||||
if (@hasDecl(root, "panic")) {
|
||||
if (@TypeOf(root.panic) != type) {
|
||||
break :p std.debug.FullPanic(root.panic); // Deprecated; make `panic` a namespace instead.
|
||||
}
|
||||
break :p root.panic;
|
||||
}
|
||||
if (@hasDecl(root, "Panic")) {
|
||||
break :p root.Panic; // Deprecated; use `panic` instead.
|
||||
}
|
||||
if (builtin.zig_backend == .stage2_riscv64) {
|
||||
break :p std.debug.simple_panic;
|
||||
}
|
||||
break :p std.debug.FullPanic(std.debug.defaultPanic);
|
||||
};
|
||||
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panicSentinelMismatch = Panic.sentinelMismatch;
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panicUnwrapError = Panic.unwrapError;
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panicOutOfBounds = Panic.outOfBounds;
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd;
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panicInactiveUnionField = Panic.inactiveUnionField;
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const panic_messages = Panic.messages;
|
||||
pub const Panic = panic;
|
||||
|
||||
pub noinline fn returnError() void {
|
||||
@branchHint(.unlikely);
|
||||
|
|
|
|||
|
|
@ -21,9 +21,124 @@ pub const SelfInfo = @import("debug/SelfInfo.zig");
|
|||
pub const Info = @import("debug/Info.zig");
|
||||
pub const Coverage = @import("debug/Coverage.zig");
|
||||
|
||||
pub const FormattedPanic = @import("debug/FormattedPanic.zig");
|
||||
pub const SimplePanic = @import("debug/SimplePanic.zig");
|
||||
pub const NoPanic = @import("debug/NoPanic.zig");
|
||||
pub const simple_panic = @import("debug/simple_panic.zig");
|
||||
pub const no_panic = @import("debug/no_panic.zig");
|
||||
|
||||
/// A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`.
|
||||
/// Safety panics will use formatted printing to provide a meaningful error message.
|
||||
/// The signature of `panicFn` should match that of `defaultPanic`.
|
||||
pub fn FullPanic(comptime panicFn: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn) type {
|
||||
return struct {
|
||||
pub const call = panicFn;
|
||||
pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
|
||||
expected, found,
|
||||
});
|
||||
}
|
||||
pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
|
||||
}
|
||||
pub fn outOfBounds(index: usize, len: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
|
||||
}
|
||||
pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
|
||||
}
|
||||
pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
|
||||
@tagName(accessed), @tagName(active),
|
||||
});
|
||||
}
|
||||
pub fn reachedUnreachable() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("reached unreachable code", null, @returnAddress());
|
||||
}
|
||||
pub fn unwrapNull() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("attempt to use null value", null, @returnAddress());
|
||||
}
|
||||
pub fn castToNull() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("cast causes pointer to be null", null, @returnAddress());
|
||||
}
|
||||
pub fn incorrectAlignment() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("incorrect alignment", null, @returnAddress());
|
||||
}
|
||||
pub fn invalidErrorCode() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("invalid error code", null, @returnAddress());
|
||||
}
|
||||
pub fn castTruncatedData() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("integer cast truncated bits", null, @returnAddress());
|
||||
}
|
||||
pub fn negativeToUnsigned() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("attempt to cast negative value to unsigned integer", null, @returnAddress());
|
||||
}
|
||||
pub fn integerOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("integer overflow", null, @returnAddress());
|
||||
}
|
||||
pub fn shlOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("left shift overflowed bits", null, @returnAddress());
|
||||
}
|
||||
pub fn shrOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("right shift overflowed bits", null, @returnAddress());
|
||||
}
|
||||
pub fn divideByZero() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("division by zero", null, @returnAddress());
|
||||
}
|
||||
pub fn exactDivisionRemainder() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("exact division produced remainder", null, @returnAddress());
|
||||
}
|
||||
pub fn integerPartOutOfBounds() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("integer part of floating point value out of bounds", null, @returnAddress());
|
||||
}
|
||||
pub fn corruptSwitch() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("switch on corrupt value", null, @returnAddress());
|
||||
}
|
||||
pub fn shiftRhsTooBig() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("shift amount is greater than the type size", null, @returnAddress());
|
||||
}
|
||||
pub fn invalidEnumValue() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("invalid enum value", null, @returnAddress());
|
||||
}
|
||||
pub fn forLenMismatch() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("for loop over objects with non-equal lengths", null, @returnAddress());
|
||||
}
|
||||
pub fn memcpyLenMismatch() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("@memcpy arguments have non-equal lengths", null, @returnAddress());
|
||||
}
|
||||
pub fn memcpyAlias() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("@memcpy arguments alias", null, @returnAddress());
|
||||
}
|
||||
pub fn noreturnReturned() noreturn {
|
||||
@branchHint(.cold);
|
||||
call("'noreturn' function returned", null, @returnAddress());
|
||||
}
|
||||
|
||||
/// To be deleted after zig1.wasm update.
|
||||
pub const messages = simple_panic.messages;
|
||||
};
|
||||
}
|
||||
|
||||
/// Unresolved source locations can be represented with a single `usize` that
|
||||
/// corresponds to a virtual memory address of the program counter. Combined
|
||||
|
|
@ -441,7 +556,7 @@ pub fn panicExtra(
|
|||
break :blk &buf;
|
||||
},
|
||||
};
|
||||
std.builtin.Panic.call(msg, trace, ret_addr);
|
||||
std.builtin.panic.call(msg, trace, ret_addr);
|
||||
}
|
||||
|
||||
/// Non-zero whenever the program triggered a panic.
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
//! This namespace is the default one used by the Zig compiler to emit various
|
||||
//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
|
||||
//!
|
||||
//! Since Zig does not have interfaces, this file serves as an example template
|
||||
//! for users to provide their own alternative panic handling.
|
||||
//!
|
||||
//! As an alternative, see `std.debug.SimplePanic`.
|
||||
|
||||
const std = @import("../std.zig");
|
||||
|
||||
/// Dumps a stack trace to standard error, then aborts.
|
||||
///
|
||||
/// Explicit calls to `@panic` lower to calling this function.
|
||||
pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic;
|
||||
|
||||
pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
|
||||
expected, found,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
|
||||
}
|
||||
|
||||
pub fn outOfBounds(index: usize, len: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
|
||||
}
|
||||
|
||||
pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
|
||||
}
|
||||
|
||||
pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
|
||||
@branchHint(.cold);
|
||||
std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
|
||||
@tagName(accessed), @tagName(active),
|
||||
});
|
||||
}
|
||||
|
||||
pub const messages = std.debug.SimplePanic.messages;
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
//! This namespace can be used with `pub const Panic = std.debug.NoPanic;` in the root file.
|
||||
//! It emits as little code as possible, for testing purposes.
|
||||
//!
|
||||
//! For a functional alternative, see `std.debug.FormattedPanic`.
|
||||
|
||||
const std = @import("../std.zig");
|
||||
|
||||
pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn outOfBounds(_: usize, _: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub const messages = struct {
|
||||
pub const reached_unreachable = "";
|
||||
pub const unwrap_null = "";
|
||||
pub const cast_to_null = "";
|
||||
pub const incorrect_alignment = "";
|
||||
pub const invalid_error_code = "";
|
||||
pub const cast_truncated_data = "";
|
||||
pub const negative_to_unsigned = "";
|
||||
pub const integer_overflow = "";
|
||||
pub const shl_overflow = "";
|
||||
pub const shr_overflow = "";
|
||||
pub const divide_by_zero = "";
|
||||
pub const exact_division_remainder = "";
|
||||
pub const integer_part_out_of_bounds = "";
|
||||
pub const corrupt_switch = "";
|
||||
pub const shift_rhs_too_big = "";
|
||||
pub const invalid_enum_value = "";
|
||||
pub const for_len_mismatch = "";
|
||||
pub const memcpy_len_mismatch = "";
|
||||
pub const memcpy_alias = "";
|
||||
pub const noreturn_returned = "";
|
||||
};
|
||||
160
lib/std/debug/no_panic.zig
Normal file
160
lib/std/debug/no_panic.zig
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//! This namespace can be used with `pub const panic = std.debug.no_panic;` in the root file.
|
||||
//! It emits as little code as possible, for testing purposes.
|
||||
//!
|
||||
//! For a functional alternative, see `std.debug.FullPanic`.
|
||||
|
||||
const std = @import("../std.zig");
|
||||
|
||||
pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn outOfBounds(_: usize, _: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn reachedUnreachable() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn unwrapNull() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn castToNull() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn incorrectAlignment() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn invalidErrorCode() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn castTruncatedData() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn negativeToUnsigned() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn integerOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn shlOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn shrOverflow() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn divideByZero() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn exactDivisionRemainder() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn integerPartOutOfBounds() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn corruptSwitch() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn shiftRhsTooBig() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn invalidEnumValue() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn forLenMismatch() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn memcpyLenMismatch() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn memcpyAlias() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
pub fn noreturnReturned() noreturn {
|
||||
@branchHint(.cold);
|
||||
@trap();
|
||||
}
|
||||
|
||||
/// To be deleted after zig1.wasm update.
|
||||
pub const messages = struct {
|
||||
pub const reached_unreachable = "";
|
||||
pub const unwrap_null = "";
|
||||
pub const cast_to_null = "";
|
||||
pub const incorrect_alignment = "";
|
||||
pub const invalid_error_code = "";
|
||||
pub const cast_truncated_data = "";
|
||||
pub const negative_to_unsigned = "";
|
||||
pub const integer_overflow = "";
|
||||
pub const shl_overflow = "";
|
||||
pub const shr_overflow = "";
|
||||
pub const divide_by_zero = "";
|
||||
pub const exact_division_remainder = "";
|
||||
pub const integer_part_out_of_bounds = "";
|
||||
pub const corrupt_switch = "";
|
||||
pub const shift_rhs_too_big = "";
|
||||
pub const invalid_enum_value = "";
|
||||
pub const for_len_mismatch = "";
|
||||
pub const memcpy_len_mismatch = "";
|
||||
pub const memcpy_alias = "";
|
||||
pub const noreturn_returned = "";
|
||||
};
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
//! This namespace is the default one used by the Zig compiler to emit various
|
||||
//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
|
||||
//! kinds of safety panics, due to the logic in `std.builtin.panic`.
|
||||
//!
|
||||
//! Since Zig does not have interfaces, this file serves as an example template
|
||||
//! for users to provide their own alternative panic handling.
|
||||
//!
|
||||
//! As an alternative, see `std.debug.FormattedPanic`.
|
||||
//! As an alternative, see `std.debug.FullPanic`.
|
||||
|
||||
const std = @import("../std.zig");
|
||||
|
||||
|
|
@ -49,6 +49,87 @@ pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
|
|||
call("access of inactive union field", null, null);
|
||||
}
|
||||
|
||||
pub fn reachedUnreachable() noreturn {
|
||||
call("reached unreachable code", null, null);
|
||||
}
|
||||
|
||||
pub fn unwrapNull() noreturn {
|
||||
call("attempt to use null value", null, null);
|
||||
}
|
||||
|
||||
pub fn castToNull() noreturn {
|
||||
call("cast causes pointer to be null", null, null);
|
||||
}
|
||||
|
||||
pub fn incorrectAlignment() noreturn {
|
||||
call("incorrect alignment", null, null);
|
||||
}
|
||||
|
||||
pub fn invalidErrorCode() noreturn {
|
||||
call("invalid error code", null, null);
|
||||
}
|
||||
|
||||
pub fn castTruncatedData() noreturn {
|
||||
call("integer cast truncated bits", null, null);
|
||||
}
|
||||
|
||||
pub fn negativeToUnsigned() noreturn {
|
||||
call("attempt to cast negative value to unsigned integer", null, null);
|
||||
}
|
||||
|
||||
pub fn integerOverflow() noreturn {
|
||||
call("integer overflow", null, null);
|
||||
}
|
||||
|
||||
pub fn shlOverflow() noreturn {
|
||||
call("left shift overflowed bits", null, null);
|
||||
}
|
||||
|
||||
pub fn shrOverflow() noreturn {
|
||||
call("right shift overflowed bits", null, null);
|
||||
}
|
||||
|
||||
pub fn divideByZero() noreturn {
|
||||
call("division by zero", null, null);
|
||||
}
|
||||
|
||||
pub fn exactDivisionRemainder() noreturn {
|
||||
call("exact division produced remainder", null, null);
|
||||
}
|
||||
|
||||
pub fn integerPartOutOfBounds() noreturn {
|
||||
call("integer part of floating point value out of bounds", null, null);
|
||||
}
|
||||
|
||||
pub fn corruptSwitch() noreturn {
|
||||
call("switch on corrupt value", null, null);
|
||||
}
|
||||
|
||||
pub fn shiftRhsTooBig() noreturn {
|
||||
call("shift amount is greater than the type size", null, null);
|
||||
}
|
||||
|
||||
pub fn invalidEnumValue() noreturn {
|
||||
call("invalid enum value", null, null);
|
||||
}
|
||||
|
||||
pub fn forLenMismatch() noreturn {
|
||||
call("for loop over objects with non-equal lengths", null, null);
|
||||
}
|
||||
|
||||
pub fn memcpyLenMismatch() noreturn {
|
||||
call("@memcpy arguments have non-equal lengths", null, null);
|
||||
}
|
||||
|
||||
pub fn memcpyAlias() noreturn {
|
||||
call("@memcpy arguments alias", null, null);
|
||||
}
|
||||
|
||||
pub fn noreturnReturned() noreturn {
|
||||
call("'noreturn' function returned", null, null);
|
||||
}
|
||||
|
||||
/// To be deleted after zig1.wasm update.
|
||||
pub const messages = struct {
|
||||
pub const reached_unreachable = "reached unreachable code";
|
||||
pub const unwrap_null = "attempt to use null value";
|
||||
|
|
@ -70,17 +151,4 @@ pub const messages = struct {
|
|||
pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
|
||||
pub const memcpy_alias = "@memcpy arguments alias";
|
||||
pub const noreturn_returned = "'noreturn' function returned";
|
||||
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const inactive_union_field = "access of inactive union field";
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const sentinel_mismatch = "sentinel mismatch";
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const unwrap_error = "attempt to unwrap error";
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const index_out_of_bounds = "index out of bounds";
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const start_index_greater_than_end = "start index is larger than end index";
|
||||
/// To be deleted after zig1.wasm is updated.
|
||||
pub const unreach = reached_unreachable;
|
||||
};
|
||||
|
|
@ -448,8 +448,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
|
|||
return comptime blk: {
|
||||
const fieldInfos = fields(T);
|
||||
var names: [fieldInfos.len][:0]const u8 = undefined;
|
||||
// This concat can be removed with the next zig1 update.
|
||||
for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
|
||||
for (&names, fieldInfos) |*name, field| name.* = field.name;
|
||||
const final = names;
|
||||
break :blk &final;
|
||||
};
|
||||
|
|
|
|||
155
src/Sema.zig
155
src/Sema.zig
|
|
@ -5918,13 +5918,14 @@ fn zirCompileLog(
|
|||
}
|
||||
|
||||
fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
const msg_inst = try sema.resolveInst(inst_data.operand);
|
||||
|
||||
// `panicWithMsg` would perform this coercion for us, but we can get a better
|
||||
// source location if we do it here.
|
||||
const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
|
||||
const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
|
||||
|
||||
if (block.isComptime()) {
|
||||
return sema.fail(block, src, "encountered @panic at comptime", .{});
|
||||
|
|
@ -5936,7 +5937,23 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
|
|||
sema.branch_hint = .cold;
|
||||
}
|
||||
|
||||
try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");
|
||||
if (!zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try block.addNoOp(.trap);
|
||||
return;
|
||||
}
|
||||
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call"));
|
||||
|
||||
const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call"));
|
||||
const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
|
||||
|
||||
const opt_usize_ty = try pt.optionalType(.usize_type);
|
||||
const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
|
||||
.ty = opt_usize_ty.toIntern(),
|
||||
.val = .none,
|
||||
} })));
|
||||
try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_stack_trace, null_ret_addr }, .@"@panic");
|
||||
}
|
||||
|
||||
fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
|
|
@ -13787,7 +13804,7 @@ fn maybeErrorUnwrap(
|
|||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const msg_inst = try sema.resolveInst(inst_data.operand);
|
||||
|
||||
const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call");
|
||||
const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call");
|
||||
const err_return_trace = try sema.getErrorReturnTrace(block);
|
||||
const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
|
||||
try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
|
||||
|
|
@ -27083,15 +27100,16 @@ fn explainWhyTypeIsNotPacked(
|
|||
/// Backends depend on panic decls being available when lowering safety-checked
|
||||
/// instructions. This function ensures the panic function will be available to
|
||||
/// be called during that time.
|
||||
fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index {
|
||||
fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index {
|
||||
const zcu = sema.pt.zcu;
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
|
||||
const panic_func = zcu.builtin_decl_values.get(panic_id.toBuiltin());
|
||||
try zcu.ensureFuncBodyAnalysisQueued(panic_func);
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
|
||||
.func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true),
|
||||
}
|
||||
return zcu.builtin_decl_values.get(panic_id.toBuiltin());
|
||||
return panic_func;
|
||||
}
|
||||
|
||||
fn addSafetyCheck(
|
||||
|
|
@ -27099,7 +27117,7 @@ fn addSafetyCheck(
|
|||
parent_block: *Block,
|
||||
src: LazySrcLoc,
|
||||
ok: Air.Inst.Ref,
|
||||
panic_id: Zcu.PanicId,
|
||||
panic_id: Zcu.SimplePanicId,
|
||||
) !void {
|
||||
const gpa = sema.gpa;
|
||||
assert(!parent_block.isComptime());
|
||||
|
|
@ -27186,29 +27204,6 @@ fn addSafetyCheckExtra(
|
|||
parent_block.instructions.appendAssumeCapacity(block_inst);
|
||||
}
|
||||
|
||||
fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
|
||||
if (!zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try block.addNoOp(.trap);
|
||||
return;
|
||||
}
|
||||
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
|
||||
|
||||
const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"Panic.call"));
|
||||
const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
|
||||
|
||||
const opt_usize_ty = try pt.optionalType(.usize_type);
|
||||
const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
|
||||
.ty = opt_usize_ty.toIntern(),
|
||||
.val = .none,
|
||||
} })));
|
||||
try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation);
|
||||
}
|
||||
|
||||
fn addSafetyCheckUnwrapError(
|
||||
sema: *Sema,
|
||||
parent_block: *Block,
|
||||
|
|
@ -27246,7 +27241,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.
|
|||
if (!zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try block.addNoOp(.trap);
|
||||
} else {
|
||||
const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError");
|
||||
const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError");
|
||||
const err_return_trace = try sema.getErrorReturnTrace(block);
|
||||
const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
|
||||
try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
|
||||
|
|
@ -27263,7 +27258,7 @@ fn addSafetyCheckIndexOob(
|
|||
) !void {
|
||||
assert(!parent_block.isComptime());
|
||||
const ok = try parent_block.addBinOp(cmp_op, index, len);
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len });
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.outOfBounds", &.{ index, len });
|
||||
}
|
||||
|
||||
fn addSafetyCheckInactiveUnionField(
|
||||
|
|
@ -27275,7 +27270,7 @@ fn addSafetyCheckInactiveUnionField(
|
|||
) !void {
|
||||
assert(!parent_block.isComptime());
|
||||
const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.inactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
}
|
||||
|
||||
fn addSafetyCheckSentinelMismatch(
|
||||
|
|
@ -27316,7 +27311,7 @@ fn addSafetyCheckSentinelMismatch(
|
|||
break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
|
||||
};
|
||||
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{
|
||||
expected_sentinel, actual_sentinel,
|
||||
});
|
||||
}
|
||||
|
|
@ -27358,9 +27353,13 @@ fn addSafetyCheckCall(
|
|||
}
|
||||
|
||||
/// This does not set `sema.branch_hint`.
|
||||
fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void {
|
||||
const msg_val = try sema.preparePanicId(src, panic_id);
|
||||
try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check");
|
||||
fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void {
|
||||
if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try block.addNoOp(.trap);
|
||||
} else {
|
||||
const panic_fn = try sema.preparePanicId(src, panic_id);
|
||||
try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{}, .@"safety check");
|
||||
}
|
||||
}
|
||||
|
||||
fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
|
|
@ -32818,7 +32817,7 @@ fn analyzeSlice(
|
|||
assert(!block.isComptime());
|
||||
try sema.requireRuntimeBlock(block, src, runtime_src.?);
|
||||
const ok = try block.addBinOp(.cmp_lte, start, end);
|
||||
try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end });
|
||||
try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end });
|
||||
}
|
||||
const new_len = if (by_length)
|
||||
try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
|
||||
|
|
@ -38525,14 +38524,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
|
|||
break :val uncoerced_val;
|
||||
},
|
||||
.func => val: {
|
||||
if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| {
|
||||
const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
|
||||
break :val .fromInterned(coerced.toInterned().?);
|
||||
}
|
||||
if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
|
||||
return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name });
|
||||
}
|
||||
break :val uncoerced_val;
|
||||
const func_ty = try sema.getExpectedBuiltinFnType(src, builtin_decl);
|
||||
const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
|
||||
break :val .fromInterned(coerced.toInterned().?);
|
||||
},
|
||||
.string => val: {
|
||||
const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src);
|
||||
|
|
@ -38567,16 +38561,19 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
|
|||
return any_changed;
|
||||
}
|
||||
|
||||
/// Given that `decl.kind() == .func`, get the type expected of the function if necessary.
|
||||
/// If this will be type checked by `Sema` anyway, this function may return `null`. In
|
||||
/// particular, generic functions should return `null`, as `Sema` will necessarily check
|
||||
/// them at instantiation time. Returning non-null is necessary only when backends can emit
|
||||
/// calls to the function, as is the case with the panic handler.
|
||||
fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type {
|
||||
/// Given that `decl.kind() == .func`, get the type expected of the function.
|
||||
fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!Type {
|
||||
const pt = sema.pt;
|
||||
return switch (decl) {
|
||||
// `noinline fn () void`
|
||||
.returnError => try pt.funcType(.{
|
||||
.param_types = &.{},
|
||||
.return_type = .void_type,
|
||||
.is_noinline = true,
|
||||
}),
|
||||
|
||||
// `fn ([]const u8, ?*StackTrace, ?usize) noreturn`
|
||||
.@"Panic.call" => try pt.funcType(.{
|
||||
.@"panic.call" => try pt.funcType(.{
|
||||
.param_types = &.{
|
||||
.slice_const_u8_type,
|
||||
(try pt.optionalType(
|
||||
|
|
@ -38589,8 +38586,17 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl)
|
|||
.return_type = .noreturn_type,
|
||||
}),
|
||||
|
||||
// `fn (anytype, anytype) noreturn`
|
||||
.@"panic.sentinelMismatch",
|
||||
.@"panic.inactiveUnionField",
|
||||
=> try pt.funcType(.{
|
||||
.param_types = &.{ .generic_poison_type, .generic_poison_type },
|
||||
.return_type = .noreturn_type,
|
||||
.is_generic = true,
|
||||
}),
|
||||
|
||||
// `fn (?*StackTrace, anyerror) noreturn`
|
||||
.@"Panic.unwrapError" => try pt.funcType(.{
|
||||
.@"panic.unwrapError" => try pt.funcType(.{
|
||||
.param_types = &.{
|
||||
(try pt.optionalType(
|
||||
(try pt.singleMutPtrType(
|
||||
|
|
@ -38603,21 +38609,38 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl)
|
|||
}),
|
||||
|
||||
// `fn (usize, usize) noreturn`
|
||||
.@"Panic.outOfBounds",
|
||||
.@"Panic.startGreaterThanEnd",
|
||||
.@"panic.outOfBounds",
|
||||
.@"panic.startGreaterThanEnd",
|
||||
=> try pt.funcType(.{
|
||||
.param_types = &.{ .usize_type, .usize_type },
|
||||
.return_type = .noreturn_type,
|
||||
}),
|
||||
|
||||
// Generic functions, so calls are necessarily validated by Sema
|
||||
.@"Panic.sentinelMismatch",
|
||||
.@"Panic.inactiveUnionField",
|
||||
=> null,
|
||||
|
||||
// Other functions called exclusively by Sema
|
||||
.returnError,
|
||||
=> null,
|
||||
// `fn () noreturn`
|
||||
.@"panic.reachedUnreachable",
|
||||
.@"panic.unwrapNull",
|
||||
.@"panic.castToNull",
|
||||
.@"panic.incorrectAlignment",
|
||||
.@"panic.invalidErrorCode",
|
||||
.@"panic.castTruncatedData",
|
||||
.@"panic.negativeToUnsigned",
|
||||
.@"panic.integerOverflow",
|
||||
.@"panic.shlOverflow",
|
||||
.@"panic.shrOverflow",
|
||||
.@"panic.divideByZero",
|
||||
.@"panic.exactDivisionRemainder",
|
||||
.@"panic.integerPartOutOfBounds",
|
||||
.@"panic.corruptSwitch",
|
||||
.@"panic.shiftRhsTooBig",
|
||||
.@"panic.invalidEnumValue",
|
||||
.@"panic.forLenMismatch",
|
||||
.@"panic.memcpyLenMismatch",
|
||||
.@"panic.memcpyAlias",
|
||||
.@"panic.noreturnReturned",
|
||||
=> try pt.funcType(.{
|
||||
.param_types = &.{},
|
||||
.return_type = .noreturn_type,
|
||||
}),
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
|
|||
153
src/Zcu.zig
153
src/Zcu.zig
|
|
@ -269,34 +269,33 @@ pub const BuiltinDecl = enum {
|
|||
@"Type.Opaque",
|
||||
@"Type.Declaration",
|
||||
|
||||
Panic,
|
||||
@"Panic.call",
|
||||
@"Panic.sentinelMismatch",
|
||||
@"Panic.unwrapError",
|
||||
@"Panic.outOfBounds",
|
||||
@"Panic.startGreaterThanEnd",
|
||||
@"Panic.inactiveUnionField",
|
||||
@"Panic.messages",
|
||||
@"Panic.messages.reached_unreachable",
|
||||
@"Panic.messages.unwrap_null",
|
||||
@"Panic.messages.cast_to_null",
|
||||
@"Panic.messages.incorrect_alignment",
|
||||
@"Panic.messages.invalid_error_code",
|
||||
@"Panic.messages.cast_truncated_data",
|
||||
@"Panic.messages.negative_to_unsigned",
|
||||
@"Panic.messages.integer_overflow",
|
||||
@"Panic.messages.shl_overflow",
|
||||
@"Panic.messages.shr_overflow",
|
||||
@"Panic.messages.divide_by_zero",
|
||||
@"Panic.messages.exact_division_remainder",
|
||||
@"Panic.messages.integer_part_out_of_bounds",
|
||||
@"Panic.messages.corrupt_switch",
|
||||
@"Panic.messages.shift_rhs_too_big",
|
||||
@"Panic.messages.invalid_enum_value",
|
||||
@"Panic.messages.for_len_mismatch",
|
||||
@"Panic.messages.memcpy_len_mismatch",
|
||||
@"Panic.messages.memcpy_alias",
|
||||
@"Panic.messages.noreturn_returned",
|
||||
panic,
|
||||
@"panic.call",
|
||||
@"panic.sentinelMismatch",
|
||||
@"panic.unwrapError",
|
||||
@"panic.outOfBounds",
|
||||
@"panic.startGreaterThanEnd",
|
||||
@"panic.inactiveUnionField",
|
||||
@"panic.reachedUnreachable",
|
||||
@"panic.unwrapNull",
|
||||
@"panic.castToNull",
|
||||
@"panic.incorrectAlignment",
|
||||
@"panic.invalidErrorCode",
|
||||
@"panic.castTruncatedData",
|
||||
@"panic.negativeToUnsigned",
|
||||
@"panic.integerOverflow",
|
||||
@"panic.shlOverflow",
|
||||
@"panic.shrOverflow",
|
||||
@"panic.divideByZero",
|
||||
@"panic.exactDivisionRemainder",
|
||||
@"panic.integerPartOutOfBounds",
|
||||
@"panic.corruptSwitch",
|
||||
@"panic.shiftRhsTooBig",
|
||||
@"panic.invalidEnumValue",
|
||||
@"panic.forLenMismatch",
|
||||
@"panic.memcpyLenMismatch",
|
||||
@"panic.memcpyAlias",
|
||||
@"panic.noreturnReturned",
|
||||
|
||||
VaList,
|
||||
|
||||
|
|
@ -345,39 +344,35 @@ pub const BuiltinDecl = enum {
|
|||
.@"Type.Declaration",
|
||||
=> .type,
|
||||
|
||||
.Panic => .type,
|
||||
.panic => .type,
|
||||
|
||||
.@"Panic.call",
|
||||
.@"Panic.sentinelMismatch",
|
||||
.@"Panic.unwrapError",
|
||||
.@"Panic.outOfBounds",
|
||||
.@"Panic.startGreaterThanEnd",
|
||||
.@"Panic.inactiveUnionField",
|
||||
.@"panic.call",
|
||||
.@"panic.sentinelMismatch",
|
||||
.@"panic.unwrapError",
|
||||
.@"panic.outOfBounds",
|
||||
.@"panic.startGreaterThanEnd",
|
||||
.@"panic.inactiveUnionField",
|
||||
.@"panic.reachedUnreachable",
|
||||
.@"panic.unwrapNull",
|
||||
.@"panic.castToNull",
|
||||
.@"panic.incorrectAlignment",
|
||||
.@"panic.invalidErrorCode",
|
||||
.@"panic.castTruncatedData",
|
||||
.@"panic.negativeToUnsigned",
|
||||
.@"panic.integerOverflow",
|
||||
.@"panic.shlOverflow",
|
||||
.@"panic.shrOverflow",
|
||||
.@"panic.divideByZero",
|
||||
.@"panic.exactDivisionRemainder",
|
||||
.@"panic.integerPartOutOfBounds",
|
||||
.@"panic.corruptSwitch",
|
||||
.@"panic.shiftRhsTooBig",
|
||||
.@"panic.invalidEnumValue",
|
||||
.@"panic.forLenMismatch",
|
||||
.@"panic.memcpyLenMismatch",
|
||||
.@"panic.memcpyAlias",
|
||||
.@"panic.noreturnReturned",
|
||||
=> .func,
|
||||
|
||||
.@"Panic.messages" => .type,
|
||||
|
||||
.@"Panic.messages.reached_unreachable",
|
||||
.@"Panic.messages.unwrap_null",
|
||||
.@"Panic.messages.cast_to_null",
|
||||
.@"Panic.messages.incorrect_alignment",
|
||||
.@"Panic.messages.invalid_error_code",
|
||||
.@"Panic.messages.cast_truncated_data",
|
||||
.@"Panic.messages.negative_to_unsigned",
|
||||
.@"Panic.messages.integer_overflow",
|
||||
.@"Panic.messages.shl_overflow",
|
||||
.@"Panic.messages.shr_overflow",
|
||||
.@"Panic.messages.divide_by_zero",
|
||||
.@"Panic.messages.exact_division_remainder",
|
||||
.@"Panic.messages.integer_part_out_of_bounds",
|
||||
.@"Panic.messages.corrupt_switch",
|
||||
.@"Panic.messages.shift_rhs_too_big",
|
||||
.@"Panic.messages.invalid_enum_value",
|
||||
.@"Panic.messages.for_len_mismatch",
|
||||
.@"Panic.messages.memcpy_len_mismatch",
|
||||
.@"Panic.messages.memcpy_alias",
|
||||
.@"Panic.messages.noreturn_returned",
|
||||
=> .string,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +418,7 @@ pub const BuiltinDecl = enum {
|
|||
const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index);
|
||||
};
|
||||
|
||||
pub const PanicId = enum {
|
||||
pub const SimplePanicId = enum {
|
||||
reached_unreachable,
|
||||
unwrap_null,
|
||||
cast_to_null,
|
||||
|
|
@ -445,19 +440,31 @@ pub const PanicId = enum {
|
|||
memcpy_alias,
|
||||
noreturn_returned,
|
||||
|
||||
pub fn toBuiltin(id: PanicId) BuiltinDecl {
|
||||
const first_msg: PanicId = @enumFromInt(0);
|
||||
const first_decl = @field(BuiltinDecl, "Panic.messages." ++ @tagName(first_msg));
|
||||
comptime {
|
||||
// Ensure that the messages are ordered the same in `BuiltinDecl` as they are here.
|
||||
for (@typeInfo(PanicId).@"enum".fields) |panic_field| {
|
||||
const expect_name = "Panic.messages." ++ panic_field.name;
|
||||
const expect_idx = @intFromEnum(first_decl) + panic_field.value;
|
||||
const actual_idx = @intFromEnum(@field(BuiltinDecl, expect_name));
|
||||
assert(expect_idx == actual_idx);
|
||||
}
|
||||
}
|
||||
return @enumFromInt(@intFromEnum(first_decl) + @intFromEnum(id));
|
||||
pub fn toBuiltin(id: SimplePanicId) BuiltinDecl {
|
||||
return switch (id) {
|
||||
// zig fmt: off
|
||||
.reached_unreachable => .@"panic.reachedUnreachable",
|
||||
.unwrap_null => .@"panic.unwrapNull",
|
||||
.cast_to_null => .@"panic.castToNull",
|
||||
.incorrect_alignment => .@"panic.incorrectAlignment",
|
||||
.invalid_error_code => .@"panic.invalidErrorCode",
|
||||
.cast_truncated_data => .@"panic.castTruncatedData",
|
||||
.negative_to_unsigned => .@"panic.negativeToUnsigned",
|
||||
.integer_overflow => .@"panic.integerOverflow",
|
||||
.shl_overflow => .@"panic.shlOverflow",
|
||||
.shr_overflow => .@"panic.shrOverflow",
|
||||
.divide_by_zero => .@"panic.divideByZero",
|
||||
.exact_division_remainder => .@"panic.exactDivisionRemainder",
|
||||
.integer_part_out_of_bounds => .@"panic.integerPartOutOfBounds",
|
||||
.corrupt_switch => .@"panic.corruptSwitch",
|
||||
.shift_rhs_too_big => .@"panic.shiftRhsTooBig",
|
||||
.invalid_enum_value => .@"panic.invalidEnumValue",
|
||||
.for_len_mismatch => .@"panic.forLenMismatch",
|
||||
.memcpy_len_mismatch => .@"panic.memcpyLenMismatch",
|
||||
.memcpy_alias => .@"panic.memcpyAlias",
|
||||
.noreturn_returned => .@"panic.noreturnReturned",
|
||||
// zig fmt: on
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
|
|||
// We use an arbitrary element to check if the state has been resolved yet.
|
||||
const to_check: Zcu.BuiltinDecl = switch (stage) {
|
||||
.main => .Type,
|
||||
.panic => .Panic,
|
||||
.panic => .panic,
|
||||
.va_list => .VaList,
|
||||
};
|
||||
if (zcu.builtin_decl_values.get(to_check) != .none) return;
|
||||
|
|
|
|||
|
|
@ -5019,18 +5019,6 @@ pub const FuncGen = struct {
|
|||
);
|
||||
}
|
||||
|
||||
fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant {
|
||||
const o = self.ng.object;
|
||||
const pt = o.pt;
|
||||
if (o.null_opt_usize == .no_init) {
|
||||
o.null_opt_usize = try self.resolveValue(Value.fromInterned(try pt.intern(.{ .opt = .{
|
||||
.ty = try pt.intern(.{ .opt_type = .usize_type }),
|
||||
.val = .none,
|
||||
} })));
|
||||
}
|
||||
return o.null_opt_usize;
|
||||
}
|
||||
|
||||
fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void {
|
||||
const o = self.ng.object;
|
||||
const zcu = o.pt.zcu;
|
||||
|
|
@ -5732,30 +5720,14 @@ pub const FuncGen = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void {
|
||||
fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void {
|
||||
const o = fg.ng.object;
|
||||
const zcu = o.pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const msg_len: u64, const msg_ptr: Builder.Constant = msg: {
|
||||
const str_val = zcu.builtin_decl_values.get(panic_id.toBuiltin());
|
||||
assert(str_val != .none);
|
||||
const slice = ip.indexToKey(str_val).slice;
|
||||
break :msg .{ Value.fromInterned(slice.len).toUnsignedInt(zcu), try o.lowerValue(slice.ptr) };
|
||||
};
|
||||
const null_opt_addr_global = try fg.resolveNullOptUsize();
|
||||
const target = zcu.getTarget();
|
||||
const llvm_usize = try o.lowerType(Type.usize);
|
||||
// example:
|
||||
// call fastcc void @test2.panic(
|
||||
// ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
|
||||
// i64 16, ; msg.len
|
||||
// ptr null, ; stack trace
|
||||
// ptr @2, ; addr (null ?usize)
|
||||
// )
|
||||
const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(.@"Panic.call"));
|
||||
const panic_nav = ip.getNav(panic_func.owner_nav);
|
||||
const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
|
||||
const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin()));
|
||||
const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
|
||||
const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
|
||||
|
||||
const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto;
|
||||
if (has_err_trace) assert(fg.err_ret_trace != .none);
|
||||
_ = try fg.wip.callIntrinsicAssumeCold();
|
||||
|
|
@ -5765,18 +5737,7 @@ pub const FuncGen = struct {
|
|||
.none,
|
||||
panic_global.typeOf(&o.builder),
|
||||
panic_global.toValue(&o.builder),
|
||||
if (has_err_trace) &.{
|
||||
fg.err_ret_trace,
|
||||
msg_ptr.toValue(),
|
||||
try o.builder.intValue(llvm_usize, msg_len),
|
||||
try o.builder.nullValue(.ptr),
|
||||
null_opt_addr_global.toValue(),
|
||||
} else &.{
|
||||
msg_ptr.toValue(),
|
||||
try o.builder.intValue(llvm_usize, msg_len),
|
||||
try o.builder.nullValue(.ptr),
|
||||
null_opt_addr_global.toValue(),
|
||||
},
|
||||
if (has_err_trace) &.{fg.err_ret_trace} else &.{},
|
||||
"",
|
||||
);
|
||||
_ = try fg.wip.@"unreachable"();
|
||||
|
|
|
|||
|
|
@ -18,18 +18,12 @@ const dev = @import("dev.zig");
|
|||
/// To use these crash report diagnostics, publish this panic in your main file
|
||||
/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
|
||||
/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
|
||||
pub const Panic = if (build_options.enable_debug_extensions) struct {
|
||||
pub const call = compilerPanic;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
} else if (dev.env == .bootstrap)
|
||||
std.debug.SimplePanic
|
||||
pub const panic = if (build_options.enable_debug_extensions)
|
||||
std.debug.FullPanic(compilerPanic)
|
||||
else if (dev.env == .bootstrap)
|
||||
std.debug.simple_panic
|
||||
else
|
||||
std.debug.FormattedPanic;
|
||||
std.debug.FullPanic(std.debug.defaultPanic);
|
||||
|
||||
/// Install signal handlers to identify crashes and report diagnostics.
|
||||
pub fn initialize() void {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ pub const std_options: std.Options = .{
|
|||
},
|
||||
};
|
||||
|
||||
pub const Panic = crash_report.Panic;
|
||||
pub const panic = crash_report.panic;
|
||||
|
||||
var wasi_preopens: fs.wasi.Preopens = undefined;
|
||||
pub fn wasi_cwd() std.os.wasi.fd_t {
|
||||
|
|
|
|||
46
test/cases/compile_errors/bad_panic_call_signature.zig
Normal file
46
test/cases/compile_errors/bad_panic_call_signature.zig
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
const simple_panic = std.debug.simple_panic;
|
||||
pub const panic = struct {
|
||||
pub fn call(msg: []const u8, bad1: usize, bad2: void) noreturn {
|
||||
_ = msg;
|
||||
_ = bad1;
|
||||
_ = bad2;
|
||||
@trap();
|
||||
}
|
||||
pub const sentinelMismatch = simple_panic.sentinelMismatch;
|
||||
pub const unwrapError = simple_panic.unwrapError;
|
||||
pub const outOfBounds = simple_panic.outOfBounds;
|
||||
pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = simple_panic.inactiveUnionField;
|
||||
pub const reachedUnreachable = simple_panic.reachedUnreachable;
|
||||
pub const unwrapNull = simple_panic.unwrapNull;
|
||||
pub const castToNull = simple_panic.castToNull;
|
||||
pub const incorrectAlignment = simple_panic.incorrectAlignment;
|
||||
pub const invalidErrorCode = simple_panic.invalidErrorCode;
|
||||
pub const castTruncatedData = simple_panic.castTruncatedData;
|
||||
pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
|
||||
pub const integerOverflow = simple_panic.integerOverflow;
|
||||
pub const shlOverflow = simple_panic.shlOverflow;
|
||||
pub const shrOverflow = simple_panic.shrOverflow;
|
||||
pub const divideByZero = simple_panic.divideByZero;
|
||||
pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
|
||||
pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
|
||||
pub const corruptSwitch = simple_panic.corruptSwitch;
|
||||
pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
|
||||
pub const invalidEnumValue = simple_panic.invalidEnumValue;
|
||||
pub const forLenMismatch = simple_panic.forLenMismatch;
|
||||
pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
|
||||
pub const memcpyAlias = simple_panic.memcpyAlias;
|
||||
pub const noreturnReturned = simple_panic.noreturnReturned;
|
||||
};
|
||||
|
||||
export fn foo(a: u8) void {
|
||||
@setRuntimeSafety(true);
|
||||
_ = a + 1; // safety check to reference the panic handler
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
// error
|
||||
//
|
||||
// :3:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn'
|
||||
// :3:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace'
|
||||
41
test/cases/compile_errors/bad_panic_generic_signature.zig
Normal file
41
test/cases/compile_errors/bad_panic_generic_signature.zig
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
const simple_panic = std.debug.simple_panic;
|
||||
pub const panic = struct {
|
||||
pub fn sentinelMismatch() void {} // invalid
|
||||
pub const call = simple_panic.call;
|
||||
pub const unwrapError = simple_panic.unwrapError;
|
||||
pub const outOfBounds = simple_panic.outOfBounds;
|
||||
pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = simple_panic.inactiveUnionField;
|
||||
pub const reachedUnreachable = simple_panic.reachedUnreachable;
|
||||
pub const unwrapNull = simple_panic.unwrapNull;
|
||||
pub const castToNull = simple_panic.castToNull;
|
||||
pub const incorrectAlignment = simple_panic.incorrectAlignment;
|
||||
pub const invalidErrorCode = simple_panic.invalidErrorCode;
|
||||
pub const castTruncatedData = simple_panic.castTruncatedData;
|
||||
pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
|
||||
pub const integerOverflow = simple_panic.integerOverflow;
|
||||
pub const shlOverflow = simple_panic.shlOverflow;
|
||||
pub const shrOverflow = simple_panic.shrOverflow;
|
||||
pub const divideByZero = simple_panic.divideByZero;
|
||||
pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
|
||||
pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
|
||||
pub const corruptSwitch = simple_panic.corruptSwitch;
|
||||
pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
|
||||
pub const invalidEnumValue = simple_panic.invalidEnumValue;
|
||||
pub const forLenMismatch = simple_panic.forLenMismatch;
|
||||
pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
|
||||
pub const memcpyAlias = simple_panic.memcpyAlias;
|
||||
pub const noreturnReturned = simple_panic.noreturnReturned;
|
||||
};
|
||||
|
||||
export fn foo(arr: *const [2]u8) void {
|
||||
@setRuntimeSafety(true);
|
||||
_ = arr[0..1 :0];
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
// error
|
||||
//
|
||||
// :3:9: error: expected type 'fn (anytype, anytype) noreturn', found 'fn () void'
|
||||
// :3:9: note: non-generic function cannot cast into a generic function
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
pub const Panic = struct {
|
||||
pub const call = badPanicSignature;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
};
|
||||
|
||||
fn badPanicSignature(msg: []const u8, bad1: usize, bad2: void) noreturn {
|
||||
_ = msg;
|
||||
_ = bad1;
|
||||
_ = bad2;
|
||||
@trap();
|
||||
}
|
||||
|
||||
export fn foo(a: u8) void {
|
||||
@setRuntimeSafety(true);
|
||||
_ = a + 1; // safety check to reference the panic handler
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
// error
|
||||
//
|
||||
// :2:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn'
|
||||
// :2:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace'
|
||||
|
|
@ -9,15 +9,7 @@ pub fn main() !u8 {
|
|||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
pub const Panic = struct {
|
||||
pub const call = myPanic;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
};
|
||||
pub const panic = std.debug.FullPanic(myPanic);
|
||||
fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
|
|
@ -33,15 +25,7 @@ pub fn main() !u8 {
|
|||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
pub const Panic = struct {
|
||||
pub const call = myPanic;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
};
|
||||
pub const panic = std.debug.FullPanic(myPanic);
|
||||
fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
|
|
@ -57,15 +41,7 @@ pub fn main() !u8 {
|
|||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
pub const Panic = struct {
|
||||
pub const call = myPanicNew;
|
||||
pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.FormattedPanic.unwrapError;
|
||||
pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
|
||||
pub const messages = std.debug.FormattedPanic.messages;
|
||||
};
|
||||
pub const panic = std.debug.FullPanic(myPanicNew);
|
||||
fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
|
|
|
|||
141
test/incremental/change_panic_handler_explicit
Normal file
141
test/incremental/change_panic_handler_explicit
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#target=x86_64-linux-selfhosted
|
||||
#target=x86_64-linux-cbe
|
||||
#target=x86_64-windows-cbe
|
||||
#update=initial version
|
||||
#file=main.zig
|
||||
pub fn main() !u8 {
|
||||
var a: u8 = undefined;
|
||||
a = 255;
|
||||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
const no_panic = std.debug.no_panic;
|
||||
pub const panic = struct {
|
||||
pub const call = myPanic;
|
||||
pub fn integerOverflow() noreturn {
|
||||
@panic("integer overflow");
|
||||
}
|
||||
pub const sentinelMismatch = no_panic.sentinelMismatch;
|
||||
pub const unwrapError = no_panic.unwrapError;
|
||||
pub const outOfBounds = no_panic.outOfBounds;
|
||||
pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = no_panic.inactiveUnionField;
|
||||
pub const reachedUnreachable = no_panic.reachedUnreachable;
|
||||
pub const unwrapNull = no_panic.unwrapNull;
|
||||
pub const castToNull = no_panic.castToNull;
|
||||
pub const incorrectAlignment = no_panic.incorrectAlignment;
|
||||
pub const invalidErrorCode = no_panic.invalidErrorCode;
|
||||
pub const castTruncatedData = no_panic.castTruncatedData;
|
||||
pub const negativeToUnsigned = no_panic.negativeToUnsigned;
|
||||
pub const shlOverflow = no_panic.shlOverflow;
|
||||
pub const shrOverflow = no_panic.shrOverflow;
|
||||
pub const divideByZero = no_panic.divideByZero;
|
||||
pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
|
||||
pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
|
||||
pub const corruptSwitch = no_panic.corruptSwitch;
|
||||
pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
|
||||
pub const invalidEnumValue = no_panic.invalidEnumValue;
|
||||
pub const forLenMismatch = no_panic.forLenMismatch;
|
||||
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
|
||||
pub const memcpyAlias = no_panic.memcpyAlias;
|
||||
pub const noreturnReturned = no_panic.noreturnReturned;
|
||||
};
|
||||
fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
}
|
||||
const std = @import("std");
|
||||
#expect_stdout="panic message: integer overflow\n"
|
||||
|
||||
#update=change the panic handler body
|
||||
#file=main.zig
|
||||
pub fn main() !u8 {
|
||||
var a: u8 = undefined;
|
||||
a = 255;
|
||||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
const no_panic = std.debug.no_panic;
|
||||
pub const panic = struct {
|
||||
pub const call = myPanic;
|
||||
pub fn integerOverflow() noreturn {
|
||||
@panic("integer overflow");
|
||||
}
|
||||
pub const sentinelMismatch = no_panic.sentinelMismatch;
|
||||
pub const unwrapError = no_panic.unwrapError;
|
||||
pub const outOfBounds = no_panic.outOfBounds;
|
||||
pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = no_panic.inactiveUnionField;
|
||||
pub const reachedUnreachable = no_panic.reachedUnreachable;
|
||||
pub const unwrapNull = no_panic.unwrapNull;
|
||||
pub const castToNull = no_panic.castToNull;
|
||||
pub const incorrectAlignment = no_panic.incorrectAlignment;
|
||||
pub const invalidErrorCode = no_panic.invalidErrorCode;
|
||||
pub const castTruncatedData = no_panic.castTruncatedData;
|
||||
pub const negativeToUnsigned = no_panic.negativeToUnsigned;
|
||||
pub const shlOverflow = no_panic.shlOverflow;
|
||||
pub const shrOverflow = no_panic.shrOverflow;
|
||||
pub const divideByZero = no_panic.divideByZero;
|
||||
pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
|
||||
pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
|
||||
pub const corruptSwitch = no_panic.corruptSwitch;
|
||||
pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
|
||||
pub const invalidEnumValue = no_panic.invalidEnumValue;
|
||||
pub const forLenMismatch = no_panic.forLenMismatch;
|
||||
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
|
||||
pub const memcpyAlias = no_panic.memcpyAlias;
|
||||
pub const noreturnReturned = no_panic.noreturnReturned;
|
||||
};
|
||||
fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
}
|
||||
const std = @import("std");
|
||||
#expect_stdout="new panic message: integer overflow\n"
|
||||
|
||||
#update=change the panic handler function value
|
||||
#file=main.zig
|
||||
pub fn main() !u8 {
|
||||
var a: u8 = undefined;
|
||||
a = 255;
|
||||
_ = a + 1;
|
||||
return 1;
|
||||
}
|
||||
const no_panic = std.debug.no_panic;
|
||||
pub const panic = struct {
|
||||
pub const call = myPanicNew;
|
||||
pub fn integerOverflow() noreturn {
|
||||
@panic("integer overflow");
|
||||
}
|
||||
pub const sentinelMismatch = std.debug.no_panic.sentinelMismatch;
|
||||
pub const unwrapError = std.debug.no_panic.unwrapError;
|
||||
pub const outOfBounds = std.debug.no_panic.outOfBounds;
|
||||
pub const startGreaterThanEnd = std.debug.no_panic.startGreaterThanEnd;
|
||||
pub const inactiveUnionField = std.debug.no_panic.inactiveUnionField;
|
||||
pub const messages = std.debug.no_panic.messages;
|
||||
pub const reachedUnreachable = no_panic.reachedUnreachable;
|
||||
pub const unwrapNull = no_panic.unwrapNull;
|
||||
pub const castToNull = no_panic.castToNull;
|
||||
pub const incorrectAlignment = no_panic.incorrectAlignment;
|
||||
pub const invalidErrorCode = no_panic.invalidErrorCode;
|
||||
pub const castTruncatedData = no_panic.castTruncatedData;
|
||||
pub const negativeToUnsigned = no_panic.negativeToUnsigned;
|
||||
pub const shlOverflow = no_panic.shlOverflow;
|
||||
pub const shrOverflow = no_panic.shrOverflow;
|
||||
pub const divideByZero = no_panic.divideByZero;
|
||||
pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
|
||||
pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
|
||||
pub const corruptSwitch = no_panic.corruptSwitch;
|
||||
pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
|
||||
pub const invalidEnumValue = no_panic.invalidEnumValue;
|
||||
pub const forLenMismatch = no_panic.forLenMismatch;
|
||||
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
|
||||
pub const memcpyAlias = no_panic.memcpyAlias;
|
||||
pub const noreturnReturned = no_panic.noreturnReturned;
|
||||
};
|
||||
fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
|
||||
std.process.exit(0);
|
||||
}
|
||||
const std = @import("std");
|
||||
#expect_stdout="third panic message: integer overflow\n"
|
||||
Loading…
Add table
Reference in a new issue