V: Incorrect operator precedence in if statement

Created on 8 Jan 2020  路  7Comments  路  Source: vlang/v

V version:
V 0.1.24 c1cc203
OS:
Ubuntu 18.04

What did you do?

fn main() {

    a := 2
    b := 2
    c := a & b
    println(c)
    if a & b > 0 { println("OK") } else {println("ERROR")}
} 

What did you expect to see?

2
OK
 ```
**What did you see instead?**

2
ERROR

**Workaround**
```v
if (a & b) > 0 { println("OK") } else {println("ERROR")}

NOTE
Very strange that using values with bit 0 different from 1 cause the bug (just to be clear: every even number)
My guess is that the condition of the if a & b is tested only against the first bit instead using all the bit of value.
Probably somewhere the compiler believe that a & b is of bool type.

Bug Confirmed

Most helpful comment

There's a similar example, where a bitwise "OR" operator has a lower priority:

fn main() {
    a := 1
    b := 2

    println(a | b)
    println((a | b) > 4)
    println(a | b > 4)

    if a | b > 4 {
        println("Should not be visible")
    } else {
        println("Should be visible")
    }
}

Expected output:

3
false
true
Should be visible

Actual output:

3
false
true
Should not be visible

The same story with bitwise "XOR" operator.

All 7 comments

There's a similar example, where a bitwise "OR" operator has a lower priority:

fn main() {
    a := 1
    b := 2

    println(a | b)
    println((a | b) > 4)
    println(a | b > 4)

    if a | b > 4 {
        println("Should not be visible")
    } else {
        println("Should be visible")
    }
}

Expected output:

3
false
true
Should be visible

Actual output:

3
false
true
Should not be visible

The same story with bitwise "XOR" operator.

Might be the lack of operator precedence in the compiler (no AST or IR). What could be happening is the result of how C handles booleans: there aren't any, only integers. 0 is false and anything else is true. Conditions generally evaluate to 1 (true) or 0 (false). If this is the case, it would make the generated code evaluate as such:

@penguindark a & b > 0 -> 2 & 2 > 0 -> 2 & (2 > 0) -> 2 & (true) -> 2 & 1 -> 0 -> false

@alexesprit a | b > 4 -> 1 | 2 > 4 -> 1 | (2 > 4) -> 1 | (false) -> 1 | 0 -> 1 -> true

I'm thinking that during check of boolean conditions, the compiler only test bit number 0.
This can explain why the bug is present only in even numbers.

I'm thinking that during check of boolean conditions, the compiler only test bit number 0.
This can explain why the bug is present only in even numbers.

Currently the compiler forces precendence of bitwise AND in case when it's compared using equality operators. Other cases are not processed.

https://github.com/vlang/v/blob/f7f5f43c4827aba166b94c2cd4d96c60eb79dac3/vlib/compiler/expression.v#L631-L647

It can be extended to cover other cases:

// Force higher precendence of bitwise operators
is_bitwise_op := tok_op in [.pipe, .amp, .xor]
open := is_bitwise_op && p.tok in [.eq, .gt, .lt, .le, .ge, .ne]

I wrote a test file to check if operator precendence is correct:


bitwise_precendence_test.v (Click to expand)

fn test_and() {
    assert (2 & 0 == 0) == ((2 & 0) == 0)
    assert (2 & 0 != 0) == ((2 & 0) != 0)
    assert (0 & 0 >= 0) == ((0 & 0) >= 0)
    assert (0 & 0 <= 0) == ((0 & 0) <= 0)
    assert (0 & 0 < 1) == ((0 & 0) < 1)
    assert (1 & 2 > 0) == ((1 & 2) > 0)
}

fn test_or() {
    assert (1 | 0 == 0) == ((1 | 0) == 0)
    assert (1 | 0 != 1) == ((1 | 0) != 1)
    assert (1 | 0 >= 2) == ((1 | 0) >= 2)
    assert (1 | 0 <= 0) == ((1 | 0) <= 0)
    assert (1 | 0 < 0) == ((1 | 0) < 0)
    assert (1 | 0 > 1) == ((1 | 0) > 1)
}

fn test_xor() {
    assert (1 ^ 0 == 2) == ((1 ^ 0) == 2)
    assert (1 ^ 0 != 2) == ((1 ^ 0) != 2)
    assert (1 ^ 0 >= 0) == ((1 ^ 0) >= 0)
    assert (1 ^ 0 <= 1) == ((1 ^ 0) <= 1)
    assert (1 ^ 0 < 0) == ((1 ^ 0) < 0)
    assert (1 ^ 0 > 1) == ((1 ^ 0) > 1)
}

Currently, this test is not passed, but it's passed with changes applied.

This will be fixed in the new AST based parser.

ok, I'll wait, meanwhile I'll use bracket for sure in the ifs ;)

Fixed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

taojy123 picture taojy123  路  3Comments

vtereshkov picture vtereshkov  路  3Comments

aurora picture aurora  路  3Comments

clpo13 picture clpo13  路  3Comments

choleraehyq picture choleraehyq  路  3Comments