Commit 17330867eb
Changed files (4)
src
test
cases
src/Sema.zig
@@ -2649,7 +2649,13 @@ pub fn analyzeAsAlign(
src: LazySrcLoc,
air_ref: Air.Inst.Ref,
) !Alignment {
- const alignment_big = try sema.analyzeAsInt(block, src, air_ref, align_ty, .{ .simple = .@"align" });
+ const alignment_big = try sema.analyzeAsInt(
+ block,
+ src,
+ air_ref,
+ align_ty,
+ .{ .simple = .@"align" },
+ );
return sema.validateAlign(block, src, alignment_big);
}
@@ -18807,7 +18813,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const abi_align: Alignment = if (inst_data.flags.has_align) blk: {
const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
extra_i += 1;
- const coerced = try sema.coerce(block, .u32, try sema.resolveInst(ref), align_src);
+ const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src);
const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" });
// Check if this happens to be the lazy alignment of our element type, in
// which case we can make this 0 without resolving it.
@@ -20325,15 +20331,11 @@ fn zirReify(
try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
).?);
- if (!try sema.intFitsInType(alignment_val, .u32, null)) {
- return sema.fail(block, src, "alignment must fit in 'u32'", .{});
+ if (!try sema.intFitsInType(alignment_val, align_ty, null)) {
+ return sema.fail(block, src, "alignment must fit in '{}'", .{align_ty.fmt(pt)});
}
-
const alignment_val_int = try alignment_val.toUnsignedIntSema(pt);
- if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) {
- return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int});
- }
- const abi_align = Alignment.fromByteUnits(alignment_val_int);
+ const abi_align = try sema.validateAlign(block, src, alignment_val_int);
const elem_ty = child_val.toType();
if (abi_align != .none) {
@@ -21017,11 +21019,7 @@ fn reifyUnion(
field_ty.* = field_type_val.toIntern();
if (any_aligns) {
const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
- if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
- // TODO: better source location
- return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
- }
- field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
+ field_aligns[field_idx] = try sema.validateAlign(block, src, byte_align);
}
}
@@ -21062,11 +21060,7 @@ fn reifyUnion(
field_ty.* = field_type_val.toIntern();
if (any_aligns) {
const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
- if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
- // TODO: better source location
- return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
- }
- field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
+ field_aligns[field_idx] = try sema.validateAlign(block, src, byte_align);
}
}
@@ -21266,7 +21260,6 @@ fn reifyStruct(
var any_comptime_fields = false;
var any_default_inits = false;
- var any_aligned_fields = false;
for (0..fields_len) |field_idx| {
const field_info = try fields_val.elemValue(pt, field_idx);
@@ -21301,11 +21294,6 @@ fn reifyStruct(
if (field_is_comptime) any_comptime_fields = true;
if (field_default_value != .none) any_default_inits = true;
- switch (try field_alignment_val.orderAgainstZeroSema(pt)) {
- .eq => {},
- .gt => any_aligned_fields = true,
- .lt => unreachable,
- }
}
const tracked_inst = try block.trackZir(inst);
@@ -21317,7 +21305,7 @@ fn reifyStruct(
.requires_comptime = .unknown,
.any_comptime_fields = any_comptime_fields,
.any_default_inits = any_default_inits,
- .any_aligned_fields = any_aligned_fields,
+ .any_aligned_fields = true,
.inits_resolved = true,
.key = .{ .reified = .{
.zir_index = tracked_inst,
@@ -21361,21 +21349,14 @@ fn reifyStruct(
return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
}
- if (any_aligned_fields) {
- if (!try sema.intFitsInType(field_alignment_val, .u32, null)) {
- return sema.fail(block, src, "alignment must fit in 'u32'", .{});
- }
-
- const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
- if (byte_align == 0) {
- if (layout != .@"packed") {
- struct_type.field_aligns.get(ip)[field_idx] = .none;
- }
- } else {
- if (layout == .@"packed") return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
- if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
- struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align);
- }
+ if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) {
+ return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
+ }
+ const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
+ if (layout == .@"packed") {
+ if (byte_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
+ } else {
+ struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
}
const field_is_comptime = field_is_comptime_val.toBool();
test/cases/compile_errors/align_zero.zig
@@ -1,52 +1,98 @@
-pub var global_var: i32 align(0) = undefined;
+var global_var: i32 align(0) = undefined;
-pub export fn a() void {
+export fn a() void {
_ = &global_var;
}
-pub extern var extern_var: i32 align(0);
+extern var extern_var: i32 align(0);
-pub export fn b() void {
+export fn b() void {
_ = &extern_var;
}
-pub export fn c() align(0) void {}
+export fn c() align(0) void {}
-pub export fn d() void {
+export fn d() void {
_ = *align(0) fn () i32;
}
-pub export fn e() void {
+export fn e() void {
var local_var: i32 align(0) = undefined;
_ = &local_var;
}
-pub export fn f() void {
+export fn f() void {
_ = *align(0) i32;
}
-pub export fn g() void {
+export fn g() void {
_ = []align(0) i32;
}
-pub export fn h() void {
+export fn h() void {
_ = struct { field: i32 align(0) };
}
-pub export fn i() void {
+export fn i() void {
_ = union { field: i32 align(0) };
}
+export fn j() void {
+ _ = @Type(.{ .@"struct" = .{
+ .layout = .auto,
+ .fields = &.{.{
+ .name = "test",
+ .type = u32,
+ .default_value_ptr = null,
+ .is_comptime = false,
+ .alignment = 0,
+ }},
+ .decls = &.{},
+ .is_tuple = false,
+ } });
+}
+
+export fn k() void {
+ _ = @Type(.{ .pointer = .{
+ .size = .one,
+ .is_const = false,
+ .is_volatile = false,
+ .alignment = 0,
+ .address_space = .generic,
+ .child = u32,
+ .is_allowzero = false,
+ .sentinel_ptr = null,
+ } });
+}
+
+export fn l() void {
+ _ = @Type(.{ .@"struct" = .{
+ .layout = .@"packed",
+ .fields = &.{.{
+ .name = "test",
+ .type = u32,
+ .default_value_ptr = null,
+ .is_comptime = false,
+ .alignment = 8,
+ }},
+ .decls = &.{},
+ .is_tuple = false,
+ } });
+}
+
// error
// backend=stage2
// target=native
//
-// :1:31: error: alignment must be >= 1
-// :7:38: error: alignment must be >= 1
-// :13:25: error: alignment must be >= 1
+// :1:27: error: alignment must be >= 1
+// :7:34: error: alignment must be >= 1
+// :13:21: error: alignment must be >= 1
// :16:16: error: alignment must be >= 1
// :20:30: error: alignment must be >= 1
// :25:16: error: alignment must be >= 1
// :29:17: error: alignment must be >= 1
// :33:35: error: alignment must be >= 1
// :37:34: error: alignment must be >= 1
+// :41:9: error: alignment can only be 0 on packed struct fields
+// :56:9: error: alignment must be >= 1
+// :69:9: error: alignment in a packed struct field must be set to 0
test/cases/compile_errors/bad_alignment_type.zig
@@ -11,5 +11,5 @@ export fn entry2() void {
// backend=stage2
// target=native
//
-// :2:22: error: expected type 'u32', found 'bool'
-// :6:21: error: fractional component prevents float value '12.34' from coercion to type 'u32'
+// :2:22: error: expected type 'u29', found 'bool'
+// :6:21: error: fractional component prevents float value '12.34' from coercion to type 'u29'
test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig
@@ -43,6 +43,6 @@ comptime {
// error
//
-// :2:9: error: alignment value '3' is not a power of two or zero
-// :14:9: error: alignment value '5' is not a power of two or zero
-// :30:9: error: alignment value '7' is not a power of two or zero
+// :2:9: error: alignment value '3' is not a power of two
+// :14:9: error: alignment value '5' is not a power of two
+// :30:9: error: alignment value '7' is not a power of two