| ... | ... | @@ -2907,8 +2907,13 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, |
| 2907 | 2907 | return return_type; |
| 2908 | 2908 | } |
| 2909 | 2909 | |
| 2910 | enum LValPurpose { |
| 2911 | LValPurposeAssign, |
| 2912 | LValPurposeAddressOf, |
| 2913 | }; |
| 2914 | |
| 2910 | 2915 | static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2911 | | AstNode *node) |
| 2916 | AstNode *node, LValPurpose purpose) |
| 2912 | 2917 | { |
| 2913 | 2918 | TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, |
| 2914 | 2919 | node->data.array_access_expr.array_ref_expr); |
| ... | ... | @@ -2923,11 +2928,20 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i |
| 2923 | 2928 | } |
| 2924 | 2929 | return_type = array_type->data.array.child_type; |
| 2925 | 2930 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 2931 | if (array_type->data.pointer.is_const && purpose == LValPurposeAssign) { |
| 2932 | add_node_error(g, node, buf_sprintf("cannot assign to constant")); |
| 2933 | return g->builtin_types.entry_invalid; |
| 2934 | } |
| 2926 | 2935 | return_type = array_type->data.pointer.child_type; |
| 2927 | 2936 | } else if (array_type->id == TypeTableEntryIdStruct && |
| 2928 | 2937 | array_type->data.structure.is_slice) |
| 2929 | 2938 | { |
| 2930 | | return_type = array_type->data.structure.fields[0].type_entry->data.pointer.child_type; |
| 2939 | TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry; |
| 2940 | if (pointer_type->data.pointer.is_const && purpose == LValPurposeAssign) { |
| 2941 | add_node_error(g, node, buf_sprintf("cannot assign to constant")); |
| 2942 | return g->builtin_types.entry_invalid; |
| 2943 | } |
| 2944 | return_type = pointer_type->data.pointer.child_type; |
| 2931 | 2945 | } else { |
| 2932 | 2946 | add_node_error(g, node, |
| 2933 | 2947 | buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); |
| ... | ... | @@ -3254,11 +3268,6 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 3254 | 3268 | zig_unreachable(); |
| 3255 | 3269 | } |
| 3256 | 3270 | |
| 3257 | | enum LValPurpose { |
| 3258 | | LValPurposeAssign, |
| 3259 | | LValPurposeAddressOf, |
| 3260 | | }; |
| 3261 | | |
| 3262 | 3271 | static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context, |
| 3263 | 3272 | AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const) |
| 3264 | 3273 | { |
| ... | ... | @@ -3288,7 +3297,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc |
| 3288 | 3297 | } |
| 3289 | 3298 | } |
| 3290 | 3299 | } else if (lhs_node->type == NodeTypeArrayAccessExpr) { |
| 3291 | | expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node); |
| 3300 | expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node, purpose); |
| 3292 | 3301 | } else if (lhs_node->type == NodeTypeFieldAccessExpr) { |
| 3293 | 3302 | expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node); |
| 3294 | 3303 | } else if (lhs_node->type == NodeTypePrefixOpExpr && |
| ... | ... | @@ -6599,7 +6608,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn |
| 6599 | 6608 | |
| 6600 | 6609 | case NodeTypeArrayAccessExpr: |
| 6601 | 6610 | // for reading array access; assignment handled elsewhere |
| 6602 | | return_type = analyze_array_access_expr(g, import, context, node); |
| 6611 | return_type = analyze_array_access_expr(g, import, context, node, LValPurposeAddressOf); |
| 6603 | 6612 | break; |
| 6604 | 6613 | case NodeTypeSliceExpr: |
| 6605 | 6614 | return_type = analyze_slice_expr(g, import, context, node); |