Commit fb523c6283
Changed files (3)
test
behavior
src/InternPool.zig
@@ -690,13 +690,13 @@ pub const Key = union(enum) {
/// The returned pointer expires with any addition to the `InternPool`.
pub fn size(self: @This(), ip: *InternPool) *u32 {
const size_field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?;
- return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]);
+ return &ip.extra.items[self.extra_index + size_field_index];
}
/// The returned pointer expires with any addition to the `InternPool`.
pub fn padding(self: @This(), ip: *InternPool) *u32 {
const padding_field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?;
- return @ptrCast(&ip.extra.items[self.extra_index + padding_field_index]);
+ return &ip.extra.items[self.extra_index + padding_field_index];
}
pub fn haveFieldTypes(self: @This(), ip: *const InternPool) bool {
@@ -2965,9 +2965,9 @@ pub const Tag = enum(u8) {
/// 1. field align: Alignment for each field; declaration order
pub const TypeUnion = struct {
flags: Flags,
- // Only valid after .have_layout
+ /// Only valid after .have_layout
size: u32,
- // Only valid after .have_layout
+ /// Only valid after .have_layout
padding: u32,
decl: Module.Decl.Index,
namespace: Module.Namespace.Index,
@@ -2983,8 +2983,9 @@ pub const Tag = enum(u8) {
status: UnionType.Status,
requires_comptime: RequiresComptime,
assumed_runtime_bits: bool,
+ assumed_pointer_aligned: bool,
alignment: Alignment,
- _: u15 = 0,
+ _: u14 = 0,
};
};
src/Sema.zig
@@ -3200,6 +3200,7 @@ fn zirUnionDecl(
.any_aligned_fields = small.any_aligned_fields,
.requires_comptime = .unknown,
.assumed_runtime_bits = false,
+ .assumed_pointer_aligned = false,
.alignment = .none,
},
.decl = new_decl_index,
@@ -20989,6 +20990,7 @@ fn zirReify(
.any_aligned_fields = any_aligned_fields,
.requires_comptime = .unknown,
.assumed_runtime_bits = false,
+ .assumed_pointer_aligned = false,
.alignment = .none,
},
.field_types = union_fields.items(.type),
@@ -34940,7 +34942,10 @@ pub fn resolveUnionAlignment(
// We'll guess "pointer-aligned", if the union has an
// underaligned pointer field then some allocations
// might require explicit alignment.
- return Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
+ union_type.flagsPtr(ip).assumed_pointer_aligned = true;
+ const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
+ union_type.flagsPtr(ip).alignment = result;
+ return result;
}
try sema.resolveTypeFieldsUnion(ty, union_type);
@@ -35064,6 +35069,18 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
);
return sema.failWithOwnedErrorMsg(null, msg);
}
+
+ if (union_obj.flagsPtr(ip).assumed_pointer_aligned and
+ alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8))))
+ {
+ const msg = try Module.ErrorMsg.create(
+ sema.gpa,
+ mod.declPtr(union_obj.decl).srcLoc(mod),
+ "union layout depends on being pointer aligned",
+ .{},
+ );
+ return sema.failWithOwnedErrorMsg(null, msg);
+ }
}
/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
test/behavior/union.zig
@@ -1868,3 +1868,16 @@ test "reinterpret packed union inside packed struct" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
try S.doTheTest();
}
+
+test "union field is a pointer to an aligned version of itself" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+
+ const E = union {
+ next: *align(1) @This(),
+ };
+ var e: E = undefined;
+ e = .{ .next = &e };
+
+ try expect(&e == e.next);
+}