mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Fix list[0].i = 5 when list[0] returns a pointer. #2888
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
- Add error message if directory with output file name already exists
|
||||
- Regression where nested lambdas would be evaluated twice.
|
||||
- Compiler crash when using arrays of vectors in lists. #2889
|
||||
- Fix `list[0].i = 5` when `list[0]` returns a pointer. #2888
|
||||
|
||||
## 0.7.9 Change list
|
||||
|
||||
|
||||
@@ -4553,7 +4553,7 @@ INLINE bool expr_is_const_ref(Expr *expr)
|
||||
|
||||
INLINE bool expr_is_const_pointer(Expr *expr)
|
||||
{
|
||||
ASSERT(expr->resolve_status == RESOLVE_DONE);
|
||||
ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_DONE);
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_POINTER;
|
||||
}
|
||||
|
||||
|
||||
@@ -1281,6 +1281,16 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos)
|
||||
expr->overload_expr = try_consume(c, TOKEN_EQ) ? OVERLOAD_ELEMENT_SET : OVERLOAD_ELEMENT_AT;
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
break;
|
||||
case TOKEN_LESS:
|
||||
case TOKEN_LESS_EQ:
|
||||
case TOKEN_GREATER:
|
||||
case TOKEN_GREATER_EQ:
|
||||
RETURN_PRINT_ERROR_HERE("Comparisons '<', '<=', '>', '>=' cannot be overloaded, only '==' and '!=' are supported.");
|
||||
case TOKEN_PLUSPLUS:
|
||||
case TOKEN_MINUSMINUS:
|
||||
RETURN_PRINT_ERROR_HERE("Increment and decrement operators '++' and '--' cannot be directly overloaded, use '+=' and '-=' instead.");
|
||||
case TOKEN_DOT:
|
||||
RETURN_PRINT_ERROR_HERE("You cannot overload '.'.");
|
||||
default:
|
||||
PARSE_EXPR:
|
||||
expr = parse_constant_expr(c);
|
||||
|
||||
@@ -6349,10 +6349,13 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo
|
||||
Expr *parent = expr->access_unresolved_expr.parent;
|
||||
if (missing_ref) *missing_ref = false;
|
||||
|
||||
int times_to_deref = 1;
|
||||
if (expr->access_unresolved_expr.is_ref)
|
||||
{
|
||||
times_to_deref = 2;
|
||||
expr_set_to_ref(parent);
|
||||
}
|
||||
|
||||
// 1. Resolve the left hand
|
||||
if (!sema_analyse_expr(context, parent)) return false;
|
||||
|
||||
@@ -6441,11 +6444,13 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo
|
||||
|
||||
// 7. Is this a pointer? If so we insert a deref.
|
||||
Type *underlying_type = type_no_optional(parent->type)->canonical;
|
||||
if (underlying_type->type_kind == TYPE_POINTER && underlying_type != type_voidptr)
|
||||
while (times_to_deref > 0 && underlying_type->type_kind == TYPE_POINTER && underlying_type != type_voidptr)
|
||||
{
|
||||
times_to_deref--;
|
||||
if (!sema_cast_rvalue(context, parent, true)) return false;
|
||||
if (!sema_expr_rewrite_insert_deref(context, expr->access_unresolved_expr.parent)) return false;
|
||||
parent = expr->access_unresolved_expr.parent;
|
||||
underlying_type = type_no_optional(parent->type)->canonical;
|
||||
}
|
||||
|
||||
// 8. Depending on parent type, we have some hard coded types
|
||||
|
||||
19
test/test_suite/overloading/operator_pointer.c3t
Normal file
19
test/test_suite/overloading/operator_pointer.c3t
Normal file
@@ -0,0 +1,19 @@
|
||||
struct Node
|
||||
{
|
||||
int i;
|
||||
}
|
||||
|
||||
struct MyList
|
||||
{
|
||||
Node** entries;
|
||||
}
|
||||
fn Node* MyList.get(&self, usz index) @operator([]) => self.entries[index];
|
||||
fn Node** MyList.get_ref(&self, usz index) @operator(&[]) => &self.entries[index];
|
||||
fn int main()
|
||||
{
|
||||
Node n;
|
||||
Node* np = &n;
|
||||
MyList list = {.entries = &np};
|
||||
list[0].i = 5;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user