Fix KNPE caused by optimizations in control-flow analysis
The problem is that when performing full analysis we do it in a backward order while result for trivial vals is filled in a forward one. It turns out that reversedInstuctions might return a superset of forward traversed instructions, e.g. in case of dead code in lambda. At the same time result for trivial vals is constant for any instruction, thus we can just return its constant value and use it in the full analysis #KT-20895 Fixed
This commit is contained in:
@@ -294,8 +294,14 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
||||
|
||||
val variableUseStatusData: Map<Instruction, Edges<ReadOnlyUseControlFlowInfo>>
|
||||
get() {
|
||||
val resultForTrivialVals = computeUseInfoForTrivialVals()
|
||||
if (rootVariables.nonTrivialVariables.isEmpty()) return resultForTrivialVals
|
||||
val edgesForTrivialVals = computeUseInfoForTrivialVals()
|
||||
if (rootVariables.nonTrivialVariables.isEmpty()) {
|
||||
return hashMapOf<Instruction, Edges<ReadOnlyUseControlFlowInfo>>().apply {
|
||||
pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
||||
put(instruction, edgesForTrivialVals)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pseudocodeVariableDataCollector.collectData(TraversalOrder.BACKWARD, UseControlFlowInfo()) { instruction: Instruction, incomingEdgesData: Collection<UseControlFlowInfo> ->
|
||||
|
||||
@@ -336,17 +342,16 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
||||
Edges(enterResult, exitResult)
|
||||
}
|
||||
}.mapValues {
|
||||
(instruction, edges) ->
|
||||
val edgeForTrivialVals = resultForTrivialVals[instruction]!!
|
||||
(_, edges) ->
|
||||
|
||||
Edges(
|
||||
edgeForTrivialVals.incoming.replaceDelegate(edges.incoming),
|
||||
edgeForTrivialVals.outgoing.replaceDelegate(edges.outgoing)
|
||||
edgesForTrivialVals.incoming.replaceDelegate(edges.incoming),
|
||||
edgesForTrivialVals.outgoing.replaceDelegate(edges.outgoing)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeUseInfoForTrivialVals(): Map<Instruction, Edges<ReadOnlyUseControlFlowInfoImpl>> {
|
||||
private fun computeUseInfoForTrivialVals(): Edges<ReadOnlyUseControlFlowInfoImpl> {
|
||||
val used = hashSetOf<VariableDescriptor>()
|
||||
|
||||
pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
||||
@@ -358,13 +363,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
||||
}
|
||||
|
||||
val constantUseInfo = ReadOnlyUseControlFlowInfoImpl(used, null)
|
||||
val constantEdges = Edges(constantUseInfo, constantUseInfo)
|
||||
val result = hashMapOf<Instruction, Edges<ReadOnlyUseControlFlowInfoImpl>>()
|
||||
|
||||
pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
||||
result[instruction] = constantEdges
|
||||
}
|
||||
return result
|
||||
return Edges(constantUseInfo, constantUseInfo)
|
||||
}
|
||||
|
||||
private fun extractValWithTrivialInitializer(instruction: Instruction): VariableDescriptor? {
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
|
||||
inline fun myRun(b: () -> Unit) = b()
|
||||
|
||||
fun foo() {
|
||||
var <!UNUSED_VARIABLE!>a<!>: Int
|
||||
return
|
||||
|
||||
<!UNREACHABLE_CODE!>myRun {
|
||||
return
|
||||
}<!>
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
public inline fun myRun(/*0*/ b: () -> kotlin.Unit): kotlin.Unit
|
||||
@@ -4397,6 +4397,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("returnInDeadLambda.kt")
|
||||
public void testReturnInDeadLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/returnInDeadLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturn")
|
||||
|
||||
+6
@@ -4397,6 +4397,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("returnInDeadLambda.kt")
|
||||
public void testReturnInDeadLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/returnInDeadLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturn")
|
||||
|
||||
Reference in New Issue
Block a user