From 56f83257993f92869049b53e8c72e03abdce9547 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 11 Sep 2016 14:12:24 -0400 Subject: [PATCH] add compile error for assigning through const pointer and slice closes #188 --- src/analyze.cpp | 27 ++++++++++++++++++--------- test/run_tests.cpp | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 17f819b46f7ff3312feeedaabf045f5f2b9d5f75..cf396e5509f150c5ef2c46d88adb2f41b890f895 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2907,8 +2907,13 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, return return_type; } +enum LValPurpose { + LValPurposeAssign, + LValPurposeAddressOf, +}; + static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode *node) + AstNode *node, LValPurpose purpose) { TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, node->data.array_access_expr.array_ref_expr); @@ -2923,11 +2928,20 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i } return_type = array_type->data.array.child_type; } else if (array_type->id == TypeTableEntryIdPointer) { + if (array_type->data.pointer.is_const && purpose == LValPurposeAssign) { + add_node_error(g, node, buf_sprintf("cannot assign to constant")); + return g->builtin_types.entry_invalid; + } return_type = array_type->data.pointer.child_type; } else if (array_type->id == TypeTableEntryIdStruct && array_type->data.structure.is_slice) { - return_type = array_type->data.structure.fields[0].type_entry->data.pointer.child_type; + TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry; + if (pointer_type->data.pointer.is_const && purpose == LValPurposeAssign) { + add_node_error(g, node, buf_sprintf("cannot assign to constant")); + return g->builtin_types.entry_invalid; + } + return_type = pointer_type->data.pointer.child_type; } else { add_node_error(g, node, 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) { zig_unreachable(); } -enum LValPurpose { - LValPurposeAssign, - LValPurposeAddressOf, -}; - static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context, AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const) { @@ -3288,7 +3297,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc } } } else if (lhs_node->type == NodeTypeArrayAccessExpr) { - expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node); + expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node, purpose); } else if (lhs_node->type == NodeTypeFieldAccessExpr) { expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node); } else if (lhs_node->type == NodeTypePrefixOpExpr && @@ -6599,7 +6608,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn case NodeTypeArrayAccessExpr: // for reading array access; assignment handled elsewhere - return_type = analyze_array_access_expr(g, import, context, node); + return_type = analyze_array_access_expr(g, import, context, node, LValPurposeAddressOf); break; case NodeTypeSliceExpr: return_type = analyze_slice_expr(g, import, context, node); diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 8fa6f33211e6a74f31fc8bed289435c7b724c4c5..10bca96abea74aea530534cdd8086bc1a8eeec5e 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1467,6 +1467,20 @@ fn f(foo: &const Foo) { foo.method(1, 2); } )SOURCE", 1, ".tmp_source.zig:7:15: error: expected 1 arguments, got 2"); + + add_compile_fail_case("assign through constant pointer", R"SOURCE( +fn f() { + var cstr = c"Hat"; + cstr[0] = 'W'; +} + )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); + + add_compile_fail_case("assign through constant slice", R"SOURCE( +pub fn f() { + var cstr: []const u8 = "Hat"; + cstr[0] = 'W'; +} + )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); } ////////////////////////////////////////////////////////////////////////////// -- 2.54.0