diff --git a/build.zig b/build.zig index ba37c1aa42..f6f929c727 100644 --- a/build.zig +++ b/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); } } } diff --git a/src/ir.cpp b/src/ir.cpp index b570117177..7dbf365355 100644 --- a/src/ir.cpp +++ b/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; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 1d8f5e17f9..c966f8771d 100644 --- a/test/compile_errors.zig +++ b/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}; diff --git a/test/tests.zig b/test/tests.zig index d88c84502d..59a0af195e 100644 --- a/test/tests.zig +++ b/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| {