authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-11 14:12:24-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-11 14:12:24-04:00
log56f83257993f92869049b53e8c72e03abdce9547
treed273f8eda971432ab8b5c11052432f24df55d9e3
parent28811234bb46824a55596a516f763a39bcbd508a

add compile error for assigning through const

pointer and slice closes #188

2 files changed, 32 insertions(+), 9 deletions(-)

src/analyze.cpp+18-9
...@@ -2907,8 +2907,13 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,...@@ -2907,8 +2907,13 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
2907 return return_type;2907 return return_type;
2908}2908}
29092909
2910enum LValPurpose {
2911 LValPurposeAssign,
2912 LValPurposeAddressOf,
2913};
2914
2910static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2915static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2911 AstNode *node)2916 AstNode *node, LValPurpose purpose)
2912{2917{
2913 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,2918 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
2914 node->data.array_access_expr.array_ref_expr);2919 node->data.array_access_expr.array_ref_expr);
...@@ -2923,11 +2928,20 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2923,11 +2928,20 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
2923 }2928 }
2924 return_type = array_type->data.array.child_type;2929 return_type = array_type->data.array.child_type;
2925 } else if (array_type->id == TypeTableEntryIdPointer) {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 return_type = array_type->data.pointer.child_type;2935 return_type = array_type->data.pointer.child_type;
2927 } else if (array_type->id == TypeTableEntryIdStruct &&2936 } else if (array_type->id == TypeTableEntryIdStruct &&
2928 array_type->data.structure.is_slice)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 } else {2945 } else {
2932 add_node_error(g, node,2946 add_node_error(g, node,
2933 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));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,11 +3268,6 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
3254 zig_unreachable();3268 zig_unreachable();
3255}3269}
32563270
3257enum LValPurpose {
3258 LValPurposeAssign,
3259 LValPurposeAddressOf,
3260};
3261
3262static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,3271static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
3263 AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const)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,7 +3297,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
3288 }3297 }
3289 }3298 }
3290 } else if (lhs_node->type == NodeTypeArrayAccessExpr) {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 } else if (lhs_node->type == NodeTypeFieldAccessExpr) {3301 } else if (lhs_node->type == NodeTypeFieldAccessExpr) {
3293 expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node);3302 expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node);
3294 } else if (lhs_node->type == NodeTypePrefixOpExpr &&3303 } else if (lhs_node->type == NodeTypePrefixOpExpr &&
...@@ -6599,7 +6608,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -6599,7 +6608,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
65996608
6600 case NodeTypeArrayAccessExpr:6609 case NodeTypeArrayAccessExpr:
6601 // for reading array access; assignment handled elsewhere6610 // 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 break;6612 break;
6604 case NodeTypeSliceExpr:6613 case NodeTypeSliceExpr:
6605 return_type = analyze_slice_expr(g, import, context, node);6614 return_type = analyze_slice_expr(g, import, context, node);
test/run_tests.cpp+14
...@@ -1467,6 +1467,20 @@ fn f(foo: &const Foo) {...@@ -1467,6 +1467,20 @@ fn f(foo: &const Foo) {
1467 foo.method(1, 2);1467 foo.method(1, 2);
1468}1468}
1469 )SOURCE", 1, ".tmp_source.zig:7:15: error: expected 1 arguments, got 2");1469 )SOURCE", 1, ".tmp_source.zig:7:15: error: expected 1 arguments, got 2");
1470
1471 add_compile_fail_case("assign through constant pointer", R"SOURCE(
1472fn f() {
1473 var cstr = c"Hat";
1474 cstr[0] = 'W';
1475}
1476 )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
1477
1478 add_compile_fail_case("assign through constant slice", R"SOURCE(
1479pub fn f() {
1480 var cstr: []const u8 = "Hat";
1481 cstr[0] = 'W';
1482}
1483 )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
1470}1484}
14711485
1472//////////////////////////////////////////////////////////////////////////////1486//////////////////////////////////////////////////////////////////////////////