diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 5cf0978bef1..850fd2a0477 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -269,10 +269,7 @@ public class JetControlFlowProcessor { } } else if (operationType == JetTokens.EQ) { - if (right != null) { - generateInstructions(right, false); - } - visitAssignment(expression.getLeft(), expression); + visitAssignment(expression.getLeft(), right, expression); } else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { if (generateCall(operationReference)) { @@ -282,7 +279,7 @@ public class JetControlFlowProcessor { Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken()); if (!descriptor.getName().equals(assignMethodName)) { // plus() called, assignment needed - visitAssignment(expression.getLeft(), expression); + visitAssignment(expression.getLeft(), null, expression); } } else { @@ -347,18 +344,22 @@ public class JetControlFlowProcessor { } } - private void visitAssignment(JetExpression lhs, JetExpression parentExpression) { + private void visitAssignment(JetExpression lhs, @Nullable JetExpression rhs, JetExpression parentExpression) { JetExpression left = JetPsiUtil.deparenthesize(lhs); if (left == null) { builder.compilationError(lhs, "No lValue in assignment"); return; } + + if (left instanceof JetArrayAccessExpression) { + generateArrayAccess((JetArrayAccessExpression) left); + recordWrite(left, parentExpression); + return; + } + if (left instanceof JetSimpleNameExpression) { // Do nothing, only record write below } - else if (left instanceof JetArrayAccessExpression) { - generateArrayAccess((JetArrayAccessExpression) left); - } else if (left instanceof JetQualifiedExpression) { // read the receiver generateInstructions(((JetQualifiedExpression) left).getReceiverExpression(), false); @@ -370,6 +371,11 @@ public class JetControlFlowProcessor { builder.unsupported(parentExpression); // TODO } + generateInstructions(rhs, false); + recordWrite(left, parentExpression); + } + + private void recordWrite(JetExpression left, JetExpression parentExpression) { VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false); if (descriptor != null) { builder.write(parentExpression, left); @@ -408,7 +414,7 @@ public class JetControlFlowProcessor { boolean incrementOrDecrement = isIncrementOrDecrement(operationType); if (incrementOrDecrement) { // We skip dup's and other subtleties here - visitAssignment(baseExpression, expression); + visitAssignment(baseExpression, null, expression); } } } @@ -797,7 +803,7 @@ public class JetControlFlowProcessor { JetExpression initializer = property.getInitializer(); if (initializer != null) { generateInstructions(initializer, false); - visitAssignment(property, property); + visitAssignment(property, null, property); } JetExpression delegate = property.getDelegateExpression(); if (delegate != null) { diff --git a/compiler/testData/cfg/ArrayAccess.instructions b/compiler/testData/cfg/ArrayAccess.instructions index 188c36430ab..76cbbb0a89e 100644 --- a/compiler/testData/cfg/ArrayAccess.instructions +++ b/compiler/testData/cfg/ArrayAccess.instructions @@ -11,29 +11,29 @@ fun foo() { --------------------- L0: NEXT:[v(val a = Array)] PREV:[] - v(val a = Array) NEXT:[r(Array)] PREV:[] - r(Array) NEXT:[r(Array)] PREV:[v(val a = Array)] - r(Array) NEXT:[w(a)] PREV:[r(Array)] - w(a) NEXT:[r(3)] PREV:[r(Array)] - r(3) NEXT:[r(4)] PREV:[w(a)] - r(4) NEXT:[r(10)] PREV:[r(3)] - r(10) NEXT:[r(a)] PREV:[r(4)] - r(a) NEXT:[r(=)] PREV:[r(10)] - r(=) NEXT:[w(a[10])] PREV:[r(a)] - w(a[10]) NEXT:[r(2)] PREV:[r(=)] - r(2) NEXT:[r(10)] PREV:[w(a[10])] - r(10) NEXT:[r(a)] PREV:[r(2)] - r(a) NEXT:[r(a[10])] PREV:[r(10)] - r(a[10]) NEXT:[r(100)] PREV:[r(a)] - r(100) NEXT:[r(10)] PREV:[r(a[10])] - r(10) NEXT:[r(a)] PREV:[r(100)] - r(a) NEXT:[r(a[10])] PREV:[r(10)] - r(a[10]) NEXT:[r(1)] PREV:[r(a)] - r(1) NEXT:[r(+=)] PREV:[r(a[10])] - r(+=) NEXT:[w(a[10])] PREV:[r(1)] - w(a[10]) NEXT:[] PREV:[r(+=)] + v(val a = Array) NEXT:[call(Array, )] PREV:[] + call(Array, ) NEXT:[w(a)] PREV:[v(val a = Array)] + w(a) NEXT:[r(3)] PREV:[call(Array, )] + r(3) NEXT:[r(a)] PREV:[w(a)] + r(a) NEXT:[r(10)] PREV:[r(3)] + r(10) NEXT:[r(4)] PREV:[r(a)] + r(4) NEXT:[call(a[10], set)] PREV:[r(10)] + call(a[10], set) NEXT:[r(2)] PREV:[r(4)] + r(2) NEXT:[r(a)] PREV:[call(a[10], set)] + r(a) NEXT:[r(10)] PREV:[r(2)] + r(10) NEXT:[call(a[10], get)] PREV:[r(a)] + call(a[10], get) NEXT:[r(100)] PREV:[r(10)] + r(100) NEXT:[r(a)] PREV:[call(a[10], get)] + r(a) NEXT:[r(10)] PREV:[r(100)] + r(10) NEXT:[call(a[10], get)] PREV:[r(a)] + call(a[10], get) NEXT:[r(1)] PREV:[r(10)] + 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:[] PREV:[r(10)] L1: - NEXT:[] PREV:[w(a[10])] + NEXT:[] PREV:[call(a[10], get)] error: NEXT:[] PREV:[] sink: diff --git a/compiler/testData/cfg/arraySet.instructions b/compiler/testData/cfg/arraySet.instructions new file mode 100644 index 00000000000..caa3d358c48 --- /dev/null +++ b/compiler/testData/cfg/arraySet.instructions @@ -0,0 +1,20 @@ +== foo == +fun foo(a: Array) { + a[1] = 2 +} +--------------------- +L0: + NEXT:[v(a: Array)] PREV:[] + v(a: Array) NEXT:[w(a)] PREV:[] + w(a) NEXT:[r(a)] PREV:[v(a: Array)] + r(a) NEXT:[r(1)] PREV:[w(a)] + r(1) NEXT:[r(2)] PREV:[r(a)] + r(2) NEXT:[call(a[1], set)] PREV:[r(1)] + call(a[1], set) NEXT:[] PREV:[r(2)] +L1: + NEXT:[] PREV:[call(a[1], set)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== diff --git a/compiler/testData/cfg/arraySet.kt b/compiler/testData/cfg/arraySet.kt new file mode 100644 index 00000000000..3c557952bae --- /dev/null +++ b/compiler/testData/cfg/arraySet.kt @@ -0,0 +1,3 @@ +fun foo(a: Array) { + a[1] = 2 +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java index e6f9e934924..bd039da6a13 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java @@ -51,6 +51,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { doTest("compiler/testData/cfg/arrayAccessExpression.kt"); } + @TestMetadata("arraySet.kt") + public void testArraySet() throws Exception { + doTest("compiler/testData/cfg/arraySet.kt"); + } + @TestMetadata("Assignments.kt") public void testAssignments() throws Exception { doTest("compiler/testData/cfg/Assignments.kt");