From 7d0278825727cc5ae634688452a7ba147b4afc8e Mon Sep 17 00:00:00 2001 From: Michael Tesar Date: Fri, 21 Aug 2026 00:46:47 +0200 Subject: [PATCH 1/3] Fix reordered compound literal comparison --- src/check_expr.cpp | 81 +++++++++++++++++++++++++++++++ tests/issues/run.sh | 1 + tests/issues/test_issue_7260.odin | 6 +++ 3 files changed, 88 insertions(+) create mode 100644 tests/issues/test_issue_7260.odin diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7c053bccf..2c4985ac8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -13035,6 +13035,48 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) { +struct IndexedCompoundLitElem { + i64 index; + Ast *elem; +}; + +gb_internal bool compound_lit_elem_index(Type *type, Ast *elem, isize positional_index, i64 *index) { + if (elem->kind != Ast_FieldValue) { + *index = cast(i64)positional_index; + return true; + } + + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + return false; + } + + if (is_type_struct(type)) { + if (fv->field->kind != Ast_Ident) { + return false; + } + Selection sel = lookup_field(type, fv->field->Ident.interned, false); + if (sel.index.count != 1) { + return false; + } + *index = sel.index[0]; + return true; + } + + if (fv->field->tav.mode != Addressing_Constant) { + return false; + } + *index = exact_value_to_i64(fv->field->tav.value); + return true; +} + +gb_internal ExactValue compound_lit_elem_value(Ast *elem) { + if (elem->kind == Ast_FieldValue) { + return elem->FieldValue.value->tav.value; + } + return elem->tav.value; +} + gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, ExactValue y) { ast_node(x_cl, CompoundLit, x.value_compound); ast_node(y_cl, CompoundLit, y.value_compound); @@ -13044,6 +13086,45 @@ gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, E } bool test = op == Token_CmpEq; + bool has_field_values = + x_cl->elems.count > 0 && x_cl->elems[0]->kind == Ast_FieldValue || + y_cl->elems.count > 0 && y_cl->elems[0]->kind == Ast_FieldValue; + + if (has_field_values) { + auto lhs_elems = array_make(temporary_allocator(), x_cl->elems.count); + auto rhs_elems = array_make(temporary_allocator(), y_cl->elems.count); + bool indices_ok = true; + + for (isize i = 0; i < x_cl->elems.count; i++) { + if (!compound_lit_elem_index(x.value_compound->tav.type, x_cl->elems[i], i, &lhs_elems[i].index) || + !compound_lit_elem_index(y.value_compound->tav.type, y_cl->elems[i], i, &rhs_elems[i].index)) { + indices_ok = false; + break; + } + lhs_elems[i].elem = x_cl->elems[i]; + rhs_elems[i].elem = y_cl->elems[i]; + } + + if (indices_ok) { + auto compare_indices = [](void const *x, void const *y) -> int { + auto x_elem = cast(IndexedCompoundLitElem const *)x; + auto y_elem = cast(IndexedCompoundLitElem const *)y; + i64 x_index = x_elem->index; + i64 y_index = y_elem->index; + return (x_index > y_index) - (x_index < y_index); + }; + array_sort(lhs_elems, compare_indices); + array_sort(rhs_elems, compare_indices); + + for (isize i = 0; i < lhs_elems.count; i++) { + if (lhs_elems[i].index != rhs_elems[i].index || + compare_exact_values(op, compound_lit_elem_value(lhs_elems[i].elem), compound_lit_elem_value(rhs_elems[i].elem)) != test) { + return !test; + } + } + return test; + } + } for (isize i = 0; i < x_cl->elems.count; i++) { Ast *lhs = x_cl->elems[i]; diff --git a/tests/issues/run.sh b/tests/issues/run.sh index f0cbea3fd..3d3535fa3 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -93,6 +93,7 @@ $ODIN build ../test_issue_7037.odin $COMMON -o:none $ODIN test ../test_issue_7356.odin $COMMON $ODIN build ../test_issue_7167.odin $COMMON $ODIN build ../test_issue_7188.odin $COMMON +$ODIN check ../test_issue_7260.odin -file -no-entry-point $COMMON_CHECK if [[ $($ODIN build ../test_issue_7108.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then echo "SUCCESSFUL 1/1" diff --git a/tests/issues/test_issue_7260.odin b/tests/issues/test_issue_7260.odin new file mode 100644 index 000000000..43b145b88 --- /dev/null +++ b/tests/issues/test_issue_7260.odin @@ -0,0 +1,6 @@ +// Tests issue #7260 https://github.com/odin-lang/Odin/issues/7260 +package test_issues + +A :: [2]int + +#assert(A{0 = 0, 1 = 1} == {1 = 1, 0 = 0}) From b6c90b18dd27405506bc1b6326144a50dbccfb81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Tesa=C5=99?= Date: Fri, 21 Aug 2026 19:18:25 +0200 Subject: [PATCH 2/3] fix failing tests --- tests/issues/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 3d3535fa3..138c88589 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -93,7 +93,7 @@ $ODIN build ../test_issue_7037.odin $COMMON -o:none $ODIN test ../test_issue_7356.odin $COMMON $ODIN build ../test_issue_7167.odin $COMMON $ODIN build ../test_issue_7188.odin $COMMON -$ODIN check ../test_issue_7260.odin -file -no-entry-point $COMMON_CHECK +$ODIN check ../test_issue_7260.odin -no-entry-point $COMMON_CHECK if [[ $($ODIN build ../test_issue_7108.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then echo "SUCCESSFUL 1/1" From 6fadf91c8462b08db5d3e0b5059b8a36cbbe848d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Tesa=C5=99?= Date: Fri, 21 Aug 2026 19:20:11 +0200 Subject: [PATCH 3/3] add windows test --- tests/issues/run.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/issues/run.bat b/tests/issues/run.bat index d01c85e14..a2224edb6 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -41,6 +41,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused ..\..\..\odin check ..\test_issue_6874.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b ..\..\..\odin check ..\test_issue_6979.odin -no-entry-point %COMMON% || exit /b ..\..\..\odin check ..\test_issue_7012.odin -no-entry-point %COMMON% || exit /b +..\..\..\odin check ..\test_issue_7260.odin -no-entry-point %COMMON% || exit /b ..\..\..\odin build ..\test_issue_7037.odin %COMMON% -o:none || 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