mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Incorrectly handles distinct enums and pointers with '+=' and '-=' #1717.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
12
test/test_suite/distinct/disntinct_add_fail.c3
Normal file
12
test/test_suite/distinct/disntinct_add_fail.c3
Normal 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'
|
||||
}
|
||||
@@ -4,7 +4,7 @@ enum Foo
|
||||
{
|
||||
ABC
|
||||
}
|
||||
distinct Abc = Foo;
|
||||
distinct Abc = inline Foo;
|
||||
distinct BarInt = int;
|
||||
enum Bar : BarInt
|
||||
{
|
||||
|
||||
35
test/test_suite/enumerations/inc_assign.c3t
Normal file
35
test/test_suite/enumerations/inc_assign.c3t
Normal 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
|
||||
}
|
||||
24
test/test_suite/enumerations/inc_assign_fail.c3
Normal file
24
test/test_suite/enumerations/inc_assign_fail.c3
Normal 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
|
||||
Reference in New Issue
Block a user