diff options
| -rw-r--r-- | src/Sema.zig | 2 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 9 | ||||
| -rw-r--r-- | test/behavior/packed-struct.zig | 12 |
3 files changed, 19 insertions, 4 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 2355e8374d..9538073e5c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -20565,8 +20565,8 @@ fn validatePackedType(ty: Type) bool { .AnyFrame, .Fn, .Array, - .Optional, => return false, + .Optional => return ty.isPtrLikeOptional(), .Void, .Bool, .Float, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5c537cd5bc..98458854d1 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3417,7 +3417,10 @@ pub const DeclGen = struct { }); const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); const small_int_ty = dg.context.intType(ty_bit_size); - const small_int_val = non_int_val.constBitCast(small_int_ty); + const small_int_val = if (field.ty.isPtrAtRuntime()) + non_int_val.constPtrToInt(small_int_ty) + else + non_int_val.constBitCast(small_int_ty); const shift_rhs = int_llvm_ty.constInt(running_bits, .False); // If the field is as large as the entire packed struct, this // zext would go from, e.g. i16 to i16. This is legal with @@ -5343,7 +5346,7 @@ pub const FuncGen = struct { const same_size_int = self.context.intType(elem_bits); const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); - } else if (field_ty.zigTypeTag() == .Pointer) { + } else if (field_ty.isPtrAtRuntime()) { const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); const same_size_int = self.context.intType(elem_bits); const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); @@ -8408,7 +8411,7 @@ pub const FuncGen = struct { const non_int_val = try self.resolveInst(elem); const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); const small_int_ty = self.dg.context.intType(ty_bit_size); - const small_int_val = if (field.ty.zigTypeTag() == .Pointer) + const small_int_val = if (field.ty.isPtrAtRuntime()) self.builder.buildPtrToInt(non_int_val, small_int_ty, "") else self.builder.buildBitCast(non_int_val, small_int_ty, ""); diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 8c34f5741b..540914bd25 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -434,3 +434,15 @@ test "@ptrToInt on a packed struct field" { }; try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2); } + +test "optional pointer in packed struct" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + + const T = packed struct { ptr: ?*const u8 }; + var n: u8 = 0; + const x = T{ .ptr = &n }; + try expect(x.ptr.? == &n); +} |
