mirror of
https://github.com/ziglang/zig.git
synced 2025-12-26 08:03:08 +00:00
Merge pull request #1857 from vegecode/boolean-switch
Switching on bools with duplicate and missing value detection: Issue …
This commit is contained in:
commit
c464ecf3bf
33
src/ir.cpp
33
src/ir.cpp
@ -19787,6 +19787,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
}
|
||||
} else if (switch_type->id == ZigTypeIdBool) {
|
||||
int seenTrue = 0;
|
||||
int seenFalse = 0;
|
||||
for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
|
||||
IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
|
||||
|
||||
IrInstruction *value = range->start->child;
|
||||
|
||||
IrInstruction *casted_value = ir_implicit_cast(ira, value, switch_type);
|
||||
if (type_is_invalid(casted_value->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
ConstExprValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
|
||||
if (!const_expr_val)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
assert(const_expr_val->type->id == ZigTypeIdBool);
|
||||
|
||||
if (const_expr_val->data.x_bool == true) {
|
||||
seenTrue += 1;
|
||||
} else {
|
||||
seenFalse += 1;
|
||||
}
|
||||
|
||||
if ((seenTrue > 1) || (seenFalse > 1)) {
|
||||
ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
}
|
||||
if (((seenTrue < 1) || (seenFalse < 1)) && !instruction->have_else_prong) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
} else if (!instruction->have_else_prong) {
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
|
||||
|
||||
@ -232,3 +232,40 @@ test "capture value of switch with all unreachable prongs" {
|
||||
};
|
||||
assert(x == 1);
|
||||
}
|
||||
|
||||
test "switching on booleans" {
|
||||
testSwitchOnBools();
|
||||
comptime testSwitchOnBools();
|
||||
}
|
||||
|
||||
fn testSwitchOnBools() void {
|
||||
assert(testSwitchOnBoolsTrueAndFalse(true) == false);
|
||||
assert(testSwitchOnBoolsTrueAndFalse(false) == true);
|
||||
|
||||
assert(testSwitchOnBoolsTrueWithElse(true) == false);
|
||||
assert(testSwitchOnBoolsTrueWithElse(false) == true);
|
||||
|
||||
assert(testSwitchOnBoolsFalseWithElse(true) == false);
|
||||
assert(testSwitchOnBoolsFalseWithElse(false) == true);
|
||||
}
|
||||
|
||||
fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
|
||||
return switch (x) {
|
||||
true => false,
|
||||
false => true,
|
||||
};
|
||||
}
|
||||
|
||||
fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
|
||||
return switch (x) {
|
||||
true => false,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
|
||||
return switch (x) {
|
||||
false => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,44 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"duplicate boolean switch value",
|
||||
\\comptime {
|
||||
\\ const x = switch (true) {
|
||||
\\ true => false,
|
||||
\\ false => true,
|
||||
\\ true => false,
|
||||
\\ };
|
||||
\\}
|
||||
\\comptime {
|
||||
\\ const x = switch (true) {
|
||||
\\ false => true,
|
||||
\\ true => false,
|
||||
\\ false => true,
|
||||
\\ };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:9: error: duplicate switch value",
|
||||
".tmp_source.zig:12:9: error: duplicate switch value",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"missing boolean switch value",
|
||||
\\comptime {
|
||||
\\ const x = switch (true) {
|
||||
\\ true => false,
|
||||
\\ };
|
||||
\\}
|
||||
\\comptime {
|
||||
\\ const x = switch (true) {
|
||||
\\ false => true,
|
||||
\\ };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:15: error: switch must handle all possibilities",
|
||||
".tmp_source.zig:7:15: error: switch must handle all possibilities",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"reading past end of pointer casted array",
|
||||
\\comptime {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user