Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit b2a78b3

Browse files
committed
Fix aliasing / nullness of CHECKCAST
1 parent a112422 commit b2a78b3

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,8 @@ object InstructionStackEffect {
249249

250250
case ATHROW => t(1, 0) // Frame.execute consumes one stack value
251251

252-
case CHECKCAST => t(0, 0)
253-
254-
case INSTANCEOF => t(1, 1)
252+
case CHECKCAST |
253+
INSTANCEOF => t(1, 1) // Frame.execute does push(pop()) for both of them
255254

256255
case MONITORENTER |
257256
MONITOREXIT => t(1, 0)

src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ final class NullnessInterpreter extends Interpreter[NullnessValue](Opcodes.ASM5)
179179
def copyOperation(insn: AbstractInsnNode, value: NullnessValue): NullnessValue = value
180180

181181
def unaryOperation(insn: AbstractInsnNode, value: NullnessValue): NullnessValue = (insn.getOpcode: @switch) match {
182+
case Opcodes.CHECKCAST => value
183+
182184
case Opcodes.NEWARRAY |
183185
Opcodes.ANEWARRAY => NullnessValue(NotNull, isSize2 = false)
184186

test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,30 @@ class NullnessAnalyzerTest extends ClearAfterClass {
202202
(end, 5, Null) // d, no change
203203
)) testNullness(a, m, insn, index, nullness)
204204
}
205+
206+
@Test
207+
def testInstanceOf(): Unit = {
208+
val code =
209+
"""def f(a: Object) = {
210+
| val x = a
211+
| x.isInstanceOf[Throwable] // x and a remain unknown - INSTANCEOF doesn't throw a NPE on null
212+
| x.toString // x and a are not null
213+
| a.asInstanceOf[String].trim // the stack value (LOAD of local a) is still not-null after the CHECKCAST
214+
|}
215+
""".stripMargin
216+
val List(m) = compileMethods(noOptCompiler)(code)
217+
val a = newNullnessAnalyzer(m)
218+
219+
val instof = "+INSTANCEOF"
220+
val tost = "+INVOKEVIRTUAL java/lang/Object.toString"
221+
val trim = "INVOKEVIRTUAL java/lang/String.trim"
222+
223+
for ((insn, index, nullness) <- List(
224+
(instof, 1, Unknown), // a after INSTANCEOF
225+
(instof, 2, Unknown), // x after INSTANCEOF
226+
(tost, 1, NotNull),
227+
(tost, 2, NotNull),
228+
(trim, 3, NotNull) // receiver at `trim`
229+
)) testNullness(a, m, insn, index, nullness)
230+
}
205231
}

0 commit comments

Comments
 (0)