Incorrectly handles distinct enums and pointers with '+=' and '-=' #1717.

This commit is contained in:
Christoffer Lerno
2024-12-25 23:09:10 +01:00
parent e5ca9065bd
commit 75ba4a1cdb
6 changed files with 98 additions and 5 deletions

View File

@@ -21,6 +21,7 @@
- Fix lexer allowing a trailing underscore (_) with hex and binary literals.
- Fix `--list-operators` CLI command printing underscore (_) and hash (#).
- Fix bug in temp allocator when temp memory is exhausted and allocation needs overaligned mem. #1715
- Incorrectly handles distinct enums and pointers with '+=' and '-=' #1717.
### Stdlib changes
- Increase BitWriter.write_bits limit up to 32 bits.

View File

@@ -5717,13 +5717,13 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
if (int_only && !type_flat_is_intlike(flat))
{
if (allow_bitstruct && flat->type_kind == TYPE_BITSTRUCT) goto BITSTRUCT_OK;
RETURN_SEMA_ERROR(left, "Expected an integer here.");
RETURN_SEMA_ERROR(left, "Expected an integer here, not a value of type %s.", type_quoted_error_string(left->type));
}
// 4. In any case, these ops are only defined on numbers.
if (!type_underlying_is_numeric(flat) && !(is_add_sub && type_underlying_may_add_sub(left->type)))
{
RETURN_SEMA_ERROR(left, "Expected a numeric type here.");
RETURN_SEMA_ERROR(left, "Expected a numeric type here, not a value of type %s.", type_quoted_error_string(left->type));
}
BITSTRUCT_OK:
@@ -5731,7 +5731,6 @@ BITSTRUCT_OK:
// 5. Analyse RHS
if (!sema_analyse_expr(context, right)) return false;
// 3. Copy type & set properties.
if (IS_OPTIONAL(right) && !IS_OPTIONAL(left))
{
@@ -5742,8 +5741,30 @@ BITSTRUCT_OK:
bool optional = IS_OPTIONAL(left) || IS_OPTIONAL(right);
// 5. In the pointer case we have to treat this differently.
if (left_type_canonical->type_kind == TYPE_POINTER)
if (flat->type_kind == TYPE_ENUM)
{
if (type_flat_distinct_inline(no_fail)->type_kind != TYPE_ENUM)
{
RETURN_SEMA_ERROR(expr, "A value of type %s cannot be added to or subtracted from.", type_quoted_error_string(left->type));
}
// 7. Finally, check that the right side is indeed an integer.
if (!type_is_integer(right->type->canonical))
{
RETURN_SEMA_ERROR(right,
"The right side was '%s' but only integers are valid on the right side of %s when the left side is an enum.",
type_to_error_string(right->type),
token_type_to_string(binaryop_to_token(expr->binary_expr.operator)));
}
if (!cast_implicit(context, right, flat->decl->enums.type_info->type, false)) return false;
goto END;
}
if (type_is_pointer_like(flat))
{
// Not inline pointer-like
if (!type_is_pointer_like(no_fail))
{
RETURN_SEMA_ERROR(expr, "A value of type %s cannot be added to or subtracted from.", type_quoted_error_string(left->type));
}
// 7. Finally, check that the right side is indeed an integer.
if (!type_is_integer(right->type->canonical))
{

View File

@@ -0,0 +1,12 @@
// #target: macos-x64
module test;
import std;
fn void main()
{
DString y;
y ^= 1; // #error: Expected an integer here
y += 1.0; // #error: A value of type 'DString'
y += 1; // #error: A value of type 'DString'
}

View File

@@ -4,7 +4,7 @@ enum Foo
{
ABC
}
distinct Abc = Foo;
distinct Abc = inline Foo;
distinct BarInt = int;
enum Bar : BarInt
{

View File

@@ -0,0 +1,35 @@
// #target: macos-x64
module test;
import std;
enum Abc
{
ABCD,
OKFEOFKE,
OFKEOFK
}
distinct Bob = inline Abc;
fn void main()
{
Abc y;
y += 1;
Bob gh;
gh += 1;
}
/* #expect: test.ll
entry:
%y = alloca i32, align 4
%gh = alloca i32, align 4
store i32 0, ptr %y, align 4
%0 = load i32, ptr %y, align 4
%add = add i32 %0, 1
store i32 %add, ptr %y, align 4
store i32 0, ptr %gh, align 4
%1 = load i32, ptr %gh, align 4
%add1 = add i32 %1, 1
store i32 %add1, ptr %gh, align 4
ret void
}

View File

@@ -0,0 +1,24 @@
// #target: macos-x64
module test;
import std;
enum Abc
{
ABCD,
OKFEOFKE,
OFKEOFK
}
distinct Bob = Abc;
fn void main()
{
Abc y;
y ^= 1; // #error: Expected an integer here, not a value of type
y += 1.0; // #error: The right side was 'double'
Bob gh;
gh += 1; // #error: A value of type 'Bob'
}
/* #expect: test.ll
feofke