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 93e6846ae579eca117f73206977de347fc7d0221..5038c4061a819f91d371a9540a7566f5bbd0a46d 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 ac1f86cce59d207f1f1f842179d6979c7d2ba71f..be6ebf20aca9abee4ca815ad9024c9e2f9acf6a9 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 6ab2dbaa7f21ed7857abb0d7997307562ff6a04e..746bfde3839ebee33255ab36af140c4c06ec89f1 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 91f56828310ef4417bd1a77c1c52a4b38e437a30..50ff2f0c94df6405b33bef87a33c888362a9ccb3 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 44e226be3314a93c5d976824fd8b82b2691db55b..e9011c3c634562881efa0abb9f74ba8ce24999fe 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 f694ea277a4b9d675c43cbb245c6ebee195bc3ef..e7b66c0d55bc8b27c66e961f4a4b473f43ef6d5b 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 7986c50eaf48ce234e727acd4ec40661bb89f582..fa131122bb5b32d64642dac35e4d84d14521005f 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 cc2e2a916b0d581553261575640c5eda58d999f5..956948dd86a70fd01f5ca1affb2970adc516f4dd 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 61843f5a8fa7e96892534bf8874c0cf014d183b0..59ee21d8cfc2689feb61a7bf81d1b3c2b99f688d 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 4ae928d24358fee50964f793cbbb2ca9df968d38..bd146c68fc9633956845e0b29951cee66ff2909b 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 4023b5ba66c3f737b8f0e795b8cbeb5e926bc17a..e5b41e717bad2636511ded73197c1d90ed67b776 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 b18ba3d83422c2b8f48a8ba0eb54bb897633ffb3..af2d7b1ca2667b857ffd833a54107496d54b712f 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 e463e51753cdb324cab7ae4dca3c6fa6947ee1e4..6f7d420646be84eb0fe062ba6a3efa76e244fbbd 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 ccdbf6771390bb7c4d1b420c49b7946320e20fe0..be451d2fc8ccd8b5528584f52a79a2675e45aaf6 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 55676f923064b465669d4f8d737f3bf6a22d21e1..f7de8129b7a5c638a9a64303f7a4d17ee0d2fe00 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 e1ea460dc35217d6fca79993ca20772639f06b84..444d09101797a3c7ff6a24e2eedda02130fba498 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 7dba3b55d82272bfddc925ca0dbfa586f1952f1e..55d6078b224622adfcd1620903301d8d70572190 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 58f15f7fab53822d4fdbc904003c63596a047ed0..8ade9ca2aaec124907768378e5b899f8f3b1d1a7 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 4633b12e0fdfb8aea748099645311ef7c42b4d6f..baf37cbe37df342289dda543266196061e81dba9 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 4d7b3c627bf8483ee8bbdf01d89e680643969206..c59238d6a7f4bd7808cc30b42bc588d328b3eb87 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 806808820f4c1afd2e0f3622ccda63085b8861dd..65e6e141cec75e79038774241bf41420cf061281 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 2bbea3d3b6af5203f7200c4c07a89c523f13a6c1..7a434cfa8ea4145a966cac9084978e8090e7aa82 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 e952da2af59beae1af7db8b827f0b2cd5cf66f1d..44b1ef8722eafed551c5f8498a72f386096ae92a 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 3cc5ac4c3914799711b5d4f047f0233b1e49237d..ea34805e32efe53636c4a358a9dfb0ed88b80f5f 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 00d4a7ecc944ac2d6cb382535e2af286315b58aa..9ee3fa4de404be18b8cd81e69c52ca3f6c744ad0 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 f23498e955f32650149e9d45aa2024a8e11540e6..da90f3ee1dc441ed95ebc57845093229245ca522 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 4f54f38e6b67e7a7dd8cee9c45369a86b53fb3f8..5be74a0ea59ad7edcedb6ef1b733289b2a52436f 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 84695cb35bcaebb797292b8270e555e3a5de550c..d3182b4745f19584374936cc009729ee91bb0210 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 badab821d34254ee30d11c4d27abfc8f09238cf6..a4b5d1372a1dc54895c39194962de123b7373e66 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 f894c96d7b5f2e497847d982145e48758fad999e..fa1a11a0c5ff529d2a0b99741b5884d246279bd5 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 b5803a30764aacda1f30385c4c8f081a8a3865ce..1fade5ce54eed22353ae36a2e0e824d16c0941ff 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 b3c011698338957fb68886668e51b15ad252f9f8..287bc54a18a3c182c3cfd41f36b2bb8a31105ad8 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 7a779f6c21ff78e6f01324e2210f30864ae904f6..72a9261750f9c8d5ec90d48f147177ba12cabc9e 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"); -- 2.54.0 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 589438297d07a307d573c59eeedfde8a432a36ca..e56d9ad20144cce50af9e248d1941da5e255741b 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; } -- 2.54.0