mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
improve extern enum
This commit is contained in:
parent
59de23dfa0
commit
0f38410ea6
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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];
|
||||
|
||||
|
||||
@ -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");
|
||||
\\
|
||||
|
||||
@ -618,6 +618,7 @@ test "peer resolution of string literals" {
|
||||
.b => "two",
|
||||
.c => "three",
|
||||
.d => "four",
|
||||
else => unreachable,
|
||||
};
|
||||
expect(mem.eql(u8, cmd, "two"));
|
||||
}
|
||||
|
||||
@ -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{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user