authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-29 05:07:17+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-29 23:06:08+01:00
log4976b58ab16069f8d3267b69ed030f29685c1abe
tree400f632d11eec4f3c330bee15d59f8fd6219c20f
parentb5fad3a40a86eb379903d6a803bdbe66dcaa5487
signaturelock-open Commit is signed but in an unrecognized format.

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

33 files changed, 149 insertions(+), 65 deletions(-)

lib/compiler_rt/clear_cache.zig+1-1
......@@ -12,7 +12,7 @@ pub const panic = @import("common.zig").panic;
1212// specified range.
1313
1414comptime {
15 _ = clear_cache;
15 _ = &clear_cache;
1616}
1717
1818fn clear_cache(start: usize, end: usize) callconv(.C) void {
lib/std/fmt.zig+1-1
......@@ -1959,7 +1959,7 @@ pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
19591959pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError;
19601960
19611961test {
1962 _ = parseFloat;
1962 _ = &parseFloat;
19631963}
19641964
19651965pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
lib/std/fs.zig+5-5
......@@ -3150,12 +3150,12 @@ fn copy_file(fd_in: os.fd_t, fd_out: os.fd_t, maybe_size: ?u64) CopyFileRawError
31503150
31513151test {
31523152 if (builtin.os.tag != .wasi) {
3153 _ = makeDirAbsolute;
3154 _ = makeDirAbsoluteZ;
3155 _ = copyFileAbsolute;
3156 _ = updateFileAbsolute;
3153 _ = &makeDirAbsolute;
3154 _ = &makeDirAbsoluteZ;
3155 _ = &copyFileAbsolute;
3156 _ = &updateFileAbsolute;
31573157 }
3158 _ = Dir.copyFile;
3158 _ = &Dir.copyFile;
31593159 _ = @import("fs/test.zig");
31603160 _ = @import("fs/path.zig");
31613161 _ = @import("fs/file.zig");
lib/std/hash_map.zig+1-1
......@@ -1605,7 +1605,7 @@ pub fn HashMapUnmanaged(
16051605
16061606 comptime {
16071607 if (builtin.mode == .Debug) {
1608 _ = dbHelper;
1608 _ = &dbHelper;
16091609 }
16101610 }
16111611 };
lib/std/multi_array_list.zig+2-2
......@@ -532,8 +532,8 @@ pub fn MultiArrayList(comptime T: type) type {
532532
533533 comptime {
534534 if (builtin.mode == .Debug) {
535 _ = dbHelper;
536 _ = Slice.dbHelper;
535 _ = &dbHelper;
536 _ = &Slice.dbHelper;
537537 }
538538 }
539539 };
lib/std/os/test.zig+1-1
......@@ -704,7 +704,7 @@ test "signalfd" {
704704 .linux, .solaris => {},
705705 else => return error.SkipZigTest,
706706 }
707 _ = os.signalfd;
707 _ = &os.signalfd;
708708}
709709
710710test "sync" {
lib/std/testing.zig+2-2
......@@ -1116,7 +1116,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
11161116pub fn refAllDecls(comptime T: type) void {
11171117 if (!builtin.is_test) return;
11181118 inline for (comptime std.meta.declarations(T)) |decl| {
1119 if (decl.is_pub) _ = @field(T, decl.name);
1119 if (decl.is_pub) _ = &@field(T, decl.name);
11201120 }
11211121}
11221122
......@@ -1132,7 +1132,7 @@ pub fn refAllDeclsRecursive(comptime T: type) void {
11321132 else => {},
11331133 }
11341134 }
1135 _ = @field(T, decl.name);
1135 _ = &@field(T, decl.name);
11361136 }
11371137 }
11381138}
src/Compilation.zig+7
......@@ -3193,6 +3193,13 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
31933193 error.OutOfMemory => return error.OutOfMemory,
31943194 error.AnalysisFail => return,
31953195 };
3196 const decl = module.declPtr(decl_index);
3197 if (decl.kind == .@"test" and comp.bin_file.options.is_test) {
3198 // Tests are always emitted in test binaries. The decl_refs are created by
3199 // Module.populateTestFunctions, but this will not queue body analysis, so do
3200 // that now.
3201 try module.ensureFuncBodyAnalysisQueued(decl.val.castTag(.function).?.data);
3202 }
31963203 },
31973204 .update_embed_file => |embed_file| {
31983205 const named_frame = tracy.namedFrame("update_embed_file");
src/Module.zig+59-15
......@@ -1638,6 +1638,10 @@ pub const Fn = struct {
16381638 inferred_error_sets: InferredErrorSetList = .{},
16391639
16401640 pub const Analysis = enum {
1641 /// This function has not yet undergone analysis, because we have not
1642 /// seen a potential runtime call. It may be analyzed in future.
1643 none,
1644 /// Analysis for this function has been queued, but not yet completed.
16411645 queued,
16421646 /// This function intentionally only has ZIR generated because it is marked
16431647 /// 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 {
43234327 .complete, .codegen_failure_retryable => {
43244328 switch (func.state) {
43254329 .sema_failure, .dependency_failure => return error.AnalysisFail,
4326 .queued => {},
4330 .none, .queued => {},
43274331 .in_progress => unreachable,
43284332 .inline_only => unreachable, // don't queue work for this
43294333 .success => return,
......@@ -4426,6 +4430,60 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
44264430 }
44274431}
44284432
4433/// Ensure this function's body is or will be analyzed and emitted. This should
4434/// be called whenever a potential runtime call of a function is seen.
4435///
4436/// The caller is responsible for ensuring the function decl itself is already
4437/// analyzed, and for ensuring it can exist at runtime (see
4438/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
4439/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4440pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
4441 const decl_index = func.owner_decl;
4442 const decl = mod.declPtr(decl_index);
4443
4444 switch (decl.analysis) {
4445 .unreferenced => unreachable,
4446 .in_progress => unreachable,
4447 .outdated => unreachable,
4448
4449 .file_failure,
4450 .sema_failure,
4451 .liveness_failure,
4452 .codegen_failure,
4453 .dependency_failure,
4454 .sema_failure_retryable,
4455 .codegen_failure_retryable,
4456 // The function analysis failed, but we've already emitted an error for
4457 // that. The callee doesn't need the function to be analyzed right now,
4458 // so its analysis can safely continue.
4459 => return,
4460
4461 .complete => {},
4462 }
4463
4464 assert(decl.has_tv);
4465
4466 switch (func.state) {
4467 .none => {},
4468 .queued => return,
4469 // As above, we don't need to forward errors here.
4470 .sema_failure, .dependency_failure => return,
4471 .in_progress => return,
4472 .inline_only => unreachable, // don't queue work for this
4473 .success => return,
4474 }
4475
4476 // Decl itself is safely analyzed, and body analysis is not yet queued
4477
4478 try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
4479 if (mod.emit_h != null) {
4480 // TODO: we ideally only want to do this if the function's type changed
4481 // since the last update
4482 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
4483 }
4484 func.state = .queued;
4485}
4486
44294487pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
44304488 const tracy = trace(@src());
44314489 defer tracy.end();
......@@ -4733,20 +4791,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47334791 decl.analysis = .complete;
47344792 decl.generation = mod.generation;
47354793
4736 const has_runtime_bits = try sema.fnHasRuntimeBits(decl.ty);
4737
4738 if (has_runtime_bits) {
4739 // We don't fully codegen the decl until later, but we do need to reserve a global
4740 // offset table index for it. This allows us to codegen decls out of dependency
4741 // order, increasing how many computations can be done in parallel.
4742 try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
4743 if (type_changed and mod.emit_h != null) {
4744 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
4745 }
4746 } else if (!prev_is_inline and prev_type_has_bits) {
4747 mod.comp.bin_file.freeDecl(decl_index);
4748 }
4749
47504794 const is_inline = decl.ty.fnCallingConvention() == .Inline;
47514795 if (decl.is_exported) {
47524796 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
src/Sema.zig+36-5
......@@ -2452,6 +2452,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24522452 .@"align" = iac.data.alignment,
24532453 .@"addrspace" = addr_space,
24542454 });
2455 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
24552456 return sema.addConstant(
24562457 ptr_ty,
24572458 try Value.Tag.decl_ref_mut.create(sema.arena, .{
......@@ -3709,6 +3710,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37093710 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
37103711 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
37113712
3713 try sema.maybeQueueFuncBodyAnalysis(decl_index);
37123714 if (var_is_mut) {
37133715 sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{
37143716 .decl_index = decl_index,
......@@ -3809,6 +3811,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38093811 // Even though we reuse the constant instruction, we still remove it from the
38103812 // block so that codegen does not see it.
38113813 block.instructions.shrinkRetainingCapacity(search_index);
3814 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
38123815 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
38133816 // if bitcast ty ref needs to be made const, make_ptr_const
38143817 // ZIR handles it later, so we can just use the ty ref here.
......@@ -5747,6 +5750,7 @@ pub fn analyzeExport(
57475750
57485751 // This decl is alive no matter what, since it's being exported
57495752 mod.markDeclAlive(exported_decl);
5753 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
57505754
57515755 const gpa = mod.gpa;
57525756
......@@ -7068,6 +7072,12 @@ fn analyzeCall(
70687072 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
70697073 }
70707074
7075 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7076 if (func_val.castTag(.function)) |func_obj| {
7077 try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);
7078 }
7079 }
7080
70717081 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
70727082 args.len);
70737083 const func_inst = try block.addInst(.{
......@@ -7585,6 +7595,8 @@ fn instantiateGenericCall(
75857595 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
75867596 }
75877597
7598 try sema.mod.ensureFuncBodyAnalysisQueued(callee);
7599
75887600 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
75897601 runtime_args_len);
75907602 const result = try block.addInst(.{
......@@ -9143,7 +9155,7 @@ fn funcCommon(
91439155 }
91449156
91459157 const is_inline = fn_ty.fnCallingConvention() == .Inline;
9146 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;
9158 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
91479159
91489160 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
91499161 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
......@@ -24279,9 +24291,7 @@ fn fieldCallBind(
2427924291 if (concrete_ty.getNamespace()) |namespace| {
2428024292 if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| {
2428124293 try sema.addReferencedBy(block, src, decl_idx);
24282 const inst = try sema.analyzeDeclRef(decl_idx);
24283
24284 const decl_val = try sema.analyzeLoad(block, src, inst, src);
24294 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
2428524295 const decl_type = sema.typeOf(decl_val);
2428624296 if (decl_type.zigTypeTag() == .Fn and
2428724297 decl_type.fnParamLen() >= 1)
......@@ -28911,7 +28921,7 @@ fn analyzeDeclVal(
2891128921 if (sema.decl_val_table.get(decl_index)) |result| {
2891228922 return result;
2891328923 }
28914 const decl_ref = try sema.analyzeDeclRef(decl_index);
28924 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);
2891528925 const result = try sema.analyzeLoad(block, src, decl_ref, src);
2891628926 if (Air.refToIndex(result)) |index| {
2891728927 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 {
2897028980 try val.copy(anon_decl.arena()),
2897128981 0, // default alignment
2897228982 );
28983 try sema.maybeQueueFuncBodyAnalysis(decl);
2897328984 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);
2897428985 return try Value.Tag.decl_ref.create(sema.arena, decl);
2897528986}
......@@ -28982,6 +28993,14 @@ fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
2898228993}
2898328994
2898428995fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref {
28996 return sema.analyzeDeclRefInner(decl_index, true);
28997}
28998
28999/// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but
29000/// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a
29001/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps
29002/// this function with `analyze_fn_body` set to true.
29003fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref {
2898529004 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
2898629005 try sema.ensureDeclAnalyzed(decl_index);
2898729006
......@@ -28997,6 +29016,9 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref
2899729016 });
2899829017 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index));
2899929018 }
29019 if (analyze_fn_body) {
29020 try sema.maybeQueueFuncBodyAnalysis(decl_index);
29021 }
2900029022 return sema.addConstant(
2900129023 try Type.ptr(sema.arena, sema.mod, .{
2900229024 .pointee_type = decl_tv.ty,
......@@ -29008,6 +29030,15 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref
2900829030 );
2900929031}
2901029032
29033fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
29034 const decl = sema.mod.declPtr(decl_index);
29035 const tv = try decl.typedValue();
29036 if (tv.ty.zigTypeTag() != .Fn) return;
29037 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
29038 const func = tv.val.castTag(.function) orelse return; // undef or extern_fn
29039 try sema.mod.ensureFuncBodyAnalysisQueued(func.data);
29040}
29041
2901129042fn analyzeRef(
2901229043 sema: *Sema,
2901329044 block: *Block,
src/type.zig+1-1
......@@ -6802,7 +6802,7 @@ pub const Type = extern union {
68026802
68036803 comptime {
68046804 if (builtin.mode == .Debug) {
6805 _ = dbHelper;
6805 _ = &dbHelper;
68066806 }
68076807 }
68086808};
src/value.zig+1-1
......@@ -5709,7 +5709,7 @@ pub const Value = extern union {
57095709
57105710 comptime {
57115711 if (builtin.mode == .Debug) {
5712 _ = dbHelper;
5712 _ = &dbHelper;
57135713 }
57145714 }
57155715};
test/behavior/sizeof_and_typeof.zig+1-1
......@@ -48,7 +48,7 @@ fn fn1(alpha: bool) void {
4848}
4949
5050test "lazy @sizeOf result is checked for definedness" {
51 _ = fn1;
51 _ = &fn1;
5252}
5353
5454const A = struct {
test/cases/compile_errors/closure_get_depends_on_failed_decl.zig+1-1
......@@ -3,7 +3,7 @@ pub inline fn instanceRequestAdapter() void {}
33pub inline fn requestAdapter(
44 comptime callbackArg: fn () callconv(.Inline) void,
55) void {
6 _ = (struct {
6 _ = &(struct {
77 pub fn callback() callconv(.C) void {
88 callbackArg();
99 }
test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig+3-2
......@@ -1,5 +1,5 @@
11const Bar = union(enum(u32)) {
2 X: i32 = 1
2 X: i32 = 1,
33};
44
55fn testCompileLog(x: Bar) void {
......@@ -7,7 +7,8 @@ fn testCompileLog(x: Bar) void {
77}
88
99pub export fn entry() void {
10 comptime testCompileLog(Bar{.X = 123});
10 comptime testCompileLog(Bar{ .X = 123 });
11 _ = &testCompileLog;
1112}
1213
1314// error
test/cases/compile_errors/compile_log.zig+6-5
......@@ -1,10 +1,11 @@
11export fn foo() void {
2 comptime bar(12, "hi",);
2 comptime bar(12, "hi");
3 _ = &bar;
34}
45fn bar(a: i32, b: []const u8) void {
5 @compileLog("begin",);
6 @compileLog("begin");
67 @compileLog("a", a, "b", b);
7 @compileLog("end",);
8 @compileLog("end");
89}
910export fn baz() void {
1011 const S = struct { a: u32 };
......@@ -15,8 +16,8 @@ export fn baz() void {
1516// backend=llvm
1617// target=native
1718//
18// :5:5: error: found compile log statement
19// :11:5: note: also here
19// :6:5: error: found compile log statement
20// :12:5: note: also here
2021//
2122// Compile Log Output:
2223// @as(*const [5:0]u8, "begin")
test/cases/compile_errors/dereference_slice.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(x: []i32) i32 {
22 return x.*;
33}
44comptime {
5 _ = entry;
5 _ = &entry;
66}
77
88// error
test/cases/compile_errors/extern_function_with_comptime_parameter.zig+3-3
......@@ -4,9 +4,9 @@ fn f() i32 {
44}
55pub extern fn entry1(b: u32, comptime a: [2]u8, c: i32) void;
66pub extern fn entry2(b: u32, noalias a: anytype, i43) void;
7comptime { _ = f; }
8comptime { _ = entry1; }
9comptime { _ = entry2; }
7comptime { _ = &f; }
8comptime { _ = &entry1; }
9comptime { _ = &entry2; }
1010
1111// error
1212// backend=stage2
test/cases/compile_errors/invalid_address_space_coercion.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *i32 {
22 return a;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// error
test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *i32 {
22 return &a.*;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// error
test/cases/compile_errors/noalias_on_non_pointer_param.zig+2-2
......@@ -2,10 +2,10 @@ fn f(noalias x: i32) void { _ = x; }
22export fn entry() void { f(1234); }
33
44fn generic(comptime T: type, noalias _: [*]T, noalias _: [*]const T, _: usize) void {}
5comptime { _ = generic; }
5comptime { _ = &generic; }
66
77fn slice(noalias _: []u8) void {}
8comptime { _ = slice; }
8comptime { _ = &slice; }
99
1010// error
1111// backend=stage2
test/cases/compile_errors/pointer_with_different_address_spaces.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.fs) i32 {
22 return a;
33}
44export fn entry2() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// error
test/cases/compile_errors/pointers_with_different_address_spaces.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: ?*addrspace(.gs) i32) *i32 {
22 return a.?;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// error
test/cases/compile_errors/slice_sentinel_mismatch-2.zig+1-1
......@@ -2,7 +2,7 @@ fn foo() [:0]u8 {
22 var x: []u8 = undefined;
33 return x;
44}
5comptime { _ = foo; }
5comptime { _ = &foo; }
66
77// error
88// backend=stage2
test/cases/llvm/address_space_pointer_access_chaining_pointer_to_optional_array.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) ?[1]i32) *addrspace(.gs) i32 {
22 return &a.*.?[0];
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/cases/llvm/address_spaces_pointer_access_chaining_array_pointer.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) [1]i32) *addrspace(.gs) i32 {
22 return &a[0];
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/cases/llvm/address_spaces_pointer_access_chaining_complex.zig+1-1
......@@ -3,7 +3,7 @@ fn entry(a: *addrspace(.gs) [1]A) *addrspace(.gs) i32 {
33 return &a[0].a.?[0];
44}
55pub fn main() void {
6 _ = entry;
6 _ = &entry;
77}
88
99// compile
test/cases/llvm/address_spaces_pointer_access_chaining_struct_pointer.zig+1-1
......@@ -3,7 +3,7 @@ fn entry(a: *addrspace(.gs) A) *addrspace(.gs) i32 {
33 return &a.a;
44}
55pub fn main() void {
6 _ = entry;
6 _ = &entry;
77}
88
99// compile
test/cases/llvm/dereferencing_though_multiple_pointers_with_address_spaces.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.fs) *addrspace(.gs) *i32) *i32 {
22 return a.*.*;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/cases/llvm/pointer_keeps_address_space.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 {
22 return a;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/cases/llvm/pointer_keeps_address_space_when_taking_address_of_dereference.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 {
22 return &a.*;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/cases/llvm/pointer_to_explicit_generic_address_space_coerces_to_implicit_pointer.zig+1-1
......@@ -2,7 +2,7 @@ fn entry(a: *addrspace(.generic) i32) *i32 {
22 return a;
33}
44pub fn main() void {
5 _ = entry;
5 _ = &entry;
66}
77
88// compile
test/link/wasm/type/build.zig+2-2
......@@ -26,10 +26,10 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
2626
2727 const check_lib = lib.checkObject();
2828 check_lib.checkStart("Section type");
29 // only 3 entries, although we have more functions.
29 // only 2 entries, although we have more functions.
3030 // This is to test functions with the same function signature
3131 // have their types deduplicated.
32 check_lib.checkNext("entries 3");
32 check_lib.checkNext("entries 2");
3333 check_lib.checkNext("params 1");
3434 check_lib.checkNext("type i32");
3535 check_lib.checkNext("returns 1");