Skip to content

Commit 0f38410

Browse files
Vexuandrewrk
authored andcommitted
improve extern enum
1 parent 59de23d commit 0f38410

File tree

7 files changed

+57
-3
lines changed

7 files changed

+57
-3
lines changed

src-self-hosted/translate_c.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
11
const expect = @import("std").testing.expect;
22
const mem = @import("std").mem;
33

4+
test "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+
431
test "enum type" {
532
const foo1 = Foo{ .One = 13 };
633
const foo2 = Foo{

0 commit comments

Comments
 (0)