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.
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.
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.
Most helpful comment
There's a similar example, where a bitwise "OR" operator has a lower priority:
Expected output:
Actual output:
The same story with bitwise "XOR" operator.