Skip to content

Commit 3d63948

Browse files
Sema: disallow tags on non-auto unions when reifying (#23488)
1 parent cf7a28f commit 3d63948

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

src/Sema.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20630,6 +20630,16 @@ fn zirReify(
2063020630
}
2063120631
const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout);
2063220632

20633+
const has_tag = tag_type_val.optionalValue(zcu) != null;
20634+
20635+
if (has_tag) {
20636+
switch (layout) {
20637+
.@"extern" => return sema.fail(block, src, "extern union does not support enum tag type", .{}),
20638+
.@"packed" => return sema.fail(block, src, "packed union does not support enum tag type", .{}),
20639+
.auto => {},
20640+
}
20641+
}
20642+
2063320643
const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .union_fields });
2063420644

2063520645
return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const Tag = @Type(.{
2+
.@"enum" = .{
3+
.tag_type = u2,
4+
.fields = &.{
5+
.{ .name = "signed", .value = 0 },
6+
.{ .name = "unsigned", .value = 1 },
7+
},
8+
.decls = &.{},
9+
.is_exhaustive = true,
10+
},
11+
});
12+
13+
const Extern = @Type(.{
14+
.@"union" = .{
15+
.layout = .@"extern",
16+
.tag_type = Tag,
17+
.fields = &.{
18+
.{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
19+
.{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
20+
},
21+
.decls = &.{},
22+
},
23+
});
24+
25+
export fn entry() void {
26+
const tagged: Extern = .{ .signed = -1 };
27+
_ = tagged;
28+
}
29+
30+
// error
31+
// backend=stage2
32+
// target=native
33+
//
34+
// :13:16: error: extern union does not support enum tag type
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const Tag = @Type(.{
2+
.@"enum" = .{
3+
.tag_type = u2,
4+
.fields = &.{
5+
.{ .name = "signed", .value = 0 },
6+
.{ .name = "unsigned", .value = 1 },
7+
},
8+
.decls = &.{},
9+
.is_exhaustive = true,
10+
},
11+
});
12+
13+
const Packed = @Type(.{
14+
.@"union" = .{
15+
.layout = .@"packed",
16+
.tag_type = Tag,
17+
.fields = &.{
18+
.{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
19+
.{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
20+
},
21+
.decls = &.{},
22+
},
23+
});
24+
25+
export fn entry() void {
26+
const tagged: Packed = .{ .signed = -1 };
27+
_ = tagged;
28+
}
29+
30+
// error
31+
// backend=stage2
32+
// target=native
33+
//
34+
// :13:16: error: packed union does not support enum tag type

0 commit comments

Comments
 (0)