zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 05cb944709d2a05a944e60f032638cae5ee01fb0 (tree)
parent b636906fb640a12107cd21637c2af67b8e9d6ebd
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 26 Jun 2026 23:35:11 +0200

Merge pull request 'Sema: more fixes' (#35707) from sinon/zig:more-fixes into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35707
Reviewed-by: Andrew Kelley <andrew@ziglang.org>

Diffstat:
Msrc/Sema.zig | 47+++++++++++++++--------------------------------
Mtest/behavior/switch.zig | 19+++++++++++++++++++
Mtest/behavior/try.zig | 12++++++++++++
Atest/cases/safety/@intCast negative to u0.zig | 22++++++++++++++++++++++
Rtest/cases/safety/@intCast to u0.zig -> test/cases/safety/@intCast positive to u0.zig | 0
5 files changed, 68 insertions(+), 32 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -9314,7 +9314,7 @@ fn intCast( break :ok all_in_range; } else ok: { const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern()); - const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst); + const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst); break :ok is_in_range; }; try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds); @@ -12012,15 +12012,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion( const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); const payload_ref: Air.Inst.Ref = payload_ref: { if (capture_by_ref) { - const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu); - const ptr_field_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = operand_ptr_info.flags.is_const, - .is_volatile = operand_ptr_info.flags.is_volatile, - .address_space = operand_ptr_info.flags.address_space, - }, - }); + const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt); + if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| { + if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty); + const field_ptr_val = try op_ptr_val.ptrField(field_index, pt); + break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty)); + } break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty); } if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| { @@ -17548,15 +17545,10 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr const is_cold = sema.branch_hint == .cold; const operand_ty = sema.typeOf(operand); - const ptr_info = operand_ty.ptrInfo(zcu); - const res_ty = try pt.ptrType(.{ - .child = err_union_ty.errorUnionPayload(zcu).toIntern(), - .flags = .{ - .is_const = ptr_info.flags.is_const, - .is_volatile = ptr_info.flags.is_volatile, - .is_allowzero = ptr_info.flags.is_allowzero, - .address_space = ptr_info.flags.address_space, - }, + const res_ty = try pt.ptrType(info: { + var new = operand_ty.ptrInfo(zcu); + new.child = err_union_ty.errorUnionPayload(zcu).toIntern(); + break :info new; }); const res_ty_ref = Air.internedToRef(res_ty.toIntern()); try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).@"struct".field_names.len + @@ -26404,23 +26396,21 @@ fn fieldCallBind( .@"struct" => { if (zcu.typeToStruct(concrete_ty)) |struct_type| { const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field; - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - - return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); + return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr); } else if (concrete_ty.isTuple(zcu)) { if (field_name.eqlSlice("len", ip)) { return .{ .direct = try pt.intRef(.usize, concrete_ty.structFieldCount(zcu)) }; } if (field_name.toUnsigned(ip)) |field_index| { if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field; - return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(field_index, zcu), field_index, object_ptr); + return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr); } } else { const max = concrete_ty.structFieldCount(zcu); for (0..max) |i_usize| { const i: u32 = @intCast(i_usize); if (field_name == concrete_ty.structFieldName(i, zcu).unwrap().?) { - return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(i, zcu), i, object_ptr); + return sema.finishFieldCallBind(block, src, ptr_ty, i, object_ptr); } } } @@ -26536,19 +26526,12 @@ fn finishFieldCallBind( block: *Block, src: LazySrcLoc, ptr_ty: Type, - field_ty: Type, field_index: u32, object_ptr: Air.Inst.Ref, ) CompileError!ResolvedFieldCallee { const pt = sema.pt; const zcu = pt.zcu; - const ptr_field_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = !ptr_ty.ptrIsMutable(zcu), - .address_space = ptr_ty.ptrAddressSpace(zcu), - }, - }); + const ptr_field_ty = try ptr_ty.fieldPtrType(field_index, pt); const container_ty = ptr_ty.childType(zcu); if (container_ty.zigTypeTag(zcu) == .@"struct") { diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig @@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" { }; } } + +test "union field pointer capture preserves alignment in inline prong" { + const U = union(enum) { + a: u32, + b: u32, + fn doTheTest(u: *align(1) const @This()) !void { + switch (u.*) { + inline .a, .b => |*a_ptr| { + comptime assert(@TypeOf(a_ptr) == *align(1) const u32); + try expect(a_ptr.* == 123); + }, + } + } + }; + try U.doTheTest(&.{ .a = 123 }); + try U.doTheTest(&.{ .b = 123 }); + try comptime U.doTheTest(&.{ .a = 123 }); + try comptime U.doTheTest(&.{ .b = 123 }); +} diff --git a/test/behavior/try.zig b/test/behavior/try.zig @@ -1,5 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); +const assert = std.debug.assert; const expect = std.testing.expect; test "try on error union" { @@ -197,3 +198,14 @@ test "try ptr propagation mutate" { try S.doTheTest(); try comptime S.doTheTest(); } + +test "try pointer expression alignment" { + const S = struct { + fn doTheTest(p: *align(1) (anyerror!u32)) !void { + comptime assert(@TypeOf(&(try p.*)) == *align(1) u32); + try expect((try p.*) == 10); + } + }; + var x: anyerror!u32 = 10; + try S.doTheTest(&x); +} diff --git a/test/cases/safety/@intCast negative to u0.zig b/test/cases/safety/@intCast negative to u0.zig @@ -0,0 +1,22 @@ +const std = @import("std"); + +pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { + _ = stack_trace; + if (std.mem.eql(u8, message, "integer does not fit in destination type")) { + std.process.exit(0); + } + std.process.exit(1); +} + +pub fn main() !void { + bar(1, -1); + return error.TestFailed; +} + +fn bar(one: u1, not_zero: i32) void { + const x = one << @intCast(not_zero); + _ = x; +} +// run +// backend=selfhosted,llvm +// target=x86_64-linux,aarch64-linux diff --git a/test/cases/safety/@intCast to u0.zig b/test/cases/safety/@intCast positive to u0.zig