From 4976b58ab16069f8d3267b69ed030f29685c1abe Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 29 May 2023 05:07:17 +0100 Subject: [PATCH 1/2] Prevent analysis of functions only referenced at comptime The idea here is that there are two ways we can reference a function at runtime: * Through a direct call, i.e. where the function is comptime-known * Through a function pointer This means we can easily perform a form of rudimentary escape analysis on functions. If we ever see a `decl_ref` or `ref` of a function, we have a function pointer, which could "leak" into runtime code, so we emit the function; but for a plain `decl_val`, there's no need to. This change means that `comptime { _ = f; }` no longer forces a function to be emitted, which was used for some things (mainly tests). These use sites have been replaced with `_ = &f;`, which still triggers analysis of the function body, since you're taking a pointer to the function. Resolves: #6256 Resolves: #15353 --- lib/compiler_rt/clear_cache.zig | 2 +- lib/std/fmt.zig | 2 +- lib/std/fs.zig | 10 +-- lib/std/hash_map.zig | 2 +- lib/std/multi_array_list.zig | 4 +- lib/std/os/test.zig | 2 +- lib/std/testing.zig | 4 +- src/Compilation.zig | 7 ++ src/Module.zig | 74 +++++++++++++++---- src/Sema.zig | 41 ++++++++-- src/type.zig | 2 +- src/value.zig | 2 +- test/behavior/sizeof_and_typeof.zig | 2 +- .../closure_get_depends_on_failed_decl.zig | 2 +- ..._tagged_enum_doesnt_crash_the_compiler.zig | 5 +- test/cases/compile_errors/compile_log.zig | 11 +-- .../compile_errors/dereference_slice.zig | 2 +- ...xtern_function_with_comptime_parameter.zig | 6 +- .../invalid_address_space_coercion.zig | 2 +- ...ace_when_taking_address_of_dereference.zig | 2 +- .../noalias_on_non_pointer_param.zig | 4 +- .../pointer_with_different_address_spaces.zig | 2 +- ...pointers_with_different_address_spaces.zig | 2 +- .../slice_sentinel_mismatch-2.zig | 2 +- ...ess_chaining_pointer_to_optional_array.zig | 2 +- ..._pointer_access_chaining_array_pointer.zig | 2 +- ...spaces_pointer_access_chaining_complex.zig | 2 +- ...pointer_access_chaining_struct_pointer.zig | 2 +- ..._multiple_pointers_with_address_spaces.zig | 2 +- .../llvm/pointer_keeps_address_space.zig | 2 +- ...ace_when_taking_address_of_dereference.zig | 2 +- ...ress_space_coerces_to_implicit_pointer.zig | 2 +- test/link/wasm/type/build.zig | 4 +- 33 files changed, 149 insertions(+), 65 deletions(-) diff --git a/lib/compiler_rt/clear_cache.zig b/lib/compiler_rt/clear_cache.zig index 93e6846ae5..5038c4061a 100644 --- a/lib/compiler_rt/clear_cache.zig +++ b/lib/compiler_rt/clear_cache.zig @@ -12,7 +12,7 @@ pub const panic = @import("common.zig").panic; // specified range. comptime { - _ = clear_cache; + _ = &clear_cache; } fn clear_cache(start: usize, end: usize) callconv(.C) void { diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index ac1f86cce5..be6ebf20ac 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1959,7 +1959,7 @@ pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError; test { - _ = parseFloat; + _ = &parseFloat; } pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 6ab2dbaa7f..746bfde383 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -3150,12 +3150,12 @@ fn copy_file(fd_in: os.fd_t, fd_out: os.fd_t, maybe_size: ?u64) CopyFileRawError test { if (builtin.os.tag != .wasi) { - _ = makeDirAbsolute; - _ = makeDirAbsoluteZ; - _ = copyFileAbsolute; - _ = updateFileAbsolute; + _ = &makeDirAbsolute; + _ = &makeDirAbsoluteZ; + _ = ©FileAbsolute; + _ = &updateFileAbsolute; } - _ = Dir.copyFile; + _ = &Dir.copyFile; _ = @import("fs/test.zig"); _ = @import("fs/path.zig"); _ = @import("fs/file.zig"); diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index 91f5682831..50ff2f0c94 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -1605,7 +1605,7 @@ pub fn HashMapUnmanaged( comptime { if (builtin.mode == .Debug) { - _ = dbHelper; + _ = &dbHelper; } } }; diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 44e226be33..e9011c3c63 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -532,8 +532,8 @@ pub fn MultiArrayList(comptime T: type) type { comptime { if (builtin.mode == .Debug) { - _ = dbHelper; - _ = Slice.dbHelper; + _ = &dbHelper; + _ = &Slice.dbHelper; } } }; diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index f694ea277a..e7b66c0d55 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -704,7 +704,7 @@ test "signalfd" { .linux, .solaris => {}, else => return error.SkipZigTest, } - _ = os.signalfd; + _ = &os.signalfd; } test "sync" { diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 7986c50eaf..fa131122bb 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -1116,7 +1116,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime pub fn refAllDecls(comptime T: type) void { if (!builtin.is_test) return; inline for (comptime std.meta.declarations(T)) |decl| { - if (decl.is_pub) _ = @field(T, decl.name); + if (decl.is_pub) _ = &@field(T, decl.name); } } @@ -1132,7 +1132,7 @@ pub fn refAllDeclsRecursive(comptime T: type) void { else => {}, } } - _ = @field(T, decl.name); + _ = &@field(T, decl.name); } } } diff --git a/src/Compilation.zig b/src/Compilation.zig index cc2e2a916b..956948dd86 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3193,6 +3193,13 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => return, }; + const decl = module.declPtr(decl_index); + if (decl.kind == .@"test" and comp.bin_file.options.is_test) { + // Tests are always emitted in test binaries. The decl_refs are created by + // Module.populateTestFunctions, but this will not queue body analysis, so do + // that now. + try module.ensureFuncBodyAnalysisQueued(decl.val.castTag(.function).?.data); + } }, .update_embed_file => |embed_file| { const named_frame = tracy.namedFrame("update_embed_file"); diff --git a/src/Module.zig b/src/Module.zig index 61843f5a8f..59ee21d8cf 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1638,6 +1638,10 @@ pub const Fn = struct { inferred_error_sets: InferredErrorSetList = .{}, pub const Analysis = enum { + /// This function has not yet undergone analysis, because we have not + /// seen a potential runtime call. It may be analyzed in future. + none, + /// Analysis for this function has been queued, but not yet completed. queued, /// This function intentionally only has ZIR generated because it is marked /// inline, which means no runtime version of the function will be generated. @@ -4323,7 +4327,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { .complete, .codegen_failure_retryable => { switch (func.state) { .sema_failure, .dependency_failure => return error.AnalysisFail, - .queued => {}, + .none, .queued => {}, .in_progress => unreachable, .inline_only => unreachable, // don't queue work for this .success => return, @@ -4426,6 +4430,60 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { } } +/// Ensure this function's body is or will be analyzed and emitted. This should +/// be called whenever a potential runtime call of a function is seen. +/// +/// The caller is responsible for ensuring the function decl itself is already +/// analyzed, and for ensuring it can exist at runtime (see +/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body +/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. +pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void { + const decl_index = func.owner_decl; + const decl = mod.declPtr(decl_index); + + switch (decl.analysis) { + .unreferenced => unreachable, + .in_progress => unreachable, + .outdated => unreachable, + + .file_failure, + .sema_failure, + .liveness_failure, + .codegen_failure, + .dependency_failure, + .sema_failure_retryable, + .codegen_failure_retryable, + // The function analysis failed, but we've already emitted an error for + // that. The callee doesn't need the function to be analyzed right now, + // so its analysis can safely continue. + => return, + + .complete => {}, + } + + assert(decl.has_tv); + + switch (func.state) { + .none => {}, + .queued => return, + // As above, we don't need to forward errors here. + .sema_failure, .dependency_failure => return, + .in_progress => return, + .inline_only => unreachable, // don't queue work for this + .success => return, + } + + // Decl itself is safely analyzed, and body analysis is not yet queued + + try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); + if (mod.emit_h != null) { + // TODO: we ideally only want to do this if the function's type changed + // since the last update + try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); + } + func.state = .queued; +} + pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -4733,20 +4791,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { decl.analysis = .complete; decl.generation = mod.generation; - const has_runtime_bits = try sema.fnHasRuntimeBits(decl.ty); - - if (has_runtime_bits) { - // We don't fully codegen the decl until later, but we do need to reserve a global - // offset table index for it. This allows us to codegen decls out of dependency - // order, increasing how many computations can be done in parallel. - try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); - if (type_changed and mod.emit_h != null) { - try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); - } - } else if (!prev_is_inline and prev_type_has_bits) { - mod.comp.bin_file.freeDecl(decl_index); - } - const is_inline = decl.ty.fnCallingConvention() == .Inline; if (decl.is_exported) { const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) }; diff --git a/src/Sema.zig b/src/Sema.zig index 4ae928d243..bd146c68fc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2452,6 +2452,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE .@"align" = iac.data.alignment, .@"addrspace" = addr_space, }); + try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index); return sema.addConstant( ptr_ty, try Value.Tag.decl_ref_mut.create(sema.arena, .{ @@ -3709,6 +3710,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const final_ptr_ty_inst = try sema.addType(final_ptr_ty); sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst; + try sema.maybeQueueFuncBodyAnalysis(decl_index); if (var_is_mut) { sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{ .decl_index = decl_index, @@ -3809,6 +3811,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com // Even though we reuse the constant instruction, we still remove it from the // block so that codegen does not see it. block.instructions.shrinkRetainingCapacity(search_index); + try sema.maybeQueueFuncBodyAnalysis(new_decl_index); sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index); // if bitcast ty ref needs to be made const, make_ptr_const // ZIR handles it later, so we can just use the ty ref here. @@ -5747,6 +5750,7 @@ pub fn analyzeExport( // This decl is alive no matter what, since it's being exported mod.markDeclAlive(exported_decl); + try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); const gpa = mod.gpa; @@ -7068,6 +7072,12 @@ fn analyzeCall( sema.owner_func.?.calls_or_awaits_errorable_fn = true; } + if (try sema.resolveMaybeUndefVal(func)) |func_val| { + if (func_val.castTag(.function)) |func_obj| { + try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data); + } + } + try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + args.len); const func_inst = try block.addInst(.{ @@ -7585,6 +7595,8 @@ fn instantiateGenericCall( sema.owner_func.?.calls_or_awaits_errorable_fn = true; } + try sema.mod.ensureFuncBodyAnalysisQueued(callee); + try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + runtime_args_len); const result = try block.addInst(.{ @@ -9143,7 +9155,7 @@ fn funcCommon( } const is_inline = fn_ty.fnCallingConvention() == .Inline; - const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued; + const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none; const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: { break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr; @@ -24279,9 +24291,7 @@ fn fieldCallBind( if (concrete_ty.getNamespace()) |namespace| { if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| { try sema.addReferencedBy(block, src, decl_idx); - const inst = try sema.analyzeDeclRef(decl_idx); - - const decl_val = try sema.analyzeLoad(block, src, inst, src); + const decl_val = try sema.analyzeDeclVal(block, src, decl_idx); const decl_type = sema.typeOf(decl_val); if (decl_type.zigTypeTag() == .Fn and decl_type.fnParamLen() >= 1) @@ -28911,7 +28921,7 @@ fn analyzeDeclVal( if (sema.decl_val_table.get(decl_index)) |result| { return result; } - const decl_ref = try sema.analyzeDeclRef(decl_index); + const decl_ref = try sema.analyzeDeclRefInner(decl_index, false); const result = try sema.analyzeLoad(block, src, decl_ref, src); if (Air.refToIndex(result)) |index| { if (sema.air_instructions.items(.tag)[index] == .constant and !block.is_typeof) { @@ -28970,6 +28980,7 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value { try val.copy(anon_decl.arena()), 0, // default alignment ); + try sema.maybeQueueFuncBodyAnalysis(decl); try sema.mod.declareDeclDependency(sema.owner_decl_index, decl); return try Value.Tag.decl_ref.create(sema.arena, decl); } @@ -28982,6 +28993,14 @@ fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value { } fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref { + return sema.analyzeDeclRefInner(decl_index, true); +} + +/// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but +/// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a +/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps +/// this function with `analyze_fn_body` set to true. +fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref { try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index); try sema.ensureDeclAnalyzed(decl_index); @@ -28997,6 +29016,9 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref }); return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index)); } + if (analyze_fn_body) { + try sema.maybeQueueFuncBodyAnalysis(decl_index); + } return sema.addConstant( try Type.ptr(sema.arena, sema.mod, .{ .pointee_type = decl_tv.ty, @@ -29008,6 +29030,15 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref ); } +fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void { + const decl = sema.mod.declPtr(decl_index); + const tv = try decl.typedValue(); + if (tv.ty.zigTypeTag() != .Fn) return; + if (!try sema.fnHasRuntimeBits(tv.ty)) return; + const func = tv.val.castTag(.function) orelse return; // undef or extern_fn + try sema.mod.ensureFuncBodyAnalysisQueued(func.data); +} + fn analyzeRef( sema: *Sema, block: *Block, diff --git a/src/type.zig b/src/type.zig index 4023b5ba66..e5b41e717b 100644 --- a/src/type.zig +++ b/src/type.zig @@ -6802,7 +6802,7 @@ pub const Type = extern union { comptime { if (builtin.mode == .Debug) { - _ = dbHelper; + _ = &dbHelper; } } }; diff --git a/src/value.zig b/src/value.zig index b18ba3d834..af2d7b1ca2 100644 --- a/src/value.zig +++ b/src/value.zig @@ -5709,7 +5709,7 @@ pub const Value = extern union { comptime { if (builtin.mode == .Debug) { - _ = dbHelper; + _ = &dbHelper; } } }; diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index e463e51753..6f7d420646 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -48,7 +48,7 @@ fn fn1(alpha: bool) void { } test "lazy @sizeOf result is checked for definedness" { - _ = fn1; + _ = &fn1; } const A = struct { diff --git a/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig b/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig index ccdbf67713..be451d2fc8 100644 --- a/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig +++ b/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig @@ -3,7 +3,7 @@ pub inline fn instanceRequestAdapter() void {} pub inline fn requestAdapter( comptime callbackArg: fn () callconv(.Inline) void, ) void { - _ = (struct { + _ = &(struct { pub fn callback() callconv(.C) void { callbackArg(); } diff --git a/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig b/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig index 55676f9230..f7de8129b7 100644 --- a/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig +++ b/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig @@ -1,5 +1,5 @@ const Bar = union(enum(u32)) { - X: i32 = 1 + X: i32 = 1, }; fn testCompileLog(x: Bar) void { @@ -7,7 +7,8 @@ fn testCompileLog(x: Bar) void { } pub export fn entry() void { - comptime testCompileLog(Bar{.X = 123}); + comptime testCompileLog(Bar{ .X = 123 }); + _ = &testCompileLog; } // error diff --git a/test/cases/compile_errors/compile_log.zig b/test/cases/compile_errors/compile_log.zig index e1ea460dc3..444d091017 100644 --- a/test/cases/compile_errors/compile_log.zig +++ b/test/cases/compile_errors/compile_log.zig @@ -1,10 +1,11 @@ export fn foo() void { - comptime bar(12, "hi",); + comptime bar(12, "hi"); + _ = &bar; } fn bar(a: i32, b: []const u8) void { - @compileLog("begin",); + @compileLog("begin"); @compileLog("a", a, "b", b); - @compileLog("end",); + @compileLog("end"); } export fn baz() void { const S = struct { a: u32 }; @@ -15,8 +16,8 @@ export fn baz() void { // backend=llvm // target=native // -// :5:5: error: found compile log statement -// :11:5: note: also here +// :6:5: error: found compile log statement +// :12:5: note: also here // // Compile Log Output: // @as(*const [5:0]u8, "begin") diff --git a/test/cases/compile_errors/dereference_slice.zig b/test/cases/compile_errors/dereference_slice.zig index 7dba3b55d8..55d6078b22 100644 --- a/test/cases/compile_errors/dereference_slice.zig +++ b/test/cases/compile_errors/dereference_slice.zig @@ -2,7 +2,7 @@ fn entry(x: []i32) i32 { return x.*; } comptime { - _ = entry; + _ = &entry; } // error diff --git a/test/cases/compile_errors/extern_function_with_comptime_parameter.zig b/test/cases/compile_errors/extern_function_with_comptime_parameter.zig index 58f15f7fab..8ade9ca2aa 100644 --- a/test/cases/compile_errors/extern_function_with_comptime_parameter.zig +++ b/test/cases/compile_errors/extern_function_with_comptime_parameter.zig @@ -4,9 +4,9 @@ fn f() i32 { } pub extern fn entry1(b: u32, comptime a: [2]u8, c: i32) void; pub extern fn entry2(b: u32, noalias a: anytype, i43) void; -comptime { _ = f; } -comptime { _ = entry1; } -comptime { _ = entry2; } +comptime { _ = &f; } +comptime { _ = &entry1; } +comptime { _ = &entry2; } // error // backend=stage2 diff --git a/test/cases/compile_errors/invalid_address_space_coercion.zig b/test/cases/compile_errors/invalid_address_space_coercion.zig index 4633b12e0f..baf37cbe37 100644 --- a/test/cases/compile_errors/invalid_address_space_coercion.zig +++ b/test/cases/compile_errors/invalid_address_space_coercion.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *i32 { return a; } pub fn main() void { - _ = entry; + _ = &entry; } // error diff --git a/test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig b/test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig index 4d7b3c627b..c59238d6a7 100644 --- a/test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig +++ b/test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *i32 { return &a.*; } pub fn main() void { - _ = entry; + _ = &entry; } // error diff --git a/test/cases/compile_errors/noalias_on_non_pointer_param.zig b/test/cases/compile_errors/noalias_on_non_pointer_param.zig index 806808820f..65e6e141ce 100644 --- a/test/cases/compile_errors/noalias_on_non_pointer_param.zig +++ b/test/cases/compile_errors/noalias_on_non_pointer_param.zig @@ -2,10 +2,10 @@ fn f(noalias x: i32) void { _ = x; } export fn entry() void { f(1234); } fn generic(comptime T: type, noalias _: [*]T, noalias _: [*]const T, _: usize) void {} -comptime { _ = generic; } +comptime { _ = &generic; } fn slice(noalias _: []u8) void {} -comptime { _ = slice; } +comptime { _ = &slice; } // error // backend=stage2 diff --git a/test/cases/compile_errors/pointer_with_different_address_spaces.zig b/test/cases/compile_errors/pointer_with_different_address_spaces.zig index 2bbea3d3b6..7a434cfa8e 100644 --- a/test/cases/compile_errors/pointer_with_different_address_spaces.zig +++ b/test/cases/compile_errors/pointer_with_different_address_spaces.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.fs) i32 { return a; } export fn entry2() void { - _ = entry; + _ = &entry; } // error diff --git a/test/cases/compile_errors/pointers_with_different_address_spaces.zig b/test/cases/compile_errors/pointers_with_different_address_spaces.zig index e952da2af5..44b1ef8722 100644 --- a/test/cases/compile_errors/pointers_with_different_address_spaces.zig +++ b/test/cases/compile_errors/pointers_with_different_address_spaces.zig @@ -2,7 +2,7 @@ fn entry(a: ?*addrspace(.gs) i32) *i32 { return a.?; } pub fn main() void { - _ = entry; + _ = &entry; } // error diff --git a/test/cases/compile_errors/slice_sentinel_mismatch-2.zig b/test/cases/compile_errors/slice_sentinel_mismatch-2.zig index 3cc5ac4c39..ea34805e32 100644 --- a/test/cases/compile_errors/slice_sentinel_mismatch-2.zig +++ b/test/cases/compile_errors/slice_sentinel_mismatch-2.zig @@ -2,7 +2,7 @@ fn foo() [:0]u8 { var x: []u8 = undefined; return x; } -comptime { _ = foo; } +comptime { _ = &foo; } // error // backend=stage2 diff --git a/test/cases/llvm/address_space_pointer_access_chaining_pointer_to_optional_array.zig b/test/cases/llvm/address_space_pointer_access_chaining_pointer_to_optional_array.zig index 00d4a7ecc9..9ee3fa4de4 100644 --- a/test/cases/llvm/address_space_pointer_access_chaining_pointer_to_optional_array.zig +++ b/test/cases/llvm/address_space_pointer_access_chaining_pointer_to_optional_array.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) ?[1]i32) *addrspace(.gs) i32 { return &a.*.?[0]; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/address_spaces_pointer_access_chaining_array_pointer.zig b/test/cases/llvm/address_spaces_pointer_access_chaining_array_pointer.zig index f23498e955..da90f3ee1d 100644 --- a/test/cases/llvm/address_spaces_pointer_access_chaining_array_pointer.zig +++ b/test/cases/llvm/address_spaces_pointer_access_chaining_array_pointer.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) [1]i32) *addrspace(.gs) i32 { return &a[0]; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/address_spaces_pointer_access_chaining_complex.zig b/test/cases/llvm/address_spaces_pointer_access_chaining_complex.zig index 4f54f38e6b..5be74a0ea5 100644 --- a/test/cases/llvm/address_spaces_pointer_access_chaining_complex.zig +++ b/test/cases/llvm/address_spaces_pointer_access_chaining_complex.zig @@ -3,7 +3,7 @@ fn entry(a: *addrspace(.gs) [1]A) *addrspace(.gs) i32 { return &a[0].a.?[0]; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/address_spaces_pointer_access_chaining_struct_pointer.zig b/test/cases/llvm/address_spaces_pointer_access_chaining_struct_pointer.zig index 84695cb35b..d3182b4745 100644 --- a/test/cases/llvm/address_spaces_pointer_access_chaining_struct_pointer.zig +++ b/test/cases/llvm/address_spaces_pointer_access_chaining_struct_pointer.zig @@ -3,7 +3,7 @@ fn entry(a: *addrspace(.gs) A) *addrspace(.gs) i32 { return &a.a; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/dereferencing_though_multiple_pointers_with_address_spaces.zig b/test/cases/llvm/dereferencing_though_multiple_pointers_with_address_spaces.zig index badab821d3..a4b5d1372a 100644 --- a/test/cases/llvm/dereferencing_though_multiple_pointers_with_address_spaces.zig +++ b/test/cases/llvm/dereferencing_though_multiple_pointers_with_address_spaces.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.fs) *addrspace(.gs) *i32) *i32 { return a.*.*; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/pointer_keeps_address_space.zig b/test/cases/llvm/pointer_keeps_address_space.zig index f894c96d7b..fa1a11a0c5 100644 --- a/test/cases/llvm/pointer_keeps_address_space.zig +++ b/test/cases/llvm/pointer_keeps_address_space.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 { return a; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/pointer_keeps_address_space_when_taking_address_of_dereference.zig b/test/cases/llvm/pointer_keeps_address_space_when_taking_address_of_dereference.zig index b5803a3076..1fade5ce54 100644 --- a/test/cases/llvm/pointer_keeps_address_space_when_taking_address_of_dereference.zig +++ b/test/cases/llvm/pointer_keeps_address_space_when_taking_address_of_dereference.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 { return &a.*; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/cases/llvm/pointer_to_explicit_generic_address_space_coerces_to_implicit_pointer.zig b/test/cases/llvm/pointer_to_explicit_generic_address_space_coerces_to_implicit_pointer.zig index b3c0116983..287bc54a18 100644 --- a/test/cases/llvm/pointer_to_explicit_generic_address_space_coerces_to_implicit_pointer.zig +++ b/test/cases/llvm/pointer_to_explicit_generic_address_space_coerces_to_implicit_pointer.zig @@ -2,7 +2,7 @@ fn entry(a: *addrspace(.generic) i32) *i32 { return a; } pub fn main() void { - _ = entry; + _ = &entry; } // compile diff --git a/test/link/wasm/type/build.zig b/test/link/wasm/type/build.zig index 7a779f6c21..72a9261750 100644 --- a/test/link/wasm/type/build.zig +++ b/test/link/wasm/type/build.zig @@ -26,10 +26,10 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const check_lib = lib.checkObject(); check_lib.checkStart("Section type"); - // only 3 entries, although we have more functions. + // only 2 entries, although we have more functions. // This is to test functions with the same function signature // have their types deduplicated. - check_lib.checkNext("entries 3"); + check_lib.checkNext("entries 2"); check_lib.checkNext("params 1"); check_lib.checkNext("type i32"); check_lib.checkNext("returns 1"); From 0f58d34ef7935dd9877f4969ed6ec7d582cd104c Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 29 May 2023 20:31:09 +0100 Subject: [PATCH 2/2] tests: disable incremental cases for now These were failing on the prior commit. Unfortunately, the fix would have been relatively complicated, and ties into underlying issues with the current incremental compilation logic. After discussing this with Andrew, we agreed that the best course of action is to completely disable incremental compilation tests for now until it's more mature, at which point we can re-enable them. --- test/src/Cases.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 589438297d..e56d9ad201 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -468,6 +468,13 @@ pub fn lowerToBuildSteps( incremental_exe: *std.Build.Step.Compile, ) void { for (self.incremental_cases.items) |incr_case| { + if (true) { + // TODO: incremental tests are disabled for now, as incremental compilation bugs were + // getting in the way of practical improvements to the compiler, and incremental + // compilation is not currently used. They should be re-enabled once incremental + // 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; }