| author | |
| committer | |
| log | 1a4b0d979027069d55ef354e6d04ea10cf455344 |
| tree | 1b983c6b5b8a18e880c4a4a9fb6c6cdf00f8a55a |
| parent | 77b40d6ecb8d04bd9d8b95b04b8ba6ce3a6ea604 |
Resolves: #158612 files changed, 43 insertions(+), 1 deletions(-)
src/AstGen.zig+17-1| ... | @@ -2982,11 +2982,27 @@ fn deferStmt( | ... | @@ -2982,11 +2982,27 @@ fn deferStmt( |
| 2982 | if (have_err_code) try gz.addDbgBlockEnd(); | 2982 | if (have_err_code) try gz.addDbgBlockEnd(); |
| 2983 | _ = try defer_gen.addBreak(.break_inline, 0, .void_value); | 2983 | _ = try defer_gen.addBreak(.break_inline, 0, .void_value); |
| 2984 | 2984 | ||
| 2985 | // We must handle ref_table for remapped_err_code manually. | ||
| 2985 | const body = defer_gen.instructionsSlice(); | 2986 | const body = defer_gen.instructionsSlice(); |
| 2986 | const body_len = gz.astgen.countBodyLenAfterFixups(body); | 2987 | const body_len = blk: { |
| 2988 | var refs: u32 = 0; | ||
| 2989 | if (have_err_code) { | ||
| 2990 | var cur_inst = remapped_err_code; | ||
| 2991 | while (gz.astgen.ref_table.get(cur_inst)) |ref_inst| { | ||
| 2992 | refs += 1; | ||
| 2993 | cur_inst = ref_inst; | ||
| 2994 | } | ||
| 2995 | } | ||
| 2996 | break :blk gz.astgen.countBodyLenAfterFixups(body) + refs; | ||
| 2997 | }; | ||
| 2987 | 2998 | ||
| 2988 | const index = @intCast(u32, gz.astgen.extra.items.len); | 2999 | const index = @intCast(u32, gz.astgen.extra.items.len); |
| 2989 | try gz.astgen.extra.ensureUnusedCapacity(gz.astgen.gpa, body_len); | 3000 | try gz.astgen.extra.ensureUnusedCapacity(gz.astgen.gpa, body_len); |
| 3001 | if (have_err_code) { | ||
| 3002 | if (gz.astgen.ref_table.fetchRemove(remapped_err_code)) |kv| { | ||
| 3003 | gz.astgen.appendPossiblyRefdBodyInst(&gz.astgen.extra, kv.value); | ||
| 3004 | } | ||
| 3005 | } | ||
| 2990 | gz.astgen.appendBodyWithFixups(body); | 3006 | gz.astgen.appendBodyWithFixups(body); |
| 2991 | 3007 | ||
| 2992 | const defer_scope = try block_arena.create(Scope.Defer); | 3008 | const defer_scope = try block_arena.create(Scope.Defer); |
test/behavior/defer.zig+26| ... | @@ -134,6 +134,32 @@ test "errdefer with payload" { | ... | @@ -134,6 +134,32 @@ test "errdefer with payload" { |
| 134 | comptime try S.doTheTest(); | 134 | comptime try S.doTheTest(); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | test "reference to errdefer payload" { | ||
| 138 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 139 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 140 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 141 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 142 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 143 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 144 | |||
| 145 | const S = struct { | ||
| 146 | fn foo() !i32 { | ||
| 147 | errdefer |a| { | ||
| 148 | const ptr = &a; | ||
| 149 | const ptr2 = &ptr; | ||
| 150 | expectEqual(error.One, ptr2.*.*) catch @panic("test failure"); | ||
| 151 | expectEqual(error.One, ptr.*) catch @panic("test failure"); | ||
| 152 | } | ||
| 153 | return error.One; | ||
| 154 | } | ||
| 155 | fn doTheTest() !void { | ||
| 156 | try expectError(error.One, foo()); | ||
| 157 | } | ||
| 158 | }; | ||
| 159 | try S.doTheTest(); | ||
| 160 | comptime try S.doTheTest(); | ||
| 161 | } | ||
| 162 | |||
| 137 | test "simple else prong doesn't emit an error for unreachable else prong" { | 163 | test "simple else prong doesn't emit an error for unreachable else prong" { |
| 138 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 164 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 139 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 165 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |