Using call for set on an indexed expression in lvalue position
This commit is contained in:
@@ -352,7 +352,8 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
generateArrayAccess((JetArrayAccessExpression) left);
|
ResolvedCall<FunctionDescriptor> setResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_SET, left);
|
||||||
|
generateArrayAccess((JetArrayAccessExpression) left, setResolvedCall);
|
||||||
recordWrite(left, parentExpression);
|
recordWrite(left, parentExpression);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -382,8 +383,8 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression) {
|
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> setResolvedCall) {
|
||||||
if (!generateCall(arrayAccessExpression)) {
|
if (!checkAndGenerateCall(arrayAccessExpression, setResolvedCall)) {
|
||||||
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
||||||
generateInstructions(index, false);
|
generateInstructions(index, false);
|
||||||
}
|
}
|
||||||
@@ -859,7 +860,7 @@ public class JetControlFlowProcessor {
|
|||||||
@Override
|
@Override
|
||||||
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
||||||
if (!generateCall(expression)) {
|
if (!generateCall(expression)) {
|
||||||
generateArrayAccess(expression);
|
generateArrayAccess(expression, getResolvedCall(expression));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1017,7 +1018,10 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateCall(JetExpression calleeExpression) {
|
private boolean generateCall(JetExpression calleeExpression) {
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCall(calleeExpression);
|
return checkAndGenerateCall(calleeExpression, getResolvedCall(calleeExpression));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAndGenerateCall(JetExpression calleeExpression, @Nullable ResolvedCall<?> resolvedCall) {
|
||||||
if (resolvedCall == null) {
|
if (resolvedCall == null) {
|
||||||
builder.compilationError(calleeExpression, "No resolved call");
|
builder.compilationError(calleeExpression, "No resolved call");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ L0:
|
|||||||
r(1) NEXT:[call(+=, plus)] PREV:[call(a[10], get)]
|
r(1) NEXT:[call(+=, plus)] PREV:[call(a[10], get)]
|
||||||
call(+=, plus) NEXT:[r(a)] PREV:[r(1)]
|
call(+=, plus) NEXT:[r(a)] PREV:[r(1)]
|
||||||
r(a) NEXT:[r(10)] PREV:[call(+=, plus)]
|
r(a) NEXT:[r(10)] PREV:[call(+=, plus)]
|
||||||
r(10) NEXT:[call(a[10], set)] PREV:[r(a)]
|
r(10) NEXT:[r(1)] PREV:[r(a)]
|
||||||
call(a[10], get) NEXT:[<END>] PREV:[r(10)]
|
r(1) NEXT:[call(a[10], set)] PREV:[r(10)]
|
||||||
|
call(a[10], set) NEXT:[<END>] PREV:[r(1)]
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>] PREV:[call(a[10], get)]
|
<END> NEXT:[<SINK>] PREV:[call(a[10], set)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
== foo ==
|
||||||
|
fun foo(a: Array<Int>) {
|
||||||
|
a[0] += 1
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
<START> NEXT:[v(a: Array<Int>)] PREV:[]
|
||||||
|
v(a: Array<Int>) NEXT:[w(a)] PREV:[<START>]
|
||||||
|
w(a) NEXT:[r(a)] PREV:[v(a: Array<Int>)]
|
||||||
|
r(a) NEXT:[r(0)] PREV:[w(a)]
|
||||||
|
r(0) NEXT:[call(a[0], get)] PREV:[r(a)]
|
||||||
|
call(a[0], get) NEXT:[r(1)] PREV:[r(0)]
|
||||||
|
r(1) NEXT:[call(+=, plus)] PREV:[call(a[0], get)]
|
||||||
|
call(+=, plus) NEXT:[r(a)] PREV:[r(1)]
|
||||||
|
r(a) NEXT:[r(0)] PREV:[call(+=, plus)]
|
||||||
|
r(0) NEXT:[r(1)] PREV:[r(a)]
|
||||||
|
r(1) NEXT:[call(a[0], set)] PREV:[r(0)]
|
||||||
|
call(a[0], set) NEXT:[<END>] PREV:[r(1)]
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[call(a[0], set)]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo(a: Array<Int>) {
|
||||||
|
a[0] += 1
|
||||||
|
}
|
||||||
@@ -56,6 +56,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
|||||||
doTest("compiler/testData/cfg/arraySet.kt");
|
doTest("compiler/testData/cfg/arraySet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("arraySetPlusAssign.kt")
|
||||||
|
public void testArraySetPlusAssign() throws Exception {
|
||||||
|
doTest("compiler/testData/cfg/arraySetPlusAssign.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Assignments.kt")
|
@TestMetadata("Assignments.kt")
|
||||||
public void testAssignments() throws Exception {
|
public void testAssignments() throws Exception {
|
||||||
doTest("compiler/testData/cfg/Assignments.kt");
|
doTest("compiler/testData/cfg/Assignments.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user