From b4b14674b479ee45e0b8fea5963b3965dab518e4 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 6 Oct 2025 20:50:56 +0200 Subject: [PATCH] - Bitstruct truncated constant error escapes `$defined` #2515 --- releasenotes.md | 1 + src/compiler/sema_expr.c | 5 +++-- src/compiler/sema_initializers.c | 4 ++-- src/compiler/sema_internal.h | 2 +- test/test_suite/bitstruct/bitrstruct_defined.c3t | 6 ++++++ 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 test/test_suite/bitstruct/bitrstruct_defined.c3t diff --git a/releasenotes.md b/releasenotes.md index d2a9e7254..d47a0fcfb 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -9,6 +9,7 @@ - Bug in `io::write_using_write_byte`. - Bitstruct value cannot be used to index a const array in compile time. #2512 - Compiler fails to stop error print in recursive macro, and also prints unnecessary "inline at" #2513. +- Bitstruct truncated constant error escapes `$defined` #2515 ### Stdlib changes diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 6e36092a8..2b0d5f68e 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6905,7 +6905,7 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef } if (left->expr_kind == EXPR_BITACCESS) { - if (!sema_bit_assignment_check(context, right, left->access_resolved_expr.ref)) return false; + if (!sema_bit_assignment_check(context, right, left->access_resolved_expr.ref, failed_ref)) return false; expr->expr_kind = EXPR_BITASSIGN; } return true; @@ -12310,7 +12310,7 @@ static inline bool sema_insert_binary_overload(SemaContext *context, Expr *expr, } // Check if the assignment fits -bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member) +bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member, bool *failed_ref) { // Don't check non-consts and non integers. if (!sema_cast_const(right) || !type_is_integer(right->type)) return true; @@ -12322,6 +12322,7 @@ bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member) if (int_bits_needed(right->const_expr.ixx) > bits) { + if (failed_ref) return *failed_ref = true, false; RETURN_SEMA_ERROR(right, "This constant would be truncated if stored in the " "bitstruct, do you need a wider bit range?"); } diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index b32ef58f5..cc9137af1 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -277,7 +277,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte if (!sema_analyse_expr_rhs(context, members[i]->type, element, true, no_match_ref, false)) return false; if (member->decl_kind == DECL_VAR && member->var.kind == VARDECL_BITMEMBER) { - if (!sema_bit_assignment_check(context, element, members[i])) return false; + if (!sema_bit_assignment_check(context, element, members[i], no_match_ref)) return false; } optional = optional || IS_OPTIONAL(element); } @@ -529,7 +529,7 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type if (!sema_analyse_expr_rhs(context, result, value, true, no_match_ref, false)) return false; if (is_bitmember) { - if (!sema_bit_assignment_check(context, value, member)) return false; + if (!sema_bit_assignment_check(context, value, member, no_match_ref)) return false; } optional = optional || IS_OPTIONAL(value); expr->resolve_status = RESOLVE_DONE; diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 80f1cf9f6..740f3d249 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -113,7 +113,7 @@ Expr *sema_resolve_string_ident(SemaContext *context, Expr *inner, bool report_m bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt); bool sema_expr_analyse_sprintf(SemaContext *context, Expr *expr, Expr *format_string, Expr **args, unsigned num_args); -bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member); +bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member, bool *failed_ref); CondResult sema_check_comp_time_bool(SemaContext *context, Expr *expr); bool sema_expr_check_assign(SemaContext *context, Expr *expr, bool *failed_ref); diff --git a/test/test_suite/bitstruct/bitrstruct_defined.c3t b/test/test_suite/bitstruct/bitrstruct_defined.c3t new file mode 100644 index 000000000..a9ab2e5b8 --- /dev/null +++ b/test/test_suite/bitstruct/bitrstruct_defined.c3t @@ -0,0 +1,6 @@ +bitstruct Test : char +{ + char type : 0..2; +} + +$assert !$defined((Test){123}); \ No newline at end of file