authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-31 01:03:05+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-03 13:36:44-07:00
log1a4b0d979027069d55ef354e6d04ea10cf455344
tree1b983c6b5b8a18e880c4a4a9fb6c6cdf00f8a55a
parent77b40d6ecb8d04bd9d8b95b04b8ba6ce3a6ea604

AstGen: handle ref_table for errdefer captures

Resolves: #15861

2 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);
29842984
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 };
29872998
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);
29913007
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}
136136
137test "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
137test "simple else prong doesn't emit an error for unreachable else prong" {163test "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; // TODO165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO