authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-15 00:05:13+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-15 19:28:53-05:00
log0f38410ea6f60ce9cebf373069d4abfcac0e77e6
treea57673939888845bd3eb1553da5d6a23342e0e7f
parent59de23dfa010c5556f79fbb8b4c637c8d150fd88
signaturelock-open Commit is signed but in an unrecognized format.

improve extern enum


7 files changed, 57 insertions(+), 3 deletions(-)

src-self-hosted/translate_c.zig+3
......@@ -282,6 +282,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
282282 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
283283 .Auto => unreachable, // Not legal on functions
284284 .Register => unreachable, // Not legal on functions
285 else => unreachable,
285286 },
286287 };
287288 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
......@@ -710,6 +711,7 @@ fn transBinaryOperator(
710711 .XorAssign,
711712 .OrAssign,
712713 => unreachable,
714 else => unreachable,
713715 }
714716}
715717
......@@ -1001,6 +1003,7 @@ fn transStringLiteral(
10011003 "TODO: support string literal kind {}",
10021004 .{kind},
10031005 ),
1006 else => unreachable,
10041007 }
10051008}
10061009
src/analyze.cpp+1-1
......@@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
26822682
26832683 // Make sure the value is unique
26842684 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
2685 if (entry != nullptr) {
2685 if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
26862686 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
26872687
26882688 Buf *val_buf = buf_alloc();
src/codegen.cpp+1-1
......@@ -3292,7 +3292,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
32923292 LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
32933293 instruction->target->value->type, tag_int_type, target_val);
32943294
3295 if (ir_want_runtime_safety(g, &instruction->base)) {
3295 if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
32963296 LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
32973297 LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");
32983298 size_t field_count = wanted_type->data.enumeration.src_field_count;
src/ir.cpp+5-1
......@@ -12728,7 +12728,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
1272812728 return ira->codegen->invalid_instruction;
1272912729
1273012730 TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
12731 if (field == nullptr) {
12731 if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
1273212732 Buf *val_buf = buf_alloc();
1273312733 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
1273412734 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
2579125791 }
2579225792 }
2579325793 if (!instruction->have_else_prong) {
25794 if (switch_type->data.enumeration.layout == ContainerLayoutExtern) {
25795 ir_add_error(ira, &instruction->base,
25796 buf_sprintf("switch on an extern enum must have an else prong"));
25797 }
2579425798 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
2579525799 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
2579625800
test/compile_errors.zig+19
......@@ -10,6 +10,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1010 "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
1111 });
1212
13 cases.add("switch on extern enum missing else prong",
14 \\const i = extern enum {
15 \\ n = 0,
16 \\ o = 2,
17 \\ p = 4,
18 \\ q = 4,
19 \\};
20 \\pub fn main() void {
21 \\ var x = @intToEnum(i, 52);
22 \\ switch (x) {
23 \\ .n,
24 \\ .o,
25 \\ .p => unreachable,
26 \\ }
27 \\}
28 , &[_][]const u8{
29 "tmp.zig:9:5: error: switch on an extern enum must have an else prong",
30 });
31
1332 cases.add("invalid float literal",
1433 \\const std = @import("std");
1534 \\
test/stage1/behavior/cast.zig+1
......@@ -618,6 +618,7 @@ test "peer resolution of string literals" {
618618 .b => "two",
619619 .c => "three",
620620 .d => "four",
621 else => unreachable,
621622 };
622623 expect(mem.eql(u8, cmd, "two"));
623624 }
test/stage1/behavior/enum.zig+27
......@@ -1,6 +1,33 @@
11const expect = @import("std").testing.expect;
22const mem = @import("std").mem;
33
4test "extern enum" {
5 const S = struct {
6 const i = extern enum {
7 n = 0,
8 o = 2,
9 p = 4,
10 q = 4,
11 };
12 fn doTheTest(y: c_int) void {
13 var x = i.o;
14 expect(@enumToInt(x) == 2);
15 x = @intToEnum(i, 12);
16 expect(@enumToInt(x) == 12);
17 x = @intToEnum(i, y);
18 expect(@enumToInt(x) == 52);
19 switch (x) {
20 .n,
21 .o,
22 .p => unreachable,
23 else => {},
24 }
25 }
26 };
27 S.doTheTest(52);
28 comptime S.doTheTest(52);
29}
30
431test "enum type" {
532 const foo1 = Foo{ .One = 13 };
633 const foo2 = Foo{