Commit ff0f97a1bc

Vexu <git@vexu.eu>
2020-04-07 22:34:30
fix missing compile error on assign to slice and array parameters
1 parent ed23dad
src/ir.cpp
@@ -27175,6 +27175,16 @@ done_with_return_type:
             if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
                 return result_loc;
             }
+
+            if (result_loc->value->type->id == ZigTypeIdPointer &&
+                result_loc->value->type->data.pointer.is_const &&
+                instruction->result_loc->id == ResultLocIdInstruction &&
+                !instruction->result_loc->allow_write_through_const)
+            {
+                ir_add_error(ira, &instruction->base.base, buf_sprintf("cannot assign to constant"));
+                return ira->codegen->invalid_inst_gen;
+            }
+
             IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
             dummy_value->value->special = ConstValSpecialRuntime;
             IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
@@ -29908,8 +29918,15 @@ static IrInstGen *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstSrcEndEx
             return result_loc;
 
         if (!was_written || instruction->result_loc->id == ResultLocIdPeer) {
+            bool can_write_to_const_ptr = true;
+            if (result_loc->value->type->id == ZigTypeIdPointer &&
+                result_loc->value->type->data.pointer.is_const &&
+                instruction->result_loc->id == ResultLocIdInstruction)
+            {
+                can_write_to_const_ptr = false;
+            }
             IrInstGen *store_ptr = ir_analyze_store_ptr(ira, &instruction->base.base, result_loc, value,
-                    instruction->result_loc->allow_write_through_const);
+                    instruction->result_loc->allow_write_through_const && can_write_to_const_ptr);
             if (type_is_invalid(store_ptr->value->type)) {
                 return ira->codegen->invalid_inst_gen;
             }
test/compile_errors.zig
@@ -2,6 +2,42 @@ const tests = @import("tests.zig");
 const std = @import("std");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("reassign to array parameter",
+        \\fn reassign(a: [3]f32) void {
+        \\    a = [3]f32{4, 5, 6};
+        \\}
+        \\export fn entry() void {
+        \\    reassign(.{1, 2, 3});
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:2:16: error: cannot assign to constant"
+    });
+
+    cases.addTest("reassign to slice parameter",
+        \\pub fn reassign(s: []const u8) void {
+        \\    s = s[0..];
+        \\}
+        \\export fn entry() void {
+        \\    reassign("foo");
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:2:10: error: cannot assign to constant"
+    });
+
+    cases.addTest("reassign to struct parameter",
+        \\const S = struct {
+        \\    x: u32,
+        \\};
+        \\fn reassign(s: S) void {
+        \\    s = S{.x = 2};
+        \\}
+        \\export fn entry() void {
+        \\    reassign(S{.x = 3});
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:5:16: error: cannot assign to constant"
+    });
+
     cases.addTest("reference to const data",
         \\export fn foo() void {
         \\    var ptr = &[_]u8{0,0,0,0};
test/tests.zig
@@ -612,7 +612,7 @@ pub const StackTracesContext = struct {
 
             const stdout = child.stdout.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
             defer b.allocator.free(stdout);
-            const stderr = child.stderr.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
+            var stderr = child.stderr.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
             defer b.allocator.free(stderr);
 
             const term = child.wait() catch |err| {
build.zig
@@ -225,10 +225,11 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
                 if (fs.path.isAbsolute(lib_arg)) {
                     try result.libs.append(lib_arg);
                 } else {
+                    var lib_arg_copy = lib_arg;
                     if (mem.endsWith(u8, lib_arg, ".lib")) {
-                        lib_arg = lib_arg[0 .. lib_arg.len - 4];
+                        lib_arg_copy = lib_arg[0 .. lib_arg.len - 4];
                     }
-                    try result.system_libs.append(lib_arg);
+                    try result.system_libs.append(lib_arg_copy);
                 }
             }
         }