Sema: cast negative to unsigned safety
This commit is contained in:
@@ -8092,6 +8092,7 @@ fn intCast(
|
||||
const is_in_range = try block.addBinOp(.cmp_lte, diff_unsigned, dest_range);
|
||||
break :ok is_in_range;
|
||||
};
|
||||
// TODO negative_to_unsigned?
|
||||
try sema.addSafetyCheck(block, ok, .cast_truncated_data);
|
||||
} else {
|
||||
const ok = if (is_vector) ok: {
|
||||
@@ -8116,7 +8117,7 @@ fn intCast(
|
||||
const ok = if (is_vector) ok: {
|
||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
||||
const zero_inst = try sema.addConstant(operand_ty, zero_val);
|
||||
const is_in_range = try block.addCmpVector(operand, zero_inst, .lte, try sema.addType(operand_ty));
|
||||
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
|
||||
const all_in_range = try block.addInst(.{
|
||||
.tag = .reduce,
|
||||
.data = .{ .reduce = .{
|
||||
@@ -8130,7 +8131,7 @@ fn intCast(
|
||||
const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);
|
||||
break :ok is_in_range;
|
||||
};
|
||||
try sema.addSafetyCheck(block, ok, .cast_truncated_data);
|
||||
try sema.addSafetyCheck(block, ok, .negative_to_unsigned);
|
||||
}
|
||||
}
|
||||
return block.addTyOp(.intcast, dest_ty, operand);
|
||||
@@ -18849,6 +18850,7 @@ pub const PanicId = enum {
|
||||
incorrect_alignment,
|
||||
invalid_error_code,
|
||||
cast_truncated_data,
|
||||
negative_to_unsigned,
|
||||
integer_overflow,
|
||||
shl_overflow,
|
||||
shr_overflow,
|
||||
@@ -19069,6 +19071,7 @@ fn safetyPanic(
|
||||
.incorrect_alignment => "incorrect alignment",
|
||||
.invalid_error_code => "invalid error code",
|
||||
.cast_truncated_data => "integer cast truncated bits",
|
||||
.negative_to_unsigned => "attempt to cast negative value to unsigned integer",
|
||||
.integer_overflow => "integer overflow",
|
||||
.shl_overflow => "left shift overflowed bits",
|
||||
.shr_overflow => "right shift overflowed bits",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
|
||||
std.process.exit(0);
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
pub fn main() !void {
|
||||
var value: c_short = -1;
|
||||
@@ -12,5 +14,5 @@ pub fn main() !void {
|
||||
return error.TestFailed;
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// backend=llvm
|
||||
// target=native
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
|
||||
std.process.exit(0);
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
const x = unsigned_cast(-10);
|
||||
if (x == 0) return error.Whatever;
|
||||
@@ -15,5 +16,5 @@ fn unsigned_cast(x: i32) u32 {
|
||||
return @intCast(u32, x);
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// backend=llvm
|
||||
// target=native
|
||||
|
||||
@@ -16,5 +16,5 @@ pub fn main() !void {
|
||||
}
|
||||
|
||||
// run
|
||||
// backend=stage1
|
||||
// backend=llvm
|
||||
// target=native
|
||||
|
||||
Reference in New Issue
Block a user