From e6270b05dcf0006867102e7b2a24f0a37a2b27b5 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 7 Mar 2022 16:26:40 +0800 Subject: [PATCH] checker: check unsigned integer compared with negative value (#13670) --- vlib/v/checker/checker.v | 22 +++++++++++++++++++ .../infix_unsigned_and_signed_int_err.out | 13 +++++++++++ .../infix_unsigned_and_signed_int_err.vv | 9 ++++++++ 3 files changed, 44 insertions(+) create mode 100644 vlib/v/checker/tests/infix_unsigned_and_signed_int_err.out create mode 100644 vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index de16370255..f8cb824020 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -819,6 +819,28 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } else if need_overload && !gen_sym.has_method('<') && node.op == .gt { c.error('cannot use `>` as `<=` operator method is not defined', left_right_pos) } + } else if left_type in ast.integer_type_idxs && right_type in ast.integer_type_idxs { + is_left_type_signed := left_type in ast.signed_integer_type_idxs + || left_type == ast.int_literal_type_idx + is_right_type_signed := right_type in ast.signed_integer_type_idxs + || right_type == ast.int_literal_type_idx + if is_left_type_signed != is_right_type_signed { + if is_right_type_signed { + if mut node.right is ast.IntegerLiteral { + if node.right.val.int() < 0 { + c.error('unsigned integer cannot be compared with negative value', + node.right.pos) + } + } + } else if is_left_type_signed { + if mut node.left is ast.IntegerLiteral { + if node.left.val.int() < 0 { + c.error('unsigned integer cannot be compared with negative value', + node.left.pos) + } + } + } + } } } .left_shift { diff --git a/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.out b/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.out new file mode 100644 index 0000000000..1895d686ff --- /dev/null +++ b/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.out @@ -0,0 +1,13 @@ +vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv:2:14: error: unsigned integer cannot be compared with negative value + 1 | fn main() { + 2 | if u32(1) < -1 { + | ~~ + 3 | println('unexpected') + 4 | } +vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv:6:5: error: unsigned integer cannot be compared with negative value + 4 | } + 5 | + 6 | if -1 > u32(1) { + | ~~ + 7 | println('unexpected') + 8 | } diff --git a/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv b/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv new file mode 100644 index 0000000000..e3404eb33a --- /dev/null +++ b/vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv @@ -0,0 +1,9 @@ +fn main() { + if u32(1) < -1 { + println('unexpected') + } + + if -1 > u32(1) { + println('unexpected') + } +}