authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-25 04:10:55+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-01-25 04:10:55+00:00
log8ba3812eeedec643dd045e0fecb8a6697f6253db
tree00c47f03ccef1a0398163b5af7063501860d18fe
parent921725427efeae591793f49291807a41112ccbf9
parentb6726913d31f9273317ab56c4d33096aee0a588f
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22594 from mlugg/panic-stuff

compiler: yet more panic handler changes

23 files changed, 828 insertions(+), 543 deletions(-)

lib/compiler_rt/common.zig+1-10
......@@ -78,16 +78,7 @@ pub const want_sparc_abi = builtin.cpu.arch.isSPARC();
7878
7979// Avoid dragging in the runtime safety mechanisms into this .o file, unless
8080// we're trying to test compiler-rt.
81pub const Panic = if (builtin.is_test) std.debug.FormattedPanic else struct {};
82
83/// To be deleted after zig1.wasm is updated.
84pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
85 if (builtin.is_test) {
86 std.debug.defaultPanic(msg, error_return_trace, ret_addr orelse @returnAddress());
87 } else {
88 unreachable;
89 }
90}
81pub const panic = if (builtin.is_test) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.no_panic;
9182
9283/// AArch64 is the only ABI (at the moment) to support f16 arguments without the
9384/// need for extending them to wider fp types.
lib/std/Target.zig+1-1
......@@ -370,7 +370,7 @@ pub const Os = struct {
370370 range: std.SemanticVersion.Range,
371371 glibc: std.SemanticVersion,
372372 /// Android API level.
373 android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated.
373 android: u32,
374374
375375 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
376376 return range.range.includesVersion(ver);
lib/std/builtin.zig+20-35
......@@ -1110,46 +1110,31 @@ pub const TestFn = struct {
11101110/// Deprecated, use the `Panic` namespace instead.
11111111/// To be deleted after 0.14.0 is released.
11121112pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn;
1113/// Deprecated, use the `Panic` namespace instead.
1114/// To be deleted after 0.14.0 is released.
1115pub const panic: PanicFn = Panic.call;
11161113
11171114/// This namespace is used by the Zig compiler to emit various kinds of safety
1118/// panics. These can be overridden by making a public `Panic` namespace in the
1115/// panics. These can be overridden by making a public `panic` namespace in the
11191116/// root source file.
1120pub const Panic: type = if (@hasDecl(root, "Panic"))
1121 root.Panic
1122else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead.
1123 DeprecatedPanic
1124else if (builtin.zig_backend == .stage2_riscv64)
1125 std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519
1126else
1127 std.debug.FormattedPanic;
1128
1129/// To be deleted after 0.14.0 is released.
1130const DeprecatedPanic = struct {
1131 pub const call = root.panic;
1132 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
1133 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
1134 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
1135 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
1136 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
1137 pub const messages = std.debug.FormattedPanic.messages;
1117pub const panic: type = p: {
1118 if (@hasDecl(root, "panic")) {
1119 if (@TypeOf(root.panic) != type) {
1120 // Deprecated; make `panic` a namespace instead.
1121 break :p std.debug.FullPanic(struct {
1122 fn panic(msg: []const u8, ra: ?usize) noreturn {
1123 root.panic(msg, @errorReturnTrace(), ra);
1124 }
1125 }.panic);
1126 }
1127 break :p root.panic;
1128 }
1129 if (@hasDecl(root, "Panic")) {
1130 break :p root.Panic; // Deprecated; use `panic` instead.
1131 }
1132 if (builtin.zig_backend == .stage2_riscv64) {
1133 break :p std.debug.simple_panic;
1134 }
1135 break :p std.debug.FullPanic(std.debug.defaultPanic);
11381136};
11391137
1140/// To be deleted after zig1.wasm is updated.
1141pub const panicSentinelMismatch = Panic.sentinelMismatch;
1142/// To be deleted after zig1.wasm is updated.
1143pub const panicUnwrapError = Panic.unwrapError;
1144/// To be deleted after zig1.wasm is updated.
1145pub const panicOutOfBounds = Panic.outOfBounds;
1146/// To be deleted after zig1.wasm is updated.
1147pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd;
1148/// To be deleted after zig1.wasm is updated.
1149pub const panicInactiveUnionField = Panic.inactiveUnionField;
1150/// To be deleted after zig1.wasm is updated.
1151pub const panic_messages = Panic.messages;
1152
11531138pub noinline fn returnError() void {
11541139 @branchHint(.unlikely);
11551140 @setRuntimeSafety(false);
lib/std/debug.zig+119-9
......@@ -21,9 +21,121 @@ pub const SelfInfo = @import("debug/SelfInfo.zig");
2121pub const Info = @import("debug/Info.zig");
2222pub const Coverage = @import("debug/Coverage.zig");
2323
24pub const FormattedPanic = @import("debug/FormattedPanic.zig");
25pub const SimplePanic = @import("debug/SimplePanic.zig");
26pub const NoPanic = @import("debug/NoPanic.zig");
24pub const simple_panic = @import("debug/simple_panic.zig");
25pub const no_panic = @import("debug/no_panic.zig");
26
27/// A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`.
28/// Safety panics will use formatted printing to provide a meaningful error message.
29/// The signature of `panicFn` should match that of `defaultPanic`.
30pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
31 return struct {
32 pub const call = panicFn;
33 pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
34 @branchHint(.cold);
35 std.debug.panicExtra(@returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
36 expected, found,
37 });
38 }
39 pub fn unwrapError(err: anyerror) noreturn {
40 @branchHint(.cold);
41 std.debug.panicExtra(@returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
42 }
43 pub fn outOfBounds(index: usize, len: usize) noreturn {
44 @branchHint(.cold);
45 std.debug.panicExtra(@returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
46 }
47 pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
48 @branchHint(.cold);
49 std.debug.panicExtra(@returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
50 }
51 pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
52 @branchHint(.cold);
53 std.debug.panicExtra(@returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
54 @tagName(accessed), @tagName(active),
55 });
56 }
57 pub fn reachedUnreachable() noreturn {
58 @branchHint(.cold);
59 call("reached unreachable code", @returnAddress());
60 }
61 pub fn unwrapNull() noreturn {
62 @branchHint(.cold);
63 call("attempt to use null value", @returnAddress());
64 }
65 pub fn castToNull() noreturn {
66 @branchHint(.cold);
67 call("cast causes pointer to be null", @returnAddress());
68 }
69 pub fn incorrectAlignment() noreturn {
70 @branchHint(.cold);
71 call("incorrect alignment", @returnAddress());
72 }
73 pub fn invalidErrorCode() noreturn {
74 @branchHint(.cold);
75 call("invalid error code", @returnAddress());
76 }
77 pub fn castTruncatedData() noreturn {
78 @branchHint(.cold);
79 call("integer cast truncated bits", @returnAddress());
80 }
81 pub fn negativeToUnsigned() noreturn {
82 @branchHint(.cold);
83 call("attempt to cast negative value to unsigned integer", @returnAddress());
84 }
85 pub fn integerOverflow() noreturn {
86 @branchHint(.cold);
87 call("integer overflow", @returnAddress());
88 }
89 pub fn shlOverflow() noreturn {
90 @branchHint(.cold);
91 call("left shift overflowed bits", @returnAddress());
92 }
93 pub fn shrOverflow() noreturn {
94 @branchHint(.cold);
95 call("right shift overflowed bits", @returnAddress());
96 }
97 pub fn divideByZero() noreturn {
98 @branchHint(.cold);
99 call("division by zero", @returnAddress());
100 }
101 pub fn exactDivisionRemainder() noreturn {
102 @branchHint(.cold);
103 call("exact division produced remainder", @returnAddress());
104 }
105 pub fn integerPartOutOfBounds() noreturn {
106 @branchHint(.cold);
107 call("integer part of floating point value out of bounds", @returnAddress());
108 }
109 pub fn corruptSwitch() noreturn {
110 @branchHint(.cold);
111 call("switch on corrupt value", @returnAddress());
112 }
113 pub fn shiftRhsTooBig() noreturn {
114 @branchHint(.cold);
115 call("shift amount is greater than the type size", @returnAddress());
116 }
117 pub fn invalidEnumValue() noreturn {
118 @branchHint(.cold);
119 call("invalid enum value", @returnAddress());
120 }
121 pub fn forLenMismatch() noreturn {
122 @branchHint(.cold);
123 call("for loop over objects with non-equal lengths", @returnAddress());
124 }
125 pub fn memcpyLenMismatch() noreturn {
126 @branchHint(.cold);
127 call("@memcpy arguments have non-equal lengths", @returnAddress());
128 }
129 pub fn memcpyAlias() noreturn {
130 @branchHint(.cold);
131 call("@memcpy arguments alias", @returnAddress());
132 }
133 pub fn noreturnReturned() noreturn {
134 @branchHint(.cold);
135 call("'noreturn' function returned", @returnAddress());
136 }
137 };
138}
27139
28140/// Unresolved source locations can be represented with a single `usize` that
29141/// corresponds to a virtual memory address of the program counter. Combined
......@@ -416,13 +528,12 @@ pub fn assertReadable(slice: []const volatile u8) void {
416528/// Equivalent to `@panic` but with a formatted message.
417529pub fn panic(comptime format: []const u8, args: anytype) noreturn {
418530 @branchHint(.cold);
419 panicExtra(@errorReturnTrace(), @returnAddress(), format, args);
531 panicExtra(@returnAddress(), format, args);
420532}
421533
422534/// Equivalent to `@panic` but with a formatted message, and with an explicitly
423/// provided `@errorReturnTrace` and return address.
535/// provided return address.
424536pub fn panicExtra(
425 trace: ?*std.builtin.StackTrace,
426537 ret_addr: ?usize,
427538 comptime format: []const u8,
428539 args: anytype,
......@@ -441,7 +552,7 @@ pub fn panicExtra(
441552 break :blk &buf;
442553 },
443554 };
444 std.builtin.Panic.call(msg, trace, ret_addr);
555 std.builtin.panic.call(msg, ret_addr);
445556}
446557
447558/// Non-zero whenever the program triggered a panic.
......@@ -455,7 +566,6 @@ threadlocal var panic_stage: usize = 0;
455566/// Dumps a stack trace to standard error, then aborts.
456567pub fn defaultPanic(
457568 msg: []const u8,
458 error_return_trace: ?*const std.builtin.StackTrace,
459569 first_trace_addr: ?usize,
460570) noreturn {
461571 @branchHint(.cold);
......@@ -542,7 +652,7 @@ pub fn defaultPanic(
542652 }
543653 stderr.print("{s}\n", .{msg}) catch posix.abort();
544654
545 if (error_return_trace) |t| dumpStackTrace(t.*);
655 if (@errorReturnTrace()) |t| dumpStackTrace(t.*);
546656 dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());
547657 }
548658
lib/std/debug/FormattedPanic.zig deleted-45
......@@ -1,45 +0,0 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.SimplePanic`.
8
9const std = @import("../std.zig");
10
11/// Dumps a stack trace to standard error, then aborts.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic;
15
16pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
17 @branchHint(.cold);
18 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
19 expected, found,
20 });
21}
22
23pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
24 @branchHint(.cold);
25 std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
26}
27
28pub fn outOfBounds(index: usize, len: usize) noreturn {
29 @branchHint(.cold);
30 std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
31}
32
33pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
34 @branchHint(.cold);
35 std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
36}
37
38pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
39 @branchHint(.cold);
40 std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
41 @tagName(accessed), @tagName(active),
42 });
43}
44
45pub const messages = std.debug.SimplePanic.messages;
lib/std/debug/NoPanic.zig deleted-59
......@@ -1,59 +0,0 @@
1//! This namespace can be used with `pub const Panic = std.debug.NoPanic;` in the root file.
2//! It emits as little code as possible, for testing purposes.
3//!
4//! For a functional alternative, see `std.debug.FormattedPanic`.
5
6const std = @import("../std.zig");
7
8pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
9 @branchHint(.cold);
10 @trap();
11}
12
13pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
14 @branchHint(.cold);
15 @trap();
16}
17
18pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
19 @branchHint(.cold);
20 @trap();
21}
22
23pub fn outOfBounds(_: usize, _: usize) noreturn {
24 @branchHint(.cold);
25 @trap();
26}
27
28pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
29 @branchHint(.cold);
30 @trap();
31}
32
33pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
34 @branchHint(.cold);
35 @trap();
36}
37
38pub const messages = struct {
39 pub const reached_unreachable = "";
40 pub const unwrap_null = "";
41 pub const cast_to_null = "";
42 pub const incorrect_alignment = "";
43 pub const invalid_error_code = "";
44 pub const cast_truncated_data = "";
45 pub const negative_to_unsigned = "";
46 pub const integer_overflow = "";
47 pub const shl_overflow = "";
48 pub const shr_overflow = "";
49 pub const divide_by_zero = "";
50 pub const exact_division_remainder = "";
51 pub const integer_part_out_of_bounds = "";
52 pub const corrupt_switch = "";
53 pub const shift_rhs_too_big = "";
54 pub const invalid_enum_value = "";
55 pub const for_len_mismatch = "";
56 pub const memcpy_len_mismatch = "";
57 pub const memcpy_alias = "";
58 pub const noreturn_returned = "";
59};
lib/std/debug/SimplePanic.zig deleted-86
......@@ -1,86 +0,0 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.FormattedPanic`.
8
9const std = @import("../std.zig");
10
11/// Prints the message to stderr without a newline and then traps.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn {
15 @branchHint(.cold);
16 _ = ert;
17 _ = ra;
18 std.debug.lockStdErr();
19 const stderr = std.io.getStdErr();
20 stderr.writeAll(msg) catch {};
21 @trap();
22}
23
24pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
25 _ = found;
26 call("sentinel mismatch", null, null);
27}
28
29pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
30 _ = ert;
31 _ = &err;
32 call("attempt to unwrap error", null, null);
33}
34
35pub fn outOfBounds(index: usize, len: usize) noreturn {
36 _ = index;
37 _ = len;
38 call("index out of bounds", null, null);
39}
40
41pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
42 _ = start;
43 _ = end;
44 call("start index is larger than end index", null, null);
45}
46
47pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
48 _ = accessed;
49 call("access of inactive union field", null, null);
50}
51
52pub const messages = struct {
53 pub const reached_unreachable = "reached unreachable code";
54 pub const unwrap_null = "attempt to use null value";
55 pub const cast_to_null = "cast causes pointer to be null";
56 pub const incorrect_alignment = "incorrect alignment";
57 pub const invalid_error_code = "invalid error code";
58 pub const cast_truncated_data = "integer cast truncated bits";
59 pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
60 pub const integer_overflow = "integer overflow";
61 pub const shl_overflow = "left shift overflowed bits";
62 pub const shr_overflow = "right shift overflowed bits";
63 pub const divide_by_zero = "division by zero";
64 pub const exact_division_remainder = "exact division produced remainder";
65 pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
66 pub const corrupt_switch = "switch on corrupt value";
67 pub const shift_rhs_too_big = "shift amount is greater than the type size";
68 pub const invalid_enum_value = "invalid enum value";
69 pub const for_len_mismatch = "for loop over objects with non-equal lengths";
70 pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
71 pub const memcpy_alias = "@memcpy arguments alias";
72 pub const noreturn_returned = "'noreturn' function returned";
73
74 /// To be deleted after zig1.wasm is updated.
75 pub const inactive_union_field = "access of inactive union field";
76 /// To be deleted after zig1.wasm is updated.
77 pub const sentinel_mismatch = "sentinel mismatch";
78 /// To be deleted after zig1.wasm is updated.
79 pub const unwrap_error = "attempt to unwrap error";
80 /// To be deleted after zig1.wasm is updated.
81 pub const index_out_of_bounds = "index out of bounds";
82 /// To be deleted after zig1.wasm is updated.
83 pub const start_index_greater_than_end = "start index is larger than end index";
84 /// To be deleted after zig1.wasm is updated.
85 pub const unreach = reached_unreachable;
86};
lib/std/debug/no_panic.zig created+136
......@@ -0,0 +1,136 @@
1//! This namespace can be used with `pub const panic = std.debug.no_panic;` in the root file.
2//! It emits as little code as possible, for testing purposes.
3//!
4//! For a functional alternative, see `std.debug.FullPanic`.
5
6const std = @import("../std.zig");
7
8pub fn call(_: []const u8, _: ?usize) noreturn {
9 @branchHint(.cold);
10 @trap();
11}
12
13pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
14 @branchHint(.cold);
15 @trap();
16}
17
18pub fn unwrapError(_: anyerror) noreturn {
19 @branchHint(.cold);
20 @trap();
21}
22
23pub fn outOfBounds(_: usize, _: usize) noreturn {
24 @branchHint(.cold);
25 @trap();
26}
27
28pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
29 @branchHint(.cold);
30 @trap();
31}
32
33pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
34 @branchHint(.cold);
35 @trap();
36}
37
38pub fn reachedUnreachable() noreturn {
39 @branchHint(.cold);
40 @trap();
41}
42
43pub fn unwrapNull() noreturn {
44 @branchHint(.cold);
45 @trap();
46}
47
48pub fn castToNull() noreturn {
49 @branchHint(.cold);
50 @trap();
51}
52
53pub fn incorrectAlignment() noreturn {
54 @branchHint(.cold);
55 @trap();
56}
57
58pub fn invalidErrorCode() noreturn {
59 @branchHint(.cold);
60 @trap();
61}
62
63pub fn castTruncatedData() noreturn {
64 @branchHint(.cold);
65 @trap();
66}
67
68pub fn negativeToUnsigned() noreturn {
69 @branchHint(.cold);
70 @trap();
71}
72
73pub fn integerOverflow() noreturn {
74 @branchHint(.cold);
75 @trap();
76}
77
78pub fn shlOverflow() noreturn {
79 @branchHint(.cold);
80 @trap();
81}
82
83pub fn shrOverflow() noreturn {
84 @branchHint(.cold);
85 @trap();
86}
87
88pub fn divideByZero() noreturn {
89 @branchHint(.cold);
90 @trap();
91}
92
93pub fn exactDivisionRemainder() noreturn {
94 @branchHint(.cold);
95 @trap();
96}
97
98pub fn integerPartOutOfBounds() noreturn {
99 @branchHint(.cold);
100 @trap();
101}
102
103pub fn corruptSwitch() noreturn {
104 @branchHint(.cold);
105 @trap();
106}
107
108pub fn shiftRhsTooBig() noreturn {
109 @branchHint(.cold);
110 @trap();
111}
112
113pub fn invalidEnumValue() noreturn {
114 @branchHint(.cold);
115 @trap();
116}
117
118pub fn forLenMismatch() noreturn {
119 @branchHint(.cold);
120 @trap();
121}
122
123pub fn memcpyLenMismatch() noreturn {
124 @branchHint(.cold);
125 @trap();
126}
127
128pub fn memcpyAlias() noreturn {
129 @branchHint(.cold);
130 @trap();
131}
132
133pub fn noreturnReturned() noreturn {
134 @branchHint(.cold);
135 @trap();
136}
lib/std/debug/simple_panic.zig created+128
......@@ -0,0 +1,128 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.FullPanic`.
8
9const std = @import("../std.zig");
10
11/// Prints the message to stderr without a newline and then traps.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub fn call(msg: []const u8, ra: ?usize) noreturn {
15 @branchHint(.cold);
16 _ = ra;
17 std.debug.lockStdErr();
18 const stderr = std.io.getStdErr();
19 stderr.writeAll(msg) catch {};
20 @trap();
21}
22
23pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
24 _ = found;
25 call("sentinel mismatch", null);
26}
27
28pub fn unwrapError(err: anyerror) noreturn {
29 _ = &err;
30 call("attempt to unwrap error", null);
31}
32
33pub fn outOfBounds(index: usize, len: usize) noreturn {
34 _ = index;
35 _ = len;
36 call("index out of bounds", null);
37}
38
39pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
40 _ = start;
41 _ = end;
42 call("start index is larger than end index", null);
43}
44
45pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
46 _ = accessed;
47 call("access of inactive union field", null);
48}
49
50pub fn reachedUnreachable() noreturn {
51 call("reached unreachable code", null);
52}
53
54pub fn unwrapNull() noreturn {
55 call("attempt to use null value", null);
56}
57
58pub fn castToNull() noreturn {
59 call("cast causes pointer to be null", null);
60}
61
62pub fn incorrectAlignment() noreturn {
63 call("incorrect alignment", null);
64}
65
66pub fn invalidErrorCode() noreturn {
67 call("invalid error code", null);
68}
69
70pub fn castTruncatedData() noreturn {
71 call("integer cast truncated bits", null);
72}
73
74pub fn negativeToUnsigned() noreturn {
75 call("attempt to cast negative value to unsigned integer", null);
76}
77
78pub fn integerOverflow() noreturn {
79 call("integer overflow", null);
80}
81
82pub fn shlOverflow() noreturn {
83 call("left shift overflowed bits", null);
84}
85
86pub fn shrOverflow() noreturn {
87 call("right shift overflowed bits", null);
88}
89
90pub fn divideByZero() noreturn {
91 call("division by zero", null);
92}
93
94pub fn exactDivisionRemainder() noreturn {
95 call("exact division produced remainder", null);
96}
97
98pub fn integerPartOutOfBounds() noreturn {
99 call("integer part of floating point value out of bounds", null);
100}
101
102pub fn corruptSwitch() noreturn {
103 call("switch on corrupt value", null);
104}
105
106pub fn shiftRhsTooBig() noreturn {
107 call("shift amount is greater than the type size", null);
108}
109
110pub fn invalidEnumValue() noreturn {
111 call("invalid enum value", null);
112}
113
114pub fn forLenMismatch() noreturn {
115 call("for loop over objects with non-equal lengths", null);
116}
117
118pub fn memcpyLenMismatch() noreturn {
119 call("@memcpy arguments have non-equal lengths", null);
120}
121
122pub fn memcpyAlias() noreturn {
123 call("@memcpy arguments alias", null);
124}
125
126pub fn noreturnReturned() noreturn {
127 call("'noreturn' function returned", null);
128}
lib/std/meta.zig+1-2
......@@ -448,8 +448,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
448448 return comptime blk: {
449449 const fieldInfos = fields(T);
450450 var names: [fieldInfos.len][:0]const u8 = undefined;
451 // This concat can be removed with the next zig1 update.
452 for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
451 for (&names, fieldInfos) |*name, field| name.* = field.name;
453452 const final = names;
454453 break :blk &final;
455454 };
src/Sema.zig+94-102
......@@ -2584,7 +2584,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
25842584 std.debug.print("compile error during Sema:\n", .{});
25852585 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
25862586 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
2587 crash_report.compilerPanic("unexpected compile error occurred", null, null);
2587 crash_report.compilerPanic("unexpected compile error occurred", null);
25882588 }
25892589
25902590 if (block) |start_block| {
......@@ -5918,13 +5918,14 @@ fn zirCompileLog(
59185918}
59195919
59205920fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
5921 const pt = sema.pt;
5922 const zcu = pt.zcu;
5923
59215924 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
59225925 const src = block.nodeOffset(inst_data.src_node);
59235926 const msg_inst = try sema.resolveInst(inst_data.operand);
59245927
5925 // `panicWithMsg` would perform this coercion for us, but we can get a better
5926 // source location if we do it here.
5927 const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
5928 const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
59285929
59295930 if (block.isComptime()) {
59305931 return sema.fail(block, src, "encountered @panic at comptime", .{});
......@@ -5936,7 +5937,22 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
59365937 sema.branch_hint = .cold;
59375938 }
59385939
5939 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");
5940 if (!zcu.backendSupportsFeature(.panic_fn)) {
5941 _ = try block.addNoOp(.trap);
5942 return;
5943 }
5944
5945 try sema.ensureMemoizedStateResolved(src, .panic);
5946 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call"));
5947
5948 const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call"));
5949
5950 const opt_usize_ty = try pt.optionalType(.usize_type);
5951 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
5952 .ty = opt_usize_ty.toIntern(),
5953 .val = .none,
5954 } })));
5955 try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_ret_addr }, .@"@panic");
59405956}
59415957
59425958fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
......@@ -13787,9 +13803,8 @@ fn maybeErrorUnwrap(
1378713803 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
1378813804 const msg_inst = try sema.resolveInst(inst_data.operand);
1378913805
13790 const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call");
13791 const err_return_trace = try sema.getErrorReturnTrace(block);
13792 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
13806 const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call");
13807 const args: [2]Air.Inst.Ref = .{ msg_inst, .null_value };
1379313808 try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
1379413809 return true;
1379513810 },
......@@ -27083,15 +27098,16 @@ fn explainWhyTypeIsNotPacked(
2708327098/// Backends depend on panic decls being available when lowering safety-checked
2708427099/// instructions. This function ensures the panic function will be available to
2708527100/// be called during that time.
27086fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index {
27101fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index {
2708727102 const zcu = sema.pt.zcu;
2708827103 try sema.ensureMemoizedStateResolved(src, .panic);
27089 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
27104 const panic_func = zcu.builtin_decl_values.get(panic_id.toBuiltin());
27105 try zcu.ensureFuncBodyAnalysisQueued(panic_func);
2709027106 switch (sema.owner.unwrap()) {
2709127107 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
2709227108 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true),
2709327109 }
27094 return zcu.builtin_decl_values.get(panic_id.toBuiltin());
27110 return panic_func;
2709527111}
2709627112
2709727113fn addSafetyCheck(
......@@ -27099,7 +27115,7 @@ fn addSafetyCheck(
2709927115 parent_block: *Block,
2710027116 src: LazySrcLoc,
2710127117 ok: Air.Inst.Ref,
27102 panic_id: Zcu.PanicId,
27118 panic_id: Zcu.SimplePanicId,
2710327119) !void {
2710427120 const gpa = sema.gpa;
2710527121 assert(!parent_block.isComptime());
......@@ -27186,29 +27202,6 @@ fn addSafetyCheckExtra(
2718627202 parent_block.instructions.appendAssumeCapacity(block_inst);
2718727203}
2718827204
27189fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void {
27190 const pt = sema.pt;
27191 const zcu = pt.zcu;
27192
27193 if (!zcu.backendSupportsFeature(.panic_fn)) {
27194 _ = try block.addNoOp(.trap);
27195 return;
27196 }
27197
27198 try sema.ensureMemoizedStateResolved(src, .panic);
27199 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
27200
27201 const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"Panic.call"));
27202 const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
27203
27204 const opt_usize_ty = try pt.optionalType(.usize_type);
27205 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
27206 .ty = opt_usize_ty.toIntern(),
27207 .val = .none,
27208 } })));
27209 try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation);
27210}
27211
2721227205fn addSafetyCheckUnwrapError(
2721327206 sema: *Sema,
2721427207 parent_block: *Block,
......@@ -27246,10 +27239,8 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.
2724627239 if (!zcu.backendSupportsFeature(.panic_fn)) {
2724727240 _ = try block.addNoOp(.trap);
2724827241 } else {
27249 const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError");
27250 const err_return_trace = try sema.getErrorReturnTrace(block);
27251 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
27252 try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
27242 const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError");
27243 try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{err}, .@"safety check");
2725327244 }
2725427245}
2725527246
......@@ -27263,7 +27254,7 @@ fn addSafetyCheckIndexOob(
2726327254) !void {
2726427255 assert(!parent_block.isComptime());
2726527256 const ok = try parent_block.addBinOp(cmp_op, index, len);
27266 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len });
27257 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.outOfBounds", &.{ index, len });
2726727258}
2726827259
2726927260fn addSafetyCheckInactiveUnionField(
......@@ -27275,7 +27266,7 @@ fn addSafetyCheckInactiveUnionField(
2727527266) !void {
2727627267 assert(!parent_block.isComptime());
2727727268 const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
27278 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag });
27269 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.inactiveUnionField", &.{ active_tag, wanted_tag });
2727927270}
2728027271
2728127272fn addSafetyCheckSentinelMismatch(
......@@ -27316,7 +27307,7 @@ fn addSafetyCheckSentinelMismatch(
2731627307 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
2731727308 };
2731827309
27319 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{
27310 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{
2732027311 expected_sentinel, actual_sentinel,
2732127312 });
2732227313}
......@@ -27358,9 +27349,13 @@ fn addSafetyCheckCall(
2735827349}
2735927350
2736027351/// This does not set `sema.branch_hint`.
27361fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void {
27362 const msg_val = try sema.preparePanicId(src, panic_id);
27363 try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check");
27352fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void {
27353 if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) {
27354 _ = try block.addNoOp(.trap);
27355 } else {
27356 const panic_fn = try sema.preparePanicId(src, panic_id);
27357 try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{}, .@"safety check");
27358 }
2736427359}
2736527360
2736627361fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
......@@ -32818,7 +32813,7 @@ fn analyzeSlice(
3281832813 assert(!block.isComptime());
3281932814 try sema.requireRuntimeBlock(block, src, runtime_src.?);
3282032815 const ok = try block.addBinOp(.cmp_lte, start, end);
32821 try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end });
32816 try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end });
3282232817 }
3282332818 const new_len = if (by_length)
3282432819 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
......@@ -38525,14 +38520,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3852538520 break :val uncoerced_val;
3852638521 },
3852738522 .func => val: {
38528 if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| {
38529 const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
38530 break :val .fromInterned(coerced.toInterned().?);
38531 }
38532 if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
38533 return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name });
38534 }
38535 break :val uncoerced_val;
38523 const func_ty = try sema.getExpectedBuiltinFnType(builtin_decl);
38524 const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
38525 break :val .fromInterned(coerced.toInterned().?);
3853638526 },
3853738527 .string => val: {
3853838528 const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src);
......@@ -38549,75 +38539,77 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3854938539 }
3855038540 }
3855138541
38552 if (stage == .panic) {
38553 // We use `getBuiltinType` because this is from an earlier stage.
38554 const stack_trace_ty = try sema.getBuiltinType(simple_src, .StackTrace);
38555 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
38556 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
38557 const null_stack_trace = try pt.intern(.{ .opt = .{
38558 .ty = opt_ptr_stack_trace_ty.toIntern(),
38559 .val = .none,
38560 } });
38561 if (null_stack_trace != zcu.null_stack_trace) {
38562 zcu.null_stack_trace = null_stack_trace;
38563 any_changed = true;
38564 }
38565 }
38566
3856738542 return any_changed;
3856838543}
3856938544
38570/// Given that `decl.kind() == .func`, get the type expected of the function if necessary.
38571/// If this will be type checked by `Sema` anyway, this function may return `null`. In
38572/// particular, generic functions should return `null`, as `Sema` will necessarily check
38573/// them at instantiation time. Returning non-null is necessary only when backends can emit
38574/// calls to the function, as is the case with the panic handler.
38575fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type {
38545/// Given that `decl.kind() == .func`, get the type expected of the function.
38546fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Type {
3857638547 const pt = sema.pt;
3857738548 return switch (decl) {
38578 // `fn ([]const u8, ?*StackTrace, ?usize) noreturn`
38579 .@"Panic.call" => try pt.funcType(.{
38549 // `noinline fn () void`
38550 .returnError => try pt.funcType(.{
38551 .param_types = &.{},
38552 .return_type = .void_type,
38553 .is_noinline = true,
38554 }),
38555
38556 // `fn ([]const u8, ?usize) noreturn`
38557 .@"panic.call" => try pt.funcType(.{
3858038558 .param_types = &.{
3858138559 .slice_const_u8_type,
38582 (try pt.optionalType(
38583 (try pt.singleMutPtrType(
38584 try sema.getBuiltinType(src, .StackTrace),
38585 )).toIntern(),
38586 )).toIntern(),
3858738560 (try pt.optionalType(.usize_type)).toIntern(),
3858838561 },
3858938562 .return_type = .noreturn_type,
3859038563 }),
3859138564
38592 // `fn (?*StackTrace, anyerror) noreturn`
38593 .@"Panic.unwrapError" => try pt.funcType(.{
38594 .param_types = &.{
38595 (try pt.optionalType(
38596 (try pt.singleMutPtrType(
38597 try sema.getBuiltinType(src, .StackTrace),
38598 )).toIntern(),
38599 )).toIntern(),
38600 .anyerror_type,
38601 },
38565 // `fn (anytype, anytype) noreturn`
38566 .@"panic.sentinelMismatch",
38567 .@"panic.inactiveUnionField",
38568 => try pt.funcType(.{
38569 .param_types = &.{ .generic_poison_type, .generic_poison_type },
38570 .return_type = .noreturn_type,
38571 .is_generic = true,
38572 }),
38573
38574 // `fn (anyerror) noreturn`
38575 .@"panic.unwrapError" => try pt.funcType(.{
38576 .param_types = &.{.anyerror_type},
3860238577 .return_type = .noreturn_type,
3860338578 }),
3860438579
3860538580 // `fn (usize, usize) noreturn`
38606 .@"Panic.outOfBounds",
38607 .@"Panic.startGreaterThanEnd",
38581 .@"panic.outOfBounds",
38582 .@"panic.startGreaterThanEnd",
3860838583 => try pt.funcType(.{
3860938584 .param_types = &.{ .usize_type, .usize_type },
3861038585 .return_type = .noreturn_type,
3861138586 }),
3861238587
38613 // Generic functions, so calls are necessarily validated by Sema
38614 .@"Panic.sentinelMismatch",
38615 .@"Panic.inactiveUnionField",
38616 => null,
38617
38618 // Other functions called exclusively by Sema
38619 .returnError,
38620 => null,
38588 // `fn () noreturn`
38589 .@"panic.reachedUnreachable",
38590 .@"panic.unwrapNull",
38591 .@"panic.castToNull",
38592 .@"panic.incorrectAlignment",
38593 .@"panic.invalidErrorCode",
38594 .@"panic.castTruncatedData",
38595 .@"panic.negativeToUnsigned",
38596 .@"panic.integerOverflow",
38597 .@"panic.shlOverflow",
38598 .@"panic.shrOverflow",
38599 .@"panic.divideByZero",
38600 .@"panic.exactDivisionRemainder",
38601 .@"panic.integerPartOutOfBounds",
38602 .@"panic.corruptSwitch",
38603 .@"panic.shiftRhsTooBig",
38604 .@"panic.invalidEnumValue",
38605 .@"panic.forLenMismatch",
38606 .@"panic.memcpyLenMismatch",
38607 .@"panic.memcpyAlias",
38608 .@"panic.noreturnReturned",
38609 => try pt.funcType(.{
38610 .param_types = &.{},
38611 .return_type = .noreturn_type,
38612 }),
3862138613
3862238614 else => unreachable,
3862338615 };
src/Zcu.zig+81-76
......@@ -219,8 +219,6 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty,
219219
220220/// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = s })`, where `s` depends on the element.
221221builtin_decl_values: BuiltinDecl.Memoized = .initFill(.none),
222/// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = .panic })`.
223null_stack_trace: InternPool.Index = .none,
224222
225223generation: u32 = 0,
226224
......@@ -269,34 +267,33 @@ pub const BuiltinDecl = enum {
269267 @"Type.Opaque",
270268 @"Type.Declaration",
271269
272 Panic,
273 @"Panic.call",
274 @"Panic.sentinelMismatch",
275 @"Panic.unwrapError",
276 @"Panic.outOfBounds",
277 @"Panic.startGreaterThanEnd",
278 @"Panic.inactiveUnionField",
279 @"Panic.messages",
280 @"Panic.messages.reached_unreachable",
281 @"Panic.messages.unwrap_null",
282 @"Panic.messages.cast_to_null",
283 @"Panic.messages.incorrect_alignment",
284 @"Panic.messages.invalid_error_code",
285 @"Panic.messages.cast_truncated_data",
286 @"Panic.messages.negative_to_unsigned",
287 @"Panic.messages.integer_overflow",
288 @"Panic.messages.shl_overflow",
289 @"Panic.messages.shr_overflow",
290 @"Panic.messages.divide_by_zero",
291 @"Panic.messages.exact_division_remainder",
292 @"Panic.messages.integer_part_out_of_bounds",
293 @"Panic.messages.corrupt_switch",
294 @"Panic.messages.shift_rhs_too_big",
295 @"Panic.messages.invalid_enum_value",
296 @"Panic.messages.for_len_mismatch",
297 @"Panic.messages.memcpy_len_mismatch",
298 @"Panic.messages.memcpy_alias",
299 @"Panic.messages.noreturn_returned",
270 panic,
271 @"panic.call",
272 @"panic.sentinelMismatch",
273 @"panic.unwrapError",
274 @"panic.outOfBounds",
275 @"panic.startGreaterThanEnd",
276 @"panic.inactiveUnionField",
277 @"panic.reachedUnreachable",
278 @"panic.unwrapNull",
279 @"panic.castToNull",
280 @"panic.incorrectAlignment",
281 @"panic.invalidErrorCode",
282 @"panic.castTruncatedData",
283 @"panic.negativeToUnsigned",
284 @"panic.integerOverflow",
285 @"panic.shlOverflow",
286 @"panic.shrOverflow",
287 @"panic.divideByZero",
288 @"panic.exactDivisionRemainder",
289 @"panic.integerPartOutOfBounds",
290 @"panic.corruptSwitch",
291 @"panic.shiftRhsTooBig",
292 @"panic.invalidEnumValue",
293 @"panic.forLenMismatch",
294 @"panic.memcpyLenMismatch",
295 @"panic.memcpyAlias",
296 @"panic.noreturnReturned",
300297
301298 VaList,
302299
......@@ -345,39 +342,35 @@ pub const BuiltinDecl = enum {
345342 .@"Type.Declaration",
346343 => .type,
347344
348 .Panic => .type,
349
350 .@"Panic.call",
351 .@"Panic.sentinelMismatch",
352 .@"Panic.unwrapError",
353 .@"Panic.outOfBounds",
354 .@"Panic.startGreaterThanEnd",
355 .@"Panic.inactiveUnionField",
345 .panic => .type,
346
347 .@"panic.call",
348 .@"panic.sentinelMismatch",
349 .@"panic.unwrapError",
350 .@"panic.outOfBounds",
351 .@"panic.startGreaterThanEnd",
352 .@"panic.inactiveUnionField",
353 .@"panic.reachedUnreachable",
354 .@"panic.unwrapNull",
355 .@"panic.castToNull",
356 .@"panic.incorrectAlignment",
357 .@"panic.invalidErrorCode",
358 .@"panic.castTruncatedData",
359 .@"panic.negativeToUnsigned",
360 .@"panic.integerOverflow",
361 .@"panic.shlOverflow",
362 .@"panic.shrOverflow",
363 .@"panic.divideByZero",
364 .@"panic.exactDivisionRemainder",
365 .@"panic.integerPartOutOfBounds",
366 .@"panic.corruptSwitch",
367 .@"panic.shiftRhsTooBig",
368 .@"panic.invalidEnumValue",
369 .@"panic.forLenMismatch",
370 .@"panic.memcpyLenMismatch",
371 .@"panic.memcpyAlias",
372 .@"panic.noreturnReturned",
356373 => .func,
357
358 .@"Panic.messages" => .type,
359
360 .@"Panic.messages.reached_unreachable",
361 .@"Panic.messages.unwrap_null",
362 .@"Panic.messages.cast_to_null",
363 .@"Panic.messages.incorrect_alignment",
364 .@"Panic.messages.invalid_error_code",
365 .@"Panic.messages.cast_truncated_data",
366 .@"Panic.messages.negative_to_unsigned",
367 .@"Panic.messages.integer_overflow",
368 .@"Panic.messages.shl_overflow",
369 .@"Panic.messages.shr_overflow",
370 .@"Panic.messages.divide_by_zero",
371 .@"Panic.messages.exact_division_remainder",
372 .@"Panic.messages.integer_part_out_of_bounds",
373 .@"Panic.messages.corrupt_switch",
374 .@"Panic.messages.shift_rhs_too_big",
375 .@"Panic.messages.invalid_enum_value",
376 .@"Panic.messages.for_len_mismatch",
377 .@"Panic.messages.memcpy_len_mismatch",
378 .@"Panic.messages.memcpy_alias",
379 .@"Panic.messages.noreturn_returned",
380 => .string,
381374 };
382375 }
383376
......@@ -423,7 +416,7 @@ pub const BuiltinDecl = enum {
423416 const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index);
424417};
425418
426pub const PanicId = enum {
419pub const SimplePanicId = enum {
427420 reached_unreachable,
428421 unwrap_null,
429422 cast_to_null,
......@@ -445,19 +438,31 @@ pub const PanicId = enum {
445438 memcpy_alias,
446439 noreturn_returned,
447440
448 pub fn toBuiltin(id: PanicId) BuiltinDecl {
449 const first_msg: PanicId = @enumFromInt(0);
450 const first_decl = @field(BuiltinDecl, "Panic.messages." ++ @tagName(first_msg));
451 comptime {
452 // Ensure that the messages are ordered the same in `BuiltinDecl` as they are here.
453 for (@typeInfo(PanicId).@"enum".fields) |panic_field| {
454 const expect_name = "Panic.messages." ++ panic_field.name;
455 const expect_idx = @intFromEnum(first_decl) + panic_field.value;
456 const actual_idx = @intFromEnum(@field(BuiltinDecl, expect_name));
457 assert(expect_idx == actual_idx);
458 }
459 }
460 return @enumFromInt(@intFromEnum(first_decl) + @intFromEnum(id));
441 pub fn toBuiltin(id: SimplePanicId) BuiltinDecl {
442 return switch (id) {
443 // zig fmt: off
444 .reached_unreachable => .@"panic.reachedUnreachable",
445 .unwrap_null => .@"panic.unwrapNull",
446 .cast_to_null => .@"panic.castToNull",
447 .incorrect_alignment => .@"panic.incorrectAlignment",
448 .invalid_error_code => .@"panic.invalidErrorCode",
449 .cast_truncated_data => .@"panic.castTruncatedData",
450 .negative_to_unsigned => .@"panic.negativeToUnsigned",
451 .integer_overflow => .@"panic.integerOverflow",
452 .shl_overflow => .@"panic.shlOverflow",
453 .shr_overflow => .@"panic.shrOverflow",
454 .divide_by_zero => .@"panic.divideByZero",
455 .exact_division_remainder => .@"panic.exactDivisionRemainder",
456 .integer_part_out_of_bounds => .@"panic.integerPartOutOfBounds",
457 .corrupt_switch => .@"panic.corruptSwitch",
458 .shift_rhs_too_big => .@"panic.shiftRhsTooBig",
459 .invalid_enum_value => .@"panic.invalidEnumValue",
460 .for_len_mismatch => .@"panic.forLenMismatch",
461 .memcpy_len_mismatch => .@"panic.memcpyLenMismatch",
462 .memcpy_alias => .@"panic.memcpyAlias",
463 .noreturn_returned => .@"panic.noreturnReturned",
464 // zig fmt: on
465 };
461466 }
462467};
463468
src/Zcu/PerThread.zig+1-1
......@@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
605605 // We use an arbitrary element to check if the state has been resolved yet.
606606 const to_check: Zcu.BuiltinDecl = switch (stage) {
607607 .main => .Type,
608 .panic => .Panic,
608 .panic => .panic,
609609 .va_list => .VaList,
610610 };
611611 if (zcu.builtin_decl_values.get(to_check) != .none) return;
src/codegen/llvm.zig+5-44
......@@ -5019,18 +5019,6 @@ pub const FuncGen = struct {
50195019 );
50205020 }
50215021
5022 fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant {
5023 const o = self.ng.object;
5024 const pt = o.pt;
5025 if (o.null_opt_usize == .no_init) {
5026 o.null_opt_usize = try self.resolveValue(Value.fromInterned(try pt.intern(.{ .opt = .{
5027 .ty = try pt.intern(.{ .opt_type = .usize_type }),
5028 .val = .none,
5029 } })));
5030 }
5031 return o.null_opt_usize;
5032 }
5033
50345022 fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void {
50355023 const o = self.ng.object;
50365024 const zcu = o.pt.zcu;
......@@ -5732,30 +5720,14 @@ pub const FuncGen = struct {
57325720 }
57335721 }
57345722
5735 fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void {
5723 fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void {
57365724 const o = fg.ng.object;
57375725 const zcu = o.pt.zcu;
5738 const ip = &zcu.intern_pool;
5739 const msg_len: u64, const msg_ptr: Builder.Constant = msg: {
5740 const str_val = zcu.builtin_decl_values.get(panic_id.toBuiltin());
5741 assert(str_val != .none);
5742 const slice = ip.indexToKey(str_val).slice;
5743 break :msg .{ Value.fromInterned(slice.len).toUnsignedInt(zcu), try o.lowerValue(slice.ptr) };
5744 };
5745 const null_opt_addr_global = try fg.resolveNullOptUsize();
57465726 const target = zcu.getTarget();
5747 const llvm_usize = try o.lowerType(Type.usize);
5748 // example:
5749 // call fastcc void @test2.panic(
5750 // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
5751 // i64 16, ; msg.len
5752 // ptr null, ; stack trace
5753 // ptr @2, ; addr (null ?usize)
5754 // )
5755 const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(.@"Panic.call"));
5756 const panic_nav = ip.getNav(panic_func.owner_nav);
5757 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5727 const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin()));
5728 const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
57585729 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5730
57595731 const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto;
57605732 if (has_err_trace) assert(fg.err_ret_trace != .none);
57615733 _ = try fg.wip.callIntrinsicAssumeCold();
......@@ -5765,18 +5737,7 @@ pub const FuncGen = struct {
57655737 .none,
57665738 panic_global.typeOf(&o.builder),
57675739 panic_global.toValue(&o.builder),
5768 if (has_err_trace) &.{
5769 fg.err_ret_trace,
5770 msg_ptr.toValue(),
5771 try o.builder.intValue(llvm_usize, msg_len),
5772 try o.builder.nullValue(.ptr),
5773 null_opt_addr_global.toValue(),
5774 } else &.{
5775 msg_ptr.toValue(),
5776 try o.builder.intValue(llvm_usize, msg_len),
5777 try o.builder.nullValue(.ptr),
5778 null_opt_addr_global.toValue(),
5779 },
5740 if (has_err_trace) &.{fg.err_ret_trace} else &.{},
57805741 "",
57815742 );
57825743 _ = try fg.wip.@"unreachable"();
src/crash_report.zig+7-13
......@@ -18,18 +18,12 @@ const dev = @import("dev.zig");
1818/// To use these crash report diagnostics, publish this panic in your main file
1919/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
2020/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
21pub const Panic = if (build_options.enable_debug_extensions) struct {
22 pub const call = compilerPanic;
23 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
24 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
25 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
26 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
27 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
28 pub const messages = std.debug.FormattedPanic.messages;
29} else if (dev.env == .bootstrap)
30 std.debug.SimplePanic
21pub const panic = if (build_options.enable_debug_extensions)
22 std.debug.FullPanic(compilerPanic)
23else if (dev.env == .bootstrap)
24 std.debug.simple_panic
3125else
32 std.debug.FormattedPanic;
26 std.debug.FullPanic(std.debug.defaultPanic);
3327
3428/// Install signal handlers to identify crashes and report diagnostics.
3529pub fn initialize() void {
......@@ -164,12 +158,12 @@ fn writeFilePath(file: *Zcu.File, writer: anytype) !void {
164158 try writer.writeAll(file.sub_file_path);
165159}
166160
167pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, maybe_ret_addr: ?usize) noreturn {
161pub fn compilerPanic(msg: []const u8, maybe_ret_addr: ?usize) noreturn {
168162 @branchHint(.cold);
169163 PanicSwitch.preDispatch();
170164 const ret_addr = maybe_ret_addr orelse @returnAddress();
171165 const stack_ctx: StackContext = .{ .current = .{ .ret_addr = ret_addr } };
172 PanicSwitch.dispatch(error_return_trace, stack_ctx, msg);
166 PanicSwitch.dispatch(@errorReturnTrace(), stack_ctx, msg);
173167}
174168
175169/// Attaches a global SIGSEGV handler
src/main.zig+1-1
......@@ -56,7 +56,7 @@ pub const std_options: std.Options = .{
5656 },
5757};
5858
59pub const Panic = crash_report.Panic;
59pub const panic = crash_report.panic;
6060
6161var wasi_preopens: fs.wasi.Preopens = undefined;
6262pub fn wasi_cwd() std.os.wasi.fd_t {
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/cases/compile_errors/bad_panic_call_signature.zig created+45
......@@ -0,0 +1,45 @@
1const simple_panic = std.debug.simple_panic;
2pub const panic = struct {
3 pub fn call(msg: []const u8, bad: usize) noreturn {
4 _ = msg;
5 _ = bad;
6 @trap();
7 }
8 pub const sentinelMismatch = simple_panic.sentinelMismatch;
9 pub const unwrapError = simple_panic.unwrapError;
10 pub const outOfBounds = simple_panic.outOfBounds;
11 pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
12 pub const inactiveUnionField = simple_panic.inactiveUnionField;
13 pub const reachedUnreachable = simple_panic.reachedUnreachable;
14 pub const unwrapNull = simple_panic.unwrapNull;
15 pub const castToNull = simple_panic.castToNull;
16 pub const incorrectAlignment = simple_panic.incorrectAlignment;
17 pub const invalidErrorCode = simple_panic.invalidErrorCode;
18 pub const castTruncatedData = simple_panic.castTruncatedData;
19 pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
20 pub const integerOverflow = simple_panic.integerOverflow;
21 pub const shlOverflow = simple_panic.shlOverflow;
22 pub const shrOverflow = simple_panic.shrOverflow;
23 pub const divideByZero = simple_panic.divideByZero;
24 pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
25 pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
26 pub const corruptSwitch = simple_panic.corruptSwitch;
27 pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
28 pub const invalidEnumValue = simple_panic.invalidEnumValue;
29 pub const forLenMismatch = simple_panic.forLenMismatch;
30 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
31 pub const memcpyAlias = simple_panic.memcpyAlias;
32 pub const noreturnReturned = simple_panic.noreturnReturned;
33};
34
35export fn foo(a: u8) void {
36 @setRuntimeSafety(true);
37 _ = a + 1; // safety check to reference the panic handler
38}
39
40const std = @import("std");
41
42// error
43//
44// :3:9: error: expected type 'fn ([]const u8, ?usize) noreturn', found 'fn ([]const u8, usize) noreturn'
45// :3:9: note: parameter 1 'usize' cannot cast into '?usize'
test/cases/compile_errors/bad_panic_generic_signature.zig created+41
......@@ -0,0 +1,41 @@
1const simple_panic = std.debug.simple_panic;
2pub const panic = struct {
3 pub fn sentinelMismatch() void {} // invalid
4 pub const call = simple_panic.call;
5 pub const unwrapError = simple_panic.unwrapError;
6 pub const outOfBounds = simple_panic.outOfBounds;
7 pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
8 pub const inactiveUnionField = simple_panic.inactiveUnionField;
9 pub const reachedUnreachable = simple_panic.reachedUnreachable;
10 pub const unwrapNull = simple_panic.unwrapNull;
11 pub const castToNull = simple_panic.castToNull;
12 pub const incorrectAlignment = simple_panic.incorrectAlignment;
13 pub const invalidErrorCode = simple_panic.invalidErrorCode;
14 pub const castTruncatedData = simple_panic.castTruncatedData;
15 pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
16 pub const integerOverflow = simple_panic.integerOverflow;
17 pub const shlOverflow = simple_panic.shlOverflow;
18 pub const shrOverflow = simple_panic.shrOverflow;
19 pub const divideByZero = simple_panic.divideByZero;
20 pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
21 pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
22 pub const corruptSwitch = simple_panic.corruptSwitch;
23 pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
24 pub const invalidEnumValue = simple_panic.invalidEnumValue;
25 pub const forLenMismatch = simple_panic.forLenMismatch;
26 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
27 pub const memcpyAlias = simple_panic.memcpyAlias;
28 pub const noreturnReturned = simple_panic.noreturnReturned;
29};
30
31export fn foo(arr: *const [2]u8) void {
32 @setRuntimeSafety(true);
33 _ = arr[0..1 :0];
34}
35
36const std = @import("std");
37
38// error
39//
40// :3:9: error: expected type 'fn (anytype, anytype) noreturn', found 'fn () void'
41// :3:9: note: non-generic function cannot cast into a generic function
test/cases/compile_errors/bad_panic_signature.zig deleted-28
......@@ -1,28 +0,0 @@
1pub const Panic = struct {
2 pub const call = badPanicSignature;
3 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
4 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
5 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
6 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
7 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
8 pub const messages = std.debug.FormattedPanic.messages;
9};
10
11fn badPanicSignature(msg: []const u8, bad1: usize, bad2: void) noreturn {
12 _ = msg;
13 _ = bad1;
14 _ = bad2;
15 @trap();
16}
17
18export fn foo(a: u8) void {
19 @setRuntimeSafety(true);
20 _ = a + 1; // safety check to reference the panic handler
21}
22
23const std = @import("std");
24
25// error
26//
27// :2:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn'
28// :2:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace'
test/incremental/change_panic_handler+6-30
......@@ -9,16 +9,8 @@ pub fn main() !u8 {
99 _ = a + 1;
1010 return 1;
1111}
12pub const Panic = struct {
13 pub const call = myPanic;
14 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
15 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
16 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
17 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
18 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
19 pub const messages = std.debug.FormattedPanic.messages;
20};
21fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
12pub const panic = std.debug.FullPanic(myPanic);
13fn myPanic(msg: []const u8, _: ?usize) noreturn {
2214 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
2315 std.process.exit(0);
2416}
......@@ -33,16 +25,8 @@ pub fn main() !u8 {
3325 _ = a + 1;
3426 return 1;
3527}
36pub const Panic = struct {
37 pub const call = myPanic;
38 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
39 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
40 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
41 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
42 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
43 pub const messages = std.debug.FormattedPanic.messages;
44};
45fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
28pub const panic = std.debug.FullPanic(myPanic);
29fn myPanic(msg: []const u8, _: ?usize) noreturn {
4630 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
4731 std.process.exit(0);
4832}
......@@ -57,16 +41,8 @@ pub fn main() !u8 {
5741 _ = a + 1;
5842 return 1;
5943}
60pub const Panic = struct {
61 pub const call = myPanicNew;
62 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
63 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
64 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
65 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
66 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
67 pub const messages = std.debug.FormattedPanic.messages;
68};
69fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
44pub const panic = std.debug.FullPanic(myPanicNew);
45fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
7046 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
7147 std.process.exit(0);
7248}
test/incremental/change_panic_handler_explicit created+141
......@@ -0,0 +1,141 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#update=initial version
5#file=main.zig
6pub fn main() !u8 {
7 var a: u8 = undefined;
8 a = 255;
9 _ = a + 1;
10 return 1;
11}
12const no_panic = std.debug.no_panic;
13pub const panic = struct {
14 pub const call = myPanic;
15 pub fn integerOverflow() noreturn {
16 @panic("integer overflow");
17 }
18 pub const sentinelMismatch = no_panic.sentinelMismatch;
19 pub const unwrapError = no_panic.unwrapError;
20 pub const outOfBounds = no_panic.outOfBounds;
21 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
22 pub const inactiveUnionField = no_panic.inactiveUnionField;
23 pub const reachedUnreachable = no_panic.reachedUnreachable;
24 pub const unwrapNull = no_panic.unwrapNull;
25 pub const castToNull = no_panic.castToNull;
26 pub const incorrectAlignment = no_panic.incorrectAlignment;
27 pub const invalidErrorCode = no_panic.invalidErrorCode;
28 pub const castTruncatedData = no_panic.castTruncatedData;
29 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
30 pub const shlOverflow = no_panic.shlOverflow;
31 pub const shrOverflow = no_panic.shrOverflow;
32 pub const divideByZero = no_panic.divideByZero;
33 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
34 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
35 pub const corruptSwitch = no_panic.corruptSwitch;
36 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
37 pub const invalidEnumValue = no_panic.invalidEnumValue;
38 pub const forLenMismatch = no_panic.forLenMismatch;
39 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
40 pub const memcpyAlias = no_panic.memcpyAlias;
41 pub const noreturnReturned = no_panic.noreturnReturned;
42};
43fn myPanic(msg: []const u8, _: ?usize) noreturn {
44 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
45 std.process.exit(0);
46}
47const std = @import("std");
48#expect_stdout="panic message: integer overflow\n"
49
50#update=change the panic handler body
51#file=main.zig
52pub fn main() !u8 {
53 var a: u8 = undefined;
54 a = 255;
55 _ = a + 1;
56 return 1;
57}
58const no_panic = std.debug.no_panic;
59pub const panic = struct {
60 pub const call = myPanic;
61 pub fn integerOverflow() noreturn {
62 @panic("integer overflow");
63 }
64 pub const sentinelMismatch = no_panic.sentinelMismatch;
65 pub const unwrapError = no_panic.unwrapError;
66 pub const outOfBounds = no_panic.outOfBounds;
67 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
68 pub const inactiveUnionField = no_panic.inactiveUnionField;
69 pub const reachedUnreachable = no_panic.reachedUnreachable;
70 pub const unwrapNull = no_panic.unwrapNull;
71 pub const castToNull = no_panic.castToNull;
72 pub const incorrectAlignment = no_panic.incorrectAlignment;
73 pub const invalidErrorCode = no_panic.invalidErrorCode;
74 pub const castTruncatedData = no_panic.castTruncatedData;
75 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
76 pub const shlOverflow = no_panic.shlOverflow;
77 pub const shrOverflow = no_panic.shrOverflow;
78 pub const divideByZero = no_panic.divideByZero;
79 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
80 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
81 pub const corruptSwitch = no_panic.corruptSwitch;
82 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
83 pub const invalidEnumValue = no_panic.invalidEnumValue;
84 pub const forLenMismatch = no_panic.forLenMismatch;
85 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
86 pub const memcpyAlias = no_panic.memcpyAlias;
87 pub const noreturnReturned = no_panic.noreturnReturned;
88};
89fn myPanic(msg: []const u8, _: ?usize) noreturn {
90 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
91 std.process.exit(0);
92}
93const std = @import("std");
94#expect_stdout="new panic message: integer overflow\n"
95
96#update=change the panic handler function value
97#file=main.zig
98pub fn main() !u8 {
99 var a: u8 = undefined;
100 a = 255;
101 _ = a + 1;
102 return 1;
103}
104const no_panic = std.debug.no_panic;
105pub const panic = struct {
106 pub const call = myPanicNew;
107 pub fn integerOverflow() noreturn {
108 @panic("integer overflow");
109 }
110 pub const sentinelMismatch = std.debug.no_panic.sentinelMismatch;
111 pub const unwrapError = std.debug.no_panic.unwrapError;
112 pub const outOfBounds = std.debug.no_panic.outOfBounds;
113 pub const startGreaterThanEnd = std.debug.no_panic.startGreaterThanEnd;
114 pub const inactiveUnionField = std.debug.no_panic.inactiveUnionField;
115 pub const messages = std.debug.no_panic.messages;
116 pub const reachedUnreachable = no_panic.reachedUnreachable;
117 pub const unwrapNull = no_panic.unwrapNull;
118 pub const castToNull = no_panic.castToNull;
119 pub const incorrectAlignment = no_panic.incorrectAlignment;
120 pub const invalidErrorCode = no_panic.invalidErrorCode;
121 pub const castTruncatedData = no_panic.castTruncatedData;
122 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
123 pub const shlOverflow = no_panic.shlOverflow;
124 pub const shrOverflow = no_panic.shrOverflow;
125 pub const divideByZero = no_panic.divideByZero;
126 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
127 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
128 pub const corruptSwitch = no_panic.corruptSwitch;
129 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
130 pub const invalidEnumValue = no_panic.invalidEnumValue;
131 pub const forLenMismatch = no_panic.forLenMismatch;
132 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
133 pub const memcpyAlias = no_panic.memcpyAlias;
134 pub const noreturnReturned = no_panic.noreturnReturned;
135};
136fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
137 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
138 std.process.exit(0);
139}
140const std = @import("std");
141#expect_stdout="third panic message: integer overflow\n"
test/src/Cases.zig-1
......@@ -358,7 +358,6 @@ pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void {
358358 var current_file: []const u8 = "none";
359359 ctx.addFromDirInner(dir, &current_file, b) catch |err| {
360360 std.debug.panicExtra(
361 @errorReturnTrace(),
362361 @returnAddress(),
363362 "test harness failed to process file '{s}': {s}\n",
364363 .{ current_file, @errorName(err) },