diff --git a/src/Sema.zig b/src/Sema.zig index 78d34a9f30..06a4873a19 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6413,9 +6413,9 @@ fn analyzeInlineCallArg( }; } const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); - try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); if (is_comptime_call) { + try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { if (err == error.AnalysisFail and sema.err != null) { try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); @@ -6440,6 +6440,20 @@ fn analyzeInlineCallArg( .ty = param_ty, .val = arg_val, }; + } else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, casted_arg) == null) or + try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_comptime) + { + try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); + } else { + // We have a comptime value but we need a runtime value to preserve inlining semantics, + const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ + .pointee_type = param_ty, + .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), + }); + const alloc = try arg_block.addTy(.alloc, ptr_type); + _ = try arg_block.addBinOp(.store, alloc, casted_arg); + const loaded = try arg_block.addTyOp(.load, param_ty, alloc); + try sema.inst_map.putNoClobber(sema.gpa, inst, loaded); } arg_i.* += 1; @@ -6448,9 +6462,10 @@ fn analyzeInlineCallArg( // No coercion needed. const uncasted_arg = uncasted_args[arg_i.*]; new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg); - try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); + const param_ty = sema.typeOf(uncasted_arg); if (is_comptime_call) { + try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { if (err == error.AnalysisFail and sema.err != null) { try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); @@ -6475,6 +6490,20 @@ fn analyzeInlineCallArg( .ty = sema.typeOf(uncasted_arg), .val = arg_val, }; + } else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, uncasted_arg)) == null or + try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_anytype_comptime) + { + try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); + } else { + // We have a comptime value but we need a runtime value to preserve inlining semantics, + const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ + .pointee_type = param_ty, + .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), + }); + const alloc = try arg_block.addTy(.alloc, ptr_type); + _ = try arg_block.addBinOp(.store, alloc, uncasted_arg); + const loaded = try arg_block.addTyOp(.load, param_ty, alloc); + try sema.inst_map.putNoClobber(sema.gpa, inst, loaded); } arg_i.* += 1; diff --git a/test/behavior.zig b/test/behavior.zig index 42c3dca3f0..a7b3ebfdda 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -105,6 +105,7 @@ test { _ = @import("behavior/bugs/13068.zig"); _ = @import("behavior/bugs/13112.zig"); _ = @import("behavior/bugs/13128.zig"); + _ = @import("behavior/bugs/13164.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/13164.zig b/test/behavior/bugs/13164.zig new file mode 100644 index 0000000000..ee9fe1c120 --- /dev/null +++ b/test/behavior/bugs/13164.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +inline fn setLimits(min: ?u32, max: ?u32) !void { + if (min != null and max != null) { + try std.testing.expect(min.? <= max.?); + } +} + +test { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + var x: u32 = 42; + try setLimits(x, null); +} diff --git a/test/cases/compile_error_in_inline_fn_call_fixed.0.zig b/test/cases/compile_error_in_inline_fn_call_fixed.0.zig deleted file mode 100644 index 1848490b07..0000000000 --- a/test/cases/compile_error_in_inline_fn_call_fixed.0.zig +++ /dev/null @@ -1,16 +0,0 @@ -pub fn main() void { - var x: usize = 3; - const y = add(10, 2, x); - if (y - 6 != 0) unreachable; -} - -inline fn add(a: usize, b: usize, c: usize) usize { - if (a == 10) @compileError("bad"); - return a + b + c; -} - -// error -// output_mode=Exe -// -// :8:18: error: bad -// :3:18: note: called from here diff --git a/test/cases/compile_error_in_inline_fn_call_fixed.1.zig b/test/cases/compile_error_in_inline_fn_call_fixed.1.zig deleted file mode 100644 index 1e61c6c790..0000000000 --- a/test/cases/compile_error_in_inline_fn_call_fixed.1.zig +++ /dev/null @@ -1,13 +0,0 @@ -pub fn main() void { - var x: usize = 3; - const y = add(1, 2, x); - if (y - 6 != 0) unreachable; -} - -inline fn add(a: usize, b: usize, c: usize) usize { - if (a == 10) @compileError("bad"); - return a + b + c; -} - -// run -//