diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 2b547a30a..2502ab352 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -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); + } } } } diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 1beb880d9..6fdf22bec 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -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 diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 41a0835b4..4f31e69e0 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -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 diff --git a/tests/issues/test_issue_7421.odin b/tests/issues/test_issue_7421.odin new file mode 100644 index 000000000..f1a8c5211 --- /dev/null +++ b/tests/issues/test_issue_7421.odin @@ -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) +} diff --git a/tests/issues/test_issue_7421_tagged_duplicate.odin b/tests/issues/test_issue_7421_tagged_duplicate.odin new file mode 100644 index 000000000..e441498da --- /dev/null +++ b/tests/issues/test_issue_7421_tagged_duplicate.odin @@ -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: + } +}