authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-08-03 09:58:23+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-08-03 09:58:23+01:00
logc80aa9f71960ed90787033293fbc4c6ccfe0fba8
tree84d5df492d5a0f6c3c31370ed97c6e58e1c14c40
parent616e69c80745cdc872b1db5ad63b919d82d9e9cb
parente82d67233b615e04fb5e4f31cd93216a2c1c2899
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22997 from Rexicon226/align-0-reify

sema: compile error on reifying align(0) fields and pointers

15 files changed, 147 insertions(+), 129 deletions(-)

lib/compiler/aro/aro/Attribute.zig+1-1
......@@ -708,7 +708,7 @@ pub const Arguments = blk: {
708708 field.* = .{
709709 .name = decl.name,
710710 .type = @field(attributes, decl.name),
711 .alignment = 0,
711 .alignment = @alignOf(@field(attributes, decl.name)),
712712 };
713713 }
714714
lib/std/meta.zig+1-1
......@@ -939,7 +939,7 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type {
939939 .type = T,
940940 .default_value_ptr = null,
941941 .is_comptime = false,
942 .alignment = 0,
942 .alignment = @alignOf(T),
943943 };
944944 }
945945
lib/std/zig/AstGen.zig+3
......@@ -5386,6 +5386,9 @@ fn unionDeclInner(
53865386 return astgen.failNode(member_node, "union field missing type", .{});
53875387 }
53885388 if (member.ast.align_expr.unwrap()) |align_expr| {
5389 if (layout == .@"packed") {
5390 return astgen.failNode(align_expr, "unable to override alignment of packed union fields", .{});
5391 }
53895392 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr);
53905393 wip_members.appendToField(@intFromEnum(align_inst));
53915394 any_aligned_fields = true;
lib/std/zig/llvm/Builder.zig+4-3
......@@ -8533,18 +8533,19 @@ pub const Metadata = enum(u32) {
85338533 .type = []const u8,
85348534 .default_value_ptr = null,
85358535 .is_comptime = false,
8536 .alignment = 0,
8536 .alignment = @alignOf([]const u8),
85378537 };
85388538 }
85398539 fmt_str = fmt_str ++ "(";
85408540 inline for (fields[2..], names) |*field, name| {
85418541 fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
8542 const T = std.fmt.Formatter(FormatData, format);
85428543 field.* = .{
85438544 .name = name,
8544 .type = std.fmt.Formatter(FormatData, format),
8545 .type = T,
85458546 .default_value_ptr = null,
85468547 .is_comptime = false,
8547 .alignment = 0,
8548 .alignment = @alignOf(T),
85488549 };
85498550 }
85508551 fmt_str = fmt_str ++ ")\n";
src/InternPool.zig+22-16
......@@ -1137,13 +1137,16 @@ const Local = struct {
11371137 const elem_info = @typeInfo(Elem).@"struct";
11381138 const elem_fields = elem_info.fields;
11391139 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;
1140 for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{
1141 .name = elem_field.name,
1142 .type = *[len]elem_field.type,
1143 .default_value_ptr = null,
1144 .is_comptime = false,
1145 .alignment = 0,
1146 };
1140 for (&new_fields, elem_fields) |*new_field, elem_field| {
1141 const T = *[len]elem_field.type;
1142 new_field.* = .{
1143 .name = elem_field.name,
1144 .type = T,
1145 .default_value_ptr = null,
1146 .is_comptime = false,
1147 .alignment = @alignOf(T),
1148 };
1149 }
11471150 return @Type(.{ .@"struct" = .{
11481151 .layout = .auto,
11491152 .fields = &new_fields,
......@@ -1158,22 +1161,25 @@ const Local = struct {
11581161 const elem_info = @typeInfo(Elem).@"struct";
11591162 const elem_fields = elem_info.fields;
11601163 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;
1161 for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{
1162 .name = elem_field.name,
1163 .type = @Type(.{ .pointer = .{
1164 for (&new_fields, elem_fields) |*new_field, elem_field| {
1165 const T = @Type(.{ .pointer = .{
11641166 .size = opts.size,
11651167 .is_const = opts.is_const,
11661168 .is_volatile = false,
1167 .alignment = 0,
1169 .alignment = @alignOf(elem_field.type),
11681170 .address_space = .generic,
11691171 .child = elem_field.type,
11701172 .is_allowzero = false,
11711173 .sentinel_ptr = null,
1172 } }),
1173 .default_value_ptr = null,
1174 .is_comptime = false,
1175 .alignment = 0,
1176 };
1174 } });
1175 new_field.* = .{
1176 .name = elem_field.name,
1177 .type = T,
1178 .default_value_ptr = null,
1179 .is_comptime = false,
1180 .alignment = @alignOf(T),
1181 };
1182 }
11771183 return @Type(.{ .@"struct" = .{
11781184 .layout = .auto,
11791185 .fields = &new_fields,
src/Sema.zig+39-65
......@@ -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
......@@ -18817,7 +18823,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1881718823 const abi_align: Alignment = if (inst_data.flags.has_align) blk: {
1881818824 const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
1881918825 extra_i += 1;
18820 const coerced = try sema.coerce(block, .u32, try sema.resolveInst(ref), align_src);
18826 const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src);
1882118827 const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" });
1882218828 // Check if this happens to be the lazy alignment of our element type, in
1882318829 // which case we can make this 0 without resolving it.
......@@ -20335,15 +20341,11 @@ fn zirReify(
2033520341 try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
2033620342 ).?);
2033720343
20338 if (!try sema.intFitsInType(alignment_val, .u32, null)) {
20339 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
20344 if (!try sema.intFitsInType(alignment_val, align_ty, null)) {
20345 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
2034020346 }
20341
2034220347 const alignment_val_int = try alignment_val.toUnsignedIntSema(pt);
20343 if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) {
20344 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int});
20345 }
20346 const abi_align = Alignment.fromByteUnits(alignment_val_int);
20348 const abi_align = try sema.validateAlign(block, src, alignment_val_int);
2034720349
2034820350 const elem_ty = child_val.toType();
2034920351 if (abi_align != .none) {
......@@ -20920,8 +20922,6 @@ fn reifyUnion(
2092020922 std.hash.autoHash(&hasher, opt_tag_type_val.toIntern());
2092120923 std.hash.autoHash(&hasher, fields_len);
2092220924
20923 var any_aligns = false;
20924
2092520925 for (0..fields_len) |field_idx| {
2092620926 const field_info = try fields_val.elemValue(pt, field_idx);
2092720927
......@@ -20930,16 +20930,11 @@ fn reifyUnion(
2093020930 const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 2));
2093120931
2093220932 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name });
20933
2093420933 std.hash.autoHash(&hasher, .{
2093520934 field_name,
2093620935 field_type_val.toIntern(),
2093720936 field_align_val.toIntern(),
2093820937 });
20939
20940 if (field_align_val.toUnsignedInt(zcu) != 0) {
20941 any_aligns = true;
20942 }
2094320938 }
2094420939
2094520940 const tracked_inst = try block.trackZir(inst);
......@@ -20956,7 +20951,7 @@ fn reifyUnion(
2095620951 true => .safety,
2095720952 false => .none,
2095820953 },
20959 .any_aligned_fields = any_aligns,
20954 .any_aligned_fields = layout != .@"packed",
2096020955 .requires_comptime = .unknown,
2096120956 .assumed_runtime_bits = false,
2096220957 .assumed_pointer_aligned = false,
......@@ -20989,8 +20984,7 @@ fn reifyUnion(
2098920984 );
2099020985 wip_ty.setName(ip, type_name.name, type_name.nav);
2099120986
20992 const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
20993 const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined;
20987 const loaded_union = ip.loadUnionType(wip_ty.index);
2099420988
2099520989 const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(zcu)) |tag_type_val| tag_ty: {
2099620990 switch (ip.indexToKey(tag_type_val.toIntern())) {
......@@ -21003,11 +20997,12 @@ fn reifyUnion(
2100320997 const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu);
2100420998 var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len);
2100520999
21006 for (field_types, 0..) |*field_ty, field_idx| {
21000 for (0..fields_len) |field_idx| {
2100721001 const field_info = try fields_val.elemValue(pt, field_idx);
2100821002
2100921003 const field_name_val = try field_info.fieldValue(pt, 0);
2101021004 const field_type_val = try field_info.fieldValue(pt, 1);
21005 const field_alignment_val = try field_info.fieldValue(pt, 2);
2101121006
2101221007 // Don't pass a reason; first loop acts as an assertion that this is valid.
2101321008 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
......@@ -21024,14 +21019,12 @@ fn reifyUnion(
2102421019 }
2102521020 seen_tags.set(enum_index);
2102621021
21027 field_ty.* = field_type_val.toIntern();
21028 if (any_aligns) {
21029 const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
21030 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
21031 // TODO: better source location
21032 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21033 }
21034 field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
21022 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21023 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21024 if (layout == .@"packed") {
21025 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});
21026 } else {
21027 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
2103521028 }
2103621029 }
2103721030
......@@ -21055,11 +21048,12 @@ fn reifyUnion(
2105521048 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
2105621049 try field_names.ensureTotalCapacity(sema.arena, fields_len);
2105721050
21058 for (field_types, 0..) |*field_ty, field_idx| {
21051 for (0..fields_len) |field_idx| {
2105921052 const field_info = try fields_val.elemValue(pt, field_idx);
2106021053
2106121054 const field_name_val = try field_info.fieldValue(pt, 0);
2106221055 const field_type_val = try field_info.fieldValue(pt, 1);
21056 const field_alignment_val = try field_info.fieldValue(pt, 2);
2106321057
2106421058 // Don't pass a reason; first loop acts as an assertion that this is valid.
2106521059 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
......@@ -21069,14 +21063,12 @@ fn reifyUnion(
2106921063 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
2107021064 }
2107121065
21072 field_ty.* = field_type_val.toIntern();
21073 if (any_aligns) {
21074 const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt);
21075 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
21076 // TODO: better source location
21077 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21078 }
21079 field_aligns[field_idx] = Alignment.fromByteUnits(byte_align);
21066 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21067 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21068 if (layout == .@"packed") {
21069 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});
21070 } else {
21071 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
2108021072 }
2108121073 }
2108221074
......@@ -21085,7 +21077,7 @@ fn reifyUnion(
2108521077 };
2108621078 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
2108721079
21088 for (field_types) |field_ty_ip| {
21080 for (loaded_union.field_types.get(ip)) |field_ty_ip| {
2108921081 const field_ty: Type = .fromInterned(field_ty_ip);
2109021082 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
2109121083 return sema.failWithOwnedErrorMsg(block, msg: {
......@@ -21119,11 +21111,6 @@ fn reifyUnion(
2111921111 }
2112021112 }
2112121113
21122 const loaded_union = ip.loadUnionType(wip_ty.index);
21123 loaded_union.setFieldTypes(ip, field_types);
21124 if (any_aligns) {
21125 loaded_union.setFieldAligns(ip, field_aligns);
21126 }
2112721114 loaded_union.setTagType(ip, enum_tag_ty);
2112821115 loaded_union.setStatus(ip, .have_field_types);
2112921116
......@@ -21276,7 +21263,6 @@ fn reifyStruct(
2127621263
2127721264 var any_comptime_fields = false;
2127821265 var any_default_inits = false;
21279 var any_aligned_fields = false;
2128021266
2128121267 for (0..fields_len) |field_idx| {
2128221268 const field_info = try fields_val.elemValue(pt, field_idx);
......@@ -21311,11 +21297,6 @@ fn reifyStruct(
2131121297
2131221298 if (field_is_comptime) any_comptime_fields = true;
2131321299 if (field_default_value != .none) any_default_inits = true;
21314 switch (try field_alignment_val.orderAgainstZeroSema(pt)) {
21315 .eq => {},
21316 .gt => any_aligned_fields = true,
21317 .lt => unreachable,
21318 }
2131921300 }
2132021301
2132121302 const tracked_inst = try block.trackZir(inst);
......@@ -21327,7 +21308,7 @@ fn reifyStruct(
2132721308 .requires_comptime = .unknown,
2132821309 .any_comptime_fields = any_comptime_fields,
2132921310 .any_default_inits = any_default_inits,
21330 .any_aligned_fields = any_aligned_fields,
21311 .any_aligned_fields = layout != .@"packed",
2133121312 .inits_resolved = true,
2133221313 .key = .{ .reified = .{
2133321314 .zir_index = tracked_inst,
......@@ -21371,21 +21352,14 @@ fn reifyStruct(
2137121352 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
2137221353 }
2137321354
21374 if (any_aligned_fields) {
21375 if (!try sema.intFitsInType(field_alignment_val, .u32, null)) {
21376 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
21377 }
21378
21379 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21380 if (byte_align == 0) {
21381 if (layout != .@"packed") {
21382 struct_type.field_aligns.get(ip)[field_idx] = .none;
21383 }
21384 } else {
21385 if (layout == .@"packed") return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
21386 if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
21387 struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align);
21388 }
21355 if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) {
21356 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
21357 }
21358 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21359 if (layout == .@"packed") {
21360 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed struct field must be set to 0", .{});
21361 } else {
21362 struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
2138921363 }
2139021364
2139121365 const field_is_comptime = field_is_comptime_val.toBool();
src/codegen/aarch64/Assemble.zig+10-7
......@@ -33,13 +33,16 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
3333 var symbols: Symbols: {
3434 const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
3535 var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
36 for (&symbol_fields, symbols) |*symbol_field, symbol| symbol_field.* = .{
37 .name = symbol.name,
38 .type = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage(),
39 .default_value_ptr = null,
40 .is_comptime = false,
41 .alignment = 0,
42 };
36 for (&symbol_fields, symbols) |*symbol_field, symbol| {
37 const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
38 symbol_field.* = .{
39 .name = symbol.name,
40 .type = Storage,
41 .default_value_ptr = null,
42 .is_comptime = false,
43 .alignment = @alignOf(Storage),
44 };
45 }
4346 break :Symbols @Type(.{ .@"struct" = .{
4447 .layout = .auto,
4548 .fields = &symbol_fields,
test/behavior/tuple.zig+4-2
......@@ -318,6 +318,8 @@ test "tuple type with void field" {
318318test "zero sized struct in tuple handled correctly" {
319319 const State = struct {
320320 const Self = @This();
321 const Inner = struct {};
322
321323 data: @Type(.{
322324 .@"struct" = .{
323325 .is_tuple = true,
......@@ -325,10 +327,10 @@ test "zero sized struct in tuple handled correctly" {
325327 .decls = &.{},
326328 .fields = &.{.{
327329 .name = "0",
328 .type = struct {},
330 .type = Inner,
329331 .default_value_ptr = null,
330332 .is_comptime = false,
331 .alignment = 0,
333 .alignment = @alignOf(Inner),
332334 }},
333335 },
334336 }),
test/behavior/type.zig+3-3
......@@ -433,8 +433,8 @@ test "Type.Union" {
433433 .layout = .@"packed",
434434 .tag_type = null,
435435 .fields = &.{
436 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
437 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
436 .{ .name = "signed", .type = i32, .alignment = 0 },
437 .{ .name = "unsigned", .type = u32, .alignment = 0 },
438438 },
439439 .decls = &.{},
440440 },
......@@ -735,7 +735,7 @@ test "struct field names sliced at comptime from larger string" {
735735 var it = std.mem.tokenizeScalar(u8, text, '\n');
736736 while (it.next()) |name| {
737737 fields = fields ++ &[_]Type.StructField{.{
738 .alignment = 0,
738 .alignment = @alignOf(usize),
739739 .name = name ++ "",
740740 .type = usize,
741741 .default_value_ptr = null,
test/cases/compile_errors/align_zero.zig+44-16
......@@ -1,52 +1,80 @@
1pub var global_var: i32 align(0) = undefined;
1var global_var: i32 align(0) = undefined;
22
3pub export fn a() void {
3export fn a() void {
44 _ = &global_var;
55}
66
7pub extern var extern_var: i32 align(0);
7extern var extern_var: i32 align(0);
88
9pub export fn b() void {
9export fn b() void {
1010 _ = &extern_var;
1111}
1212
13pub export fn c() align(0) void {}
13export fn c() align(0) void {}
1414
15pub export fn d() void {
15export fn d() void {
1616 _ = *align(0) fn () i32;
1717}
1818
19pub export fn e() void {
19export fn e() void {
2020 var local_var: i32 align(0) = undefined;
2121 _ = &local_var;
2222}
2323
24pub export fn f() void {
24export fn f() void {
2525 _ = *align(0) i32;
2626}
2727
28pub export fn g() void {
28export fn g() void {
2929 _ = []align(0) i32;
3030}
3131
32pub export fn h() void {
32export fn h() void {
3333 _ = struct { field: i32 align(0) };
3434}
3535
36pub export fn i() void {
36export fn i() void {
3737 _ = union { field: i32 align(0) };
3838}
3939
40export 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
55export 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
4068// error
41// backend=stage2
42// target=native
4369//
44// :1:31: error: alignment must be >= 1
45// :7:38: error: alignment must be >= 1
46// :13:25: error: alignment must be >= 1
70// :1:27: error: alignment must be >= 1
71// :7:34: error: alignment must be >= 1
72// :13:21: error: alignment must be >= 1
4773// :16:16: error: alignment must be >= 1
4874// :20:30: error: alignment must be >= 1
4975// :25:16: error: alignment must be >= 1
5076// :29:17: error: alignment must be >= 1
5177// :33:35: error: alignment must be >= 1
5278// :37:34: error: alignment must be >= 1
79// :41:9: error: alignment must be >= 1
80// :56:9: error: alignment must be >= 1
test/cases/compile_errors/bad_alignment_type.zig+2-2
......@@ -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/packed_struct_field_alignment_unavailable_for_reify_type.zig deleted-9
......@@ -1,9 +0,0 @@
1export fn entry() void {
2 _ = @Type(.{ .@"struct" = .{ .layout = .@"packed", .fields = &.{
3 .{ .name = "one", .type = u4, .default_value_ptr = null, .is_comptime = false, .alignment = 2 },
4 }, .decls = &.{}, .is_tuple = false } });
5}
6
7// error
8//
9// :2:9: error: alignment in a packed struct field must be set to 0
test/cases/compile_errors/packed_union_alignment_override.zig created+9
......@@ -0,0 +1,9 @@
1const U = packed union {
2 x: f32,
3 y: u8 align(10),
4 z: u32,
5};
6
7// error
8//
9// :3:17: error: unable to override alignment of packed union fields
test/cases/compile_errors/reify_struct.zig+2-1
......@@ -75,4 +75,5 @@ comptime {
7575// :16:5: error: tuple field name '3' does not match field index 0
7676// :30:5: error: comptime field without default initialization value
7777// :44:5: error: extern struct fields cannot be marked comptime
78// :58:5: error: alignment in a packed struct field must be set to 0
78// :58:5: error: alignment of a packed struct field must be set to 0
79
test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig+3-3
......@@ -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