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,
29072907 return return_type;
29082908}
29092909
2910enum LValPurpose {
2911 LValPurposeAssign,
2912 LValPurposeAddressOf,
2913};
2914
29102915static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2911 AstNode *node)
2916 AstNode *node, LValPurpose purpose)
29122917{
29132918 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
29142919 node->data.array_access_expr.array_ref_expr);
......@@ -2923,11 +2928,20 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
29232928 }
29242929 return_type = array_type->data.array.child_type;
29252930 } 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 }
29262935 return_type = array_type->data.pointer.child_type;
29272936 } else if (array_type->id == TypeTableEntryIdStruct &&
29282937 array_type->data.structure.is_slice)
29292938 {
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;
29312945 } else {
29322946 add_node_error(g, node,
29332947 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) {
32543268 zig_unreachable();
32553269}
32563270
3257enum LValPurpose {
3258 LValPurposeAssign,
3259 LValPurposeAddressOf,
3260};
3261
32623271static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
32633272 AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const)
32643273{
......@@ -3288,7 +3297,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
32883297 }
32893298 }
32903299 } 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);
32923301 } else if (lhs_node->type == NodeTypeFieldAccessExpr) {
32933302 expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node);
32943303 } else if (lhs_node->type == NodeTypePrefixOpExpr &&
......@@ -6599,7 +6608,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
65996608
66006609 case NodeTypeArrayAccessExpr:
66016610 // 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);
66036612 break;
66046613 case NodeTypeSliceExpr:
66056614 return_type = analyze_slice_expr(g, import, context, node);
test/run_tests.cpp+14
......@@ -1467,6 +1467,20 @@ fn f(foo: &const Foo) {
14671467 foo.method(1, 2);
14681468}
14691469 )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");
14701484}
14711485
14721486//////////////////////////////////////////////////////////////////////////////