| author | |
| committer | |
| log | ff0f97a1bcab4d27212c67b0ebc6233adf2f0de9 |
| tree | def7d8a41a2821eefc613fdec76c77aaf9c2fd7f |
| parent | ed23dad4877cd93fd684852b17e0e554ef71e297 |
| signature |
4 files changed, 58 insertions(+), 4 deletions(-)
build.zig+3-2| ... | @@ -225,10 +225,11 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | ... | @@ -225,10 +225,11 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 225 | if (fs.path.isAbsolute(lib_arg)) { | 225 | if (fs.path.isAbsolute(lib_arg)) { |
| 226 | try result.libs.append(lib_arg); | 226 | try result.libs.append(lib_arg); |
| 227 | } else { | 227 | } else { |
| 228 | var lib_arg_copy = lib_arg; | ||
| 228 | if (mem.endsWith(u8, lib_arg, ".lib")) { | 229 | if (mem.endsWith(u8, lib_arg, ".lib")) { |
| 229 | lib_arg = lib_arg[0 .. lib_arg.len - 4]; | 230 | lib_arg_copy = lib_arg[0 .. lib_arg.len - 4]; |
| 230 | } | 231 | } |
| 231 | try result.system_libs.append(lib_arg); | 232 | try result.system_libs.append(lib_arg_copy); |
| 232 | } | 233 | } |
| 233 | } | 234 | } |
| 234 | } | 235 | } |
src/ir.cpp+18-1| ... | @@ -27175,6 +27175,16 @@ done_with_return_type: | ... | @@ -27175,6 +27175,16 @@ done_with_return_type: |
| 27175 | if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { | 27175 | if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { |
| 27176 | return result_loc; | 27176 | return result_loc; |
| 27177 | } | 27177 | } |
| 27178 | |||
| 27179 | if (result_loc->value->type->id == ZigTypeIdPointer && | ||
| 27180 | result_loc->value->type->data.pointer.is_const && | ||
| 27181 | instruction->result_loc->id == ResultLocIdInstruction && | ||
| 27182 | !instruction->result_loc->allow_write_through_const) | ||
| 27183 | { | ||
| 27184 | ir_add_error(ira, &instruction->base.base, buf_sprintf("cannot assign to constant")); | ||
| 27185 | return ira->codegen->invalid_inst_gen; | ||
| 27186 | } | ||
| 27187 | |||
| 27178 | IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type); | 27188 | IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type); |
| 27179 | dummy_value->value->special = ConstValSpecialRuntime; | 27189 | dummy_value->value->special = ConstValSpecialRuntime; |
| 27180 | IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base, | 27190 | IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base, |
| ... | @@ -29908,8 +29918,15 @@ static IrInstGen *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstSrcEndEx | ... | @@ -29908,8 +29918,15 @@ static IrInstGen *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstSrcEndEx |
| 29908 | return result_loc; | 29918 | return result_loc; |
| 29909 | 29919 | ||
| 29910 | if (!was_written || instruction->result_loc->id == ResultLocIdPeer) { | 29920 | if (!was_written || instruction->result_loc->id == ResultLocIdPeer) { |
| 29921 | bool can_write_to_const_ptr = true; | ||
| 29922 | if (result_loc->value->type->id == ZigTypeIdPointer && | ||
| 29923 | result_loc->value->type->data.pointer.is_const && | ||
| 29924 | instruction->result_loc->id == ResultLocIdInstruction) | ||
| 29925 | { | ||
| 29926 | can_write_to_const_ptr = false; | ||
| 29927 | } | ||
| 29911 | IrInstGen *store_ptr = ir_analyze_store_ptr(ira, &instruction->base.base, result_loc, value, | 29928 | IrInstGen *store_ptr = ir_analyze_store_ptr(ira, &instruction->base.base, result_loc, value, |
| 29912 | instruction->result_loc->allow_write_through_const); | 29929 | instruction->result_loc->allow_write_through_const && can_write_to_const_ptr); |
| 29913 | if (type_is_invalid(store_ptr->value->type)) { | 29930 | if (type_is_invalid(store_ptr->value->type)) { |
| 29914 | return ira->codegen->invalid_inst_gen; | 29931 | return ira->codegen->invalid_inst_gen; |
| 29915 | } | 29932 | } |
test/compile_errors.zig+36| ... | @@ -2,6 +2,42 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,42 @@ const tests = @import("tests.zig"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("reassign to array parameter", | ||
| 6 | \\fn reassign(a: [3]f32) void { | ||
| 7 | \\ a = [3]f32{4, 5, 6}; | ||
| 8 | \\} | ||
| 9 | \\export fn entry() void { | ||
| 10 | \\ reassign(.{1, 2, 3}); | ||
| 11 | \\} | ||
| 12 | , &[_][]const u8{ | ||
| 13 | "tmp.zig:2:16: error: cannot assign to constant" | ||
| 14 | }); | ||
| 15 | |||
| 16 | cases.addTest("reassign to slice parameter", | ||
| 17 | \\pub fn reassign(s: []const u8) void { | ||
| 18 | \\ s = s[0..]; | ||
| 19 | \\} | ||
| 20 | \\export fn entry() void { | ||
| 21 | \\ reassign("foo"); | ||
| 22 | \\} | ||
| 23 | , &[_][]const u8{ | ||
| 24 | "tmp.zig:2:10: error: cannot assign to constant" | ||
| 25 | }); | ||
| 26 | |||
| 27 | cases.addTest("reassign to struct parameter", | ||
| 28 | \\const S = struct { | ||
| 29 | \\ x: u32, | ||
| 30 | \\}; | ||
| 31 | \\fn reassign(s: S) void { | ||
| 32 | \\ s = S{.x = 2}; | ||
| 33 | \\} | ||
| 34 | \\export fn entry() void { | ||
| 35 | \\ reassign(S{.x = 3}); | ||
| 36 | \\} | ||
| 37 | , &[_][]const u8{ | ||
| 38 | "tmp.zig:5:16: error: cannot assign to constant" | ||
| 39 | }); | ||
| 40 | |||
| 5 | cases.addTest("reference to const data", | 41 | cases.addTest("reference to const data", |
| 6 | \\export fn foo() void { | 42 | \\export fn foo() void { |
| 7 | \\ var ptr = &[_]u8{0,0,0,0}; | 43 | \\ var ptr = &[_]u8{0,0,0,0}; |
test/tests.zig+1-1| ... | @@ -612,7 +612,7 @@ pub const StackTracesContext = struct { | ... | @@ -612,7 +612,7 @@ pub const StackTracesContext = struct { |
| 612 | 612 | ||
| 613 | const stdout = child.stdout.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable; | 613 | const stdout = child.stdout.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable; |
| 614 | defer b.allocator.free(stdout); | 614 | defer b.allocator.free(stdout); |
| 615 | const stderr = child.stderr.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable; | 615 | var stderr = child.stderr.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable; |
| 616 | defer b.allocator.free(stderr); | 616 | defer b.allocator.free(stderr); |
| 617 | 617 | ||
| 618 | const term = child.wait() catch |err| { | 618 | const term = child.wait() catch |err| { |