Control-Flow Analysis: Do not skip pseudocode for value arguments if they are matched with errors
This commit is contained in:
@@ -459,9 +459,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
|||||||
val rhsArgument = valueArguments.lastOrNull()
|
val rhsArgument = valueArguments.lastOrNull()
|
||||||
var argumentValues = SmartFMap.emptyMap<PseudoValue, ValueParameterDescriptor>()
|
var argumentValues = SmartFMap.emptyMap<PseudoValue, ValueParameterDescriptor>()
|
||||||
for (valueArgument in valueArguments) {
|
for (valueArgument in valueArguments) {
|
||||||
val argumentMapping = setResolvedCall.getArgumentMapping(valueArgument)
|
val argumentMapping = setResolvedCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: continue
|
||||||
if (argumentMapping.isError() || argumentMapping !is ArgumentMatch) continue
|
|
||||||
|
|
||||||
val parameterDescriptor = argumentMapping.valueParameter
|
val parameterDescriptor = argumentMapping.valueParameter
|
||||||
if (valueArgument !== rhsArgument) {
|
if (valueArgument !== rhsArgument) {
|
||||||
argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues)
|
argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues)
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
== A ==
|
||||||
|
class A
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== set ==
|
||||||
|
fun A.set(n: Int, m: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(n: Int)
|
||||||
|
magic[FAKE_INITIALIZER](n: Int) -> <v0>
|
||||||
|
w(n|<v0>)
|
||||||
|
v(m: Int)
|
||||||
|
magic[FAKE_INITIALIZER](m: Int) -> <v1>
|
||||||
|
w(m|<v1>)
|
||||||
|
2 mark({ })
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
A()["1"] = 2
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({ A()["1"] = 2 })
|
||||||
|
mark(A()["1"])
|
||||||
|
mark(A())
|
||||||
|
call(A(), <init>) -> <v0>
|
||||||
|
mark("1")
|
||||||
|
r("1") -> <v1>
|
||||||
|
r(2) -> <v2>
|
||||||
|
call(A()["1"] = 2, set|<v0>, <v1>, <v2>) -> <v3>
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
fun A.set(n: Int, m: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A()["1"] = 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
== A ==
|
||||||
|
class A
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== set ==
|
||||||
|
fun A.set(n: Int, m: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](n: Int) -> <v0>
|
||||||
|
<v1>: Int NEW: magic[FAKE_INITIALIZER](m: Int) -> <v1>
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
A()["1"] = 2
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
A() <v0>: A NEW: call(A(), <init>) -> <v0>
|
||||||
|
"1" <v1>: Int NEW: r("1") -> <v1>
|
||||||
|
2 <v2>: Int NEW: r(2) -> <v2>
|
||||||
|
A()["1"] = 2 <v3>: * NEW: call(A()["1"] = 2, set|<v0>, <v1>, <v2>) -> <v3>
|
||||||
|
{ A()["1"] = 2 } <v3>: * COPY
|
||||||
|
=====================
|
||||||
@@ -156,6 +156,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("setWithTypeMismatch.kt")
|
||||||
|
public void testSetWithTypeMismatch() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/setWithTypeMismatch.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/cfg/controlStructures")
|
@TestMetadata("compiler/testData/cfg/controlStructures")
|
||||||
|
|||||||
@@ -158,6 +158,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("setWithTypeMismatch.kt")
|
||||||
|
public void testSetWithTypeMismatch() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/setWithTypeMismatch.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/cfg/controlStructures")
|
@TestMetadata("compiler/testData/cfg/controlStructures")
|
||||||
|
|||||||
Reference in New Issue
Block a user