Commit c92816fbef
Changed files (2)
src-self-hosted
test
stage2
src-self-hosted/test.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const link = @import("link.zig");
const Module = @import("Module.zig");
+const ErrorMsg = Module.ErrorMsg;
const Allocator = std.mem.Allocator;
const zir = @import("zir.zig");
const Package = @import("Package.zig");
@@ -18,6 +19,7 @@ test "self-hosted" {
pub const TestContext = struct {
zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
zir_transform_cases: std.ArrayList(ZIRTransformCase),
+ zir_error_cases: std.ArrayList(ZIRErrorCase),
pub const ZIRCompareOutputCase = struct {
name: []const u8,
@@ -55,6 +57,15 @@ pub const TestContext = struct {
}
};
+ pub const ZIRErrorCase = struct {
+ name: []const u8,
+ src: [:0]const u8,
+ expected_file_errors: []const ErrorMsg,
+ expected_decl_errors: []const ErrorMsg,
+ expected_export_errors: []const ErrorMsg,
+ cross_target: std.zig.CrossTarget,
+ };
+
pub fn addZIRCompareOutput(
ctx: *TestContext,
name: []const u8,
@@ -87,30 +98,38 @@ pub const TestContext = struct {
}) catch unreachable;
}
- pub fn addZIRMulti(
+ pub fn addZIRError(
ctx: *TestContext,
name: []const u8,
cross_target: std.zig.CrossTarget,
- ) *ZIRTransformCase {
- const case = ctx.zir_transform_cases.addOne() catch unreachable;
- case.* = .{
+ src: [:0]const u8,
+ expected_file_errors: []const ErrorMsg,
+ expected_decl_errors: []const ErrorMsg,
+ expected_export_errors: []const ErrorMsg,
+ ) void {
+ ctx.zir_error_cases.append(.{
.name = name,
+ .src = src,
+ .expected_file_errors = expected_file_errors,
+ .expected_decl_errors = expected_decl_errors,
+ .expected_export_errors = expected_export_errors,
.cross_target = cross_target,
- .updates = std.ArrayList(ZIRTransformCase.Update).init(std.heap.page_allocator),
- };
- return case;
+ }) catch unreachable;
}
fn init(self: *TestContext) !void {
+ const allocator = std.heap.page_allocator;
self.* = .{
- .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(std.heap.page_allocator),
- .zir_transform_cases = std.ArrayList(ZIRTransformCase).init(std.heap.page_allocator),
+ .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(allocator),
+ .zir_transform_cases = std.ArrayList(ZIRTransformCase).init(allocator),
+ .zir_error_cases = std.ArrayList(ZIRErrorCase).init(allocator),
};
}
fn deinit(self: *TestContext) void {
self.zir_cmp_output_cases.deinit();
self.zir_transform_cases.deinit();
+ self.zir_error_cases.deinit();
self.* = undefined;
}
@@ -133,6 +152,12 @@ pub const TestContext = struct {
try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, info.target);
try std.testing.allocator_instance.validate();
}
+ for (self.zir_error_cases.items) |case| {
+ std.testing.base_allocator_instance.reset();
+ const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.cross_target);
+ try self.runOneZIRErrorCase(std.testing.allocator, root_node, case, info.target);
+ try std.testing.allocator_instance.validate();
+ }
}
fn runOneZIRCmpOutputCase(
@@ -300,6 +325,105 @@ pub const TestContext = struct {
}
}
}
+
+ fn runOneZIRErrorCase(
+ self: *TestContext,
+ allocator: *Allocator,
+ root_node: *std.Progress.Node,
+ case: ZIRErrorCase,
+ target: std.Target,
+ ) !void {
+ var tmp = std.testing.tmpDir(.{});
+ defer tmp.cleanup();
+
+ var prg_node = root_node.start(case.name, 1);
+ prg_node.activate();
+ defer prg_node.end();
+
+ const tmp_src_path = "test-case.zir";
+ try tmp.dir.writeFile(tmp_src_path, case.src);
+
+ const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
+ defer root_pkg.destroy();
+
+ var module = try Module.init(allocator, .{
+ .target = target,
+ .output_mode = .Obj,
+ .optimize_mode = .Debug,
+ .bin_file_dir = tmp.dir,
+ .bin_file_path = "test-case.o",
+ .root_pkg = root_pkg,
+ });
+ defer module.deinit();
+
+ var module_node = prg_node.start("parse/analysis/codegen", null);
+ module_node.activate();
+ const failed = f: {
+ module.update() catch break :f true;
+ break :f false;
+ };
+ if (!failed) {
+ return error.DidNotFail;
+ }
+ module_node.end();
+ {
+ var i = module.failed_files.iterator();
+ var index: usize = 0;
+ while (i.next()) |pair| : (index += 1) {
+ if (index == case.expected_file_errors.len) {
+ return error.UnexpectedError;
+ }
+ const v1 = pair.value.*;
+ const v2 = case.expected_file_errors[index];
+ if (v1.byte_offset != v2.byte_offset) {
+ std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
+ return error.ExpectedErrorElsewhere;
+ }
+ if (!std.mem.eql(u8, v1.msg, v2.msg)) {
+ std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
+ return error.ExpectedOtherError;
+ }
+ }
+ }
+ {
+ var i = module.failed_decls.iterator();
+ var index: usize = 0;
+ while (i.next()) |pair| : (index += 1) {
+ if (index == case.expected_decl_errors.len) {
+ return error.UnexpectedError;
+ }
+ const v1 = pair.value.*;
+ const v2 = case.expected_decl_errors[index];
+ if (v1.byte_offset != v2.byte_offset) {
+ std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
+ return error.ExpectedErrorElsewhere;
+ }
+ if (!std.mem.eql(u8, v1.msg, v2.msg)) {
+ std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
+ return error.ExpectedOtherError;
+ }
+ }
+ }
+ {
+ var i = module.failed_exports.iterator();
+ var index: usize = 0;
+ while (i.next()) |pair| : (index += 1) {
+ if (index == case.expected_export_errors.len) {
+ return error.UnexpectedError;
+ }
+ const v1 = pair.value.*;
+ const v2 = case.expected_export_errors[index];
+ if (v1.byte_offset != v2.byte_offset) {
+ std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
+ return error.ExpectedErrorElsewhere;
+ }
+ if (!std.mem.eql(u8, v1.msg, v2.msg)) {
+ std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
+ return error.ExpectedOtherError;
+ }
+ }
+ }
+ }
};
fn debugPrintErrors(src: []const u8, errors: var) void {
test/stage2/compile_errors.zig
@@ -1,8 +1,29 @@
const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
+const std = @import("std");
+
+const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg;
+
+const linux_x64 = std.zig.CrossTarget{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+};
pub fn addCases(ctx: *TestContext) !void {
// TODO: re-enable these tests.
// https://github.com/ziglang/zig/issues/1364
+ ctx.addZIRError("test", linux_x64,
+ \\@noreturn = primitive(noreturn)
+ \\@void = primitive(void)
+ \\@usize = primitive(usize)
+ \\
+ \\@start_fnty = fntype([], @noreturn, cc=Naked)
+ \\@start = fn(@start_fnty, {
+ \\ %0 = call(%test, [])
+ \\})
+ , &[_]ErrorMsg{.{
+ .byte_offset = 168,
+ .msg = "unrecognized identifier: %test",
+ }}, &[_]ErrorMsg{}, &[_]ErrorMsg{});
//try ctx.testCompileError(
// \\export fn entry() void {}