authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-10-03 12:51:39+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-03 12:51:39+03:00
loge31cc80130ee7e4b61b63d1d1a0fc0a84fbb15ff
tree9d08c75af32a03e28a50ee0c5594c44cabf46099
parentb5034bd7765565f838466d8b212140097a1eefba
parent65016dff322c9344cc5e7bf9d6ad6907de940c7f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6427 from tadeokondrak/enums-explicit-tag-type-extern-allowed

Allow enums with explicit extern-allowed tag types in extern types

4 files changed, 75 insertions(+), 4 deletions(-)

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