Commit d656c2a7ab
Changed files (26)
lib
std
Build
Step
src
test
doc/langref.html.in
@@ -988,13 +988,13 @@ fn addOne(number: i32) i32 {
printed to standard error by the default test runner:
</p>
<dl>
- <dt><samp>Test [1/2] test.expect addOne adds one to 41...</samp></dt>
+ <dt><samp>1/2 testing_introduction.test.expect addOne adds one to 41...</samp></dt>
<dd>Lines like this indicate which test, out of the total number of tests, is being run.
- In this case, <samp>[1/2]</samp> indicates that the first test, out of a total of
- two test, is being run. Note that, when the test runner program's standard error is output
+ In this case, <samp>1/2</samp> indicates that the first test, out of a total of two tests,
+ is being run. Note that, when the test runner program's standard error is output
to the terminal, these lines are cleared when a test succeeds.
</dd>
- <dt><samp>Test [2/2] decltest.addOne...</samp></dt>
+ <dt><samp>2/2 testing_introduction.decltest.addOne...</samp></dt>
<dd>When the test name is an identifier, the default test runner uses the text
decltest instead of test.
</dd>
lib/std/Build/Step/Compile.zig
@@ -54,7 +54,7 @@ global_base: ?u64 = null,
/// Set via options; intended to be read-only after that.
zig_lib_dir: ?LazyPath,
exec_cmd_args: ?[]const ?[]const u8,
-filter: ?[]const u8,
+filters: []const []const u8,
test_runner: ?[]const u8,
test_server_mode: bool,
wasi_exec_model: ?std.builtin.WasiExecModel = null,
@@ -223,7 +223,7 @@ pub const Options = struct {
linkage: ?Linkage = null,
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
- filter: ?[]const u8 = null,
+ filters: []const []const u8 = &.{},
test_runner: ?[]const u8 = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
@@ -310,7 +310,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.installed_headers = ArrayList(*Step).init(owner.allocator),
.zig_lib_dir = null,
.exec_cmd_args = null,
- .filter = options.filter,
+ .filters = options.filters,
.test_runner = options.test_runner,
.test_server_mode = options.test_runner == null,
.rdynamic = false,
@@ -1297,7 +1297,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
try zig_args.append(b.fmt("0x{x}", .{image_base}));
}
- if (self.filter) |filter| {
+ for (self.filters) |filter| {
try zig_args.append("--test-filter");
try zig_args.append(filter);
}
lib/std/Build.zig
@@ -855,7 +855,9 @@ pub const TestOptions = struct {
optimize: std.builtin.OptimizeMode = .Debug,
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
+ /// deprecated: use `.filters = &.{filter}` instead of `.filter = filter`.
filter: ?[]const u8 = null,
+ filters: []const []const u8 = &.{},
test_runner: ?[]const u8 = null,
link_libc: ?bool = null,
single_threaded: ?bool = null,
@@ -888,7 +890,12 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
.error_tracing = options.error_tracing,
},
.max_rss = options.max_rss,
- .filter = options.filter,
+ .filters = if (options.filter != null and options.filters.len > 0) filters: {
+ const filters = b.allocator.alloc([]const u8, 1 + options.filters.len) catch @panic("OOM");
+ filters[0] = b.dupe(options.filter.?);
+ for (filters[1..], options.filters) |*dest, source| dest.* = b.dupe(source);
+ break :filters filters;
+ } else b.dupeStrings(if (options.filter) |filter| &.{filter} else options.filters),
.test_runner = options.test_runner,
.use_llvm = options.use_llvm,
.use_lld = options.use_lld,
@@ -993,9 +1000,7 @@ pub fn dupe(self: *Build, bytes: []const u8) []u8 {
/// Duplicates an array of strings without the need to handle out of memory.
pub fn dupeStrings(self: *Build, strings: []const []const u8) [][]u8 {
const array = self.allocator.alloc([]u8, strings.len) catch @panic("OOM");
- for (strings, 0..) |s, i| {
- array[i] = self.dupe(s);
- }
+ for (array, strings) |*dest, source| dest.* = self.dupe(source);
return array;
}
src/arch/wasm/CodeGen.zig
@@ -7223,7 +7223,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();
- const fqn = ip.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod));
+ const fqn = ip.stringToSlice(try mod.declPtr(enum_decl_index).fullyQualifiedName(mod));
const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
// check if we already generated code for this.
src/codegen/llvm.zig
@@ -1163,7 +1163,7 @@ pub const Object = struct {
const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
const namespace = self.module.namespacePtr(namespace_index);
- const debug_type = try self.lowerDebugType(namespace.ty);
+ const debug_type = try self.lowerDebugType(namespace.getType(self.module));
self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
}
@@ -1797,7 +1797,7 @@ pub const Object = struct {
return updateExportedGlobal(self, mod, global_index, exports);
} else {
const fqn = try self.builder.string(
- mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)),
+ mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)),
);
try global_index.rename(fqn, &self.builder);
global_index.setLinkage(.internal, &self.builder);
@@ -2835,15 +2835,13 @@ pub const Object = struct {
const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");
const std_namespace = mod.namespacePtr(mod.declPtr(std_file.root_decl.unwrap().?).src_namespace);
- const builtin_decl = std_namespace.decls
- .getKeyAdapted(builtin_str, Module.DeclAdapter{ .mod = mod }).?;
+ const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Module.DeclAdapter{ .zcu = mod }).?;
const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace");
// buffer is only used for int_type, `builtin` is a struct.
const builtin_ty = mod.declPtr(builtin_decl).val.toType();
const builtin_namespace = builtin_ty.getNamespace(mod).?;
- const stack_trace_decl_index = builtin_namespace.decls
- .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?;
+ const stack_trace_decl_index = builtin_namespace.decls.getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .zcu = mod }).?;
const stack_trace_decl = mod.declPtr(stack_trace_decl_index);
// Sema should have ensured that StackTrace was analyzed.
@@ -2886,7 +2884,7 @@ pub const Object = struct {
try o.builder.string(ip.stringToSlice(if (is_extern)
decl.name
else
- try decl.getFullyQualifiedName(zcu))),
+ try decl.fullyQualifiedName(zcu))),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@@ -3100,7 +3098,7 @@ pub const Object = struct {
const variable_index = try o.builder.addVariable(
try o.builder.string(mod.intern_pool.stringToSlice(
- if (is_extern) decl.name else try decl.getFullyQualifiedName(mod),
+ if (is_extern) decl.name else try decl.fullyQualifiedName(mod),
)),
try o.lowerType(decl.ty),
toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
@@ -3325,7 +3323,7 @@ pub const Object = struct {
}
const name = try o.builder.string(ip.stringToSlice(
- try mod.declPtr(struct_type.decl.unwrap().?).getFullyQualifiedName(mod),
+ try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod),
));
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
@@ -3481,7 +3479,7 @@ pub const Object = struct {
}
const name = try o.builder.string(ip.stringToSlice(
- try mod.declPtr(union_obj.decl).getFullyQualifiedName(mod),
+ try mod.declPtr(union_obj.decl).fullyQualifiedName(mod),
));
const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
@@ -4599,7 +4597,7 @@ pub const Object = struct {
const usize_ty = try o.lowerType(Type.usize);
const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
- const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
+ const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(zcu);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
@@ -6613,7 +6611,7 @@ pub const FuncGen = struct {
.base_line = self.base_line,
});
- const fqn = try decl.getFullyQualifiedName(zcu);
+ const fqn = try decl.fullyQualifiedName(zcu);
const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
const fn_ty = try zcu.funcType(.{
@@ -9643,7 +9641,7 @@ pub const FuncGen = struct {
if (gop.found_existing) return gop.value_ptr.*;
errdefer assert(o.named_enum_map.remove(enum_type.decl));
- const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
+ const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(zcu);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
src/codegen/spirv.zig
@@ -2019,7 +2019,7 @@ const DeclGen = struct {
// Append the actual code into the functions section.
try self.spv.addFunction(spv_decl_index, self.func);
- const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
+ const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module));
try self.spv.debugName(decl_id, fqn);
// Temporarily generate a test kernel declaration if this is a test function.
@@ -2055,7 +2055,7 @@ const DeclGen = struct {
.id_result = decl_id,
.storage_class = actual_storage_class,
});
- const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
+ const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module));
try self.spv.debugName(decl_id, fqn);
if (opt_init_val) |init_val| {
src/link/Elf/ZigObject.zig
@@ -903,7 +903,7 @@ fn updateDeclCode(
const gpa = elf_file.base.comp.gpa;
const mod = elf_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
@@ -1001,7 +1001,7 @@ fn updateTlv(
const gpa = elf_file.base.comp.gpa;
const mod = elf_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateTlv {s} ({*})", .{ decl_name, decl });
@@ -1300,7 +1300,7 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(name);
@@ -1482,7 +1482,7 @@ pub fn updateDeclLineNumber(
defer tracy.end();
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
src/link/MachO/ZigObject.zig
@@ -792,7 +792,7 @@ fn updateDeclCode(
const gpa = macho_file.base.comp.gpa;
const mod = macho_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
@@ -876,7 +876,7 @@ fn updateTlv(
) !void {
const mod = macho_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateTlv {s} ({*})", .{ decl_name, decl });
@@ -1079,7 +1079,7 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(name);
src/link/Coff.zig
@@ -1176,7 +1176,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.Dec
gop.value_ptr.* = .{};
}
const unnamed_consts = gop.value_ptr;
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
const index = unnamed_consts.items.len;
const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(sym_name);
@@ -1427,7 +1427,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com
const mod = self.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits(0));
src/link/Dwarf.zig
@@ -1082,7 +1082,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
defer tracy.end();
const decl = mod.declPtr(decl_index);
- const decl_linkage_name = try decl.getFullyQualifiedName(mod);
+ const decl_linkage_name = try decl.fullyQualifiedName(mod);
log.debug("initDeclState {}{*}", .{ decl_linkage_name.fmt(&mod.intern_pool), decl });
src/link/Plan9.zig
@@ -478,7 +478,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De
}
const unnamed_consts = gop.value_ptr;
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
const index = unnamed_consts.items.len;
// name is freed when the unnamed const is freed
src/link/Wasm.zig
@@ -662,7 +662,7 @@ pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) !At
const symbol = atom.symbolLoc().getSymbol(wasm);
const mod = wasm.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
symbol.name = try wasm.string_table.put(gpa, full_name);
}
return gop.value_ptr.*;
@@ -1598,7 +1598,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.De
defer tracy.end();
const decl = mod.declPtr(decl_index);
- const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
try dw.updateDeclLineNumber(mod, decl_index);
@@ -1612,7 +1612,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex, code: []const
const atom_index = wasm.decls.get(decl_index).?;
const atom = wasm.getAtomPtr(atom_index);
const symbol = &wasm.symbols.items[atom.sym_index];
- const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
symbol.name = try wasm.string_table.put(gpa, full_name);
symbol.tag = symbol_tag;
try atom.code.appendSlice(gpa, code);
@@ -1678,7 +1678,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec
const parent_atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
const parent_atom = wasm.getAtom(parent_atom_index);
const local_index = parent_atom.locals.items.len;
- const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+ const fqn = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{
fqn, local_index,
});
src/Compilation.zig
@@ -217,7 +217,7 @@ libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,
/// This mutex guards all `Compilation` mutable state.
mutex: std.Thread.Mutex = .{},
-test_filter: ?[]const u8,
+test_filters: []const []const u8,
test_name_prefix: ?[]const u8,
emit_asm: ?EmitLoc,
@@ -1097,7 +1097,7 @@ pub const CreateOptions = struct {
native_system_include_paths: []const []const u8 = &.{},
clang_preprocessor_mode: ClangPreprocessorMode = .no,
reference_trace: ?u32 = null,
- test_filter: ?[]const u8 = null,
+ test_filters: []const []const u8 = &.{},
test_name_prefix: ?[]const u8 = null,
test_runner_path: ?[]const u8 = null,
subsystem: ?std.Target.SubSystem = null,
@@ -1506,7 +1506,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.formatted_panics = formatted_panics,
.time_report = options.time_report,
.stack_report = options.stack_report,
- .test_filter = options.test_filter,
+ .test_filters = options.test_filters,
.test_name_prefix = options.test_name_prefix,
.debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
.debug_compile_errors = options.debug_compile_errors,
@@ -1613,7 +1613,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
hash.add(options.config.use_lib_llvm);
hash.add(options.config.dll_export_fns);
hash.add(options.config.is_test);
- hash.addOptionalBytes(options.test_filter);
+ hash.addListOfBytes(options.test_filters);
hash.addOptionalBytes(options.test_name_prefix);
hash.add(options.skip_linker_dependencies);
hash.add(formatted_panics);
@@ -2475,7 +2475,7 @@ fn addNonIncrementalStuffToCacheManifest(
try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });
// Synchronize with other matching comments: ZigOnlyHashStuff
- man.hash.addOptionalBytes(comp.test_filter);
+ man.hash.addListOfBytes(comp.test_filters);
man.hash.addOptionalBytes(comp.test_name_prefix);
man.hash.add(comp.skip_linker_dependencies);
man.hash.add(comp.formatted_panics);
src/InternPool.zig
@@ -7904,7 +7904,7 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex)
ip.namespacePtr(index).* = .{
.parent = undefined,
.file_scope = undefined,
- .ty = undefined,
+ .decl_index = undefined,
};
ip.namespaces_free_list.append(gpa, index) catch {
// In order to keep `destroyNamespace` a non-fallible function, we ignore memory
src/main.zig
@@ -596,7 +596,7 @@ const usage_build_generic =
\\ --export=[value] (WebAssembly) Force a symbol to be exported
\\
\\Test Options:
- \\ --test-filter [text] Skip tests that do not match filter
+ \\ --test-filter [text] Skip tests that do not match any filter
\\ --test-name-prefix [text] Add prefix to all tests
\\ --test-cmd [arg] Specify test execution command one arg at a time
\\ --test-cmd-bin Appends test binary path to test cmd args
@@ -869,7 +869,7 @@ fn buildOutputType(
var link_emit_relocs = false;
var build_id: ?std.zig.BuildId = null;
var runtime_args_start: ?usize = null;
- var test_filter: ?[]const u8 = null;
+ var test_filters: std.ArrayListUnmanaged([]const u8) = .{};
var test_name_prefix: ?[]const u8 = null;
var test_runner_path: ?[]const u8 = null;
var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena);
@@ -909,7 +909,7 @@ fn buildOutputType(
var rc_source_files_owner_index: usize = 0;
// null means replace with the test executable binary
- var test_exec_args = std.ArrayList(?[]const u8).init(arena);
+ var test_exec_args: std.ArrayListUnmanaged(?[]const u8) = .{};
// These get set by CLI flags and then snapshotted when a `--mod` flag is
// encountered.
@@ -1278,13 +1278,13 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "--libc")) {
create_module.libc_paths_file = args_iter.nextOrFatal();
} else if (mem.eql(u8, arg, "--test-filter")) {
- test_filter = args_iter.nextOrFatal();
+ try test_filters.append(arena, args_iter.nextOrFatal());
} else if (mem.eql(u8, arg, "--test-name-prefix")) {
test_name_prefix = args_iter.nextOrFatal();
} else if (mem.eql(u8, arg, "--test-runner")) {
test_runner_path = args_iter.nextOrFatal();
} else if (mem.eql(u8, arg, "--test-cmd")) {
- try test_exec_args.append(args_iter.nextOrFatal());
+ try test_exec_args.append(arena, args_iter.nextOrFatal());
} else if (mem.eql(u8, arg, "--cache-dir")) {
override_local_cache_dir = args_iter.nextOrFatal();
} else if (mem.eql(u8, arg, "--global-cache-dir")) {
@@ -1334,7 +1334,7 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) {
create_module.each_lib_rpath = false;
} else if (mem.eql(u8, arg, "--test-cmd-bin")) {
- try test_exec_args.append(null);
+ try test_exec_args.append(arena, null);
} else if (mem.eql(u8, arg, "--test-no-exec")) {
test_no_exec = true;
} else if (mem.eql(u8, arg, "-ftime-report")) {
@@ -3246,7 +3246,7 @@ fn buildOutputType(
.time_report = time_report,
.stack_report = stack_report,
.build_id = build_id,
- .test_filter = test_filter,
+ .test_filters = test_filters.items,
.test_name_prefix = test_name_prefix,
.test_runner_path = test_runner_path,
.disable_lld_caching = disable_lld_caching,
@@ -3369,16 +3369,15 @@ fn buildOutputType(
const c_code_path = try fs.path.join(arena, &[_][]const u8{
c_code_directory.path orelse ".", c_code_loc.basename,
});
- try test_exec_args.append(self_exe_path);
- try test_exec_args.append("run");
+ try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
if (zig_lib_directory.path) |p| {
- try test_exec_args.appendSlice(&.{ "-I", p });
+ try test_exec_args.appendSlice(arena, &.{ "-I", p });
}
if (create_module.resolved_options.link_libc) {
- try test_exec_args.append("-lc");
+ try test_exec_args.append(arena, "-lc");
} else if (target.os.tag == .windows) {
- try test_exec_args.appendSlice(&.{
+ try test_exec_args.appendSlice(arena, &.{
"--subsystem", "console",
"-lkernel32", "-lntdll",
});
@@ -3386,17 +3385,15 @@ fn buildOutputType(
const first_cli_mod = create_module.modules.values()[0];
if (first_cli_mod.target_arch_os_abi) |triple| {
- try test_exec_args.append("-target");
- try test_exec_args.append(triple);
+ try test_exec_args.appendSlice(arena, &.{ "-target", triple });
}
if (first_cli_mod.target_mcpu) |mcpu| {
- try test_exec_args.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
+ try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
}
if (create_module.dynamic_linker) |dl| {
- try test_exec_args.append("--dynamic-linker");
- try test_exec_args.append(dl);
+ try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
}
- try test_exec_args.append(c_code_path);
+ try test_exec_args.append(arena, c_code_path);
}
const run_or_test = switch (arg_mode) {
src/Module.zig
@@ -411,15 +411,15 @@ pub const Decl = struct {
/// This state detects dependency loops.
in_progress,
/// The file corresponding to this Decl had a parse error or ZIR error.
- /// There will be a corresponding ErrorMsg in Module.failed_files.
+ /// There will be a corresponding ErrorMsg in Zcu.failed_files.
file_failure,
/// This Decl might be OK but it depends on another one which did not
/// successfully complete semantic analysis.
dependency_failure,
/// Semantic analysis failure.
- /// There will be a corresponding ErrorMsg in Module.failed_decls.
+ /// There will be a corresponding ErrorMsg in Zcu.failed_decls.
sema_failure,
- /// There will be a corresponding ErrorMsg in Module.failed_decls.
+ /// There will be a corresponding ErrorMsg in Zcu.failed_decls.
codegen_failure,
/// Sematic analysis and constant value codegen of this Decl has
/// succeeded. However, the Decl may be outdated due to an in-progress
@@ -494,77 +494,45 @@ pub const Decl = struct {
return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
}
- pub fn srcLoc(decl: Decl, mod: *Module) SrcLoc {
- return decl.nodeOffsetSrcLoc(0, mod);
+ pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc {
+ return decl.nodeOffsetSrcLoc(0, zcu);
}
- pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, mod: *Module) SrcLoc {
+ pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, zcu: *Zcu) SrcLoc {
return .{
- .file_scope = decl.getFileScope(mod),
+ .file_scope = decl.getFileScope(zcu),
.parent_decl_node = decl.src_node,
.lazy = LazySrcLoc.nodeOffset(node_offset),
};
}
- pub fn srcToken(decl: Decl, mod: *Module) Ast.TokenIndex {
- const tree = &decl.getFileScope(mod).tree;
+ pub fn srcToken(decl: Decl, zcu: *Zcu) Ast.TokenIndex {
+ const tree = &decl.getFileScope(zcu).tree;
return tree.firstToken(decl.src_node);
}
- pub fn srcByteOffset(decl: Decl, mod: *Module) u32 {
- const tree = &decl.getFileScope(mod).tree;
+ pub fn srcByteOffset(decl: Decl, zcu: *Zcu) u32 {
+ const tree = &decl.getFileScope(zcu).tree;
return tree.tokens.items(.start)[decl.srcToken()];
}
- pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
+ pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
if (decl.name_fully_qualified) {
- try writer.print("{}", .{decl.name.fmt(&mod.intern_pool)});
+ try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)});
} else {
- try mod.namespacePtr(decl.src_namespace).renderFullyQualifiedName(mod, decl.name, writer);
+ try zcu.namespacePtr(decl.src_namespace).renderFullyQualifiedName(zcu, decl.name, writer);
}
}
- pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void {
- return mod.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(mod, decl.name, writer);
+ pub fn renderFullyQualifiedDebugName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
+ return zcu.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(zcu, decl.name, writer);
}
- pub fn getFullyQualifiedName(decl: Decl, mod: *Module) !InternPool.NullTerminatedString {
- if (decl.name_fully_qualified) return decl.name;
-
- const ip = &mod.intern_pool;
- const count = count: {
- var count: usize = ip.stringToSlice(decl.name).len + 1;
- var ns: Namespace.Index = decl.src_namespace;
- while (true) {
- const namespace = mod.namespacePtr(ns);
- const ns_decl = mod.declPtr(namespace.getDeclIndex(mod));
- count += ip.stringToSlice(ns_decl.name).len + 1;
- ns = namespace.parent.unwrap() orelse {
- count += namespace.file_scope.sub_file_path.len;
- break :count count;
- };
- }
- };
-
- const gpa = mod.gpa;
- const start = ip.string_bytes.items.len;
- // Protects reads of interned strings from being reallocated during the call to
- // renderFullyQualifiedName.
- try ip.string_bytes.ensureUnusedCapacity(gpa, count);
- decl.renderFullyQualifiedName(mod, ip.string_bytes.writer(gpa)) catch unreachable;
-
- // Sanitize the name for nvptx which is more restrictive.
- // TODO This should be handled by the backend, not the frontend. Have a
- // look at how the C backend does it for inspiration.
- const cpu_arch = mod.root_mod.resolved_target.result.cpu.arch;
- if (cpu_arch.isNvptx()) {
- for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) {
- '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
- else => {},
- };
- }
-
- return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start);
+ pub fn fullyQualifiedName(decl: Decl, zcu: *Zcu) !InternPool.NullTerminatedString {
+ return if (decl.name_fully_qualified)
+ decl.name
+ else
+ zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name);
}
pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
@@ -572,38 +540,38 @@ pub const Decl = struct {
return TypedValue{ .ty = decl.ty, .val = decl.val };
}
- pub fn internValue(decl: *Decl, mod: *Module) Allocator.Error!InternPool.Index {
+ pub fn internValue(decl: *Decl, zcu: *Zcu) Allocator.Error!InternPool.Index {
assert(decl.has_tv);
- const ip_index = try decl.val.intern(decl.ty, mod);
+ const ip_index = try decl.val.intern(decl.ty, zcu);
decl.val = Value.fromInterned(ip_index);
return ip_index;
}
- pub fn isFunction(decl: Decl, mod: *const Module) !bool {
+ pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool {
const tv = try decl.typedValue();
- return tv.ty.zigTypeTag(mod) == .Fn;
+ return tv.ty.zigTypeTag(zcu) == .Fn;
}
/// If the Decl owns its value and it is a struct, return it,
/// otherwise null.
- pub fn getOwnedStruct(decl: Decl, mod: *Module) ?InternPool.Key.StructType {
+ pub fn getOwnedStruct(decl: Decl, zcu: *Zcu) ?InternPool.Key.StructType {
if (!decl.owns_tv) return null;
if (decl.val.ip_index == .none) return null;
- return mod.typeToStruct(decl.val.toType());
+ return zcu.typeToStruct(decl.val.toType());
}
/// If the Decl owns its value and it is a union, return it,
/// otherwise null.
- pub fn getOwnedUnion(decl: Decl, mod: *Module) ?InternPool.UnionType {
+ pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.UnionType {
if (!decl.owns_tv) return null;
if (decl.val.ip_index == .none) return null;
- return mod.typeToUnion(decl.val.toType());
+ return zcu.typeToUnion(decl.val.toType());
}
- pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
+ pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func {
const i = decl.getOwnedFunctionIndex();
if (i == .none) return null;
- return switch (mod.intern_pool.indexToKey(i)) {
+ return switch (zcu.intern_pool.indexToKey(i)) {
.func => |func| func,
else => null,
};
@@ -616,24 +584,24 @@ pub const Decl = struct {
/// If the Decl owns its value and it is an extern function, returns it,
/// otherwise null.
- pub fn getOwnedExternFunc(decl: Decl, mod: *Module) ?InternPool.Key.ExternFunc {
- return if (decl.owns_tv) decl.val.getExternFunc(mod) else null;
+ pub fn getOwnedExternFunc(decl: Decl, zcu: *Zcu) ?InternPool.Key.ExternFunc {
+ return if (decl.owns_tv) decl.val.getExternFunc(zcu) else null;
}
/// If the Decl owns its value and it is a variable, returns it,
/// otherwise null.
- pub fn getOwnedVariable(decl: Decl, mod: *Module) ?InternPool.Key.Variable {
- return if (decl.owns_tv) decl.val.getVariable(mod) else null;
+ pub fn getOwnedVariable(decl: Decl, zcu: *Zcu) ?InternPool.Key.Variable {
+ return if (decl.owns_tv) decl.val.getVariable(zcu) else null;
}
/// Gets the namespace that this Decl creates by being a struct, union,
/// enum, or opaque.
- pub fn getInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
+ pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {
if (!decl.has_tv) return .none;
return switch (decl.val.ip_index) {
.empty_struct_type => .none,
.none => .none,
- else => switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
+ else => switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) {
.opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
.struct_type => |struct_type| struct_type.namespace,
.union_type => |union_type| union_type.namespace.toOptional(),
@@ -644,19 +612,19 @@ pub const Decl = struct {
}
/// Like `getInnerNamespaceIndex`, but only returns it if the Decl is the owner.
- pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
+ pub fn getOwnedInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {
if (!decl.owns_tv) return .none;
- return decl.getInnerNamespaceIndex(mod);
+ return decl.getInnerNamespaceIndex(zcu);
}
/// Same as `getOwnedInnerNamespaceIndex` but additionally obtains the pointer.
- pub fn getOwnedInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
- return mod.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(mod));
+ pub fn getOwnedInnerNamespace(decl: Decl, zcu: *Zcu) ?*Namespace {
+ return zcu.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(zcu));
}
/// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
- pub fn getInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
- return mod.namespacePtrUnwrap(decl.getInnerNamespaceIndex(mod));
+ pub fn getInnerNamespace(decl: Decl, zcu: *Zcu) ?*Namespace {
+ return zcu.namespacePtrUnwrap(decl.getInnerNamespaceIndex(zcu));
}
pub fn dump(decl: *Decl) void {
@@ -674,27 +642,27 @@ pub const Decl = struct {
std.debug.print("\n", .{});
}
- pub fn getFileScope(decl: Decl, mod: *Module) *File {
- return mod.namespacePtr(decl.src_namespace).file_scope;
+ pub fn getFileScope(decl: Decl, zcu: *Zcu) *File {
+ return zcu.namespacePtr(decl.src_namespace).file_scope;
}
- pub fn getExternDecl(decl: Decl, mod: *Module) OptionalIndex {
+ pub fn getExternDecl(decl: Decl, zcu: *Zcu) OptionalIndex {
assert(decl.has_tv);
- return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
+ return switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) {
.variable => |variable| if (variable.is_extern) variable.decl.toOptional() else .none,
.extern_func => |extern_func| extern_func.decl.toOptional(),
else => .none,
};
}
- pub fn isExtern(decl: Decl, mod: *Module) bool {
- return decl.getExternDecl(mod) != .none;
+ pub fn isExtern(decl: Decl, zcu: *Zcu) bool {
+ return decl.getExternDecl(zcu) != .none;
}
- pub fn getAlignment(decl: Decl, mod: *Module) Alignment {
+ pub fn getAlignment(decl: Decl, zcu: *Zcu) Alignment {
assert(decl.has_tv);
if (decl.alignment != .none) return decl.alignment;
- return decl.ty.abiAlignment(mod);
+ return decl.ty.abiAlignment(zcu);
}
};
@@ -704,7 +672,7 @@ pub const EmitH = struct {
};
pub const DeclAdapter = struct {
- mod: *Module,
+ zcu: *Zcu,
pub fn hash(self: @This(), s: InternPool.NullTerminatedString) u32 {
_ = self;
@@ -713,8 +681,7 @@ pub const DeclAdapter = struct {
pub fn eql(self: @This(), a: InternPool.NullTerminatedString, b_decl_index: Decl.Index, b_index: usize) bool {
_ = b_index;
- const b_decl = self.mod.declPtr(b_decl_index);
- return a == b_decl.name;
+ return a == self.zcu.declPtr(b_decl_index).name;
}
};
@@ -723,7 +690,7 @@ pub const Namespace = struct {
parent: OptionalIndex,
file_scope: *File,
/// Will be a struct, enum, union, or opaque.
- ty: Type,
+ decl_index: Decl.Index,
/// Direct children of the namespace.
/// Declaration order is preserved via entry order.
/// These are only declarations named directly by the AST; anonymous
@@ -739,7 +706,7 @@ pub const Namespace = struct {
const OptionalIndex = InternPool.OptionalNamespaceIndex;
const DeclContext = struct {
- module: *Module,
+ zcu: *Zcu,
pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 {
const decl = ctx.module.declPtr(decl_index);
@@ -757,39 +724,87 @@ pub const Namespace = struct {
// This renders e.g. "std.fs.Dir.OpenOptions"
pub fn renderFullyQualifiedName(
ns: Namespace,
- mod: *Module,
+ zcu: *Zcu,
name: InternPool.NullTerminatedString,
writer: anytype,
) @TypeOf(writer).Error!void {
if (ns.parent.unwrap()) |parent| {
- const decl = mod.declPtr(ns.getDeclIndex(mod));
- try mod.namespacePtr(parent).renderFullyQualifiedName(mod, decl.name, writer);
+ try zcu.namespacePtr(parent).renderFullyQualifiedName(
+ zcu,
+ zcu.declPtr(ns.decl_index).name,
+ writer,
+ );
} else {
try ns.file_scope.renderFullyQualifiedName(writer);
}
- if (name != .empty) try writer.print(".{}", .{name.fmt(&mod.intern_pool)});
+ if (name != .empty) try writer.print(".{}", .{name.fmt(&zcu.intern_pool)});
}
/// This renders e.g. "std/fs.zig:Dir.OpenOptions"
pub fn renderFullyQualifiedDebugName(
ns: Namespace,
- mod: *Module,
+ zcu: *Zcu,
name: InternPool.NullTerminatedString,
writer: anytype,
) @TypeOf(writer).Error!void {
- const separator_char: u8 = if (ns.parent.unwrap()) |parent| sep: {
- const decl = mod.declPtr(ns.getDeclIndex(mod));
- try mod.namespacePtr(parent).renderFullyQualifiedDebugName(mod, decl.name, writer);
+ const sep: u8 = if (ns.parent.unwrap()) |parent| sep: {
+ try zcu.namespacePtr(parent).renderFullyQualifiedDebugName(
+ zcu,
+ zcu.declPtr(ns.decl_index).name,
+ writer,
+ );
break :sep '.';
} else sep: {
try ns.file_scope.renderFullyQualifiedDebugName(writer);
break :sep ':';
};
- if (name != .empty) try writer.print("{c}{}", .{ separator_char, name.fmt(&mod.intern_pool) });
+ if (name != .empty) try writer.print("{c}{}", .{ sep, name.fmt(&zcu.intern_pool) });
}
- pub fn getDeclIndex(ns: Namespace, mod: *Module) Decl.Index {
- return ns.ty.getOwnerDecl(mod);
+ pub fn fullyQualifiedName(
+ ns: Namespace,
+ zcu: *Zcu,
+ name: InternPool.NullTerminatedString,
+ ) !InternPool.NullTerminatedString {
+ const ip = &zcu.intern_pool;
+ const count = count: {
+ var count: usize = ip.stringToSlice(name).len + 1;
+ var cur_ns = &ns;
+ while (true) {
+ const decl = zcu.declPtr(cur_ns.decl_index);
+ count += ip.stringToSlice(decl.name).len + 1;
+ cur_ns = zcu.namespacePtr(cur_ns.parent.unwrap() orelse {
+ count += ns.file_scope.sub_file_path.len;
+ break :count count;
+ });
+ }
+ };
+
+ const gpa = zcu.gpa;
+ const start = ip.string_bytes.items.len;
+ // Protects reads of interned strings from being reallocated during the call to
+ // renderFullyQualifiedName.
+ try ip.string_bytes.ensureUnusedCapacity(gpa, count);
+ ns.renderFullyQualifiedName(zcu, name, ip.string_bytes.writer(gpa)) catch unreachable;
+
+ // Sanitize the name for nvptx which is more restrictive.
+ // TODO This should be handled by the backend, not the frontend. Have a
+ // look at how the C backend does it for inspiration.
+ const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch;
+ if (cpu_arch.isNvptx()) {
+ for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) {
+ '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
+ else => {},
+ };
+ }
+
+ return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start);
+ }
+
+ pub fn getType(ns: Namespace, zcu: *Zcu) Type {
+ const decl = zcu.declPtr(ns.decl_index);
+ assert(decl.has_tv);
+ return decl.val.toType();
}
};
@@ -2559,9 +2574,8 @@ pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namesp
pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
const decl = mod.declPtr(decl_index);
const namespace = mod.namespacePtr(decl.src_namespace);
- if (namespace.parent != .none)
- return false;
- return decl_index == namespace.getDeclIndex(mod);
+ if (namespace.parent != .none) return false;
+ return decl_index == namespace.decl_index;
}
fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {
@@ -3592,7 +3606,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
defer liveness.deinit(gpa);
if (dump_air) {
- const fqn = try decl.getFullyQualifiedName(zcu);
+ const fqn = try decl.fullyQualifiedName(zcu);
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
@import("print_air.zig").dump(zcu, air, liveness);
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
@@ -3738,7 +3752,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
// InternPool index.
const new_namespace_index = try mod.createNamespace(.{
.parent = .none,
- .ty = undefined,
+ .decl_index = undefined,
.file_scope = file,
});
const new_namespace = mod.namespacePtr(new_namespace_index);
@@ -3749,6 +3763,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
errdefer @panic("TODO error handling");
file.root_decl = new_decl_index.toOptional();
+ new_namespace.decl_index = new_decl_index;
new_decl.name = try file.fullyQualifiedName(mod);
new_decl.name_fully_qualified = true;
@@ -3808,7 +3823,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
_ = try decl.internValue(mod);
}
- new_namespace.ty = Type.fromInterned(struct_ty);
new_decl.val = Value.fromInterned(struct_ty);
new_decl.has_tv = true;
new_decl.owns_tv = true;
@@ -3881,7 +3895,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
const std_decl = mod.declPtr(std_file.root_decl.unwrap().?);
const std_namespace = std_decl.getInnerNamespace(mod).?;
const builtin_str = try ip.getOrPutString(gpa, "builtin");
- const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .mod = mod }) orelse break :blk .none);
+ const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .zcu = mod }) orelse break :blk .none);
const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none;
if (decl.src_namespace != builtin_namespace) break :blk .none;
// We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index.
@@ -4576,8 +4590,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
const gop = try namespace.decls.getOrPutContextAdapted(
gpa,
decl_name,
- DeclAdapter{ .mod = zcu },
- Namespace.DeclContext{ .module = zcu },
+ DeclAdapter{ .zcu = zcu },
+ Namespace.DeclContext{ .zcu = zcu },
);
const comp = zcu.comp;
if (!gop.found_existing) {
@@ -4600,12 +4614,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
.@"test" => a: {
if (!comp.config.is_test) break :a false;
if (decl_mod != zcu.main_mod) break :a false;
- if (is_named_test) {
- if (comp.test_filter) |test_filter| {
- if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) {
- break :a false;
- }
- }
+ if (is_named_test and comp.test_filters.len > 0) {
+ const decl_fqn = ip.stringToSlice(try namespace.fullyQualifiedName(zcu, decl_name));
+ for (comp.test_filters) |test_filter| {
+ if (mem.indexOf(u8, decl_fqn, test_filter)) |_| break;
+ } else break :a false;
}
try zcu.test_functions.put(gpa, new_decl_index, {});
break :a true;
@@ -5622,7 +5635,7 @@ pub fn populateTestFunctions(
const test_functions_str = try ip.getOrPutString(gpa, "test_functions");
const decl_index = builtin_namespace.decls.getKeyAdapted(
test_functions_str,
- DeclAdapter{ .mod = mod },
+ DeclAdapter{ .zcu = mod },
).?;
{
// We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`
@@ -5646,8 +5659,7 @@ pub fn populateTestFunctions(
for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| {
const test_decl = mod.declPtr(test_decl_index);
- // TODO: write something like getCoercedInts to avoid needing to dupe
- const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(test_decl.name));
+ const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod)));
defer gpa.free(test_decl_name);
const test_name_decl_index = n: {
const test_name_decl_ty = try mod.arrayType(.{
@@ -6359,17 +6371,13 @@ pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc
}
pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) !InternPool.NullTerminatedString {
- return mod.declPtr(opaque_type.decl).getFullyQualifiedName(mod);
+ return mod.declPtr(opaque_type.decl).fullyQualifiedName(mod);
}
pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
return mod.declPtr(decl_index).getFileScope(mod);
}
-pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index {
- return mod.namespacePtr(namespace_index).getDeclIndex(mod);
-}
-
/// Returns null in the following cases:
/// * `@TypeOf(.{})`
/// * A struct which has no fields (`struct {}`).
src/Sema.zig
@@ -2801,10 +2801,9 @@ fn zirStructDecl(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer mod.destroyNamespace(new_namespace_index);
const struct_ty = ty: {
@@ -2821,7 +2820,6 @@ fn zirStructDecl(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(struct_ty);
- new_namespace.ty = Type.fromInterned(struct_ty);
const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
try mod.finalizeAnonDecl(new_decl_index);
@@ -2990,10 +2988,9 @@ fn zirEnumDecl(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer if (!done) mod.destroyNamespace(new_namespace_index);
const decls = sema.code.bodySlice(extra_index, decls_len);
@@ -3036,7 +3033,6 @@ fn zirEnumDecl(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(incomplete_enum.index);
- new_namespace.ty = Type.fromInterned(incomplete_enum.index);
const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index);
try mod.finalizeAnonDecl(new_decl_index);
@@ -3248,10 +3244,9 @@ fn zirUnionDecl(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer mod.destroyNamespace(new_namespace_index);
const union_ty = ty: {
@@ -3292,7 +3287,6 @@ fn zirUnionDecl(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(union_ty);
- new_namespace.ty = Type.fromInterned(union_ty);
const decls = sema.code.bodySlice(extra_index, decls_len);
try mod.scanNamespace(new_namespace_index, decls, new_decl);
@@ -3346,10 +3340,9 @@ fn zirOpaqueDecl(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer mod.destroyNamespace(new_namespace_index);
const opaque_ty = try mod.intern(.{ .opaque_type = .{
@@ -3362,7 +3355,6 @@ fn zirOpaqueDecl(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(opaque_ty);
- new_namespace.ty = Type.fromInterned(opaque_ty);
const decls = sema.code.bodySlice(extra_index, decls_len);
try mod.scanNamespace(new_namespace_index, decls, new_decl);
@@ -4834,7 +4826,7 @@ fn validateStructInit(
if (root_msg) |msg| {
if (mod.typeToStruct(struct_ty)) |struct_type| {
const decl = mod.declPtr(struct_type.decl.unwrap().?);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
try mod.errNoteNonLazy(
decl.srcLoc(mod),
msg,
@@ -4961,7 +4953,7 @@ fn validateStructInit(
if (root_msg) |msg| {
if (mod.typeToStruct(struct_ty)) |struct_type| {
const decl = mod.declPtr(struct_type.decl.unwrap().?);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
try mod.errNoteNonLazy(
decl.srcLoc(mod),
msg,
@@ -5355,7 +5347,7 @@ fn failWithBadStructFieldAccess(
const mod = sema.mod;
const gpa = sema.gpa;
const decl = mod.declPtr(struct_type.decl.unwrap().?);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
const msg = msg: {
const msg = try sema.errMsg(
@@ -5382,7 +5374,7 @@ fn failWithBadUnionFieldAccess(
const gpa = sema.gpa;
const decl = mod.declPtr(union_obj.decl);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
const msg = msg: {
const msg = try sema.errMsg(
@@ -6504,8 +6496,7 @@ fn lookupInNamespace(
const mod = sema.mod;
const namespace = mod.namespacePtr(namespace_index);
- const namespace_decl_index = namespace.getDeclIndex(mod);
- const namespace_decl = mod.declPtr(namespace_decl_index);
+ const namespace_decl = mod.declPtr(namespace.decl_index);
if (namespace_decl.analysis == .file_failure) {
return error.AnalysisFail;
}
@@ -6526,7 +6517,7 @@ fn lookupInNamespace(
while (check_i < checked_namespaces.count()) : (check_i += 1) {
const check_ns = checked_namespaces.keys()[check_i];
- if (check_ns.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .mod = mod })) |decl_index| {
+ if (check_ns.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .zcu = mod })) |decl_index| {
// Skip decls which are not marked pub, which are in a different
// file than the `a.b`/`@hasDecl` syntax.
const decl = mod.declPtr(decl_index);
@@ -6584,7 +6575,7 @@ fn lookupInNamespace(
return sema.failWithOwnedErrorMsg(block, msg);
},
}
- } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .mod = mod })) |decl_index| {
+ } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .zcu = mod })) |decl_index| {
return decl_index;
}
@@ -17210,7 +17201,7 @@ fn zirThis(
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const mod = sema.mod;
- const this_decl_index = mod.namespaceDeclIndex(block.namespace);
+ const this_decl_index = mod.namespacePtr(block.namespace).decl_index;
const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand));
return sema.analyzeDeclVal(block, src, this_decl_index);
}
@@ -20075,7 +20066,7 @@ fn finishStructInit(
if (root_msg) |msg| {
if (mod.typeToStruct(struct_ty)) |struct_type| {
const decl = mod.declPtr(struct_type.decl.unwrap().?);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
try mod.errNoteNonLazy(
decl.srcLoc(mod),
msg,
@@ -21404,10 +21395,9 @@ fn zirReify(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer mod.destroyNamespace(new_namespace_index);
const opaque_ty = try mod.intern(.{ .opaque_type = .{
@@ -21420,7 +21410,6 @@ fn zirReify(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(opaque_ty);
- new_namespace.ty = Type.fromInterned(opaque_ty);
const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
try mod.finalizeAnonDecl(new_decl_index);
@@ -21614,10 +21603,9 @@ fn zirReify(
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
- .ty = undefined,
+ .decl_index = new_decl_index,
.file_scope = block.getFileScope(mod),
});
- const new_namespace = mod.namespacePtr(new_namespace_index);
errdefer mod.destroyNamespace(new_namespace_index);
const union_ty = try ip.getUnionType(gpa, .{
@@ -21649,7 +21637,6 @@ fn zirReify(
new_decl.ty = Type.type;
new_decl.val = Value.fromInterned(union_ty);
- new_namespace.ty = Type.fromInterned(union_ty);
const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
try mod.finalizeAnonDecl(new_decl_index);
@@ -37260,7 +37247,7 @@ fn generateUnionTagTypeNumbered(
const src_decl = mod.declPtr(block.src_decl);
const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
errdefer mod.destroyDecl(new_decl_index);
- const fqn = try decl.getFullyQualifiedName(mod);
+ const fqn = try decl.fullyQualifiedName(mod);
const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
.ty = Type.noreturn,
@@ -37269,7 +37256,6 @@ fn generateUnionTagTypeNumbered(
errdefer mod.abortAnonDecl(new_decl_index);
const new_decl = mod.declPtr(new_decl_index);
- new_decl.name_fully_qualified = true;
new_decl.owns_tv = true;
new_decl.name_fully_qualified = true;
@@ -37310,7 +37296,7 @@ fn generateUnionTagTypeSimple(
.val = Value.@"unreachable",
});
};
- const fqn = try mod.declPtr(decl_index).getFullyQualifiedName(mod);
+ const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod);
const src_decl = mod.declPtr(block.src_decl);
const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
errdefer mod.destroyDecl(new_decl_index);
test/src/Cases.zig
@@ -537,7 +537,7 @@ pub fn lowerToBuildSteps(
self: *Cases,
b: *std.Build,
parent_step: *std.Build.Step,
- opt_test_filter: ?[]const u8,
+ test_filters: []const []const u8,
cases_dir_path: []const u8,
incremental_exe: *std.Build.Step.Compile,
) void {
@@ -552,9 +552,9 @@ pub fn lowerToBuildSteps(
// compilation is in a happier state.
continue;
}
- if (opt_test_filter) |test_filter| {
- if (std.mem.indexOf(u8, incr_case.base_path, test_filter) == null) continue;
- }
+ for (test_filters) |test_filter| {
+ if (std.mem.indexOf(u8, incr_case.base_path, test_filter)) |_| break;
+ } else if (test_filters.len > 0) continue;
const case_base_path_with_dir = std.fs.path.join(b.allocator, &.{
cases_dir_path, incr_case.base_path,
}) catch @panic("OOM");
@@ -573,9 +573,9 @@ pub fn lowerToBuildSteps(
assert(case.updates.items.len == 1);
const update = case.updates.items[0];
- if (opt_test_filter) |test_filter| {
- if (std.mem.indexOf(u8, case.name, test_filter) == null) continue;
- }
+ for (test_filters) |test_filter| {
+ if (std.mem.indexOf(u8, case.name, test_filter)) |_| break;
+ } else if (test_filters.len > 0) continue;
const writefiles = b.addWriteFiles();
var file_sources = std.StringHashMap(std.Build.LazyPath).init(b.allocator);
@@ -685,9 +685,9 @@ pub fn lowerToBuildSteps(
for (self.translate.items) |case| switch (case.kind) {
.run => |output| {
const annotated_case_name = b.fmt("run-translated-c {s}", .{case.name});
- if (opt_test_filter) |filter| {
- if (std.mem.indexOf(u8, annotated_case_name, filter) == null) continue;
- }
+ for (test_filters) |test_filter| {
+ if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (test_filters.len > 0) continue;
if (!std.process.can_spawn) {
std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)});
continue; // Pass test.
@@ -721,9 +721,9 @@ pub fn lowerToBuildSteps(
},
.translate => |output| {
const annotated_case_name = b.fmt("zig translate-c {s}", .{case.name});
- if (opt_test_filter) |filter| {
- if (std.mem.indexOf(u8, annotated_case_name, filter) == null) continue;
- }
+ for (test_filters) |test_filter| {
+ if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (test_filters.len > 0) continue;
const write_src = b.addWriteFiles();
const file_source = write_src.add("tmp.c", case.input);
@@ -1440,9 +1440,9 @@ fn runCases(self: *Cases, zig_exe_path: []const u8) !void {
assert(case.backend != .stage1);
- if (build_options.test_filter) |test_filter| {
- if (std.mem.indexOf(u8, case.name, test_filter) == null) continue;
- }
+ for (build_options.test_filters) |test_filter| {
+ if (std.mem.indexOf(u8, case.name, test_filter)) |_| break;
+ } else if (build_options.test_filters.len > 0) continue;
var prg_node = root_node.start(case.name, case.updates.items.len);
prg_node.activate();
test/src/CompareOutput.zig
@@ -4,7 +4,7 @@
b: *std.Build,
step: *std.Build.Step,
test_index: usize,
-test_filter: ?[]const u8,
+test_filters: []const []const u8,
optimize_modes: []const OptimizeMode,
const Special = enum {
@@ -90,9 +90,9 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run assemble-and-link {s}", .{
case.name,
}) catch @panic("OOM");
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
- }
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
@@ -113,9 +113,9 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run compare-output {s} ({s})", .{
case.name, @tagName(optimize),
}) catch @panic("OOM");
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
- }
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
@@ -139,9 +139,9 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
// TODO iterate over self.optimize_modes and test this in both
// debug and release safe mode
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run safety {s}", .{case.name}) catch @panic("OOM");
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
- }
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
test/src/run_translated_c.zig
@@ -1,106 +0,0 @@
-// This is the implementation of the test harness for running translated
-// C code. For the actual test cases, see test/run_translated_c.zig.
-const std = @import("std");
-const ArrayList = std.ArrayList;
-const fmt = std.fmt;
-const mem = std.mem;
-const fs = std.fs;
-
-pub const RunTranslatedCContext = struct {
- b: *std.Build,
- step: *std.Build.Step,
- test_index: usize,
- test_filter: ?[]const u8,
- target: std.Build.ResolvedTarget,
-
- const TestCase = struct {
- name: []const u8,
- sources: ArrayList(SourceFile),
- expected_stdout: []const u8,
- allow_warnings: bool,
-
- const SourceFile = struct {
- filename: []const u8,
- source: []const u8,
- };
-
- pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
- self.sources.append(SourceFile{
- .filename = filename,
- .source = source,
- }) catch unreachable;
- }
- };
-
- pub fn create(
- self: *RunTranslatedCContext,
- allow_warnings: bool,
- filename: []const u8,
- name: []const u8,
- source: []const u8,
- expected_stdout: []const u8,
- ) *TestCase {
- const tc = self.b.allocator.create(TestCase) catch unreachable;
- tc.* = TestCase{
- .name = name,
- .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
- .expected_stdout = expected_stdout,
- .allow_warnings = allow_warnings,
- };
-
- tc.addSourceFile(filename, source);
- return tc;
- }
-
- pub fn add(
- self: *RunTranslatedCContext,
- name: []const u8,
- source: []const u8,
- expected_stdout: []const u8,
- ) void {
- const tc = self.create(false, "source.c", name, source, expected_stdout);
- self.addCase(tc);
- }
-
- pub fn addAllowWarnings(
- self: *RunTranslatedCContext,
- name: []const u8,
- source: []const u8,
- expected_stdout: []const u8,
- ) void {
- const tc = self.create(true, "source.c", name, source, expected_stdout);
- self.addCase(tc);
- }
-
- pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
- const b = self.b;
-
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
- }
-
- const write_src = b.addWriteFiles();
- for (case.sources.items) |src_file| {
- _ = write_src.add(src_file.filename, src_file.source);
- }
- const translate_c = b.addTranslateC(.{
- .root_source_file = write_src.files.items[0].getPath(),
- .target = b.host,
- .optimize = .Debug,
- });
-
- translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
- const exe = translate_c.addExecutable(.{});
- exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
- exe.linkLibC();
- const run = b.addRunArtifact(exe);
- run.step.name = b.fmt("{s} run", .{annotated_case_name});
- if (!case.allow_warnings) {
- run.expectStdErrEqual("");
- }
- run.expectStdOutEqual(case.expected_stdout);
-
- self.step.dependOn(&run.step);
- }
-};
test/src/RunTranslatedC.zig
@@ -0,0 +1,103 @@
+b: *std.Build,
+step: *std.Build.Step,
+test_index: usize,
+test_filters: []const []const u8,
+target: std.Build.ResolvedTarget,
+
+const TestCase = struct {
+ name: []const u8,
+ sources: ArrayList(SourceFile),
+ expected_stdout: []const u8,
+ allow_warnings: bool,
+
+ const SourceFile = struct {
+ filename: []const u8,
+ source: []const u8,
+ };
+
+ pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
+ self.sources.append(SourceFile{
+ .filename = filename,
+ .source = source,
+ }) catch unreachable;
+ }
+};
+
+pub fn create(
+ self: *RunTranslatedCContext,
+ allow_warnings: bool,
+ filename: []const u8,
+ name: []const u8,
+ source: []const u8,
+ expected_stdout: []const u8,
+) *TestCase {
+ const tc = self.b.allocator.create(TestCase) catch unreachable;
+ tc.* = TestCase{
+ .name = name,
+ .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
+ .expected_stdout = expected_stdout,
+ .allow_warnings = allow_warnings,
+ };
+
+ tc.addSourceFile(filename, source);
+ return tc;
+}
+
+pub fn add(
+ self: *RunTranslatedCContext,
+ name: []const u8,
+ source: []const u8,
+ expected_stdout: []const u8,
+) void {
+ const tc = self.create(false, "source.c", name, source, expected_stdout);
+ self.addCase(tc);
+}
+
+pub fn addAllowWarnings(
+ self: *RunTranslatedCContext,
+ name: []const u8,
+ source: []const u8,
+ expected_stdout: []const u8,
+) void {
+ const tc = self.create(true, "source.c", name, source, expected_stdout);
+ self.addCase(tc);
+}
+
+pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
+ const b = self.b;
+
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
+
+ const write_src = b.addWriteFiles();
+ for (case.sources.items) |src_file| {
+ _ = write_src.add(src_file.filename, src_file.source);
+ }
+ const translate_c = b.addTranslateC(.{
+ .root_source_file = write_src.files.items[0].getPath(),
+ .target = b.host,
+ .optimize = .Debug,
+ });
+
+ translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
+ const exe = translate_c.addExecutable(.{});
+ exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
+ exe.linkLibC();
+ const run = b.addRunArtifact(exe);
+ run.step.name = b.fmt("{s} run", .{annotated_case_name});
+ if (!case.allow_warnings) {
+ run.expectStdErrEqual("");
+ }
+ run.expectStdOutEqual(case.expected_stdout);
+
+ self.step.dependOn(&run.step);
+}
+
+const RunTranslatedCContext = @This();
+const std = @import("std");
+const ArrayList = std.ArrayList;
+const fmt = std.fmt;
+const mem = std.mem;
+const fs = std.fs;
test/src/StackTrace.zig
@@ -1,7 +1,7 @@
b: *std.Build,
step: *Step,
test_index: usize,
-test_filter: ?[]const u8,
+test_filters: []const []const u8,
optimize_modes: []const OptimizeMode,
check_exe: *std.Build.Step.Compile,
@@ -47,9 +47,9 @@ fn addExpect(
const annotated_case_name = fmt.allocPrint(b.allocator, "check {s} ({s})", .{
name, @tagName(optimize_mode),
}) catch @panic("OOM");
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
- }
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
const write_src = b.addWriteFile("source.zig", source);
const exe = b.addExecutable(.{
test/src/translate_c.zig
@@ -1,121 +0,0 @@
-// This is the implementation of the test harness.
-// For the actual test cases, see test/translate_c.zig.
-const std = @import("std");
-const ArrayList = std.ArrayList;
-const fmt = std.fmt;
-const mem = std.mem;
-const fs = std.fs;
-
-pub const TranslateCContext = struct {
- b: *std.Build,
- step: *std.Build.Step,
- test_index: usize,
- test_filter: ?[]const u8,
-
- const TestCase = struct {
- name: []const u8,
- sources: ArrayList(SourceFile),
- expected_lines: ArrayList([]const u8),
- allow_warnings: bool,
- target: std.Target.Query = .{},
-
- const SourceFile = struct {
- filename: []const u8,
- source: []const u8,
- };
-
- pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
- self.sources.append(SourceFile{
- .filename = filename,
- .source = source,
- }) catch unreachable;
- }
-
- pub fn addExpectedLine(self: *TestCase, text: []const u8) void {
- self.expected_lines.append(text) catch unreachable;
- }
- };
-
- pub fn create(
- self: *TranslateCContext,
- allow_warnings: bool,
- filename: []const u8,
- name: []const u8,
- source: []const u8,
- expected_lines: []const []const u8,
- ) *TestCase {
- const tc = self.b.allocator.create(TestCase) catch unreachable;
- tc.* = TestCase{
- .name = name,
- .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
- .expected_lines = ArrayList([]const u8).init(self.b.allocator),
- .allow_warnings = allow_warnings,
- };
-
- tc.addSourceFile(filename, source);
- var arg_i: usize = 0;
- while (arg_i < expected_lines.len) : (arg_i += 1) {
- tc.addExpectedLine(expected_lines[arg_i]);
- }
- return tc;
- }
-
- pub fn add(
- self: *TranslateCContext,
- name: []const u8,
- source: []const u8,
- expected_lines: []const []const u8,
- ) void {
- const tc = self.create(false, "source.h", name, source, expected_lines);
- self.addCase(tc);
- }
-
- pub fn addWithTarget(
- self: *TranslateCContext,
- name: []const u8,
- target: std.Target.Query,
- source: []const u8,
- expected_lines: []const []const u8,
- ) void {
- const tc = self.create(false, "source.h", name, source, expected_lines);
- tc.target = target;
- self.addCase(tc);
- }
-
- pub fn addAllowWarnings(
- self: *TranslateCContext,
- name: []const u8,
- source: []const u8,
- expected_lines: []const []const u8,
- ) void {
- const tc = self.create(true, "source.h", name, source, expected_lines);
- self.addCase(tc);
- }
-
- pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
- const b = self.b;
-
- const translate_c_cmd = "translate-c";
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;
- if (self.test_filter) |filter| {
- if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
- }
-
- const write_src = b.addWriteFiles();
- for (case.sources.items) |src_file| {
- _ = write_src.add(src_file.filename, src_file.source);
- }
-
- const translate_c = b.addTranslateC(.{
- .root_source_file = write_src.files.items[0].getPath(),
- .target = b.resolveTargetQuery(case.target),
- .optimize = .Debug,
- });
-
- translate_c.step.name = annotated_case_name;
-
- const check_file = translate_c.addCheckFile(case.expected_lines.items);
-
- self.step.dependOn(&check_file.step);
- }
-};
test/src/TranslateC.zig
@@ -0,0 +1,118 @@
+b: *std.Build,
+step: *std.Build.Step,
+test_index: usize,
+test_filters: []const []const u8,
+
+const TestCase = struct {
+ name: []const u8,
+ sources: ArrayList(SourceFile),
+ expected_lines: ArrayList([]const u8),
+ allow_warnings: bool,
+ target: std.Target.Query = .{},
+
+ const SourceFile = struct {
+ filename: []const u8,
+ source: []const u8,
+ };
+
+ pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
+ self.sources.append(SourceFile{
+ .filename = filename,
+ .source = source,
+ }) catch unreachable;
+ }
+
+ pub fn addExpectedLine(self: *TestCase, text: []const u8) void {
+ self.expected_lines.append(text) catch unreachable;
+ }
+};
+
+pub fn create(
+ self: *TranslateCContext,
+ allow_warnings: bool,
+ filename: []const u8,
+ name: []const u8,
+ source: []const u8,
+ expected_lines: []const []const u8,
+) *TestCase {
+ const tc = self.b.allocator.create(TestCase) catch unreachable;
+ tc.* = TestCase{
+ .name = name,
+ .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
+ .expected_lines = ArrayList([]const u8).init(self.b.allocator),
+ .allow_warnings = allow_warnings,
+ };
+
+ tc.addSourceFile(filename, source);
+ var arg_i: usize = 0;
+ while (arg_i < expected_lines.len) : (arg_i += 1) {
+ tc.addExpectedLine(expected_lines[arg_i]);
+ }
+ return tc;
+}
+
+pub fn add(
+ self: *TranslateCContext,
+ name: []const u8,
+ source: []const u8,
+ expected_lines: []const []const u8,
+) void {
+ const tc = self.create(false, "source.h", name, source, expected_lines);
+ self.addCase(tc);
+}
+
+pub fn addWithTarget(
+ self: *TranslateCContext,
+ name: []const u8,
+ target: std.Target.Query,
+ source: []const u8,
+ expected_lines: []const []const u8,
+) void {
+ const tc = self.create(false, "source.h", name, source, expected_lines);
+ tc.target = target;
+ self.addCase(tc);
+}
+
+pub fn addAllowWarnings(
+ self: *TranslateCContext,
+ name: []const u8,
+ source: []const u8,
+ expected_lines: []const []const u8,
+) void {
+ const tc = self.create(true, "source.h", name, source, expected_lines);
+ self.addCase(tc);
+}
+
+pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
+ const b = self.b;
+
+ const translate_c_cmd = "translate-c";
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;
+ for (self.test_filters) |test_filter| {
+ if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+ } else if (self.test_filters.len > 0) return;
+
+ const write_src = b.addWriteFiles();
+ for (case.sources.items) |src_file| {
+ _ = write_src.add(src_file.filename, src_file.source);
+ }
+
+ const translate_c = b.addTranslateC(.{
+ .root_source_file = write_src.files.items[0].getPath(),
+ .target = b.resolveTargetQuery(case.target),
+ .optimize = .Debug,
+ });
+
+ translate_c.step.name = annotated_case_name;
+
+ const check_file = translate_c.addCheckFile(case.expected_lines.items);
+
+ self.step.dependOn(&check_file.step);
+}
+
+const TranslateCContext = @This();
+const std = @import("std");
+const ArrayList = std.ArrayList;
+const fmt = std.fmt;
+const mem = std.mem;
+const fs = std.fs;
test/tests.zig
@@ -15,8 +15,8 @@ const run_translated_c = @import("run_translated_c.zig");
const link = @import("link.zig");
// Implementations
-pub const TranslateCContext = @import("src/translate_c.zig").TranslateCContext;
-pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTranslatedCContext;
+pub const TranslateCContext = @import("src/TranslateC.zig");
+pub const RunTranslatedCContext = @import("src/RunTranslatedC.zig");
pub const CompareOutputContext = @import("src/CompareOutput.zig");
pub const StackTracesContext = @import("src/StackTrace.zig");
@@ -619,7 +619,7 @@ const c_abi_targets = [_]CAbiTarget{
pub fn addCompareOutputTests(
b: *std.Build,
- test_filter: ?[]const u8,
+ test_filters: []const []const u8,
optimize_modes: []const OptimizeMode,
) *Step {
const cases = b.allocator.create(CompareOutputContext) catch @panic("OOM");
@@ -627,7 +627,7 @@ pub fn addCompareOutputTests(
.b = b,
.step = b.step("test-compare-output", "Run the compare output tests"),
.test_index = 0,
- .test_filter = test_filter,
+ .test_filters = test_filters,
.optimize_modes = optimize_modes,
};
@@ -638,7 +638,7 @@ pub fn addCompareOutputTests(
pub fn addStackTraceTests(
b: *std.Build,
- test_filter: ?[]const u8,
+ test_filters: []const []const u8,
optimize_modes: []const OptimizeMode,
) *Step {
const check_exe = b.addExecutable(.{
@@ -653,7 +653,7 @@ pub fn addStackTraceTests(
.b = b,
.step = b.step("test-stack-traces", "Run the stack trace tests"),
.test_index = 0,
- .test_filter = test_filter,
+ .test_filters = test_filters,
.optimize_modes = optimize_modes,
.check_exe = check_exe,
};
@@ -983,13 +983,13 @@ pub fn addCliTests(b: *std.Build) *Step {
return step;
}
-pub fn addAssembleAndLinkTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step {
+pub fn addAssembleAndLinkTests(b: *std.Build, test_filters: []const []const u8, optimize_modes: []const OptimizeMode) *Step {
const cases = b.allocator.create(CompareOutputContext) catch @panic("OOM");
cases.* = CompareOutputContext{
.b = b,
.step = b.step("test-asm-link", "Run the assemble and link tests"),
.test_index = 0,
- .test_filter = test_filter,
+ .test_filters = test_filters,
.optimize_modes = optimize_modes,
};
@@ -998,13 +998,13 @@ pub fn addAssembleAndLinkTests(b: *std.Build, test_filter: ?[]const u8, optimize
return cases.step;
}
-pub fn addTranslateCTests(b: *std.Build, test_filter: ?[]const u8) *Step {
+pub fn addTranslateCTests(b: *std.Build, test_filters: []const []const u8) *Step {
const cases = b.allocator.create(TranslateCContext) catch @panic("OOM");
cases.* = TranslateCContext{
.b = b,
.step = b.step("test-translate-c", "Run the C translation tests"),
.test_index = 0,
- .test_filter = test_filter,
+ .test_filters = test_filters,
};
translate_c.addCases(cases);
@@ -1014,7 +1014,7 @@ pub fn addTranslateCTests(b: *std.Build, test_filter: ?[]const u8) *Step {
pub fn addRunTranslatedCTests(
b: *std.Build,
- test_filter: ?[]const u8,
+ test_filters: []const []const u8,
target: std.Build.ResolvedTarget,
) *Step {
const cases = b.allocator.create(RunTranslatedCContext) catch @panic("OOM");
@@ -1022,7 +1022,7 @@ pub fn addRunTranslatedCTests(
.b = b,
.step = b.step("test-run-translated-c", "Run the Run-Translated-C tests"),
.test_index = 0,
- .test_filter = test_filter,
+ .test_filters = test_filters,
.target = target,
};
@@ -1032,7 +1032,7 @@ pub fn addRunTranslatedCTests(
}
const ModuleTestOptions = struct {
- test_filter: ?[]const u8,
+ test_filters: []const []const u8,
root_src: []const u8,
name: []const u8,
desc: []const u8,
@@ -1115,7 +1115,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
.optimize = test_target.optimize_mode,
.target = resolved_target,
.max_rss = max_rss,
- .filter = options.test_filter,
+ .filters = options.test_filters,
.link_libc = test_target.link_libc,
.single_threaded = test_target.single_threaded,
.use_llvm = test_target.use_llvm,
@@ -1291,7 +1291,7 @@ pub fn addCAbiTests(b: *std.Build, skip_non_native: bool, skip_release: bool) *S
pub fn addCases(
b: *std.Build,
parent_step: *Step,
- opt_test_filter: ?[]const u8,
+ test_filters: []const []const u8,
check_case_exe: *std.Build.Step.Compile,
build_options: @import("cases.zig").BuildOptions,
) !void {
@@ -1310,7 +1310,7 @@ pub fn addCases(
cases.lowerToBuildSteps(
b,
parent_step,
- opt_test_filter,
+ test_filters,
cases_dir_path,
check_case_exe,
);
build.zig
@@ -390,7 +390,7 @@ pub fn build(b: *std.Build) !void {
}
}
- const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
+ const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{};
const test_cases_options = b.addOptions();
check_case_exe.root_module.addOptions("build_options", test_cases_options);
@@ -418,7 +418,7 @@ pub fn build(b: *std.Build) !void {
test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir);
test_cases_options.addOption([:0]const u8, "version", version);
test_cases_options.addOption(std.SemanticVersion, "semver", semver);
- test_cases_options.addOption(?[]const u8, "test_filter", test_filter);
+ test_cases_options.addOption([]const []const u8, "test_filters", test_filters);
var chosen_opt_modes_buf: [4]builtin.OptimizeMode = undefined;
var chosen_mode_index: usize = 0;
@@ -454,7 +454,7 @@ pub fn build(b: *std.Build) !void {
}).step);
const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
- try tests.addCases(b, test_cases_step, test_filter, check_case_exe, .{
+ try tests.addCases(b, test_cases_step, test_filters, check_case_exe, .{
.enable_llvm = enable_llvm,
.llvm_has_m68k = llvm_has_m68k,
.llvm_has_csky = llvm_has_csky,
@@ -464,7 +464,7 @@ pub fn build(b: *std.Build) !void {
test_step.dependOn(test_cases_step);
test_step.dependOn(tests.addModuleTests(b, .{
- .test_filter = test_filter,
+ .test_filters = test_filters,
.root_src = "test/behavior.zig",
.name = "behavior",
.desc = "Run the behavior tests",
@@ -477,7 +477,7 @@ pub fn build(b: *std.Build) !void {
}));
test_step.dependOn(tests.addModuleTests(b, .{
- .test_filter = test_filter,
+ .test_filters = test_filters,
.root_src = "test/c_import.zig",
.name = "c-import",
.desc = "Run the @cImport tests",
@@ -489,7 +489,7 @@ pub fn build(b: *std.Build) !void {
}));
test_step.dependOn(tests.addModuleTests(b, .{
- .test_filter = test_filter,
+ .test_filters = test_filters,
.root_src = "lib/compiler_rt.zig",
.name = "compiler-rt",
.desc = "Run the compiler_rt tests",
@@ -501,7 +501,7 @@ pub fn build(b: *std.Build) !void {
}));
test_step.dependOn(tests.addModuleTests(b, .{
- .test_filter = test_filter,
+ .test_filters = test_filters,
.root_src = "lib/c.zig",
.name = "universal-libc",
.desc = "Run the universal libc tests",
@@ -512,7 +512,7 @@ pub fn build(b: *std.Build) !void {
.skip_libc = true,
}));
- test_step.dependOn(tests.addCompareOutputTests(b, test_filter, optimization_modes));
+ test_step.dependOn(tests.addCompareOutputTests(b, test_filters, optimization_modes));
test_step.dependOn(tests.addStandaloneTests(
b,
optimization_modes,
@@ -523,16 +523,16 @@ pub fn build(b: *std.Build) !void {
));
test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, false, enable_symlinks_windows));
- test_step.dependOn(tests.addStackTraceTests(b, test_filter, optimization_modes));
+ test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));
test_step.dependOn(tests.addCliTests(b));
- test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, optimization_modes));
- test_step.dependOn(tests.addTranslateCTests(b, test_filter));
+ test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));
+ test_step.dependOn(tests.addTranslateCTests(b, test_filters));
if (!skip_run_translated_c) {
- test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target));
+ test_step.dependOn(tests.addRunTranslatedCTests(b, test_filters, target));
}
test_step.dependOn(tests.addModuleTests(b, .{
- .test_filter = test_filter,
+ .test_filters = test_filters,
.root_src = "lib/std/std.zig",
.name = "std",
.desc = "Run the standard library tests",