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.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
* running build-exe with cached ZIR crashes
|
||||
* implement lazy struct field resolution; don't resolve struct fields until
|
||||
they are needed.
|
||||
* decouple AstGen from Module, Compilation
|
||||
* AstGen threadlocal
|
||||
* extern "foo" for vars and for functions
|
||||
|
||||
@@ -3197,7 +3197,7 @@ fn testDecl(
|
||||
const test_token = main_tokens[node];
|
||||
const str_lit_token = test_token + 1;
|
||||
if (token_tags[str_lit_token] == .string_literal) {
|
||||
break :blk (try astgen.strLitAsString(str_lit_token)).index;
|
||||
break :blk try astgen.testNameString(str_lit_token);
|
||||
}
|
||||
// String table index 1 has a special meaning here of test decl with no name.
|
||||
break :blk 1;
|
||||
@@ -7806,3 +7806,14 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
|
||||
const gpa = astgen.gpa;
|
||||
const string_bytes = &astgen.string_bytes;
|
||||
const str_index = @intCast(u32, string_bytes.items.len);
|
||||
const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);
|
||||
try string_bytes.append(gpa, 0); // Indicates this is a test.
|
||||
try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
|
||||
try string_bytes.append(gpa, 0);
|
||||
return str_index;
|
||||
}
|
||||
|
||||
@@ -3817,7 +3817,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
|
||||
const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
|
||||
|
||||
// Every Decl needs a name.
|
||||
const decl_name: [:0]const u8 = switch (decl_name_index) {
|
||||
const raw_decl_name: [:0]const u8 = switch (decl_name_index) {
|
||||
0 => name: {
|
||||
if (is_exported) {
|
||||
const i = iter.usingnamespace_index;
|
||||
@@ -3836,6 +3836,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
|
||||
},
|
||||
else => zir.nullTerminatedString(decl_name_index),
|
||||
};
|
||||
const decl_name = if (raw_decl_name.len != 0) raw_decl_name else name: {
|
||||
const test_name = zir.nullTerminatedString(decl_name_index + 1);
|
||||
break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
|
||||
};
|
||||
log.debug("scan decl {s} is_pub={}", .{ decl_name, is_pub });
|
||||
|
||||
// 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
|
||||
gop.entry.value = new_decl;
|
||||
// Exported decls, comptime decls, usingnamespace decls, and
|
||||
// test decls if in test mode, get analyzed.
|
||||
const is_named_test = raw_decl_name.len == 0;
|
||||
const want_analysis = is_exported or switch (decl_name_index) {
|
||||
0 => true, // comptime decl
|
||||
1 => mod.comp.bin_file.options.is_test, // test decl
|
||||
else => false, // TODO set to true for named tests when testing
|
||||
else => is_named_test and mod.comp.bin_file.options.is_test,
|
||||
};
|
||||
if (want_analysis) {
|
||||
mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
|
||||
|
||||
22
src/Zir.zig
22
src/Zir.zig
@@ -2421,6 +2421,8 @@ pub const Inst = struct {
|
||||
/// - 0 means comptime or usingnamespace decl.
|
||||
/// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
|
||||
/// - 1 means test decl with no name.
|
||||
/// - if there is a 0 byte at the position `name` indexes, it indicates
|
||||
/// this is a test decl, and the name starts at `name+1`.
|
||||
/// value: Index,
|
||||
/// align: Ref, // if corresponding bit is set
|
||||
/// link_section: Ref, // if corresponding bit is set
|
||||
@@ -2459,6 +2461,8 @@ pub const Inst = struct {
|
||||
/// - 0 means comptime or usingnamespace decl.
|
||||
/// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
|
||||
/// - 1 means test decl with no name.
|
||||
/// - if there is a 0 byte at the position `name` indexes, it indicates
|
||||
/// this is a test decl, and the name starts at `name+1`.
|
||||
/// value: Index,
|
||||
/// align: Ref, // if corresponding bit is set
|
||||
/// link_section: Ref, // if corresponding bit is set
|
||||
@@ -2492,6 +2496,8 @@ pub const Inst = struct {
|
||||
/// - 0 means comptime or usingnamespace decl.
|
||||
/// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
|
||||
/// - 1 means test decl with no name.
|
||||
/// - if there is a 0 byte at the position `name` indexes, it indicates
|
||||
/// this is a test decl, and the name starts at `name+1`.
|
||||
/// value: Index,
|
||||
/// align: Ref, // if corresponding bit is set
|
||||
/// link_section: Ref, // if corresponding bit is set
|
||||
@@ -2535,8 +2541,9 @@ pub const Inst = struct {
|
||||
/// - 0 means comptime or usingnamespace decl.
|
||||
/// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
|
||||
/// - 1 means test decl with no name.
|
||||
/// - if there is a 0 byte at the position `name` indexes, it indicates
|
||||
/// this is a test decl, and the name starts at `name+1`.
|
||||
/// value: Index,
|
||||
/// - one of: block_inline
|
||||
/// align: Ref, // if corresponding bit is set
|
||||
/// link_section: Ref, // if corresponding bit is set
|
||||
/// }
|
||||
@@ -3631,7 +3638,6 @@ const Writer = struct {
|
||||
const line = self.code.extra[extra_index];
|
||||
extra_index += 1;
|
||||
const decl_name_index = self.code.extra[extra_index];
|
||||
const decl_name = self.code.nullTerminatedString(decl_name_index);
|
||||
extra_index += 1;
|
||||
const decl_index = self.code.extra[extra_index];
|
||||
extra_index += 1;
|
||||
@@ -3653,10 +3659,18 @@ const Writer = struct {
|
||||
const name = if (is_exported) "usingnamespace" else "comptime";
|
||||
try stream.writeAll(pub_str);
|
||||
try stream.writeAll(name);
|
||||
} else if (decl_name_index == 1) {
|
||||
try stream.writeAll("test");
|
||||
} else {
|
||||
const raw_decl_name = self.code.nullTerminatedString(decl_name_index);
|
||||
const decl_name = if (raw_decl_name.len == 0)
|
||||
self.code.nullTerminatedString(decl_name_index + 1)
|
||||
else
|
||||
raw_decl_name;
|
||||
const test_str = if (raw_decl_name.len == 0) "test " else "";
|
||||
const export_str = if (is_exported) "export " else "";
|
||||
try stream.print("{s}{s}{}", .{
|
||||
pub_str, export_str, std.zig.fmtId(decl_name),
|
||||
try stream.print("{s}{s}{s}{}", .{
|
||||
pub_str, test_str, export_str, std.zig.fmtId(decl_name),
|
||||
});
|
||||
if (align_inst != .none) {
|
||||
try stream.writeAll(" align(");
|
||||
|
||||
Reference in New Issue
Block a user