RFR: 8280067: Incorrect code generated for unary - on char operand

Vicente Romero vromero at openjdk.java.net
Thu Jan 20 17:12:48 UTC 2022


On Thu, 20 Jan 2022 12:31:57 GMT, Jan Lahoda <jlahoda at openjdk.org> wrote:

> Consider the following snippet of code:
> 
> Character var = (char) -(false ? (char) param : (char) 2);
> 
> 
> The `javac` frontend will not put a constant type on `false ? (char) param : (char) 2` (i.e. it will not constant-fold `(char) 2` to the whole conditional expression). This seems correct, as this is not (I think) a constant expression. But then, in the code generator:
> -`Gen.visitUnary` is called, which requests to evaluate the argument, specifying the type should be `int`.
> -when the argument (i.e. `false ? (char) param : (char) 2`) is evaluted, it produces an `ImmediateItem` with the constant, of type `char`, skipping the "then" expression, as that is never reached
> -then the type of the `Item` is converted using `coerce` to the desired type (`int`). But in `ImmediateItem.coerce`, `char` is considered to be "equivalent" to `int`, and no conversion happens, and the same (`char`) `ImmediateItem` is returned
> -`Gen.visitUnary` will push the constant  the stack and will produce the `ineg` instruction, but will (effectively) use the type of the parameter's `Item` for its result
> -so the outermost `char` cast is a no-op, because the stack's top is considered to be `char` - but that is not correct, because `char` is unsigned, and the actual value at the top of the stack is `-2`.
> 
> This can then lead to various wrong behavior, including an exception from `Character.valueOf(char)`.
> 
> The proposal is to produce an `Item` with the correct type (i.e. `int`) in `ImmediateItem.coerce` for `char`-typed `ImmediateItem`s. `Item`s of type `byte`/`short` are kept as they are, even though it is not clear to me if simply producing an `int`-typed `Item` would not work equally well. But returning an `Item` with type `char` when `int` is requested seems wrong due to the unsigned property of `char`.

I'm seeing that Lower is reducing the conditional to `(char)(char)2` at `Lower::visitConditional` could it be that the type is wrongly set to `int` somewhere before reaching to `Gen`?

-------------

PR: https://git.openjdk.java.net/jdk/pull/7156


More information about the compiler-dev mailing list