Commit 79702c144d

Andrew Kelley <andrew@ziglang.org>
2021-10-27 00:43:57
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.
1 parent c6b3d06
Changed files (2)
src
test
behavior
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);
 }
 
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();
+}