Allow (Foo)0 bitstruct casts even if type sizes do not match.

This commit is contained in:
Christoffer Lerno
2025-10-25 20:33:47 +02:00
parent 8aaf54e8b1
commit a38a627a1d
6 changed files with 69 additions and 11 deletions

View File

@@ -15,6 +15,7 @@
- ABI change for vectors: store and pass them as arrays #2542.
- Add @simd and @align attributes to typedef #2543.
- Rename `@extern` to `@cname`, deprecating the old name #2493.
- Allow `(Foo)0` bitstruct casts even if type sizes do not match.
### Fixes
- Bug in `io::write_using_write_byte`.

View File

@@ -1523,7 +1523,24 @@ static bool rule_int_to_bits(CastContext *cc, bool is_explicit, bool is_silent)
{
Type *base_type = cc->to->decl->strukt.container_type->type;
Type *from_type = cc->from;
bool success = type_is_integer(base_type) && type_size(from_type) == type_size(base_type);
Expr *expr = cc->expr;
bool success = false;
do
{
if (!type_is_integer(base_type)) break;
if (type_size(base_type) == type_size(from_type))
{
success = true;
break;
}
if (!sema_cast_const(expr) || !expr_is_const_int(expr)) break;
if (!int_fits(cc->expr->const_expr.ixx, base_type->canonical->type_kind))
{
if (is_silent) return false;
RETURN_CAST_ERROR(expr, "The value '%s' does not fit in the container type of the bitstruct %s, which is %s.", int_to_str(cc->expr->const_expr.ixx, 10, false), type_quoted_error_string(cc->to), type_quoted_error_string(base_type));
}
success = true;
} while (0);
if (!is_explicit || !success) return sema_cast_error(cc, success, is_silent);
return true;
}
@@ -1857,7 +1874,16 @@ static void cast_expand_to_vec(Expr *expr, Type *type)
}
static void cast_bitstruct_to_int_arr(Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
static void cast_int_arr_to_bitstruct(Expr *expr, Type *type) { expr_rewrite_recast(expr, type); }
static void cast_int_arr_to_bitstruct(Expr *expr, Type *type)
{
if (expr_is_const_int(expr))
{
Type *widening_type = type_flatten(type)->decl->strukt.container_type->type->canonical;
expr->const_expr.ixx.type = widening_type->type_kind;
expr->type = widening_type;
}
expr_rewrite_recast(expr, type);
}
static void cast_bitstruct_to_bool(Expr *expr, Type *type)
{

View File

@@ -1,14 +1,18 @@
module bug_repro;
bitstruct Edge_Flags : char {
bool left;
bool top;
bool right;
bool bottom;
bitstruct Edge_Flags : char
{
bool left;
bool top;
bool right;
bool bottom;
}
fn int main() {
Edge_Flags edges;
Edge_Flags a = edges & (Edge_Flags)(1 << 0); // #error: 'int'
return 0;
fn int main()
{
Edge_Flags edges;
Edge_Flags a = edges & (Edge_Flags)(1 << 8); // #error: The value '256' does not fit in the container type of the bitstruct
int x = 0;
Edge_Flags ab = edges & (Edge_Flags)x; // #error: 'int'
return 0;
}

View File

@@ -0,0 +1,27 @@
// #target: macos-x64
module test;
bitstruct Foo : char
{
bool baz;
}
fn int main()
{
char ch = 0;
Foo foo1 = (Foo)ch;
Foo foo2 = (Foo)0;
return 0;
}
/* #expect: test.ll
entry:
%ch = alloca i8, align 1
%foo1 = alloca i8, align 1
%foo2 = alloca i8, align 1
store i8 0, ptr %ch, align 1
%0 = load i8, ptr %ch, align 1
store i8 %0, ptr %foo1, align 1
store i8 0, ptr %foo2, align 1
ret i32 0
}