AnyDSL/impala

Constant expression for smallest i32 emits undef

ergawy opened this issue · 2 comments

The following code:

extern "C" {
    fn print_int(i32) -> ();
}

fn main() -> i32 {
    let test : i32 = 1 << 31;
    print_int(test);

    0
}

emits test value as undef while it should be the smallest i32 value.

Currently, we follow the C-standard in terms of what is considered undefined and what not. The C-Standard says to E1 << E2:

If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

But 2^31 is not representable in i32, hence the behavior is undefined and the behavior of the compiler is correct.

However, that being said, I checked what clang does. Doing things like 1 << 31 seems to be such a common pattern that clang has the mercy to simply do what you would expect. We have three options:

  1. Stick to the C-Standard and leave everything as it is.
  2. Do what clang (and others) are doing.
  3. Do sth completely different.

After discussion with Richard we are likely doing option 2). In the long run, however, I'd like bake this into the type system...

For the moment, we decided for option 2, but in the long run we would like to track the wrap-around property in the type.