authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-28 17:13:43+03:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-30 09:57:38+02:00
log2e7dc5e15192431c64eca458ecfdce3d07b89f69
treeabaf49ad2840c5ac799105e79dd0b536daed30ba
parent03b356e34af37d74cf92087c0303a1b2c74d3afc

Sema: improve vector overflow errors


5 files changed, 62 insertions(+), 46 deletions(-)

src/Sema.zig+35-17
......@@ -139,6 +139,7 @@ pub const Block = struct {
139139
140140 is_comptime: bool,
141141 is_typeof: bool = false,
142 is_coerce_result_ptr: bool = false,
142143
143144 /// when null, it is determined by build mode, changed by @setRuntimeSafety
144145 want_safety: ?bool = null,
......@@ -1734,9 +1735,20 @@ fn failWithErrorSetCodeMissing(
17341735 });
17351736}
17361737
1737fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value) CompileError {
1738fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: usize) CompileError {
1739 if (int_ty.zigTypeTag() == .Vector) {
1740 const msg = msg: {
1741 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{
1742 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),
1743 });
1744 errdefer msg.destroy(sema.gpa);
1745 try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index});
1746 break :msg msg;
1747 };
1748 return sema.failWithOwnedErrorMsg(block, msg);
1749 }
17381750 return sema.fail(block, src, "overflow of integer type '{}' with value '{}'", .{
1739 int_ty.fmt(sema.mod), val.fmtValue(Type.@"comptime_int", sema.mod),
1751 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),
17401752 });
17411753}
17421754
......@@ -1971,6 +1983,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
19711983 // kind of transformations to make on the result pointer.
19721984 var trash_block = block.makeSubBlock();
19731985 trash_block.is_comptime = false;
1986 trash_block.is_coerce_result_ptr = true;
19741987 defer trash_block.instructions.deinit(sema.gpa);
19751988
19761989 const dummy_ptr = try trash_block.addTy(.alloc, sema.typeOf(ptr));
......@@ -10453,8 +10466,9 @@ fn analyzeArithmetic(
1045310466 if (maybe_rhs_val) |rhs_val| {
1045410467 if (is_int) {
1045510468 const sum = try sema.intAdd(block, src, lhs_val, rhs_val, resolved_type);
10456 if (!(try sema.intFitsInType(block, src, sum, resolved_type))) {
10457 return sema.failWithIntegerOverflow(block, src, resolved_type, sum);
10469 var vector_index: usize = undefined;
10470 if (!(try sema.intFitsInType(block, src, sum, resolved_type, &vector_index))) {
10471 return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vector_index);
1045810472 }
1045910473 return sema.addConstant(resolved_type, sum);
1046010474 } else {
......@@ -10547,8 +10561,9 @@ fn analyzeArithmetic(
1054710561 if (maybe_rhs_val) |rhs_val| {
1054810562 if (is_int) {
1054910563 const diff = try sema.intSub(block, src, lhs_val, rhs_val, resolved_type);
10550 if (!(try sema.intFitsInType(block, src, diff, resolved_type))) {
10551 return sema.failWithIntegerOverflow(block, src, resolved_type, diff);
10564 var vector_index: usize = undefined;
10565 if (!(try sema.intFitsInType(block, src, diff, resolved_type, &vector_index))) {
10566 return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vector_index);
1055210567 }
1055310568 return sema.addConstant(resolved_type, diff);
1055410569 } else {
......@@ -10921,8 +10936,9 @@ fn analyzeArithmetic(
1092110936 }
1092210937 if (is_int) {
1092310938 const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, target);
10924 if (!(try sema.intFitsInType(block, src, product, resolved_type))) {
10925 return sema.failWithIntegerOverflow(block, src, resolved_type, product);
10939 var vector_index: usize = undefined;
10940 if (!(try sema.intFitsInType(block, src, product, resolved_type, &vector_index))) {
10941 return sema.failWithIntegerOverflow(block, src, resolved_type, product, vector_index);
1092610942 }
1092710943 return sema.addConstant(resolved_type, product);
1092810944 } else {
......@@ -16456,15 +16472,15 @@ fn analyzeShuffle(
1645616472 }
1645716473 if (unsigned >= operand_info[chosen][0]) {
1645816474 const msg = msg: {
16459 const msg = try sema.errMsg(block, mask_src, "mask index {d} has out-of-bounds selection", .{i});
16475 const msg = try sema.errMsg(block, mask_src, "mask index '{d}' has out-of-bounds selection", .{i});
1646016476 errdefer msg.destroy(sema.gpa);
1646116477
16462 try sema.errNote(block, operand_info[chosen][1], msg, "selected index {d} out of bounds of '{}'", .{
16478 try sema.errNote(block, operand_info[chosen][1], msg, "selected index '{d}' out of bounds of '{}'", .{
1646316479 unsigned,
1646416480 operand_info[chosen][2].fmt(sema.mod),
1646516481 });
1646616482
16467 if (chosen == 1) {
16483 if (chosen == 0) {
1646816484 try sema.errNote(block, b_src, msg, "selections from the second vector are specified with negative numbers", .{});
1646916485 }
1647016486
......@@ -17750,7 +17766,7 @@ fn zirBuiltinExtern(
1775017766}
1775117767
1775217768fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
17753 if (sema.func == null and !block.is_typeof) {
17769 if (sema.func == null and !block.is_typeof and !block.is_coerce_result_ptr) {
1775417770 return sema.fail(block, src, "instruction illegal outside function body", .{});
1775517771 }
1775617772}
......@@ -19881,7 +19897,7 @@ fn coerce(
1988119897 .Int, .ComptimeInt => {
1988219898 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
1988319899 // comptime known integer to other number
19884 if (!(try sema.intFitsInType(block, inst_src, val, dest_ty))) {
19900 if (!(try sema.intFitsInType(block, inst_src, val, dest_ty, null))) {
1988519901 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });
1988619902 }
1988719903 return try sema.addConstant(dest_ty, val);
......@@ -25829,7 +25845,7 @@ fn floatToIntScalar(
2582925845 else
2583025846 try Value.Tag.int_big_positive.create(sema.arena, result_limbs);
2583125847
25832 if (!(try sema.intFitsInType(block, src, result, int_ty))) {
25848 if (!(try sema.intFitsInType(block, src, result, int_ty, null))) {
2583325849 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
2583425850 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),
2583525851 });
......@@ -25845,6 +25861,7 @@ fn intFitsInType(
2584525861 src: LazySrcLoc,
2584625862 self: Value,
2584725863 ty: Type,
25864 vector_index: ?*usize,
2584825865) CompileError!bool {
2584925866 const target = sema.mod.getTarget();
2585025867 switch (self.tag()) {
......@@ -25954,8 +25971,9 @@ fn intFitsInType(
2595425971
2595525972 .aggregate => {
2595625973 assert(ty.zigTypeTag() == .Vector);
25957 for (self.castTag(.aggregate).?.data) |elem| {
25958 if (!(try sema.intFitsInType(block, src, elem, ty.scalarType()))) {
25974 for (self.castTag(.aggregate).?.data) |elem, i| {
25975 if (!(try sema.intFitsInType(block, src, elem, ty.scalarType(), null))) {
25976 if (vector_index) |some| some.* = i;
2595925977 return false;
2596025978 }
2596125979 }
......@@ -25993,7 +26011,7 @@ fn enumHasInt(
2599326011 int: Value,
2599426012) CompileError!bool {
2599526013 switch (ty.tag()) {
25996 .enum_nonexhaustive => return sema.intFitsInType(block, src, int, ty),
26014 .enum_nonexhaustive => return sema.intFitsInType(block, src, int, ty, null),
2599726015 .enum_full => {
2599826016 const enum_full = ty.castTag(.enum_full).?.data;
2599926017 const tag_ty = enum_full.tag_ty;
test/cases/compile_errors/comptime_vector_overflow_shows_the_index.zig created+13
......@@ -0,0 +1,13 @@
1comptime {
2 var a: @import("std").meta.Vector(4, u8) = [_]u8{ 1, 2, 255, 4 };
3 var b: @import("std").meta.Vector(4, u8) = [_]u8{ 5, 6, 1, 8 };
4 var x = a + b;
5 _ = x;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :4:15: error: overflow of vector type '@Vector(4, u8)' with value '.{ 6, 8, 256, 12 }'
13// :4:15: note: when computing vector element at index '2'
test/cases/compile_errors/shuffle_with_selected_index_past_first_vector_length.zig created+14
......@@ -0,0 +1,14 @@
1export fn entry() void {
2 const v: @import("std").meta.Vector(4, u32) = [4]u32{ 10, 11, 12, 13 };
3 const x: @import("std").meta.Vector(4, u32) = [4]u32{ 14, 15, 16, 17 };
4 var z = @shuffle(u32, v, x, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 });
5 _ = z;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :4:39: error: mask index '4' has out-of-bounds selection
13// :4:27: note: selected index '7' out of bounds of '@Vector(4, u32)'
14// :4:30: note: selections from the second vector are specified with negative numbers
test/cases/compile_errors/stage1/test/comptime_vector_overflow_shows_the_index.zig deleted-14
......@@ -1,14 +0,0 @@
1comptime {
2 var a: @import("std").meta.Vector(4, u8) = [_]u8{ 1, 2, 255, 4 };
3 var b: @import("std").meta.Vector(4, u8) = [_]u8{ 5, 6, 1, 8 };
4 var x = a + b;
5 _ = x;
6}
7
8// error
9// backend=stage1
10// target=native
11// is_test=1
12//
13// tmp.zig:4:15: error: operation caused overflow
14// tmp.zig:4:15: note: when computing vector element at index 2
test/cases/compile_errors/stage1/test/shuffle_with_selected_index_past_first_vector_length.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 const v: @import("std").meta.Vector(4, u32) = [4]u32{ 10, 11, 12, 13 };
3 const x: @import("std").meta.Vector(4, u32) = [4]u32{ 14, 15, 16, 17 };
4 var z = @shuffle(u32, v, x, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 });
5 _ = z;
6}
7
8// error
9// backend=stage1
10// target=native
11// is_test=1
12//
13// tmp.zig:4:39: error: mask index '4' has out-of-bounds selection
14// tmp.zig:4:27: note: selected index '7' out of bounds of @Vector(4, u32)
15// tmp.zig:4:30: note: selections from the second vector are specified with negative numbers