Commit 0f38410ea6
Changed files (7)
src-self-hosted
test
src/analyze.cpp
@@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
// Make sure the value is unique
auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
- if (entry != nullptr) {
+ if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
Buf *val_buf = buf_alloc();
src/codegen.cpp
@@ -3292,7 +3292,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
instruction->target->value->type, tag_int_type, target_val);
- if (ir_want_runtime_safety(g, &instruction->base)) {
+ if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");
size_t field_count = wanted_type->data.enumeration.src_field_count;
src/ir.cpp
@@ -12728,7 +12728,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
return ira->codegen->invalid_instruction;
TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
- if (field == nullptr) {
+ if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &val->data.x_bigint, 10);
ErrorMsg *msg = ir_add_error(ira, source_instr,
@@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
}
}
if (!instruction->have_else_prong) {
+ if (switch_type->data.enumeration.layout == ContainerLayoutExtern) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("switch on an extern enum must have an else prong"));
+ }
for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
src-self-hosted/translate_c.zig
@@ -282,6 +282,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
.Auto => unreachable, // Not legal on functions
.Register => unreachable, // Not legal on functions
+ else => unreachable,
},
};
const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
@@ -710,6 +711,7 @@ fn transBinaryOperator(
.XorAssign,
.OrAssign,
=> unreachable,
+ else => unreachable,
}
}
@@ -1001,6 +1003,7 @@ fn transStringLiteral(
"TODO: support string literal kind {}",
.{kind},
),
+ else => unreachable,
}
}
test/stage1/behavior/cast.zig
@@ -618,6 +618,7 @@ test "peer resolution of string literals" {
.b => "two",
.c => "three",
.d => "four",
+ else => unreachable,
};
expect(mem.eql(u8, cmd, "two"));
}
test/stage1/behavior/enum.zig
@@ -1,6 +1,33 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
+test "extern enum" {
+ const S = struct {
+ const i = extern enum {
+ n = 0,
+ o = 2,
+ p = 4,
+ q = 4,
+ };
+ fn doTheTest(y: c_int) void {
+ var x = i.o;
+ expect(@enumToInt(x) == 2);
+ x = @intToEnum(i, 12);
+ expect(@enumToInt(x) == 12);
+ x = @intToEnum(i, y);
+ expect(@enumToInt(x) == 52);
+ switch (x) {
+ .n,
+ .o,
+ .p => unreachable,
+ else => {},
+ }
+ }
+ };
+ S.doTheTest(52);
+ comptime S.doTheTest(52);
+}
+
test "enum type" {
const foo1 = Foo{ .One = 13 };
const foo2 = Foo{
test/compile_errors.zig
@@ -10,6 +10,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
});
+ cases.add("switch on extern enum missing else prong",
+ \\const i = extern enum {
+ \\ n = 0,
+ \\ o = 2,
+ \\ p = 4,
+ \\ q = 4,
+ \\};
+ \\pub fn main() void {
+ \\ var x = @intToEnum(i, 52);
+ \\ switch (x) {
+ \\ .n,
+ \\ .o,
+ \\ .p => unreachable,
+ \\ }
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:9:5: error: switch on an extern enum must have an else prong",
+ });
+
cases.add("invalid float literal",
\\const std = @import("std");
\\