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
signature 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 {...@@ -282,6 +282,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
282 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),282 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
283 .Auto => unreachable, // Not legal on functions283 .Auto => unreachable, // Not legal on functions
284 .Register => unreachable, // Not legal on functions284 .Register => unreachable, // Not legal on functions
285 else => unreachable,
285 },286 },
286 };287 };
287 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {288 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
...@@ -710,6 +711,7 @@ fn transBinaryOperator(...@@ -710,6 +711,7 @@ fn transBinaryOperator(
710 .XorAssign,711 .XorAssign,
711 .OrAssign,712 .OrAssign,
712 => unreachable,713 => unreachable,
714 else => unreachable,
713 }715 }
714}716}
715717
...@@ -1001,6 +1003,7 @@ fn transStringLiteral(...@@ -1001,6 +1003,7 @@ fn transStringLiteral(
1001 "TODO: support string literal kind {}",1003 "TODO: support string literal kind {}",
1002 .{kind},1004 .{kind},
1003 ),1005 ),
1006 else => unreachable,
1004 }1007 }
1005}1008}
10061009
src/analyze.cpp+1-1
...@@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
26822682
2683 // Make sure the value is unique2683 // Make sure the value is unique
2684 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);2684 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) {
2686 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2686 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
26872687
2688 Buf *val_buf = buf_alloc();2688 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,...@@ -3292,7 +3292,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
3292 LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),3292 LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
3293 instruction->target->value->type, tag_int_type, target_val);3293 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) {
3296 LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");3296 LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
3297 LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");3297 LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");
3298 size_t field_count = wanted_type->data.enumeration.src_field_count;3298 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...@@ -12728,7 +12728,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
12728 return ira->codegen->invalid_instruction;12728 return ira->codegen->invalid_instruction;
1272912729
12730 TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);12730 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) {
12732 Buf *val_buf = buf_alloc();12732 Buf *val_buf = buf_alloc();
12733 bigint_append_buf(val_buf, &val->data.x_bigint, 10);12733 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
12734 ErrorMsg *msg = ir_add_error(ira, source_instr,12734 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
25791 }25791 }
25792 }25792 }
25793 if (!instruction->have_else_prong) {25793 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 }
25794 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {25798 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
25795 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];25799 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 {...@@ -10,6 +10,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10 "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",10 "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
11 });11 });
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
13 cases.add("invalid float literal",32 cases.add("invalid float literal",
14 \\const std = @import("std");33 \\const std = @import("std");
15 \\34 \\
test/stage1/behavior/cast.zig+1
...@@ -618,6 +618,7 @@ test "peer resolution of string literals" {...@@ -618,6 +618,7 @@ test "peer resolution of string literals" {
618 .b => "two",618 .b => "two",
619 .c => "three",619 .c => "three",
620 .d => "four",620 .d => "four",
621 else => unreachable,
621 };622 };
622 expect(mem.eql(u8, cmd, "two"));623 expect(mem.eql(u8, cmd, "two"));
623 }624 }
test/stage1/behavior/enum.zig+27
...@@ -1,6 +1,33 @@...@@ -1,6 +1,33 @@
1const expect = @import("std").testing.expect;1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;2const 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
4test "enum type" {31test "enum type" {
5 const foo1 = Foo{ .One = 13 };32 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{33 const foo2 = Foo{