Skip to content

Commit 1733086

Browse files
committed
Sema: compile error on reifying align(0) struct fields
1 parent a00edbd commit 1733086

File tree

4 files changed

+87
-60
lines changed

4 files changed

+87
-60
lines changed

src/Sema.zig

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,7 +2649,13 @@ pub fn analyzeAsAlign(
26492649
src: LazySrcLoc,
26502650
air_ref: Air.Inst.Ref,
26512651
) !Alignment {
2652-
const alignment_big = try sema.analyzeAsInt(block, src, air_ref, align_ty, .{ .simple = .@"align" });
2652+
const alignment_big = try sema.analyzeAsInt(
2653+
block,
2654+
src,
2655+
air_ref,
2656+
align_ty,
2657+
.{ .simple = .@"align" },
2658+
);
26532659
return sema.validateAlign(block, src, alignment_big);
26542660
}
26552661

@@ -18807,7 +18813,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1880718813
const abi_align: Alignment = if (inst_data.flags.has_align) blk: {
1880818814
const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
1880918815
extra_i += 1;
18810-
const coerced = try sema.coerce(block, .u32, try sema.resolveInst(ref), align_src);
18816+
const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src);
1881118817
const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" });
1881218818
// Check if this happens to be the lazy alignment of our element type, in
1881318819
// which case we can make this 0 without resolving it.
@@ -20325,15 +20331,11 @@ fn zirReify(
2032520331
try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
2032620332
).?);
2032720333

20328-
if (!try sema.intFitsInType(alignment_val, .u32, null)) {
20329-
return sema.fail(block, src, "alignment must fit in 'u32'", .{});
20334+
if (!try sema.intFitsInType(alignment_val, align_ty, null)) {
20335+
return sema.fail(block, src, "alignment must fit in '{}'", .{align_ty.fmt(pt)});
2033020336
}
20331-
2033220337
const alignment_val_int = try alignment_val.toUnsignedIntSema(pt);
20333-
if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) {
20334-
return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int});
20335-
}
20336-
const abi_align = Alignment.fromByteUnits(alignment_val_int);
20338+
const abi_align = try sema.validateAlign(block, src, alignment_val_int);
2033720339

2033820340
const elem_ty = child_val.toType();
2033920341
if (abi_align != .none) {
@@ -21017,11 +21019,7 @@ fn reifyUnion(
2101721019
field_ty.* = field_type_val.toIntern();
2101821020
if (any_aligns) {
2101921021
const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
21020-
if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
21021-
// TODO: better source location
21022-
return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21023-
}
21024-
field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
21022+
field_aligns[field_idx] = try sema.validateAlign(block, src, byte_align);
2102521023
}
2102621024
}
2102721025

@@ -21062,11 +21060,7 @@ fn reifyUnion(
2106221060
field_ty.* = field_type_val.toIntern();
2106321061
if (any_aligns) {
2106421062
const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
21065-
if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
21066-
// TODO: better source location
21067-
return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21068-
}
21069-
field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
21063+
field_aligns[field_idx] = try sema.validateAlign(block, src, byte_align);
2107021064
}
2107121065
}
2107221066

@@ -21266,7 +21260,6 @@ fn reifyStruct(
2126621260

2126721261
var any_comptime_fields = false;
2126821262
var any_default_inits = false;
21269-
var any_aligned_fields = false;
2127021263

2127121264
for (0..fields_len) |field_idx| {
2127221265
const field_info = try fields_val.elemValue(pt, field_idx);
@@ -21301,11 +21294,6 @@ fn reifyStruct(
2130121294

2130221295
if (field_is_comptime) any_comptime_fields = true;
2130321296
if (field_default_value != .none) any_default_inits = true;
21304-
switch (try field_alignment_val.orderAgainstZeroSema(pt)) {
21305-
.eq => {},
21306-
.gt => any_aligned_fields = true,
21307-
.lt => unreachable,
21308-
}
2130921297
}
2131021298

2131121299
const tracked_inst = try block.trackZir(inst);
@@ -21317,7 +21305,7 @@ fn reifyStruct(
2131721305
.requires_comptime = .unknown,
2131821306
.any_comptime_fields = any_comptime_fields,
2131921307
.any_default_inits = any_default_inits,
21320-
.any_aligned_fields = any_aligned_fields,
21308+
.any_aligned_fields = true,
2132121309
.inits_resolved = true,
2132221310
.key = .{ .reified = .{
2132321311
.zir_index = tracked_inst,
@@ -21361,21 +21349,14 @@ fn reifyStruct(
2136121349
return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
2136221350
}
2136321351

21364-
if (any_aligned_fields) {
21365-
if (!try sema.intFitsInType(field_alignment_val, .u32, null)) {
21366-
return sema.fail(block, src, "alignment must fit in 'u32'", .{});
21367-
}
21368-
21369-
const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21370-
if (byte_align == 0) {
21371-
if (layout != .@"packed") {
21372-
struct_type.field_aligns.get(ip)[field_idx] = .none;
21373-
}
21374-
} else {
21375-
if (layout == .@"packed") return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
21376-
if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21377-
struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align);
21378-
}
21352+
if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) {
21353+
return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
21354+
}
21355+
const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21356+
if (layout == .@"packed") {
21357+
if (byte_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
21358+
} else {
21359+
struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
2137921360
}
2138021361

2138121362
const field_is_comptime = field_is_comptime_val.toBool();
Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,98 @@
1-
pub var global_var: i32 align(0) = undefined;
1+
var global_var: i32 align(0) = undefined;
22

3-
pub export fn a() void {
3+
export fn a() void {
44
_ = &global_var;
55
}
66

7-
pub extern var extern_var: i32 align(0);
7+
extern var extern_var: i32 align(0);
88

9-
pub export fn b() void {
9+
export fn b() void {
1010
_ = &extern_var;
1111
}
1212

13-
pub export fn c() align(0) void {}
13+
export fn c() align(0) void {}
1414

15-
pub export fn d() void {
15+
export fn d() void {
1616
_ = *align(0) fn () i32;
1717
}
1818

19-
pub export fn e() void {
19+
export fn e() void {
2020
var local_var: i32 align(0) = undefined;
2121
_ = &local_var;
2222
}
2323

24-
pub export fn f() void {
24+
export fn f() void {
2525
_ = *align(0) i32;
2626
}
2727

28-
pub export fn g() void {
28+
export fn g() void {
2929
_ = []align(0) i32;
3030
}
3131

32-
pub export fn h() void {
32+
export fn h() void {
3333
_ = struct { field: i32 align(0) };
3434
}
3535

36-
pub export fn i() void {
36+
export fn i() void {
3737
_ = union { field: i32 align(0) };
3838
}
3939

40+
export fn j() void {
41+
_ = @Type(.{ .@"struct" = .{
42+
.layout = .auto,
43+
.fields = &.{.{
44+
.name = "test",
45+
.type = u32,
46+
.default_value_ptr = null,
47+
.is_comptime = false,
48+
.alignment = 0,
49+
}},
50+
.decls = &.{},
51+
.is_tuple = false,
52+
} });
53+
}
54+
55+
export fn k() void {
56+
_ = @Type(.{ .pointer = .{
57+
.size = .one,
58+
.is_const = false,
59+
.is_volatile = false,
60+
.alignment = 0,
61+
.address_space = .generic,
62+
.child = u32,
63+
.is_allowzero = false,
64+
.sentinel_ptr = null,
65+
} });
66+
}
67+
68+
export fn l() void {
69+
_ = @Type(.{ .@"struct" = .{
70+
.layout = .@"packed",
71+
.fields = &.{.{
72+
.name = "test",
73+
.type = u32,
74+
.default_value_ptr = null,
75+
.is_comptime = false,
76+
.alignment = 8,
77+
}},
78+
.decls = &.{},
79+
.is_tuple = false,
80+
} });
81+
}
82+
4083
// error
4184
// backend=stage2
4285
// target=native
4386
//
44-
// :1:31: error: alignment must be >= 1
45-
// :7:38: error: alignment must be >= 1
46-
// :13:25: error: alignment must be >= 1
87+
// :1:27: error: alignment must be >= 1
88+
// :7:34: error: alignment must be >= 1
89+
// :13:21: error: alignment must be >= 1
4790
// :16:16: error: alignment must be >= 1
4891
// :20:30: error: alignment must be >= 1
4992
// :25:16: error: alignment must be >= 1
5093
// :29:17: error: alignment must be >= 1
5194
// :33:35: error: alignment must be >= 1
5295
// :37:34: error: alignment must be >= 1
96+
// :41:9: error: alignment can only be 0 on packed struct fields
97+
// :56:9: error: alignment must be >= 1
98+
// :69:9: error: alignment in a packed struct field must be set to 0

test/cases/compile_errors/bad_alignment_type.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ export fn entry2() void {
1111
// backend=stage2
1212
// target=native
1313
//
14-
// :2:22: error: expected type 'u32', found 'bool'
15-
// :6:21: error: fractional component prevents float value '12.34' from coercion to type 'u32'
14+
// :2:22: error: expected type 'u29', found 'bool'
15+
// :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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ comptime {
4343

4444
// error
4545
//
46-
// :2:9: error: alignment value '3' is not a power of two or zero
47-
// :14:9: error: alignment value '5' is not a power of two or zero
48-
// :30:9: error: alignment value '7' is not a power of two or zero
46+
// :2:9: error: alignment value '3' is not a power of two
47+
// :14:9: error: alignment value '5' is not a power of two
48+
// :30:9: error: alignment value '7' is not a power of two

0 commit comments

Comments
 (0)