aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-06-17 20:01:50 +0100
committermlugg <mlugg@mlugg.co.uk>2024-06-17 20:01:50 +0100
commitf37d0725fa4c6a0b5e4e9ca4d25e2760dc06764d (patch)
tree33b6fd35a429d3af5ebddeb47e29f428aa212e82
parentb8d2323b88e68bb5af061dd7e488f51aa0ae8176 (diff)
downloadzig-f37d0725fa4c6a0b5e4e9ca4d25e2760dc06764d.tar.gz
zig-f37d0725fa4c6a0b5e4e9ca4d25e2760dc06764d.zip
Sema: fix callconv detection in generic functions
When analyzing `zirFunc` to instantiate a generic function, `sema.owner_decl` is not the owner Decl of the generic instance, but instead of the call site, so that dependencies are propagated correctly. (This aligns with the fact that in future, generic instantiations will not have a corresponding `Cau`.) So, when deciding the callconv in this case, we must check `sema.generic_owner` to determine whether the function is exported.
-rw-r--r--src/Sema.zig18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index c8a8aeeb91..6714af7685 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -9347,13 +9347,17 @@ fn zirFunc(
src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
}
- // If this instruction has a body it means it's the type of the `owner_decl`
- // otherwise it's a function type without a `callconv` attribute and should
- // never be `.C`.
- const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(sema.owner_decl_index).is_exported)
- .C
- else
- .Unspecified;
+ // If this instruction has a body, then it's a function declaration, and we decide
+ // the callconv based on whether it is exported. Otherwise, the callconv defaults
+ // to `.Unspecified`.
+ const cc: std.builtin.CallingConvention = if (has_body) cc: {
+ const fn_is_exported = if (sema.generic_owner != .none) exported: {
+ const generic_owner_fn = mod.funcInfo(sema.generic_owner);
+ const generic_owner_decl = mod.declPtr(generic_owner_fn.owner_decl);
+ break :exported generic_owner_decl.is_exported;
+ } else sema.owner_decl.is_exported;
+ break :cc if (fn_is_exported) .C else .Unspecified;
+ } else .Unspecified;
return sema.funcCommon(
block,