| author | |
| committer | |
| log | c80aa9f71960ed90787033293fbc4c6ccfe0fba8 |
| tree | 84d5df492d5a0f6c3c31370ed97c6e58e1c14c40 |
| parent | 616e69c80745cdc872b1db5ad63b919d82d9e9cb |
| parent | e82d67233b615e04fb5e4f31cd93216a2c1c2899 |
| signature |
sema: compile error on reifying align(0) fields and pointers15 files changed, 147 insertions(+), 129 deletions(-)
lib/compiler/aro/aro/Attribute.zig+1-1| ... | @@ -708,7 +708,7 @@ pub const Arguments = blk: { | ... | @@ -708,7 +708,7 @@ pub const Arguments = blk: { |
| 708 | field.* = .{ | 708 | field.* = .{ |
| 709 | .name = decl.name, | 709 | .name = decl.name, |
| 710 | .type = @field(attributes, decl.name), | 710 | .type = @field(attributes, decl.name), |
| 711 | .alignment = 0, | 711 | .alignment = @alignOf(@field(attributes, decl.name)), |
| 712 | }; | 712 | }; |
| 713 | } | 713 | } |
| 714 | 714 |
lib/std/meta.zig+1-1| ... | @@ -939,7 +939,7 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type { | ... | @@ -939,7 +939,7 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type { |
| 939 | .type = T, | 939 | .type = T, |
| 940 | .default_value_ptr = null, | 940 | .default_value_ptr = null, |
| 941 | .is_comptime = false, | 941 | .is_comptime = false, |
| 942 | .alignment = 0, | 942 | .alignment = @alignOf(T), |
| 943 | }; | 943 | }; |
| 944 | } | 944 | } |
| 945 | 945 |
lib/std/zig/AstGen.zig+3| ... | @@ -5386,6 +5386,9 @@ fn unionDeclInner( | ... | @@ -5386,6 +5386,9 @@ fn unionDeclInner( |
| 5386 | return astgen.failNode(member_node, "union field missing type", .{}); | 5386 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 5387 | } | 5387 | } |
| 5388 | if (member.ast.align_expr.unwrap()) |align_expr| { | 5388 | 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 | } | ||
| 5389 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); | 5392 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); |
| 5390 | wip_members.appendToField(@intFromEnum(align_inst)); | 5393 | wip_members.appendToField(@intFromEnum(align_inst)); |
| 5391 | any_aligned_fields = true; | 5394 | any_aligned_fields = true; |
lib/std/zig/llvm/Builder.zig+4-3| ... | @@ -8533,18 +8533,19 @@ pub const Metadata = enum(u32) { | ... | @@ -8533,18 +8533,19 @@ pub const Metadata = enum(u32) { |
| 8533 | .type = []const u8, | 8533 | .type = []const u8, |
| 8534 | .default_value_ptr = null, | 8534 | .default_value_ptr = null, |
| 8535 | .is_comptime = false, | 8535 | .is_comptime = false, |
| 8536 | .alignment = 0, | 8536 | .alignment = @alignOf([]const u8), |
| 8537 | }; | 8537 | }; |
| 8538 | } | 8538 | } |
| 8539 | fmt_str = fmt_str ++ "("; | 8539 | fmt_str = fmt_str ++ "("; |
| 8540 | inline for (fields[2..], names) |*field, name| { | 8540 | inline for (fields[2..], names) |*field, name| { |
| 8541 | fmt_str = fmt_str ++ "{[" ++ name ++ "]f}"; | 8541 | fmt_str = fmt_str ++ "{[" ++ name ++ "]f}"; |
| 8542 | const T = std.fmt.Formatter(FormatData, format); | ||
| 8542 | field.* = .{ | 8543 | field.* = .{ |
| 8543 | .name = name, | 8544 | .name = name, |
| 8544 | .type = std.fmt.Formatter(FormatData, format), | 8545 | .type = T, |
| 8545 | .default_value_ptr = null, | 8546 | .default_value_ptr = null, |
| 8546 | .is_comptime = false, | 8547 | .is_comptime = false, |
| 8547 | .alignment = 0, | 8548 | .alignment = @alignOf(T), |
| 8548 | }; | 8549 | }; |
| 8549 | } | 8550 | } |
| 8550 | fmt_str = fmt_str ++ ")\n"; | 8551 | fmt_str = fmt_str ++ ")\n"; |
src/InternPool.zig+22-16| ... | @@ -1137,13 +1137,16 @@ const Local = struct { | ... | @@ -1137,13 +1137,16 @@ const Local = struct { |
| 1137 | const elem_info = @typeInfo(Elem).@"struct"; | 1137 | const elem_info = @typeInfo(Elem).@"struct"; |
| 1138 | const elem_fields = elem_info.fields; | 1138 | const elem_fields = elem_info.fields; |
| 1139 | var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; | 1139 | var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; |
| 1140 | for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{ | 1140 | for (&new_fields, elem_fields) |*new_field, elem_field| { |
| 1141 | .name = elem_field.name, | 1141 | const T = *[len]elem_field.type; |
| 1142 | .type = *[len]elem_field.type, | 1142 | new_field.* = .{ |
| 1143 | .default_value_ptr = null, | 1143 | .name = elem_field.name, |
| 1144 | .is_comptime = false, | 1144 | .type = T, |
| 1145 | .alignment = 0, | 1145 | .default_value_ptr = null, |
| 1146 | }; | 1146 | .is_comptime = false, |
| 1147 | .alignment = @alignOf(T), | ||
| 1148 | }; | ||
| 1149 | } | ||
| 1147 | return @Type(.{ .@"struct" = .{ | 1150 | return @Type(.{ .@"struct" = .{ |
| 1148 | .layout = .auto, | 1151 | .layout = .auto, |
| 1149 | .fields = &new_fields, | 1152 | .fields = &new_fields, |
| ... | @@ -1158,22 +1161,25 @@ const Local = struct { | ... | @@ -1158,22 +1161,25 @@ const Local = struct { |
| 1158 | const elem_info = @typeInfo(Elem).@"struct"; | 1161 | const elem_info = @typeInfo(Elem).@"struct"; |
| 1159 | const elem_fields = elem_info.fields; | 1162 | const elem_fields = elem_info.fields; |
| 1160 | var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; | 1163 | var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; |
| 1161 | for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{ | 1164 | for (&new_fields, elem_fields) |*new_field, elem_field| { |
| 1162 | .name = elem_field.name, | 1165 | const T = @Type(.{ .pointer = .{ |
| 1163 | .type = @Type(.{ .pointer = .{ | ||
| 1164 | .size = opts.size, | 1166 | .size = opts.size, |
| 1165 | .is_const = opts.is_const, | 1167 | .is_const = opts.is_const, |
| 1166 | .is_volatile = false, | 1168 | .is_volatile = false, |
| 1167 | .alignment = 0, | 1169 | .alignment = @alignOf(elem_field.type), |
| 1168 | .address_space = .generic, | 1170 | .address_space = .generic, |
| 1169 | .child = elem_field.type, | 1171 | .child = elem_field.type, |
| 1170 | .is_allowzero = false, | 1172 | .is_allowzero = false, |
| 1171 | .sentinel_ptr = null, | 1173 | .sentinel_ptr = null, |
| 1172 | } }), | 1174 | } }); |
| 1173 | .default_value_ptr = null, | 1175 | new_field.* = .{ |
| 1174 | .is_comptime = false, | 1176 | .name = elem_field.name, |
| 1175 | .alignment = 0, | 1177 | .type = T, |
| 1176 | }; | 1178 | .default_value_ptr = null, |
| 1179 | .is_comptime = false, | ||
| 1180 | .alignment = @alignOf(T), | ||
| 1181 | }; | ||
| 1182 | } | ||
| 1177 | return @Type(.{ .@"struct" = .{ | 1183 | return @Type(.{ .@"struct" = .{ |
| 1178 | .layout = .auto, | 1184 | .layout = .auto, |
| 1179 | .fields = &new_fields, | 1185 | .fields = &new_fields, |
src/Sema.zig+39-65| ... | @@ -2649,7 +2649,13 @@ pub fn analyzeAsAlign( | ... | @@ -2649,7 +2649,13 @@ pub fn analyzeAsAlign( |
| 2649 | src: LazySrcLoc, | 2649 | src: LazySrcLoc, |
| 2650 | air_ref: Air.Inst.Ref, | 2650 | air_ref: Air.Inst.Ref, |
| 2651 | ) !Alignment { | 2651 | ) !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 | ); | ||
| 2653 | return sema.validateAlign(block, src, alignment_big); | 2659 | return sema.validateAlign(block, src, alignment_big); |
| 2654 | } | 2660 | } |
| 2655 | 2661 | ||
| ... | @@ -18817,7 +18823,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -18817,7 +18823,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18817 | const abi_align: Alignment = if (inst_data.flags.has_align) blk: { | 18823 | const abi_align: Alignment = if (inst_data.flags.has_align) blk: { |
| 18818 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); | 18824 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 18819 | extra_i += 1; | 18825 | 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); |
| 18821 | const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); | 18827 | const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); |
| 18822 | // Check if this happens to be the lazy alignment of our element type, in | 18828 | // Check if this happens to be the lazy alignment of our element type, in |
| 18823 | // which case we can make this 0 without resolving it. | 18829 | // which case we can make this 0 without resolving it. |
| ... | @@ -20335,15 +20341,11 @@ fn zirReify( | ... | @@ -20335,15 +20341,11 @@ fn zirReify( |
| 20335 | try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), | 20341 | try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), |
| 20336 | ).?); | 20342 | ).?); |
| 20337 | 20343 | ||
| 20338 | if (!try sema.intFitsInType(alignment_val, .u32, null)) { | 20344 | if (!try sema.intFitsInType(alignment_val, align_ty, null)) { |
| 20339 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 20345 | return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)}); |
| 20340 | } | 20346 | } |
| 20341 | |||
| 20342 | const alignment_val_int = try alignment_val.toUnsignedIntSema(pt); | 20347 | const alignment_val_int = try alignment_val.toUnsignedIntSema(pt); |
| 20343 | if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) { | 20348 | const abi_align = try sema.validateAlign(block, src, 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); | ||
| 20347 | 20349 | ||
| 20348 | const elem_ty = child_val.toType(); | 20350 | const elem_ty = child_val.toType(); |
| 20349 | if (abi_align != .none) { | 20351 | if (abi_align != .none) { |
| ... | @@ -20920,8 +20922,6 @@ fn reifyUnion( | ... | @@ -20920,8 +20922,6 @@ fn reifyUnion( |
| 20920 | std.hash.autoHash(&hasher, opt_tag_type_val.toIntern()); | 20922 | std.hash.autoHash(&hasher, opt_tag_type_val.toIntern()); |
| 20921 | std.hash.autoHash(&hasher, fields_len); | 20923 | std.hash.autoHash(&hasher, fields_len); |
| 20922 | 20924 | ||
| 20923 | var any_aligns = false; | ||
| 20924 | |||
| 20925 | for (0..fields_len) |field_idx| { | 20925 | for (0..fields_len) |field_idx| { |
| 20926 | const field_info = try fields_val.elemValue(pt, field_idx); | 20926 | const field_info = try fields_val.elemValue(pt, field_idx); |
| 20927 | 20927 | ||
| ... | @@ -20930,16 +20930,11 @@ fn reifyUnion( | ... | @@ -20930,16 +20930,11 @@ fn reifyUnion( |
| 20930 | const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 2)); | 20930 | const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 2)); |
| 20931 | 20931 | ||
| 20932 | const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name }); | 20932 | const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name }); |
| 20933 | |||
| 20934 | std.hash.autoHash(&hasher, .{ | 20933 | std.hash.autoHash(&hasher, .{ |
| 20935 | field_name, | 20934 | field_name, |
| 20936 | field_type_val.toIntern(), | 20935 | field_type_val.toIntern(), |
| 20937 | field_align_val.toIntern(), | 20936 | field_align_val.toIntern(), |
| 20938 | }); | 20937 | }); |
| 20939 | |||
| 20940 | if (field_align_val.toUnsignedInt(zcu) != 0) { | ||
| 20941 | any_aligns = true; | ||
| 20942 | } | ||
| 20943 | } | 20938 | } |
| 20944 | 20939 | ||
| 20945 | const tracked_inst = try block.trackZir(inst); | 20940 | const tracked_inst = try block.trackZir(inst); |
| ... | @@ -20956,7 +20951,7 @@ fn reifyUnion( | ... | @@ -20956,7 +20951,7 @@ fn reifyUnion( |
| 20956 | true => .safety, | 20951 | true => .safety, |
| 20957 | false => .none, | 20952 | false => .none, |
| 20958 | }, | 20953 | }, |
| 20959 | .any_aligned_fields = any_aligns, | 20954 | .any_aligned_fields = layout != .@"packed", |
| 20960 | .requires_comptime = .unknown, | 20955 | .requires_comptime = .unknown, |
| 20961 | .assumed_runtime_bits = false, | 20956 | .assumed_runtime_bits = false, |
| 20962 | .assumed_pointer_aligned = false, | 20957 | .assumed_pointer_aligned = false, |
| ... | @@ -20989,8 +20984,7 @@ fn reifyUnion( | ... | @@ -20989,8 +20984,7 @@ fn reifyUnion( |
| 20989 | ); | 20984 | ); |
| 20990 | wip_ty.setName(ip, type_name.name, type_name.nav); | 20985 | wip_ty.setName(ip, type_name.name, type_name.nav); |
| 20991 | 20986 | ||
| 20992 | const field_types = try sema.arena.alloc(InternPool.Index, fields_len); | 20987 | const loaded_union = ip.loadUnionType(wip_ty.index); |
| 20993 | const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined; | ||
| 20994 | 20988 | ||
| 20995 | const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(zcu)) |tag_type_val| tag_ty: { | 20989 | const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(zcu)) |tag_type_val| tag_ty: { |
| 20996 | switch (ip.indexToKey(tag_type_val.toIntern())) { | 20990 | switch (ip.indexToKey(tag_type_val.toIntern())) { |
| ... | @@ -21003,11 +20997,12 @@ fn reifyUnion( | ... | @@ -21003,11 +20997,12 @@ fn reifyUnion( |
| 21003 | const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu); | 20997 | const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu); |
| 21004 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); | 20998 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); |
| 21005 | 20999 | ||
| 21006 | for (field_types, 0..) |*field_ty, field_idx| { | 21000 | for (0..fields_len) |field_idx| { |
| 21007 | const field_info = try fields_val.elemValue(pt, field_idx); | 21001 | const field_info = try fields_val.elemValue(pt, field_idx); |
| 21008 | 21002 | ||
| 21009 | const field_name_val = try field_info.fieldValue(pt, 0); | 21003 | const field_name_val = try field_info.fieldValue(pt, 0); |
| 21010 | const field_type_val = try field_info.fieldValue(pt, 1); | 21004 | const field_type_val = try field_info.fieldValue(pt, 1); |
| 21005 | const field_alignment_val = try field_info.fieldValue(pt, 2); | ||
| 21011 | 21006 | ||
| 21012 | // Don't pass a reason; first loop acts as an assertion that this is valid. | 21007 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| 21013 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); | 21008 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| ... | @@ -21024,14 +21019,12 @@ fn reifyUnion( | ... | @@ -21024,14 +21019,12 @@ fn reifyUnion( |
| 21024 | } | 21019 | } |
| 21025 | seen_tags.set(enum_index); | 21020 | seen_tags.set(enum_index); |
| 21026 | 21021 | ||
| 21027 | field_ty.* = field_type_val.toIntern(); | 21022 | loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern(); |
| 21028 | if (any_aligns) { | 21023 | const byte_align = try field_alignment_val.toUnsignedIntSema(pt); |
| 21029 | const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt); | 21024 | if (layout == .@"packed") { |
| 21030 | if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) { | 21025 | if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{}); |
| 21031 | // TODO: better source location | 21026 | } else { |
| 21032 | return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); | 21027 | loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align); |
| 21033 | } | ||
| 21034 | field_aligns[field_idx] = Alignment.fromByteUnits(byte_align); | ||
| 21035 | } | 21028 | } |
| 21036 | } | 21029 | } |
| 21037 | 21030 | ||
| ... | @@ -21055,11 +21048,12 @@ fn reifyUnion( | ... | @@ -21055,11 +21048,12 @@ fn reifyUnion( |
| 21055 | var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; | 21048 | var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; |
| 21056 | try field_names.ensureTotalCapacity(sema.arena, fields_len); | 21049 | try field_names.ensureTotalCapacity(sema.arena, fields_len); |
| 21057 | 21050 | ||
| 21058 | for (field_types, 0..) |*field_ty, field_idx| { | 21051 | for (0..fields_len) |field_idx| { |
| 21059 | const field_info = try fields_val.elemValue(pt, field_idx); | 21052 | const field_info = try fields_val.elemValue(pt, field_idx); |
| 21060 | 21053 | ||
| 21061 | const field_name_val = try field_info.fieldValue(pt, 0); | 21054 | const field_name_val = try field_info.fieldValue(pt, 0); |
| 21062 | const field_type_val = try field_info.fieldValue(pt, 1); | 21055 | const field_type_val = try field_info.fieldValue(pt, 1); |
| 21056 | const field_alignment_val = try field_info.fieldValue(pt, 2); | ||
| 21063 | 21057 | ||
| 21064 | // Don't pass a reason; first loop acts as an assertion that this is valid. | 21058 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| 21065 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); | 21059 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| ... | @@ -21069,14 +21063,12 @@ fn reifyUnion( | ... | @@ -21069,14 +21063,12 @@ fn reifyUnion( |
| 21069 | return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)}); | 21063 | return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)}); |
| 21070 | } | 21064 | } |
| 21071 | 21065 | ||
| 21072 | field_ty.* = field_type_val.toIntern(); | 21066 | loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern(); |
| 21073 | if (any_aligns) { | 21067 | const byte_align = try field_alignment_val.toUnsignedIntSema(pt); |
| 21074 | const byte_align = try (try field_info.fieldValue(pt, 2)).toUnsignedIntSema(pt); | 21068 | if (layout == .@"packed") { |
| 21075 | if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) { | 21069 | if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{}); |
| 21076 | // TODO: better source location | 21070 | } else { |
| 21077 | return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); | 21071 | loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align); |
| 21078 | } | ||
| 21079 | field_aligns[field_idx] = Alignment.fromByteUnits(byte_align); | ||
| 21080 | } | 21072 | } |
| 21081 | } | 21073 | } |
| 21082 | 21074 | ||
| ... | @@ -21085,7 +21077,7 @@ fn reifyUnion( | ... | @@ -21085,7 +21077,7 @@ fn reifyUnion( |
| 21085 | }; | 21077 | }; |
| 21086 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error | 21078 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error |
| 21087 | 21079 | ||
| 21088 | for (field_types) |field_ty_ip| { | 21080 | for (loaded_union.field_types.get(ip)) |field_ty_ip| { |
| 21089 | const field_ty: Type = .fromInterned(field_ty_ip); | 21081 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 21090 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | 21082 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { |
| 21091 | return sema.failWithOwnedErrorMsg(block, msg: { | 21083 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | @@ -21119,11 +21111,6 @@ fn reifyUnion( | ... | @@ -21119,11 +21111,6 @@ fn reifyUnion( |
| 21119 | } | 21111 | } |
| 21120 | } | 21112 | } |
| 21121 | 21113 | ||
| 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 | } | ||
| 21127 | loaded_union.setTagType(ip, enum_tag_ty); | 21114 | loaded_union.setTagType(ip, enum_tag_ty); |
| 21128 | loaded_union.setStatus(ip, .have_field_types); | 21115 | loaded_union.setStatus(ip, .have_field_types); |
| 21129 | 21116 | ||
| ... | @@ -21276,7 +21263,6 @@ fn reifyStruct( | ... | @@ -21276,7 +21263,6 @@ fn reifyStruct( |
| 21276 | 21263 | ||
| 21277 | var any_comptime_fields = false; | 21264 | var any_comptime_fields = false; |
| 21278 | var any_default_inits = false; | 21265 | var any_default_inits = false; |
| 21279 | var any_aligned_fields = false; | ||
| 21280 | 21266 | ||
| 21281 | for (0..fields_len) |field_idx| { | 21267 | for (0..fields_len) |field_idx| { |
| 21282 | const field_info = try fields_val.elemValue(pt, field_idx); | 21268 | const field_info = try fields_val.elemValue(pt, field_idx); |
| ... | @@ -21311,11 +21297,6 @@ fn reifyStruct( | ... | @@ -21311,11 +21297,6 @@ fn reifyStruct( |
| 21311 | 21297 | ||
| 21312 | if (field_is_comptime) any_comptime_fields = true; | 21298 | if (field_is_comptime) any_comptime_fields = true; |
| 21313 | if (field_default_value != .none) any_default_inits = true; | 21299 | 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 | } | ||
| 21319 | } | 21300 | } |
| 21320 | 21301 | ||
| 21321 | const tracked_inst = try block.trackZir(inst); | 21302 | const tracked_inst = try block.trackZir(inst); |
| ... | @@ -21327,7 +21308,7 @@ fn reifyStruct( | ... | @@ -21327,7 +21308,7 @@ fn reifyStruct( |
| 21327 | .requires_comptime = .unknown, | 21308 | .requires_comptime = .unknown, |
| 21328 | .any_comptime_fields = any_comptime_fields, | 21309 | .any_comptime_fields = any_comptime_fields, |
| 21329 | .any_default_inits = any_default_inits, | 21310 | .any_default_inits = any_default_inits, |
| 21330 | .any_aligned_fields = any_aligned_fields, | 21311 | .any_aligned_fields = layout != .@"packed", |
| 21331 | .inits_resolved = true, | 21312 | .inits_resolved = true, |
| 21332 | .key = .{ .reified = .{ | 21313 | .key = .{ .reified = .{ |
| 21333 | .zir_index = tracked_inst, | 21314 | .zir_index = tracked_inst, |
| ... | @@ -21371,21 +21352,14 @@ fn reifyStruct( | ... | @@ -21371,21 +21352,14 @@ fn reifyStruct( |
| 21371 | return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); | 21352 | return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); |
| 21372 | } | 21353 | } |
| 21373 | 21354 | ||
| 21374 | if (any_aligned_fields) { | 21355 | if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) { |
| 21375 | if (!try sema.intFitsInType(field_alignment_val, .u32, null)) { | 21356 | return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)}); |
| 21376 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 21357 | } |
| 21377 | } | 21358 | const byte_align = try field_alignment_val.toUnsignedIntSema(pt); |
| 21378 | 21359 | if (layout == .@"packed") { | |
| 21379 | const byte_align = try field_alignment_val.toUnsignedIntSema(pt); | 21360 | if (byte_align != 0) return sema.fail(block, src, "alignment of a packed struct field must be set to 0", .{}); |
| 21380 | if (byte_align == 0) { | 21361 | } else { |
| 21381 | if (layout != .@"packed") { | 21362 | struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align); |
| 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 | } | ||
| 21389 | } | 21363 | } |
| 21390 | 21364 | ||
| 21391 | const field_is_comptime = field_is_comptime_val.toBool(); | 21365 | 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 { | ... | @@ -33,13 +33,16 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 33 | var symbols: Symbols: { | 33 | var symbols: Symbols: { |
| 34 | const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields; | 34 | const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields; |
| 35 | var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined; | 35 | var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined; |
| 36 | for (&symbol_fields, symbols) |*symbol_field, symbol| symbol_field.* = .{ | 36 | for (&symbol_fields, symbols) |*symbol_field, symbol| { |
| 37 | .name = symbol.name, | 37 | const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage(); |
| 38 | .type = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage(), | 38 | symbol_field.* = .{ |
| 39 | .default_value_ptr = null, | 39 | .name = symbol.name, |
| 40 | .is_comptime = false, | 40 | .type = Storage, |
| 41 | .alignment = 0, | 41 | .default_value_ptr = null, |
| 42 | }; | 42 | .is_comptime = false, |
| 43 | .alignment = @alignOf(Storage), | ||
| 44 | }; | ||
| 45 | } | ||
| 43 | break :Symbols @Type(.{ .@"struct" = .{ | 46 | break :Symbols @Type(.{ .@"struct" = .{ |
| 44 | .layout = .auto, | 47 | .layout = .auto, |
| 45 | .fields = &symbol_fields, | 48 | .fields = &symbol_fields, |
test/behavior/tuple.zig+4-2| ... | @@ -318,6 +318,8 @@ test "tuple type with void field" { | ... | @@ -318,6 +318,8 @@ test "tuple type with void field" { |
| 318 | test "zero sized struct in tuple handled correctly" { | 318 | test "zero sized struct in tuple handled correctly" { |
| 319 | const State = struct { | 319 | const State = struct { |
| 320 | const Self = @This(); | 320 | const Self = @This(); |
| 321 | const Inner = struct {}; | ||
| 322 | |||
| 321 | data: @Type(.{ | 323 | data: @Type(.{ |
| 322 | .@"struct" = .{ | 324 | .@"struct" = .{ |
| 323 | .is_tuple = true, | 325 | .is_tuple = true, |
| ... | @@ -325,10 +327,10 @@ test "zero sized struct in tuple handled correctly" { | ... | @@ -325,10 +327,10 @@ test "zero sized struct in tuple handled correctly" { |
| 325 | .decls = &.{}, | 327 | .decls = &.{}, |
| 326 | .fields = &.{.{ | 328 | .fields = &.{.{ |
| 327 | .name = "0", | 329 | .name = "0", |
| 328 | .type = struct {}, | 330 | .type = Inner, |
| 329 | .default_value_ptr = null, | 331 | .default_value_ptr = null, |
| 330 | .is_comptime = false, | 332 | .is_comptime = false, |
| 331 | .alignment = 0, | 333 | .alignment = @alignOf(Inner), |
| 332 | }}, | 334 | }}, |
| 333 | }, | 335 | }, |
| 334 | }), | 336 | }), |
test/behavior/type.zig+3-3| ... | @@ -433,8 +433,8 @@ test "Type.Union" { | ... | @@ -433,8 +433,8 @@ test "Type.Union" { |
| 433 | .layout = .@"packed", | 433 | .layout = .@"packed", |
| 434 | .tag_type = null, | 434 | .tag_type = null, |
| 435 | .fields = &.{ | 435 | .fields = &.{ |
| 436 | .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, | 436 | .{ .name = "signed", .type = i32, .alignment = 0 }, |
| 437 | .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, | 437 | .{ .name = "unsigned", .type = u32, .alignment = 0 }, |
| 438 | }, | 438 | }, |
| 439 | .decls = &.{}, | 439 | .decls = &.{}, |
| 440 | }, | 440 | }, |
| ... | @@ -735,7 +735,7 @@ test "struct field names sliced at comptime from larger string" { | ... | @@ -735,7 +735,7 @@ test "struct field names sliced at comptime from larger string" { |
| 735 | var it = std.mem.tokenizeScalar(u8, text, '\n'); | 735 | var it = std.mem.tokenizeScalar(u8, text, '\n'); |
| 736 | while (it.next()) |name| { | 736 | while (it.next()) |name| { |
| 737 | fields = fields ++ &[_]Type.StructField{.{ | 737 | fields = fields ++ &[_]Type.StructField{.{ |
| 738 | .alignment = 0, | 738 | .alignment = @alignOf(usize), |
| 739 | .name = name ++ "", | 739 | .name = name ++ "", |
| 740 | .type = usize, | 740 | .type = usize, |
| 741 | .default_value_ptr = null, | 741 | .default_value_ptr = null, |
test/cases/compile_errors/align_zero.zig+44-16| ... | @@ -1,52 +1,80 @@ | ... | @@ -1,52 +1,80 @@ |
| 1 | pub var global_var: i32 align(0) = undefined; | 1 | var global_var: i32 align(0) = undefined; |
| 2 | 2 | ||
| 3 | pub export fn a() void { | 3 | export fn a() void { |
| 4 | _ = &global_var; | 4 | _ = &global_var; |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | pub extern var extern_var: i32 align(0); | 7 | extern var extern_var: i32 align(0); |
| 8 | 8 | ||
| 9 | pub export fn b() void { | 9 | export fn b() void { |
| 10 | _ = &extern_var; | 10 | _ = &extern_var; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub export fn c() align(0) void {} | 13 | export fn c() align(0) void {} |
| 14 | 14 | ||
| 15 | pub export fn d() void { | 15 | export fn d() void { |
| 16 | _ = *align(0) fn () i32; | 16 | _ = *align(0) fn () i32; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | pub export fn e() void { | 19 | export fn e() void { |
| 20 | var local_var: i32 align(0) = undefined; | 20 | var local_var: i32 align(0) = undefined; |
| 21 | _ = &local_var; | 21 | _ = &local_var; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | pub export fn f() void { | 24 | export fn f() void { |
| 25 | _ = *align(0) i32; | 25 | _ = *align(0) i32; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | pub export fn g() void { | 28 | export fn g() void { |
| 29 | _ = []align(0) i32; | 29 | _ = []align(0) i32; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | pub export fn h() void { | 32 | export fn h() void { |
| 33 | _ = struct { field: i32 align(0) }; | 33 | _ = struct { field: i32 align(0) }; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | pub export fn i() void { | 36 | export fn i() void { |
| 37 | _ = union { field: i32 align(0) }; | 37 | _ = union { field: i32 align(0) }; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 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 | |||
| 40 | // error | 68 | // error |
| 41 | // backend=stage2 | ||
| 42 | // target=native | ||
| 43 | // | 69 | // |
| 44 | // :1:31: error: alignment must be >= 1 | 70 | // :1:27: error: alignment must be >= 1 |
| 45 | // :7:38: error: alignment must be >= 1 | 71 | // :7:34: error: alignment must be >= 1 |
| 46 | // :13:25: error: alignment must be >= 1 | 72 | // :13:21: error: alignment must be >= 1 |
| 47 | // :16:16: error: alignment must be >= 1 | 73 | // :16:16: error: alignment must be >= 1 |
| 48 | // :20:30: error: alignment must be >= 1 | 74 | // :20:30: error: alignment must be >= 1 |
| 49 | // :25:16: error: alignment must be >= 1 | 75 | // :25:16: error: alignment must be >= 1 |
| 50 | // :29:17: error: alignment must be >= 1 | 76 | // :29:17: error: alignment must be >= 1 |
| 51 | // :33:35: error: alignment must be >= 1 | 77 | // :33:35: error: alignment must be >= 1 |
| 52 | // :37:34: error: alignment must be >= 1 | 78 | // :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 { | ... | @@ -11,5 +11,5 @@ export fn entry2() void { |
| 11 | // backend=stage2 | 11 | // backend=stage2 |
| 12 | // target=native | 12 | // target=native |
| 13 | // | 13 | // |
| 14 | // :2:22: error: expected type 'u32', found 'bool' | 14 | // :2:22: error: expected type 'u29', found 'bool' |
| 15 | // :6:21: error: fractional component prevents float value '12.34' from coercion to type 'u32' | 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 @@ | ||
| 1 | export 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 @@ | ||
| 1 | const 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 { | ... | @@ -75,4 +75,5 @@ comptime { |
| 75 | // :16:5: error: tuple field name '3' does not match field index 0 | 75 | // :16:5: error: tuple field name '3' does not match field index 0 |
| 76 | // :30:5: error: comptime field without default initialization value | 76 | // :30:5: error: comptime field without default initialization value |
| 77 | // :44:5: error: extern struct fields cannot be marked comptime | 77 | // :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 { | ... | @@ -43,6 +43,6 @@ comptime { |
| 43 | 43 | ||
| 44 | // error | 44 | // error |
| 45 | // | 45 | // |
| 46 | // :2:9: error: alignment value '3' 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 or zero | 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 or zero | 48 | // :30:9: error: alignment value '7' is not a power of two |