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

Jan Lahoda jlahoda at openjdk.java.net
Thu Jan 20 12:42:14 UTC 2022


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`.

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

Commit messages:
 - 8280067: Incorrect code generated for unary - on char operand

Changes: https://git.openjdk.java.net/jdk/pull/7156/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=7156&range=00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8280067
  Stats: 187 lines in 2 files changed: 185 ins; 0 del; 2 mod
  Patch: https://git.openjdk.java.net/jdk/pull/7156.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/7156/head:pull/7156

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


More information about the compiler-dev mailing list