From 79702c144d713de126d37637630c7b25ee9ecc82 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Oct 2021 15:43:57 -0700 Subject: [PATCH] Sema: fix ret_ptr when inlining Previously, it would emit a ret_ptr AIR instruction but that is not correct because such an instruction would reference the result pointer of the caller function rather than the callee function. Instead, we emit an alloc instruction in this case. `ret_load` already handles inlining correctly. --- src/Sema.zig | 8 ++++++++ test/behavior/fn.zig | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index d61aa52be48a4de52acc6c387f07803a5b52bf33..87216348f2da07f907accb59ff54c9015f76e7c1 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1958,6 +1958,14 @@ fn zirRetPtr( .pointee_type = sema.fn_ret_ty, .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), }); + + if (block.inlining != null) { + // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr. + // TODO when functions gain result location support, the inlining struct in + // Block should contain the return pointer, and we would pass that through here. + return block.addTy(.alloc, ptr_type); + } + return block.addTy(.ret_ptr, ptr_type); } diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index b00c2f7a5997be688b1379984f6d85812d54f3a2..80f1f4d9199d19a9ca28306110fd10e601eb604f 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -90,3 +90,34 @@ test "discard the result of a function that returns a struct" { S.entry(); comptime S.entry(); } + +test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" { + const S = struct { + field: u32, + + fn doTheTest() !void { + bar2 = actualFn; + const result = try foo(); + try expect(result.field == 1234); + } + + const Foo = struct { field: u32 }; + + fn foo() !Foo { + var res: Foo = undefined; + res.field = bar(); + return res; + } + + inline fn bar() u32 { + return bar2.?(); + } + + var bar2: ?fn () u32 = null; + + fn actualFn() u32 { + return 1234; + } + }; + try S.doTheTest(); +} -- 2.54.0