mirror of
https://github.com/odin-lang/Odin.git
synced 2026-09-02 02:03:35 +00:00
checker: Do not deduplicate cases in tagless switches
Tagless switch cases are ordered predicates, so distinct constant conditions may fold to the same Boolean value. Restrict duplicate-case tracking to explicitly tagged switches and add positive and negative regression coverage for issue #7421.
This commit is contained in:
@@ -1167,6 +1167,8 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
||||
ast_node(ss, SwitchStmt, node);
|
||||
|
||||
Operand x = {};
|
||||
// Tagless switch cases are independent predicates, not case values.
|
||||
bool check_duplicate_cases = ss->tag != nullptr;
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed | Stmt_FallthroughAllowed;
|
||||
check_open_scope(ctx, node);
|
||||
@@ -1292,7 +1294,9 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
||||
Operand b1 = rhs;
|
||||
check_comparison(ctx, expr, &a1, &b1, Token_LtEq);
|
||||
|
||||
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
|
||||
if (check_duplicate_cases) {
|
||||
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
|
||||
}
|
||||
|
||||
if (is_type_string16(x.type)) {
|
||||
// NOTE(bill): Force dependency for strings here
|
||||
@@ -1325,7 +1329,9 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
||||
}
|
||||
t = default_type(t);
|
||||
add_type_info_type(ctx, t);
|
||||
add_type_to_seen_map(ctx, &seen, y);
|
||||
if (check_duplicate_cases) {
|
||||
add_type_to_seen_map(ctx, &seen, y);
|
||||
}
|
||||
} else {
|
||||
convert_to_typed(ctx, &y, x.type);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
@@ -1342,7 +1348,9 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
||||
continue;
|
||||
}
|
||||
update_untyped_expr_type(ctx, z.expr, x.type, !is_type_untyped(x.type));
|
||||
add_to_seen_map(ctx, &seen, y);
|
||||
if (check_duplicate_cases) {
|
||||
add_to_seen_map(ctx, &seen, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
|
||||
..\..\..\odin check ..\test_issue_foreign_redeclaration_mismatch.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b
|
||||
..\..\..\odin doc ..\test_issue_asm_doc_category.odin -file 2>&1 | find /c "asm templates" | findstr /x "1" || exit /b
|
||||
..\..\..\odin build ..\test_issue_7037.odin %COMMON% -o:none || exit /b
|
||||
..\..\..\odin test ..\test_issue_7421.odin %COMMON% || exit /b
|
||||
..\..\..\odin check ..\test_issue_7421_tagged_duplicate.odin %COMMON% 2>&1 | find /c "Error: Duplicate case" | findstr /x "1" || exit /b
|
||||
..\..\..\odin build ..\test_issue_7188.odin %COMMON% || exit /b
|
||||
clang -c ..\test_issue_sysv_abi.c -o test_issue_sysv_abi_c.o || exit /b
|
||||
..\..\..\odin test ..\test_issue_sysv_abi.odin %COMMON% || exit /b
|
||||
|
||||
@@ -91,6 +91,13 @@ $ODIN check ../test_issue_6979.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN test ../test_issue_7008.odin $COMMON
|
||||
$ODIN check ../test_issue_7012.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN build ../test_issue_7037.odin $COMMON -o:none
|
||||
$ODIN test ../test_issue_7421.odin $COMMON
|
||||
if [[ $($ODIN check ../test_issue_7421_tagged_duplicate.odin $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error: Duplicate case") -eq 1 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
$ODIN check ../test_issue_7429.odin $COMMON_CHECK
|
||||
$ODIN test ../test_issue_7356.odin $COMMON
|
||||
$ODIN test ../test_issue_7336.odin $COMMON
|
||||
|
||||
25
tests/issues/test_issue_7421.odin
Normal file
25
tests/issues/test_issue_7421.odin
Normal file
@@ -0,0 +1,25 @@
|
||||
// Tests issue #7421: constant conditions in a tagless switch are conditions,
|
||||
// not values to compare against one another for duplicate cases.
|
||||
// https://github.com/odin-lang/Odin/issues/7421
|
||||
package test_issues
|
||||
|
||||
import "core:testing"
|
||||
|
||||
Issue_7421_Alias :: u16
|
||||
|
||||
@(test)
|
||||
test_issue_7421_tagless_switch_constant_conditions :: proc(t: ^testing.T) {
|
||||
selected := 0
|
||||
switch {
|
||||
case Issue_7421_Alias == u16:
|
||||
selected = 1
|
||||
case Issue_7421_Alias == i32:
|
||||
selected = 2
|
||||
case Issue_7421_Alias == string:
|
||||
selected = 3
|
||||
case:
|
||||
selected = 4
|
||||
}
|
||||
|
||||
testing.expect_value(t, selected, 1)
|
||||
}
|
||||
10
tests/issues/test_issue_7421_tagged_duplicate.odin
Normal file
10
tests/issues/test_issue_7421_tagged_duplicate.odin
Normal file
@@ -0,0 +1,10 @@
|
||||
// Regression guard for issue #7421: tagged switches still reject duplicate cases.
|
||||
package test_issues
|
||||
|
||||
main :: proc() {
|
||||
value := false
|
||||
switch value {
|
||||
case false:
|
||||
case false:
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user