Merge branch 'master' into type_call_null_arg

This commit is contained in:
Jeroen van Rijn
2026-08-22 03:12:01 +02:00
committed by GitHub
8 changed files with 91 additions and 6 deletions

View File

@@ -473,7 +473,11 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr,
check_type_path_pop(ctx);
Type *base = base_type(bt);
if (is_distinct && bt->kind == Type_Named && base->kind == Type_Enum) {
if (base == nullptr) {
// `bt` is a named type that is still being checked, e.g. a cycle back through a
// pointer or slice, so chain to it and let it resolve when it does.
base = bt;
} else if (is_distinct && bt->kind == Type_Named && base->kind == Type_Enum) {
base = clone_enum_type(ctx, base, named);
}
named->Named.base = base;
@@ -881,10 +885,10 @@ gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) {
if (x_base->Struct.is_raw_union) {
return true;
}
if (x->Struct.fields.count == y->Struct.fields.count) {
for (isize i = 0; i < x->Struct.fields.count; i++) {
Entity *a = x->Struct.fields[i];
Entity *b = y->Struct.fields[i];
if (x_base->Struct.fields.count == y_base->Struct.fields.count) {
for (isize i = 0; i < x_base->Struct.fields.count; i++) {
Entity *a = x_base->Struct.fields[i];
Entity *b = y_base->Struct.fields[i];
bool similar = signature_parameter_similar_enough(a->type, b->type);
if (!similar) {
// NOTE(bill): If the fields are not similar enough, then stop.

View File

@@ -4139,7 +4139,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type)
}
#endif
if (type->kind == Type_Named && type->Named.base == nullptr || is_type_typed(type)) {
if (type->kind == Type_Named && base_type(type) == nullptr || is_type_typed(type)) {
add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value);
} else {
gbString name = type_to_string(type);

View File

@@ -6546,6 +6546,11 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
return lb_build_addr_from_entity(p, e, expr);
case_end;
case_ast_node(bd, BasicDirective, expr);
lbValue ptr = lb_address_from_load_or_generate_local(p, lb_build_expr(p, expr));
return lb_addr(ptr);
case_end;
case_ast_node(se, SelectorExpr, expr);
Ast *sel_node = unparen_expr(se->selector);
if (sel_node->kind == Ast_Ident) {

View File

@@ -0,0 +1,26 @@
package test_internal
import "core:testing"
@(private="file")
returns_at :: proc(early: bool, got: ^i32) -> (expected: i32) {
defer got^ = #branch_location.line
if early {
return #line
}
return #line
}
// A selector on `#branch_location` reached `lb_build_addr`, which had no case for a directive
@(test)
branch_location_field_access :: proc(t: ^testing.T) {
got: i32
expected := returns_at(true, &got)
testing.expect_value(t, got, expected)
expected = returns_at(false, &got)
testing.expect_value(t, got, expected)
}

View File

@@ -43,6 +43,8 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
..\..\..\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 check ..\test_issue_ellipsis_type_call.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "10" || exit /b
..\..\..\odin check ..\test_issue_foreign_redeclaration.odin -no-entry-point %COMMON% || exit /b
..\..\..\odin check ..\test_issue_foreign_redeclaration_mismatch.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || 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

View File

@@ -94,6 +94,13 @@ $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 -no-entry-point $COMMON_CHECK
$ODIN check ../test_issue_foreign_redeclaration.odin -no-entry-point $COMMON_CHECK
if [[ $($ODIN check ../test_issue_foreign_redeclaration_mismatch.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
echo "SUCCESSFUL 1/1"
else
echo "SUCCESSFUL 0/1"
exit 1
fi
if [[ $($ODIN check ../test_issue_ellipsis_type_call.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 10 ]]; then
echo "SUCCESSFUL 1/1"

View File

@@ -0,0 +1,23 @@
// Two declarations of the same foreign symbol whose parameters reach a named struct through a
// slice or a field read the wrong member of the type union and segfaulted the compiler
package test_issues
foreign import lib "this_library_does_not_exist"
Inner :: struct { a: i32, b: i32 }
Other :: struct { c: i32, d: i32 }
Wrap1 :: struct { f: Inner }
Wrap2 :: struct { f: Other }
@(default_calling_convention="c")
foreign lib {
@(link_name="via_slice") slice_1 :: proc(x: []Inner) ---
@(link_name="via_field") field_1 :: proc(x: Wrap1) ---
}
@(default_calling_convention="c")
foreign lib {
@(link_name="via_slice") slice_2 :: proc(x: []Other) ---
@(link_name="via_field") field_2 :: proc(x: Wrap2) ---
}

View File

@@ -0,0 +1,18 @@
// The field comparison that guards this had been reading a type's name as its field list, so
// signatures this different were accepted whenever the two names differed in length
package test_issues
foreign import lib "this_library_does_not_exist"
Ints :: struct { a: i32, b: i32 }
Floats :: struct { c: f32, d: f32 }
@(default_calling_convention="c")
foreign lib {
@(link_name="mismatched") mismatched_1 :: proc(x: []Ints) ---
}
@(default_calling_convention="c")
foreign lib {
@(link_name="mismatched") mismatched_2 :: proc(x: []Floats) ---
}