Using call for set on an indexed expression in lvalue position

This commit is contained in:
Andrey Breslav
2013-12-03 18:08:51 +04:00
parent a5854560f0
commit 28acbcb219
5 changed files with 46 additions and 8 deletions
@@ -352,7 +352,8 @@ public class JetControlFlowProcessor {
}
if (left instanceof JetArrayAccessExpression) {
generateArrayAccess((JetArrayAccessExpression) left);
ResolvedCall<FunctionDescriptor> setResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_SET, left);
generateArrayAccess((JetArrayAccessExpression) left, setResolvedCall);
recordWrite(left, parentExpression);
return;
}
@@ -382,8 +383,8 @@ public class JetControlFlowProcessor {
}
}
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression) {
if (!generateCall(arrayAccessExpression)) {
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> setResolvedCall) {
if (!checkAndGenerateCall(arrayAccessExpression, setResolvedCall)) {
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
generateInstructions(index, false);
}
@@ -859,7 +860,7 @@ public class JetControlFlowProcessor {
@Override
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
if (!generateCall(expression)) {
generateArrayAccess(expression);
generateArrayAccess(expression, getResolvedCall(expression));
}
}
@@ -1017,7 +1018,10 @@ public class JetControlFlowProcessor {
}
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) {
builder.compilationError(calleeExpression, "No resolved call");
return false;
@@ -30,10 +30,11 @@ L0:
r(1) NEXT:[call(+=, plus)] PREV:[call(a[10], get)]
call(+=, plus) NEXT:[r(a)] PREV:[r(1)]
r(a) NEXT:[r(10)] PREV:[call(+=, plus)]
r(10) NEXT:[call(a[10], set)] PREV:[r(a)]
call(a[10], get) NEXT:[<END>] PREV:[r(10)]
r(10) NEXT:[r(1)] PREV:[r(a)]
r(1) NEXT:[call(a[10], set)] PREV:[r(10)]
call(a[10], set) NEXT:[<END>] PREV:[r(1)]
L1:
<END> NEXT:[<SINK>] PREV:[call(a[10], get)]
<END> NEXT:[<SINK>] PREV:[call(a[10], set)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
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");
}
@TestMetadata("arraySetPlusAssign.kt")
public void testArraySetPlusAssign() throws Exception {
doTest("compiler/testData/cfg/arraySetPlusAssign.kt");
}
@TestMetadata("Assignments.kt")
public void testAssignments() throws Exception {
doTest("compiler/testData/cfg/Assignments.kt");