srctree

Jacob Young parent 429e542f d656c2a7
test: rework how filtering works

  • * make test names contain the fully qualified name
  • * make test filters match the fully qualified name
  • * allow multiple test filters, where a test is skipped if it does not
  • match any of the specified filters
inlinesplit
build.zig added: 520, removed: 532, total 0
@@ -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",
 
doc/langref.html.in added: 520, removed: 532, total 0
@@ -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.zig added: 520, removed: 532, total 0
@@ -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;
}
 
 
lib/std/Build/Step/Compile.zig added: 520, removed: 532, total 0
@@ -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);
}
 
src/Compilation.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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/Module.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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);
 
src/arch/wasm/CodeGen.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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/Coff.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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/Elf/ZigObject.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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/Plan9.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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/main.zig added: 520, removed: 532, total 0
@@ -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) {
 
test/src/Cases.zig added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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",
 
filename was Deleted added: 520, removed: 532, total 0
@@ -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 added: 520, removed: 532, total 0
@@ -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(.{
 
filename was Deleted added: 520, removed: 532, total 0
@@ -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;
 
ev/null added: 520, removed: 532, total 0
@@ -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);
}
};
 
ev/null added: 520, removed: 532, total 0
@@ -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/tests.zig added: 520, removed: 532, total 0
@@ -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,
);