mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
Merge pull request #6427 from tadeokondrak/enums-explicit-tag-type-extern-allowed
Allow enums with explicit extern-allowed tag types in extern types
This commit is contained in:
commit
e31cc80130
@ -1456,6 +1456,7 @@ struct ZigTypeEnum {
|
||||
ContainerLayout layout;
|
||||
ResolveStatus resolve_status;
|
||||
|
||||
bool has_explicit_tag_type;
|
||||
bool non_exhaustive;
|
||||
bool resolve_loop_flag;
|
||||
};
|
||||
|
@ -1802,10 +1802,18 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
||||
}
|
||||
return type_allowed_in_extern(g, child_type, result);
|
||||
}
|
||||
case ZigTypeIdEnum:
|
||||
*result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
|
||||
type_entry->data.enumeration.layout == ContainerLayoutPacked;
|
||||
return ErrorNone;
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||
return err;
|
||||
ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
|
||||
if (type_entry->data.enumeration.has_explicit_tag_type) {
|
||||
return type_allowed_in_extern(g, tag_int_type, result);
|
||||
} else {
|
||||
*result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
|
||||
type_entry->data.enumeration.layout == ContainerLayoutPacked;
|
||||
return ErrorNone;
|
||||
}
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
*result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
|
||||
type_entry->data.unionation.layout == ContainerLayoutPacked;
|
||||
@ -2639,9 +2647,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
|
||||
wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
|
||||
enum_type->data.enumeration.has_explicit_tag_type = true;
|
||||
}
|
||||
} else {
|
||||
wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
|
||||
enum_type->data.enumeration.has_explicit_tag_type = true;
|
||||
}
|
||||
|
||||
if (wanted_tag_int_type != nullptr) {
|
||||
|
@ -20,6 +20,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:2:20: error: use of undefined value here causes undefined behavior",
|
||||
});
|
||||
|
||||
cases.add("extern struct with non-extern-compatible integer tag type",
|
||||
\\pub const E = enum(u31) { A, B, C };
|
||||
\\pub const S = extern struct {
|
||||
\\ e: E,
|
||||
\\};
|
||||
\\export fn entry() void {
|
||||
\\ const s: S = undefined;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:3:5: error: extern structs cannot contain fields of type 'E'",
|
||||
});
|
||||
|
||||
cases.add("@Type for exhaustive enum with non-integer tag type",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Tag = @Type(.{
|
||||
@ -38,6 +50,47 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:2:20: error: TypeInfo.Enum.tag_type must be an integer type, not 'bool'",
|
||||
});
|
||||
|
||||
cases.add("extern struct with extern-compatible but inferred integer tag type",
|
||||
\\pub const E = enum {
|
||||
\\@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",
|
||||
\\@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23",
|
||||
\\@"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34",
|
||||
\\@"35",@"36",@"37",@"38",@"39",@"40",@"41",@"42",@"43",@"44",@"45",
|
||||
\\@"46",@"47",@"48",@"49",@"50",@"51",@"52",@"53",@"54",@"55",@"56",
|
||||
\\@"57",@"58",@"59",@"60",@"61",@"62",@"63",@"64",@"65",@"66",@"67",
|
||||
\\@"68",@"69",@"70",@"71",@"72",@"73",@"74",@"75",@"76",@"77",@"78",
|
||||
\\@"79",@"80",@"81",@"82",@"83",@"84",@"85",@"86",@"87",@"88",@"89",
|
||||
\\@"90",@"91",@"92",@"93",@"94",@"95",@"96",@"97",@"98",@"99",@"100",
|
||||
\\@"101",@"102",@"103",@"104",@"105",@"106",@"107",@"108",@"109",
|
||||
\\@"110",@"111",@"112",@"113",@"114",@"115",@"116",@"117",@"118",
|
||||
\\@"119",@"120",@"121",@"122",@"123",@"124",@"125",@"126",@"127",
|
||||
\\@"128",@"129",@"130",@"131",@"132",@"133",@"134",@"135",@"136",
|
||||
\\@"137",@"138",@"139",@"140",@"141",@"142",@"143",@"144",@"145",
|
||||
\\@"146",@"147",@"148",@"149",@"150",@"151",@"152",@"153",@"154",
|
||||
\\@"155",@"156",@"157",@"158",@"159",@"160",@"161",@"162",@"163",
|
||||
\\@"164",@"165",@"166",@"167",@"168",@"169",@"170",@"171",@"172",
|
||||
\\@"173",@"174",@"175",@"176",@"177",@"178",@"179",@"180",@"181",
|
||||
\\@"182",@"183",@"184",@"185",@"186",@"187",@"188",@"189",@"190",
|
||||
\\@"191",@"192",@"193",@"194",@"195",@"196",@"197",@"198",@"199",
|
||||
\\@"200",@"201",@"202",@"203",@"204",@"205",@"206",@"207",@"208",
|
||||
\\@"209",@"210",@"211",@"212",@"213",@"214",@"215",@"216",@"217",
|
||||
\\@"218",@"219",@"220",@"221",@"222",@"223",@"224",@"225",@"226",
|
||||
\\@"227",@"228",@"229",@"230",@"231",@"232",@"233",@"234",@"235",
|
||||
\\@"236",@"237",@"238",@"239",@"240",@"241",@"242",@"243",@"244",
|
||||
\\@"245",@"246",@"247",@"248",@"249",@"250",@"251",@"252",@"253",
|
||||
\\@"254",@"255"
|
||||
\\};
|
||||
\\pub const S = extern struct {
|
||||
\\ e: E,
|
||||
\\};
|
||||
\\export fn entry() void {
|
||||
\\ if (@TagType(E) != u8) @compileError("did not infer u8 tag type");
|
||||
\\ const s: S = undefined;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:31:5: error: extern structs cannot contain fields of type 'E'",
|
||||
});
|
||||
|
||||
cases.add("@Type for tagged union with extra enum field",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Tag = @Type(.{
|
||||
|
7
test/stage1/behavior/bugs/1467.zig
Normal file
7
test/stage1/behavior/bugs/1467.zig
Normal file
@ -0,0 +1,7 @@
|
||||
pub const E = enum(u32) { A, B, C };
|
||||
pub const S = extern struct {
|
||||
e: E,
|
||||
};
|
||||
test "bug 1467" {
|
||||
const s: S = undefined;
|
||||
}
|
Loading…
Reference in New Issue
Block a user