From 54635185c4e308722ad50b40534a1dddc8797c3d Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 8 Jul 2023 07:02:32 +0300 Subject: [PATCH] cgen: ensure that `<<` and `>>` has higher precedence in the generated C code, than arithmetic operations (diff between C and V precedences) (#18814) --- vlib/v/gen/c/infix.v | 11 +++++++++++ vlib/v/tests/shift_test.v | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 2bf4d5320e..0d74b77a94 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -35,8 +35,17 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { g.infix_expr_arithmetic_op(node) } .left_shift { + // `a << b` can mean many things in V ... + // TODO: disambiguate everything in the checker; cgen should not decide all this. + // Instead it should be as simple, as the branch for .right_shift is. + // `array << val` should have its own separate operation internally. g.infix_expr_left_shift_op(node) } + .right_shift { + g.write('(') + g.gen_plain_infix_expr(node) + g.write(')') + } .and, .logical_or { g.infix_expr_and_or_op(node) } @@ -846,7 +855,9 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { } } } else { + g.write('(') g.gen_plain_infix_expr(node) + g.write(')') } } diff --git a/vlib/v/tests/shift_test.v b/vlib/v/tests/shift_test.v index 69e6694428..29193a510e 100644 --- a/vlib/v/tests/shift_test.v +++ b/vlib/v/tests/shift_test.v @@ -1,5 +1,21 @@ type MyInt = int +fn test_shift_left_precedence() { + x := u32(20) + base := u32(1) + shift := u32(3) + assert x + base << shift == (x + (base << shift)), '<< should have higher precedence than +' + assert x - base << shift == (x - (base << shift)), '<< should have higher precedence than -' +} + +fn test_shift_right_precedence() { + x := u32(20) + base := u32(100) + shift := u32(2) + assert x + base >> shift == (x + (base >> shift)), '>> should have higher precedence than +' + assert x - base >> shift == (x - (base >> shift)), '>> should have higher precedence than -' +} + fn test_shift_operators() { // check that shift works with all integer types // as the right-hand side operand