authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-02 14:58:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-02 14:58:27-07:00
log0611aa39858e6d7613cda3b3da981ff6b208a5e8
tree271d5fa44237d19d7fb4b09d21b84c939658b9ca
parent4dd724d06a99d7b82b1b1758d28aa5559550f5bb

stage2: test decls encode that they are tests in ZIR

This allows Sema to namespace them separately from function decls with the same name. Ran into this in std.math.order conflicting with a test with the same name.

4 files changed, 40 insertions(+), 7 deletions(-)

BRANCH_TODO+3
...@@ -1,3 +1,6 @@...@@ -1,3 +1,6 @@
1 * running build-exe with cached ZIR crashes
2 * implement lazy struct field resolution; don't resolve struct fields until
3 they are needed.
1 * decouple AstGen from Module, Compilation4 * decouple AstGen from Module, Compilation
2 * AstGen threadlocal5 * AstGen threadlocal
3 * extern "foo" for vars and for functions6 * extern "foo" for vars and for functions
src/AstGen.zig+12-1
...@@ -3197,7 +3197,7 @@ fn testDecl(...@@ -3197,7 +3197,7 @@ fn testDecl(
3197 const test_token = main_tokens[node];3197 const test_token = main_tokens[node];
3198 const str_lit_token = test_token + 1;3198 const str_lit_token = test_token + 1;
3199 if (token_tags[str_lit_token] == .string_literal) {3199 if (token_tags[str_lit_token] == .string_literal) {
3200 break :blk (try astgen.strLitAsString(str_lit_token)).index;3200 break :blk try astgen.testNameString(str_lit_token);
3201 }3201 }
3202 // String table index 1 has a special meaning here of test decl with no name.3202 // String table index 1 has a special meaning here of test decl with no name.
3203 break :blk 1;3203 break :blk 1;
...@@ -7806,3 +7806,14 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {...@@ -7806,3 +7806,14 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
7806 };7806 };
7807 }7807 }
7808}7808}
7809
7810fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
7811 const gpa = astgen.gpa;
7812 const string_bytes = &astgen.string_bytes;
7813 const str_index = @intCast(u32, string_bytes.items.len);
7814 const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);
7815 try string_bytes.append(gpa, 0); // Indicates this is a test.
7816 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7817 try string_bytes.append(gpa, 0);
7818 return str_index;
7819}
src/Module.zig+7-2
...@@ -3817,7 +3817,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3817,7 +3817,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3817 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);3817 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
38183818
3819 // Every Decl needs a name.3819 // Every Decl needs a name.
3820 const decl_name: [:0]const u8 = switch (decl_name_index) {3820 const raw_decl_name: [:0]const u8 = switch (decl_name_index) {
3821 0 => name: {3821 0 => name: {
3822 if (is_exported) {3822 if (is_exported) {
3823 const i = iter.usingnamespace_index;3823 const i = iter.usingnamespace_index;
...@@ -3836,6 +3836,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3836,6 +3836,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3836 },3836 },
3837 else => zir.nullTerminatedString(decl_name_index),3837 else => zir.nullTerminatedString(decl_name_index),
3838 };3838 };
3839 const decl_name = if (raw_decl_name.len != 0) raw_decl_name else name: {
3840 const test_name = zir.nullTerminatedString(decl_name_index + 1);
3841 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
3842 };
3839 log.debug("scan decl {s} is_pub={}", .{ decl_name, is_pub });3843 log.debug("scan decl {s} is_pub={}", .{ decl_name, is_pub });
38403844
3841 // We create a Decl for it regardless of analysis status.3845 // We create a Decl for it regardless of analysis status.
...@@ -3847,10 +3851,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3847,10 +3851,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3847 gop.entry.value = new_decl;3851 gop.entry.value = new_decl;
3848 // Exported decls, comptime decls, usingnamespace decls, and3852 // Exported decls, comptime decls, usingnamespace decls, and
3849 // test decls if in test mode, get analyzed.3853 // test decls if in test mode, get analyzed.
3854 const is_named_test = raw_decl_name.len == 0;
3850 const want_analysis = is_exported or switch (decl_name_index) {3855 const want_analysis = is_exported or switch (decl_name_index) {
3851 0 => true, // comptime decl3856 0 => true, // comptime decl
3852 1 => mod.comp.bin_file.options.is_test, // test decl3857 1 => mod.comp.bin_file.options.is_test, // test decl
3853 else => false, // TODO set to true for named tests when testing3858 else => is_named_test and mod.comp.bin_file.options.is_test,
3854 };3859 };
3855 if (want_analysis) {3860 if (want_analysis) {
3856 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3861 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
src/Zir.zig+18-4
...@@ -2421,6 +2421,8 @@ pub const Inst = struct {...@@ -2421,6 +2421,8 @@ pub const Inst = struct {
2421 /// - 0 means comptime or usingnamespace decl.2421 /// - 0 means comptime or usingnamespace decl.
2422 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2422 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2423 /// - 1 means test decl with no name.2423 /// - 1 means test decl with no name.
2424 /// - if there is a 0 byte at the position `name` indexes, it indicates
2425 /// this is a test decl, and the name starts at `name+1`.
2424 /// value: Index,2426 /// value: Index,
2425 /// align: Ref, // if corresponding bit is set2427 /// align: Ref, // if corresponding bit is set
2426 /// link_section: Ref, // if corresponding bit is set2428 /// link_section: Ref, // if corresponding bit is set
...@@ -2459,6 +2461,8 @@ pub const Inst = struct {...@@ -2459,6 +2461,8 @@ pub const Inst = struct {
2459 /// - 0 means comptime or usingnamespace decl.2461 /// - 0 means comptime or usingnamespace decl.
2460 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2462 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2461 /// - 1 means test decl with no name.2463 /// - 1 means test decl with no name.
2464 /// - if there is a 0 byte at the position `name` indexes, it indicates
2465 /// this is a test decl, and the name starts at `name+1`.
2462 /// value: Index,2466 /// value: Index,
2463 /// align: Ref, // if corresponding bit is set2467 /// align: Ref, // if corresponding bit is set
2464 /// link_section: Ref, // if corresponding bit is set2468 /// link_section: Ref, // if corresponding bit is set
...@@ -2492,6 +2496,8 @@ pub const Inst = struct {...@@ -2492,6 +2496,8 @@ pub const Inst = struct {
2492 /// - 0 means comptime or usingnamespace decl.2496 /// - 0 means comptime or usingnamespace decl.
2493 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2497 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2494 /// - 1 means test decl with no name.2498 /// - 1 means test decl with no name.
2499 /// - if there is a 0 byte at the position `name` indexes, it indicates
2500 /// this is a test decl, and the name starts at `name+1`.
2495 /// value: Index,2501 /// value: Index,
2496 /// align: Ref, // if corresponding bit is set2502 /// align: Ref, // if corresponding bit is set
2497 /// link_section: Ref, // if corresponding bit is set2503 /// link_section: Ref, // if corresponding bit is set
...@@ -2535,8 +2541,9 @@ pub const Inst = struct {...@@ -2535,8 +2541,9 @@ pub const Inst = struct {
2535 /// - 0 means comptime or usingnamespace decl.2541 /// - 0 means comptime or usingnamespace decl.
2536 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2542 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2537 /// - 1 means test decl with no name.2543 /// - 1 means test decl with no name.
2544 /// - if there is a 0 byte at the position `name` indexes, it indicates
2545 /// this is a test decl, and the name starts at `name+1`.
2538 /// value: Index,2546 /// value: Index,
2539 /// - one of: block_inline
2540 /// align: Ref, // if corresponding bit is set2547 /// align: Ref, // if corresponding bit is set
2541 /// link_section: Ref, // if corresponding bit is set2548 /// link_section: Ref, // if corresponding bit is set
2542 /// }2549 /// }
...@@ -3631,7 +3638,6 @@ const Writer = struct {...@@ -3631,7 +3638,6 @@ const Writer = struct {
3631 const line = self.code.extra[extra_index];3638 const line = self.code.extra[extra_index];
3632 extra_index += 1;3639 extra_index += 1;
3633 const decl_name_index = self.code.extra[extra_index];3640 const decl_name_index = self.code.extra[extra_index];
3634 const decl_name = self.code.nullTerminatedString(decl_name_index);
3635 extra_index += 1;3641 extra_index += 1;
3636 const decl_index = self.code.extra[extra_index];3642 const decl_index = self.code.extra[extra_index];
3637 extra_index += 1;3643 extra_index += 1;
...@@ -3653,10 +3659,18 @@ const Writer = struct {...@@ -3653,10 +3659,18 @@ const Writer = struct {
3653 const name = if (is_exported) "usingnamespace" else "comptime";3659 const name = if (is_exported) "usingnamespace" else "comptime";
3654 try stream.writeAll(pub_str);3660 try stream.writeAll(pub_str);
3655 try stream.writeAll(name);3661 try stream.writeAll(name);
3662 } else if (decl_name_index == 1) {
3663 try stream.writeAll("test");
3656 } else {3664 } else {
3665 const raw_decl_name = self.code.nullTerminatedString(decl_name_index);
3666 const decl_name = if (raw_decl_name.len == 0)
3667 self.code.nullTerminatedString(decl_name_index + 1)
3668 else
3669 raw_decl_name;
3670 const test_str = if (raw_decl_name.len == 0) "test " else "";
3657 const export_str = if (is_exported) "export " else "";3671 const export_str = if (is_exported) "export " else "";
3658 try stream.print("{s}{s}{}", .{3672 try stream.print("{s}{s}{s}{}", .{
3659 pub_str, export_str, std.zig.fmtId(decl_name),3673 pub_str, test_str, export_str, std.zig.fmtId(decl_name),
3660 });3674 });
3661 if (align_inst != .none) {3675 if (align_inst != .none) {
3662 try stream.writeAll(" align(");3676 try stream.writeAll(" align(");