authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-18 13:25:13-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-08-18 13:25:13-07:00
log001ec07772f35ffee031429a558506b89d02cdca
tree2c626a0670ba522cc201e5af8d922e2c395b8ed5
parentc1483eb05c221b4f0c0c357bf75b828f722fa44d
parent52178d14b080d0bbf5e1fe8ed25ce1c26ea18566
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24249 from antlilja/dwarf-extern-arg

Fix compiler crash when passing a comptime extern function arg to a function

8 files changed, 243 insertions(+), 65 deletions(-)

src/InternPool.zig+10-3
......@@ -2257,6 +2257,7 @@ pub const Key = union(enum) {
22572257 /// The `Nav` corresponding to this extern symbol.
22582258 /// This is ignored by hashing and equality.
22592259 owner_nav: Nav.Index,
2260 source: Tag.Extern.Flags.Source,
22602261 };
22612262
22622263 pub const Func = struct {
......@@ -2859,7 +2860,7 @@ pub const Key = union(enum) {
28592860 asBytes(&e.is_threadlocal) ++ asBytes(&e.is_dll_import) ++
28602861 asBytes(&e.relocation) ++
28612862 asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++
2862 asBytes(&e.zir_index)),
2863 asBytes(&e.zir_index) ++ &[1]u8{@intFromEnum(e.source)}),
28632864 };
28642865 }
28652866
......@@ -2958,7 +2959,8 @@ pub const Key = union(enum) {
29582959 a_info.is_const == b_info.is_const and
29592960 a_info.alignment == b_info.alignment and
29602961 a_info.@"addrspace" == b_info.@"addrspace" and
2961 a_info.zir_index == b_info.zir_index;
2962 a_info.zir_index == b_info.zir_index and
2963 a_info.source == b_info.source;
29622964 },
29632965 .func => |a_info| {
29642966 const b_info = b.func;
......@@ -5967,7 +5969,10 @@ pub const Tag = enum(u8) {
59675969 is_threadlocal: bool,
59685970 is_dll_import: bool,
59695971 relocation: std.builtin.ExternOptions.Relocation,
5970 _: u25 = 0,
5972 source: Source,
5973 _: u24 = 0,
5974
5975 pub const Source = enum(u1) { builtin, syntax };
59715976 };
59725977 };
59735978
......@@ -7320,6 +7325,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
73207325 .@"addrspace" = nav.status.fully_resolved.@"addrspace",
73217326 .zir_index = extra.zir_index,
73227327 .owner_nav = extra.owner_nav,
7328 .source = extra.flags.source,
73237329 } };
73247330 },
73257331 .func_instance => .{ .func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
......@@ -9212,6 +9218,7 @@ pub fn getExtern(
92129218 .is_threadlocal = key.is_threadlocal,
92139219 .is_dll_import = key.is_dll_import,
92149220 .relocation = key.relocation,
9221 .source = key.source,
92159222 },
92169223 .zir_index = key.zir_index,
92179224 .owner_nav = owner_nav,
src/Sema.zig+1
......@@ -25768,6 +25768,7 @@ fn zirBuiltinExtern(
2576825768 },
2576925769 },
2577025770 .owner_nav = undefined, // ignored by `getExtern`
25771 .source = .builtin,
2577125772 });
2577225773
2577325774 const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav);
src/Zcu/PerThread.zig+2
......@@ -1249,6 +1249,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
12491249 .@"addrspace" = modifiers.@"addrspace",
12501250 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction
12511251 .owner_nav = undefined, // ignored by `getExtern`
1252 .source = .syntax,
12521253 }));
12531254 },
12541255 };
......@@ -3435,6 +3436,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V
34353436 .@"addrspace" = e.@"addrspace",
34363437 .zir_index = e.zir_index,
34373438 .owner_nav = undefined, // ignored by `getExtern`.
3439 .source = e.source,
34383440 });
34393441 return Value.fromInterned(coerced);
34403442 },
src/link/Dwarf.zig+212-57
......@@ -1720,7 +1720,7 @@ pub const WipNav = struct {
17201720 std.leb.writeUnsignedFixed(
17211721 block_bytes,
17221722 wip_nav.debug_info.written()[block.abbrev_code..][0..block_bytes],
1723 try wip_nav.dwarf.refAbbrevCode(.empty_block),
1723 @intCast(try wip_nav.dwarf.refAbbrevCode(.empty_block)),
17241724 );
17251725 std.mem.writeInt(u32, wip_nav.debug_info.written()[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);
17261726 wip_nav.any_children = true;
......@@ -1782,7 +1782,7 @@ pub const WipNav = struct {
17821782 std.leb.writeUnsignedFixed(
17831783 inlined_func_bytes,
17841784 wip_nav.debug_info.written()[block.abbrev_code..][0..inlined_func_bytes],
1785 try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func),
1785 @intCast(try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func)),
17861786 );
17871787 std.mem.writeInt(u32, wip_nav.debug_info.written()[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);
17881788 try wip_nav.setInlineFunc(func);
......@@ -2077,7 +2077,11 @@ pub const WipNav = struct {
20772077 const ty = value.typeOf(zcu);
20782078 if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null);
20792079 if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
2080 if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav);
2080 if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(switch (ip.indexToKey(value.toIntern())) {
2081 else => unreachable,
2082 .func => |func| func.owner_nav,
2083 .@"extern" => |@"extern"| @"extern".owner_nav,
2084 });
20812085 const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern());
20822086 const unit: Unit.Index = .main;
20832087 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
......@@ -2250,6 +2254,8 @@ pub const WipNav = struct {
22502254 .decl_func,
22512255 .decl_nullary_func_generic,
22522256 .decl_func_generic,
2257 .decl_extern_nullary_func,
2258 .decl_extern_func,
22532259 => false,
22542260 .generic_decl_var,
22552261 .generic_decl_const,
......@@ -2585,7 +2591,7 @@ pub fn initWipNav(
25852591 pt: Zcu.PerThread,
25862592 nav_index: InternPool.Nav.Index,
25872593 sym_index: u32,
2588) error{ OutOfMemory, CodegenFail }!?WipNav {
2594) error{ OutOfMemory, CodegenFail }!WipNav {
25892595 return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {
25902596 error.OutOfMemory => error.OutOfMemory,
25912597 else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),
......@@ -2597,7 +2603,7 @@ fn initWipNavInner(
25972603 pt: Zcu.PerThread,
25982604 nav_index: InternPool.Nav.Index,
25992605 sym_index: u32,
2600) !?WipNav {
2606) !WipNav {
26012607 const zcu = pt.zcu;
26022608 const ip = &zcu.intern_pool;
26032609
......@@ -2613,15 +2619,6 @@ fn initWipNavInner(
26132619 nav.fqn.fmt(ip),
26142620 });
26152621
2616 const nav_val = zcu.navValue(nav_index);
2617 const nav_key = ip.indexToKey(nav_val.toIntern());
2618 switch (nav_key) {
2619 // Ignore @extern
2620 .@"extern" => |@"extern"| if (decl.linkage != .@"extern" or
2621 !@"extern".name.eqlSlice(file.zir.?.nullTerminatedString(decl.name), ip)) return null,
2622 else => {},
2623 }
2624
26252622 const mod = file.mod.?;
26262623 const unit = try dwarf.getUnit(mod);
26272624 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
......@@ -2654,44 +2651,63 @@ fn initWipNavInner(
26542651 };
26552652 errdefer wip_nav.deinit();
26562653
2657 switch (nav_key) {
2658 else => {
2659 const diw = &wip_nav.debug_info.writer;
2660 try wip_nav.declCommon(.{
2661 .decl = .decl_var,
2662 .generic_decl = .generic_decl_var,
2663 .decl_instance = .decl_instance_var,
2664 }, &nav, inst_info.file, &decl);
2665 try wip_nav.strp(nav.fqn.toSlice(ip));
2666 const ty: Type = nav_val.typeOf(zcu);
2667 const addr: Loc = .{ .addr_reloc = sym_index };
2668 const loc: Loc = if (decl.is_threadlocal) loc: {
2669 const target = zcu.comp.root_mod.resolved_target.result;
2670 break :loc switch (target.cpu.arch) {
2671 .x86_64 => .{ .form_tls_address = &addr },
2672 else => .empty,
2654 const nav_val = zcu.navValue(nav_index);
2655 nav_val: switch (ip.indexToKey(nav_val.toIntern())) {
2656 .@"extern" => |@"extern"| switch (@"extern".source) {
2657 .builtin => {
2658 const maybe_func_type = switch (ip.indexToKey(@"extern".ty)) {
2659 .func_type => |func_type| func_type,
2660 else => null,
26732661 };
2674 } else addr;
2675 switch (decl.kind) {
2676 .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,
2677 .@"const" => {
2678 const const_ty_reloc_index = try wip_nav.refForward();
2679 try wip_nav.infoExprLoc(loc);
2680 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2681 ty.abiAlignment(zcu).toByteUnits().?);
2682 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2683 wip_nav.finishForward(const_ty_reloc_index);
2684 try wip_nav.abbrevCode(.is_const);
2685 try wip_nav.refType(ty);
2686 },
2687 .@"var" => {
2688 try wip_nav.refType(ty);
2689 try wip_nav.infoExprLoc(loc);
2690 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2691 ty.abiAlignment(zcu).toByteUnits().?);
2692 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2662 const diw = &wip_nav.debug_info.writer;
2663 try wip_nav.abbrevCode(if (maybe_func_type) |func_type|
2664 if (func_type.param_types.len > 0 or func_type.is_var_args) .builtin_extern_func else .builtin_extern_nullary_func
2665 else
2666 .builtin_extern_var);
2667 try wip_nav.refType(.fromInterned(zcu.fileRootType(inst_info.file)));
2668 try wip_nav.strp(@"extern".name.toSlice(ip));
2669 try wip_nav.refType(.fromInterned(if (maybe_func_type) |func_type| func_type.return_type else @"extern".ty));
2670 if (maybe_func_type) |func_type| {
2671 try wip_nav.infoAddrSym(sym_index, 0);
2672 try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type)));
2673 if (func_type.param_types.len > 0 or func_type.is_var_args) {
2674 for (func_type.param_types.get(ip)) |param_type| {
2675 try wip_nav.abbrevCode(.extern_param);
2676 try wip_nav.refType(.fromInterned(param_type));
2677 }
2678 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
2679 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
2680 }
2681 } else try wip_nav.infoExprLoc(.{ .addr_reloc = sym_index });
2682 },
2683 .syntax => switch (ip.isFunctionType(@"extern".ty)) {
2684 false => continue :nav_val .{ .variable = undefined },
2685 true => {
2686 const func_type = ip.indexToKey(@"extern".ty).func_type;
2687 const diw = &wip_nav.debug_info.writer;
2688 try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{
2689 .decl = .decl_extern_func,
2690 .generic_decl = .generic_decl_func,
2691 .decl_instance = .decl_instance_extern_func,
2692 } else .{
2693 .decl = .decl_extern_nullary_func,
2694 .generic_decl = .generic_decl_func,
2695 .decl_instance = .decl_instance_extern_nullary_func,
2696 }, &nav, inst_info.file, &decl);
2697 try wip_nav.strp(@"extern".name.toSlice(ip));
2698 try wip_nav.refType(.fromInterned(func_type.return_type));
2699 try wip_nav.infoAddrSym(sym_index, 0);
2700 try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type)));
2701 if (func_type.param_types.len > 0 or func_type.is_var_args) {
2702 for (func_type.param_types.get(ip)) |param_type| {
2703 try wip_nav.abbrevCode(.extern_param);
2704 try wip_nav.refType(.fromInterned(param_type));
2705 }
2706 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
2707 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
2708 }
26932709 },
2694 }
2710 },
26952711 },
26962712 .func => |func| if (func.owner_nav != nav_index) {
26972713 try wip_nav.declCommon(.{
......@@ -2752,7 +2768,10 @@ fn initWipNavInner(
27522768 .generic_decl = .generic_decl_func,
27532769 .decl_instance = .decl_instance_func,
27542770 }, &nav, inst_info.file, &decl);
2755 try wip_nav.strp(nav.fqn.toSlice(ip));
2771 try wip_nav.strp(switch (decl.linkage) {
2772 .normal => nav.fqn,
2773 .@"extern", .@"export" => nav.name,
2774 }.toSlice(ip));
27562775 try wip_nav.refType(.fromInterned(func_type.return_type));
27572776 try wip_nav.infoAddrSym(sym_index, 0);
27582777 wip_nav.func_high_pc = @intCast(diw.end);
......@@ -2763,7 +2782,7 @@ fn initWipNavInner(
27632782 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
27642783 }.toByteUnits().?);
27652784 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2766 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
2785 try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type)));
27672786
27682787 const dlw = &wip_nav.debug_line.writer;
27692788 try dlw.writeByte(DW.LNS.extended_op);
......@@ -2801,6 +2820,47 @@ fn initWipNavInner(
28012820 try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0);
28022821 }
28032822 },
2823 else => {
2824 const diw = &wip_nav.debug_info.writer;
2825 try wip_nav.declCommon(.{
2826 .decl = .decl_var,
2827 .generic_decl = .generic_decl_var,
2828 .decl_instance = .decl_instance_var,
2829 }, &nav, inst_info.file, &decl);
2830 try wip_nav.strp(switch (decl.linkage) {
2831 .normal => nav.fqn,
2832 .@"extern", .@"export" => nav.name,
2833 }.toSlice(ip));
2834 const ty: Type = nav_val.typeOf(zcu);
2835 const addr: Loc = .{ .addr_reloc = sym_index };
2836 const loc: Loc = if (decl.is_threadlocal) loc: {
2837 const target = zcu.comp.root_mod.resolved_target.result;
2838 break :loc switch (target.cpu.arch) {
2839 .x86_64 => .{ .form_tls_address = &addr },
2840 else => .empty,
2841 };
2842 } else addr;
2843 switch (decl.kind) {
2844 .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,
2845 .@"const" => {
2846 const const_ty_reloc_index = try wip_nav.refForward();
2847 try wip_nav.infoExprLoc(loc);
2848 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2849 ty.abiAlignment(zcu).toByteUnits().?);
2850 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2851 wip_nav.finishForward(const_ty_reloc_index);
2852 try wip_nav.abbrevCode(.is_const);
2853 try wip_nav.refType(ty);
2854 },
2855 .@"var" => {
2856 try wip_nav.refType(ty);
2857 try wip_nav.infoExprLoc(loc);
2858 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2859 ty.abiAlignment(zcu).toByteUnits().?);
2860 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2861 },
2862 }
2863 },
28042864 }
28052865 return wip_nav;
28062866}
......@@ -2891,11 +2951,11 @@ fn finishWipNavFuncWriterError(
28912951 std.leb.writeUnsignedFixed(
28922952 AbbrevCode.decl_bytes,
28932953 abbrev_code_buf,
2894 try dwarf.refAbbrevCode(switch (abbrev_code) {
2954 @intCast(try dwarf.refAbbrevCode(switch (abbrev_code) {
28952955 else => unreachable,
28962956 .decl_func => .decl_nullary_func,
28972957 .decl_instance_func => .decl_instance_nullary_func,
2898 }),
2958 })),
28992959 );
29002960 }
29012961 }
......@@ -3357,7 +3417,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
33573417 .generic_decl = .generic_decl_var,
33583418 .decl_instance = .decl_instance_var,
33593419 }, &nav, inst_info.file, &decl);
3360 try wip_nav.strp(nav.fqn.toSlice(ip));
3420 try wip_nav.strp(switch (decl.linkage) {
3421 .normal => nav.fqn,
3422 .@"extern", .@"export" => nav.name,
3423 }.toSlice(ip));
33613424 const nav_ty = nav_val.typeOf(zcu);
33623425 try wip_nav.refType(nav_ty);
33633426 try wip_nav.blockValue(nav_src_loc, nav_val);
......@@ -3387,7 +3450,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
33873450 .generic_decl = .generic_decl_const,
33883451 .decl_instance = .decl_instance_const,
33893452 }, &nav, inst_info.file, &decl);
3390 try wip_nav.strp(nav.fqn.toSlice(ip));
3453 try wip_nav.strp(switch (decl.linkage) {
3454 .normal => nav.fqn,
3455 .@"extern", .@"export" => nav.name,
3456 }.toSlice(ip));
33913457 const nav_ty_reloc_index = try wip_nav.refForward();
33923458 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
33933459 nav_ty.abiAlignment(zcu).toByteUnits().?);
......@@ -5109,6 +5175,8 @@ const AbbrevCode = enum {
51095175 decl_func,
51105176 decl_nullary_func_generic,
51115177 decl_func_generic,
5178 decl_extern_nullary_func,
5179 decl_extern_func,
51125180 generic_decl_var,
51135181 generic_decl_const,
51145182 generic_decl_func,
......@@ -5128,6 +5196,8 @@ const AbbrevCode = enum {
51285196 decl_instance_func,
51295197 decl_instance_nullary_func_generic,
51305198 decl_instance_func_generic,
5199 decl_instance_extern_nullary_func,
5200 decl_instance_extern_func,
51315201 // the rest are unrestricted other than empty variants must not be longer
51325202 // than the non-empty variant, and so should appear first
51335203 compile_unit,
......@@ -5179,6 +5249,9 @@ const AbbrevCode = enum {
51795249 packed_struct_type,
51805250 empty_union_type,
51815251 union_type,
5252 builtin_extern_nullary_func,
5253 builtin_extern_func,
5254 builtin_extern_var,
51825255 empty_block,
51835256 block,
51845257 empty_inlined_func,
......@@ -5193,6 +5266,7 @@ const AbbrevCode = enum {
51935266 unnamed_comptime_arg_comptime_state,
51945267 comptime_arg_runtime_bits_comptime_state,
51955268 unnamed_comptime_arg_runtime_bits_comptime_state,
5269 extern_param,
51965270 local_var,
51975271 local_const,
51985272 local_const_runtime_bits,
......@@ -5214,7 +5288,7 @@ const AbbrevCode = enum {
52145288 comptime_value_elem_runtime_bits,
52155289 comptime_value_elem_comptime_state,
52165290
5217 const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_func_generic));
5291 const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_extern_func));
52185292 comptime {
52195293 assert(uleb128Bytes(@intFromEnum(AbbrevCode.pad_1)) == 1);
52205294 assert(uleb128Bytes(@intFromEnum(AbbrevCode.pad_n)) == 1);
......@@ -5389,6 +5463,27 @@ const AbbrevCode = enum {
53895463 .{ .type, .ref_addr },
53905464 },
53915465 },
5466 .decl_extern_nullary_func = .{
5467 .tag = .subprogram,
5468 .attrs = decl_abbrev_common_attrs ++ .{
5469 .{ .linkage_name, .strp },
5470 .{ .type, .ref_addr },
5471 .{ .low_pc, .addr },
5472 .{ .external, .flag_present },
5473 .{ .noreturn, .flag },
5474 },
5475 },
5476 .decl_extern_func = .{
5477 .tag = .subprogram,
5478 .children = true,
5479 .attrs = decl_abbrev_common_attrs ++ .{
5480 .{ .linkage_name, .strp },
5481 .{ .type, .ref_addr },
5482 .{ .low_pc, .addr },
5483 .{ .external, .flag_present },
5484 .{ .noreturn, .flag },
5485 },
5486 },
53925487 .generic_decl_var = .{
53935488 .tag = .variable,
53945489 .attrs = generic_decl_abbrev_common_attrs,
......@@ -5537,6 +5632,27 @@ const AbbrevCode = enum {
55375632 .{ .type, .ref_addr },
55385633 },
55395634 },
5635 .decl_instance_extern_nullary_func = .{
5636 .tag = .subprogram,
5637 .attrs = decl_instance_abbrev_common_attrs ++ .{
5638 .{ .linkage_name, .strp },
5639 .{ .type, .ref_addr },
5640 .{ .low_pc, .addr },
5641 .{ .external, .flag_present },
5642 .{ .noreturn, .flag },
5643 },
5644 },
5645 .decl_instance_extern_func = .{
5646 .tag = .subprogram,
5647 .children = true,
5648 .attrs = decl_instance_abbrev_common_attrs ++ .{
5649 .{ .linkage_name, .strp },
5650 .{ .type, .ref_addr },
5651 .{ .low_pc, .addr },
5652 .{ .external, .flag_present },
5653 .{ .noreturn, .flag },
5654 },
5655 },
55405656 .compile_unit = .{
55415657 .tag = .compile_unit,
55425658 .children = true,
......@@ -5934,6 +6050,39 @@ const AbbrevCode = enum {
59346050 .{ .alignment, .udata },
59356051 },
59366052 },
6053 .builtin_extern_nullary_func = .{
6054 .tag = .subprogram,
6055 .attrs = &.{
6056 .{ .ZIG_parent, .ref_addr },
6057 .{ .linkage_name, .strp },
6058 .{ .type, .ref_addr },
6059 .{ .low_pc, .addr },
6060 .{ .external, .flag_present },
6061 .{ .noreturn, .flag },
6062 },
6063 },
6064 .builtin_extern_func = .{
6065 .tag = .subprogram,
6066 .children = true,
6067 .attrs = &.{
6068 .{ .ZIG_parent, .ref_addr },
6069 .{ .linkage_name, .strp },
6070 .{ .type, .ref_addr },
6071 .{ .low_pc, .addr },
6072 .{ .external, .flag_present },
6073 .{ .noreturn, .flag },
6074 },
6075 },
6076 .builtin_extern_var = .{
6077 .tag = .variable,
6078 .attrs = &.{
6079 .{ .ZIG_parent, .ref_addr },
6080 .{ .linkage_name, .strp },
6081 .{ .type, .ref_addr },
6082 .{ .location, .exprloc },
6083 .{ .external, .flag_present },
6084 },
6085 },
59376086 .empty_block = .{
59386087 .tag = .lexical_block,
59396088 .attrs = &.{
......@@ -6053,6 +6202,12 @@ const AbbrevCode = enum {
60536202 .{ .ZIG_comptime_value, .ref_addr },
60546203 },
60556204 },
6205 .extern_param = .{
6206 .tag = .formal_parameter,
6207 .attrs = &.{
6208 .{ .type, .ref_addr },
6209 },
6210 },
60566211 .local_var = .{
60576212 .tag = .variable,
60586213 .attrs = &.{
src/link/Elf/ZigObject.zig+2-2
......@@ -1543,8 +1543,8 @@ pub fn updateNav(
15431543 @"extern".lib_name.toSlice(ip),
15441544 );
15451545 if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true;
1546 if (self.dwarf) |*dwarf| dwarf: {
1547 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
1546 if (self.dwarf) |*dwarf| {
1547 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
15481548 defer debug_wip_nav.deinit();
15491549 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
15501550 error.OutOfMemory => return error.OutOfMemory,
src/link/MachO/ZigObject.zig+2-2
......@@ -877,8 +877,8 @@ pub fn updateNav(
877877 const lib_name = @"extern".lib_name.toSlice(ip);
878878 const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
879879 if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true;
880 if (self.dwarf) |*dwarf| dwarf: {
881 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
880 if (self.dwarf) |*dwarf| {
881 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
882882 defer debug_wip_nav.deinit();
883883 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
884884 error.OutOfMemory => return error.OutOfMemory,
test/behavior/extern.zig+13
......@@ -56,3 +56,16 @@ test "coerce extern function types" {
5656
5757 _ = @as(fn () callconv(.c) ?*u32, c_extern_function);
5858}
59
60fn a_function(func: fn () callconv(.c) void) void {
61 _ = func;
62}
63
64test "pass extern function to function" {
65 a_function(struct {
66 extern fn an_extern_function() void;
67 }.an_extern_function);
68 a_function(@extern(*const fn () callconv(.c) void, .{ .name = "an_extern_function" }).*);
69}
70
71export fn an_extern_function() void {}
test/incremental/change_exports+1-1
......@@ -1,4 +1,4 @@
1#target=x86_64-linux-selfhosted
1//#target=x86_64-linux-selfhosted
22#target=x86_64-linux-cbe
33#target=x86_64-windows-cbe
44