| author | |
| committer | |
| log | ae7b32eb62cb00a09fe2e0e30b307eb83e9f0a86 |
| tree | abe5edeef5d656feb5dcf82d5a8e93db67fd2afc |
| parent | 3c73f711771e41e9176e973c64484f0ce5e0eeed |
26 files changed, 161 insertions(+), 113 deletions(-)
lib/c.zig+1-1| ... | ... | @@ -82,7 +82,7 @@ fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 { |
| 82 | 82 | var d = dest.?; |
| 83 | 83 | var n = len; |
| 84 | 84 | while (true) { |
| 85 | d.* = c; | |
| 85 | d[0] = c; | |
| 86 | 86 | n -= 1; |
| 87 | 87 | if (n == 0) break; |
| 88 | 88 | d += 1; |
lib/std/os.zig+1-1| ... | ... | @@ -1868,7 +1868,7 @@ pub fn getenv(key: []const u8) ?[]const u8 { |
| 1868 | 1868 | } |
| 1869 | 1869 | // Search the entire `environ` because we don't have a null terminated pointer. |
| 1870 | 1870 | var ptr = std.c.environ; |
| 1871 | while (ptr.*) |line| : (ptr += 1) { | |
| 1871 | while (ptr[0]) |line| : (ptr += 1) { | |
| 1872 | 1872 | var line_i: usize = 0; |
| 1873 | 1873 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} |
| 1874 | 1874 | const this_key = line[0..line_i]; |
lib/std/process.zig+1-1| ... | ... | @@ -313,7 +313,7 @@ pub fn getEnvMap(allocator: Allocator) !EnvMap { |
| 313 | 313 | return result; |
| 314 | 314 | } else if (builtin.link_libc) { |
| 315 | 315 | var ptr = std.c.environ; |
| 316 | while (ptr.*) |line| : (ptr += 1) { | |
| 316 | while (ptr[0]) |line| : (ptr += 1) { | |
| 317 | 317 | var line_i: usize = 0; |
| 318 | 318 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} |
| 319 | 319 | const key = line[0..line_i]; |
src/AstGen.zig+2| ... | ... | @@ -812,6 +812,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 812 | 812 | |
| 813 | 813 | .deref => { |
| 814 | 814 | const lhs = try expr(gz, scope, .none, node_datas[node].lhs); |
| 815 | _ = try gz.addUnTok(.validate_deref, lhs, main_tokens[node]); | |
| 815 | 816 | switch (rl) { |
| 816 | 817 | .ref => return lhs, |
| 817 | 818 | else => { |
| ... | ... | @@ -2500,6 +2501,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2500 | 2501 | .memset, |
| 2501 | 2502 | .validate_array_init_ty, |
| 2502 | 2503 | .validate_struct_init_ty, |
| 2504 | .validate_deref, | |
| 2503 | 2505 | => break :b true, |
| 2504 | 2506 | } |
| 2505 | 2507 | } else switch (maybe_unused_result) { |
src/Sema.zig+27| ... | ... | @@ -1080,6 +1080,11 @@ fn analyzeBodyInner( |
| 1080 | 1080 | i += 1; |
| 1081 | 1081 | continue; |
| 1082 | 1082 | }, |
| 1083 | .validate_deref => { | |
| 1084 | try sema.zirValidateDeref(block, inst); | |
| 1085 | i += 1; | |
| 1086 | continue; | |
| 1087 | }, | |
| 1083 | 1088 | .@"export" => { |
| 1084 | 1089 | try sema.zirExport(block, inst); |
| 1085 | 1090 | i += 1; |
| ... | ... | @@ -3849,6 +3854,28 @@ fn zirValidateArrayInit( |
| 3849 | 3854 | } |
| 3850 | 3855 | } |
| 3851 | 3856 | |
| 3857 | fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3858 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; | |
| 3859 | const src = inst_data.src(); | |
| 3860 | const operand_src: LazySrcLoc = .{ .token_offset = inst_data.src_tok + 1 }; | |
| 3861 | const operand = try sema.resolveInst(inst_data.operand); | |
| 3862 | const operand_ty = sema.typeOf(operand); | |
| 3863 | ||
| 3864 | if (operand_ty.zigTypeTag() != .Pointer) { | |
| 3865 | return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)}); | |
| 3866 | } else switch (operand_ty.ptrSize()) { | |
| 3867 | .One, .C => {}, | |
| 3868 | .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 3869 | .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 3870 | } | |
| 3871 | ||
| 3872 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { | |
| 3873 | if (val.isUndef()) { | |
| 3874 | return sema.fail(block, src, "cannot dereference undefined value", .{}); | |
| 3875 | } | |
| 3876 | } | |
| 3877 | } | |
| 3878 | ||
| 3852 | 3879 | fn failWithBadMemberAccess( |
| 3853 | 3880 | sema: *Sema, |
| 3854 | 3881 | block: *Block, |
src/Zir.zig+6| ... | ... | @@ -729,6 +729,9 @@ pub const Inst = struct { |
| 729 | 729 | /// Same as `validate_array_init` but additionally communicates that the |
| 730 | 730 | /// resulting array initialization value is within a comptime scope. |
| 731 | 731 | validate_array_init_comptime, |
| 732 | /// Check that operand type supports the dereference operand (.*). | |
| 733 | /// Uses the `un_tok` field. | |
| 734 | validate_deref, | |
| 732 | 735 | /// A struct literal with a specified type, with no fields. |
| 733 | 736 | /// Uses the `un_node` field. |
| 734 | 737 | struct_init_empty, |
| ... | ... | @@ -1156,6 +1159,7 @@ pub const Inst = struct { |
| 1156 | 1159 | .validate_struct_init_comptime, |
| 1157 | 1160 | .validate_array_init, |
| 1158 | 1161 | .validate_array_init_comptime, |
| 1162 | .validate_deref, | |
| 1159 | 1163 | .struct_init_empty, |
| 1160 | 1164 | .struct_init, |
| 1161 | 1165 | .struct_init_ref, |
| ... | ... | @@ -1309,6 +1313,7 @@ pub const Inst = struct { |
| 1309 | 1313 | .validate_struct_init_comptime, |
| 1310 | 1314 | .validate_array_init, |
| 1311 | 1315 | .validate_array_init_comptime, |
| 1316 | .validate_deref, | |
| 1312 | 1317 | .@"export", |
| 1313 | 1318 | .export_value, |
| 1314 | 1319 | .set_cold, |
| ... | ... | @@ -1709,6 +1714,7 @@ pub const Inst = struct { |
| 1709 | 1714 | .validate_struct_init_comptime = .pl_node, |
| 1710 | 1715 | .validate_array_init = .pl_node, |
| 1711 | 1716 | .validate_array_init_comptime = .pl_node, |
| 1717 | .validate_deref = .un_tok, | |
| 1712 | 1718 | .struct_init_empty = .un_node, |
| 1713 | 1719 | .field_type = .pl_node, |
| 1714 | 1720 | .field_type_ref = .pl_node, |
src/print_zir.zig+1| ... | ... | @@ -242,6 +242,7 @@ const Writer = struct { |
| 242 | 242 | .ret_tok, |
| 243 | 243 | .ensure_err_payload_void, |
| 244 | 244 | .closure_capture, |
| 245 | .validate_deref, | |
| 245 | 246 | => try self.writeUnTok(stream, inst), |
| 246 | 247 | |
| 247 | 248 | .bool_br_and, |
test/cases/compile_errors/assign_to_invalid_dereference.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | export fn entry() void { | |
| 2 | 'a'.* = 1; | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage2 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // :2:8: error: cannot dereference non-pointer type 'comptime_int' |
test/cases/compile_errors/deref_on_undefined_value.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | comptime { | |
| 2 | var a: *u8 = undefined; | |
| 3 | _ = a.*; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :3:10: error: cannot dereference undefined value |
test/cases/compile_errors/deref_slice_and_get_len_field.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | export fn entry() void { | |
| 2 | var a: []u8 = undefined; | |
| 3 | _ = a.*.len; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :3:10: error: index syntax required for slice type '[]u8' |
test/cases/compile_errors/dereference_an_array.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | var s_buffer: [10]u8 = undefined; | |
| 2 | pub fn pass(in: []u8) []u8 { | |
| 3 | var out = &s_buffer; | |
| 4 | out.*.* = in[0]; | |
| 5 | return out.*[0..1]; | |
| 6 | } | |
| 7 | ||
| 8 | export fn entry() usize { return @sizeOf(@TypeOf(&pass)); } | |
| 9 | ||
| 10 | // error | |
| 11 | // backend=stage2 | |
| 12 | // target=native | |
| 13 | // | |
| 14 | // :4:10: error: cannot dereference non-pointer type '[10]u8' |
test/cases/compile_errors/dereference_slice.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | fn entry(x: []i32) i32 { | |
| 2 | return x.*; | |
| 3 | } | |
| 4 | comptime { | |
| 5 | _ = entry; | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // backend=stage2 | |
| 10 | // target=native | |
| 11 | // | |
| 12 | // :2:13: error: index syntax required for slice type '[]i32' |
test/cases/compile_errors/dereference_unknown_length_pointer.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | export fn entry(x: [*]i32) i32 { | |
| 2 | return x.*; | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage2 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // :2:13: error: index syntax required for unknown-length pointer type '[*]i32' |
test/cases/compile_errors/invalid_deref_on_switch_target.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | comptime { | |
| 2 | var tile = Tile.Empty; | |
| 3 | switch (tile.*) { | |
| 4 | Tile.Empty => {}, | |
| 5 | Tile.Filled => {}, | |
| 6 | } | |
| 7 | } | |
| 8 | const Tile = enum { | |
| 9 | Empty, | |
| 10 | Filled, | |
| 11 | }; | |
| 12 | ||
| 13 | // error | |
| 14 | // backend=stage2 | |
| 15 | // target=native | |
| 16 | // | |
| 17 | // :3:17: error: cannot dereference non-pointer type 'tmp.Tile' |
test/cases/compile_errors/invalid_multiple_dereferences.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | export fn a() void { | |
| 2 | var box = Box{ .field = 0 }; | |
| 3 | box.*.field = 1; | |
| 4 | } | |
| 5 | export fn b() void { | |
| 6 | var box = Box{ .field = 0 }; | |
| 7 | var boxPtr = &box; | |
| 8 | boxPtr.*.*.field = 1; | |
| 9 | } | |
| 10 | pub const Box = struct { | |
| 11 | field: i32, | |
| 12 | }; | |
| 13 | ||
| 14 | // error | |
| 15 | // backend=stage2 | |
| 16 | // target=native | |
| 17 | // | |
| 18 | // :3:8: error: cannot dereference non-pointer type 'tmp.Box' | |
| 19 | // :8:13: error: cannot dereference non-pointer type 'tmp.Box' |
test/cases/compile_errors/stage1/comptime_ptrcast_of_zero-sized_type.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | fn foo() void { | |
| 2 | const node: struct {} = undefined; | |
| 3 | const vla_ptr = @ptrCast([*]const u8, &node); | |
| 4 | _ = vla_ptr; | |
| 5 | } | |
| 6 | comptime { foo(); } | |
| 7 | ||
| 8 | // error | |
| 9 | // backend=stage1 | |
| 10 | // target=native | |
| 11 | // | |
| 12 | // tmp.zig:3:21: error: '*const struct:2:17' and '[*]const u8' do not have the same in-memory representation |
test/cases/compile_errors/stage1/deref_on_undefined_value.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | comptime { | |
| 2 | var a: *u8 = undefined; | |
| 3 | _ = a.*; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // tmp.zig:3:9: error: attempt to dereference undefined value |
test/cases/compile_errors/stage1/obj/assign_to_invalid_dereference.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | 'a'.* = 1; | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage1 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int' |
test/cases/compile_errors/stage1/obj/comptime_ptrcast_of_zero-sized_type.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | fn foo() void { | |
| 2 | const node: struct {} = undefined; | |
| 3 | const vla_ptr = @ptrCast([*]const u8, &node); | |
| 4 | _ = vla_ptr; | |
| 5 | } | |
| 6 | comptime { foo(); } | |
| 7 | ||
| 8 | // error | |
| 9 | // backend=stage1 | |
| 10 | // target=native | |
| 11 | // | |
| 12 | // tmp.zig:3:21: error: '*const struct:2:17' and '[*]const u8' do not have the same in-memory representation |
test/cases/compile_errors/stage1/obj/deref_slice_and_get_len_field.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | var a: []u8 = undefined; | |
| 3 | _ = a.*.len; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // tmp.zig:3:10: error: attempt to dereference non-pointer type '[]u8' |
test/cases/compile_errors/stage1/obj/dereference_an_array.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | var s_buffer: [10]u8 = undefined; | |
| 2 | pub fn pass(in: []u8) []u8 { | |
| 3 | var out = &s_buffer; | |
| 4 | out.*.* = in[0]; | |
| 5 | return out.*[0..1]; | |
| 6 | } | |
| 7 | ||
| 8 | export fn entry() usize { return @sizeOf(@TypeOf(pass)); } | |
| 9 | ||
| 10 | // error | |
| 11 | // backend=stage1 | |
| 12 | // target=native | |
| 13 | // | |
| 14 | // tmp.zig:4:10: error: attempt to dereference non-pointer type '[10]u8' |
test/cases/compile_errors/stage1/obj/dereference_unknown_length_pointer.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | export fn entry(x: [*]i32) i32 { | |
| 2 | return x.*; | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage1 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // tmp.zig:2:13: error: index syntax required for unknown-length pointer type '[*]i32' |
test/cases/compile_errors/stage1/obj/invalid_deref_on_switch_target.zig deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | comptime { | |
| 2 | var tile = Tile.Empty; | |
| 3 | switch (tile.*) { | |
| 4 | Tile.Empty => {}, | |
| 5 | Tile.Filled => {}, | |
| 6 | } | |
| 7 | } | |
| 8 | const Tile = enum { | |
| 9 | Empty, | |
| 10 | Filled, | |
| 11 | }; | |
| 12 | ||
| 13 | // error | |
| 14 | // backend=stage1 | |
| 15 | // target=native | |
| 16 | // | |
| 17 | // tmp.zig:3:17: error: attempt to dereference non-pointer type 'Tile' |
test/cases/compile_errors/stage1/obj/invalid_multiple_dereferences.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | export fn a() void { | |
| 2 | var box = Box{ .field = 0 }; | |
| 3 | box.*.field = 1; | |
| 4 | } | |
| 5 | export fn b() void { | |
| 6 | var box = Box{ .field = 0 }; | |
| 7 | var boxPtr = &box; | |
| 8 | boxPtr.*.*.field = 1; | |
| 9 | } | |
| 10 | pub const Box = struct { | |
| 11 | field: i32, | |
| 12 | }; | |
| 13 | ||
| 14 | // error | |
| 15 | // backend=stage1 | |
| 16 | // target=native | |
| 17 | // | |
| 18 | // tmp.zig:3:8: error: attempt to dereference non-pointer type 'Box' | |
| 19 | // tmp.zig:8:13: error: attempt to dereference non-pointer type 'Box' |
test/cases/compile_errors/stage1/obj/take_slice_of_invalid_dereference.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | const x = 'a'.*[0..]; | |
| 3 | _ = x; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int' |
test/cases/compile_errors/take_slice_of_invalid_dereference.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | export fn entry() void { | |
| 2 | const x = 'a'.*[0..]; | |
| 3 | _ = x; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :2:18: error: cannot dereference non-pointer type 'comptime_int' |