- Compiler crash when concatenating structs and arrays to an untyped list.

This commit is contained in:
Christoffer Lerno
2025-12-11 03:46:15 +01:00
parent 1fc522ec9c
commit 37d42d555d
3 changed files with 82 additions and 1 deletions

View File

@@ -14,6 +14,7 @@
- Hex escapes like `"\x80"` would be incorrectly lowered. #2623 - Hex escapes like `"\x80"` would be incorrectly lowered. #2623
- Ignore const null check on deref in `$defined` and `$sizeof` #2633. - Ignore const null check on deref in `$defined` and `$sizeof` #2633.
- Subscripting of constant slices would sometimes be considered non-constant #2635. - Subscripting of constant slices would sometimes be considered non-constant #2635.
- Compiler crash when concatenating structs and arrays to an untyped list.
### Stdlib changes ### Stdlib changes
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.

View File

@@ -425,9 +425,20 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *
UNREACHABLE UNREACHABLE
case CONST_INIT_ARRAY_FULL: case CONST_INIT_ARRAY_FULL:
{ {
Expr *el;
FOREACH(ConstInitializer *, val, init->init_array_full) FOREACH(ConstInitializer *, val, init->init_array_full)
{ {
vec_add(untyped_exprs, val->init_value); switch (val->kind)
{
case CONST_INIT_VALUE:
vec_add(untyped_exprs, val->init_value);
break;
default:
el = expr_new_expr(EXPR_CONST, single_expr);
expr_rewrite_const_initializer(el, val->type, val);
vec_add(untyped_exprs, el);
break;
}
} }
continue; continue;
} }

View File

@@ -0,0 +1,69 @@
module assert_repro;
import assert_repro::macros;
struct ArrayEntry
{
int x;
}
macro cause_assert()
{
ArrayEntry[] $slice = {{1}, {2}, {3}};
$slice = macros::replace {ArrayEntry} ($slice, 0, {4});
}
fn int main()
{
cause_assert();
return 0;
}
<*
This contains macros for working with arrays at compile time
*>
module assert_repro::macros { ValueT };
alias SliceT = ValueT[];
macro SliceT slice(SliceT $from, usz $start, usz $end = usz.max)
{
$if $start >= $from.len:
return (SliceT){};
$else
$if $end >= $from.len:
return $from[$start..];
$else
return $from[$start..$end-1];
$endif
$endif
}
macro SliceT insert(SliceT $array, usz $position, ValueT $value)
{
$if $position == $array.len:
return $array +++ {$value};
$else
$if $position == 0:
return {$value} +++ $array;
$else
return slice($array, 0, $position) +++ {$value} +++ slice($array, $position);
$endif
$endif
}
macro SliceT remove(SliceT $array, usz $position)
{
$if $position == $array.len - 1:
return slice($array, 0, $array.len - 1);
$else
$if $position == 0:
return slice($array, 1);
$else
return slice($array, 0, $position) +++ slice($array, $position + 1);
$endif
$endif
}
macro SliceT replace(SliceT $array, usz $position, ValueT $value)
{
return insert(remove($array,$position),$position,$value);
}