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
signature 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");