aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-27 14:52:00 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-27 14:52:00 -0700
commite494ce760428cde79b63e9a9016c4af06484eef3 (patch)
tree3205a2de5e327e61883c1d2dec37e027fe079842 /src/Module.zig
parentc1a5ff34f3f68a2a0bc32828ab483328cd436fea (diff)
downloadzig-e494ce760428cde79b63e9a9016c4af06484eef3.tar.gz
zig-e494ce760428cde79b63e9a9016c4af06484eef3.zip
stage2: fix small memory leak of test_functions when using `zig test`
The way `zig test` works is that it uses a stand-in var test_functions: []const TestFn = undefined; during semantic analysis, but then just before codegen, it swaps out the value with a constant like this: const test_functions: []const TestFn = .{foo, bar, baz, etc}; Before this commit, the `Module.Variable` associated with the stand-in value was leaked; now it is properly cleaned up before being replaced.
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 2c51b0ab69..f0b3701e6e 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4767,15 +4767,25 @@ pub fn populateTestFunctions(mod: *Module) !void {
try mod.linkerUpdateDecl(array_decl);
{
- var arena_instance = decl.value_arena.?.promote(gpa);
- defer decl.value_arena.?.* = arena_instance.state;
- const arena = &arena_instance.allocator;
+ var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
+ errdefer new_decl_arena.deinit();
+ const arena = &new_decl_arena.allocator;
- decl.ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena));
- decl.val = try Value.Tag.slice.create(arena, .{
+ // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.
+ const new_ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena));
+ const new_val = try Value.Tag.slice.create(arena, .{
.ptr = try Value.Tag.decl_ref.create(arena, array_decl),
.len = try Value.Tag.int_u64.create(arena, mod.test_functions.count()),
});
+
+ // Since we are replacing the Decl's value we must perform cleanup on the
+ // previous value.
+ decl.clearValues(gpa);
+ decl.ty = new_ty;
+ decl.val = new_val;
+ decl.has_tv = true;
+
+ try decl.finalizeNewArena(&new_decl_arena);
}
try mod.linkerUpdateDecl(decl);
}