Proper order of arguments in array setter calls

This commit is contained in:
Andrey Breslav
2013-12-03 17:59:47 +04:00
parent 163e5cfbb4
commit a5854560f0
5 changed files with 67 additions and 33 deletions
@@ -269,10 +269,7 @@ public class JetControlFlowProcessor {
} }
} }
else if (operationType == JetTokens.EQ) { else if (operationType == JetTokens.EQ) {
if (right != null) { visitAssignment(expression.getLeft(), right, expression);
generateInstructions(right, false);
}
visitAssignment(expression.getLeft(), expression);
} }
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
if (generateCall(operationReference)) { if (generateCall(operationReference)) {
@@ -282,7 +279,7 @@ public class JetControlFlowProcessor {
Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken()); Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
if (!descriptor.getName().equals(assignMethodName)) { if (!descriptor.getName().equals(assignMethodName)) {
// plus() called, assignment needed // plus() called, assignment needed
visitAssignment(expression.getLeft(), expression); visitAssignment(expression.getLeft(), null, expression);
} }
} }
else { 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); JetExpression left = JetPsiUtil.deparenthesize(lhs);
if (left == null) { if (left == null) {
builder.compilationError(lhs, "No lValue in assignment"); builder.compilationError(lhs, "No lValue in assignment");
return; return;
} }
if (left instanceof JetArrayAccessExpression) {
generateArrayAccess((JetArrayAccessExpression) left);
recordWrite(left, parentExpression);
return;
}
if (left instanceof JetSimpleNameExpression) { if (left instanceof JetSimpleNameExpression) {
// Do nothing, only record write below // Do nothing, only record write below
} }
else if (left instanceof JetArrayAccessExpression) {
generateArrayAccess((JetArrayAccessExpression) left);
}
else if (left instanceof JetQualifiedExpression) { else if (left instanceof JetQualifiedExpression) {
// read the receiver // read the receiver
generateInstructions(((JetQualifiedExpression) left).getReceiverExpression(), false); generateInstructions(((JetQualifiedExpression) left).getReceiverExpression(), false);
@@ -370,6 +371,11 @@ public class JetControlFlowProcessor {
builder.unsupported(parentExpression); // TODO 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); VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
if (descriptor != null) { if (descriptor != null) {
builder.write(parentExpression, left); builder.write(parentExpression, left);
@@ -408,7 +414,7 @@ public class JetControlFlowProcessor {
boolean incrementOrDecrement = isIncrementOrDecrement(operationType); boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
if (incrementOrDecrement) { if (incrementOrDecrement) {
// We skip dup's and other subtleties here // 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(); JetExpression initializer = property.getInitializer();
if (initializer != null) { if (initializer != null) {
generateInstructions(initializer, false); generateInstructions(initializer, false);
visitAssignment(property, property); visitAssignment(property, null, property);
} }
JetExpression delegate = property.getDelegateExpression(); JetExpression delegate = property.getDelegateExpression();
if (delegate != null) { if (delegate != null) {
+22 -22
View File
@@ -11,29 +11,29 @@ fun foo() {
--------------------- ---------------------
L0: L0:
<START> NEXT:[v(val a = Array<Int>)] PREV:[] <START> NEXT:[v(val a = Array<Int>)] PREV:[]
v(val a = Array<Int>) NEXT:[r(Array)] PREV:[<START>] v(val a = Array<Int>) NEXT:[call(Array, <init>)] PREV:[<START>]
r(Array) NEXT:[r(Array<Int>)] PREV:[v(val a = Array<Int>)] call(Array, <init>) NEXT:[w(a)] PREV:[v(val a = Array<Int>)]
r(Array<Int>) NEXT:[w(a)] PREV:[r(Array)] w(a) NEXT:[r(3)] PREV:[call(Array, <init>)]
w(a) NEXT:[r(3)] PREV:[r(Array<Int>)] r(3) NEXT:[r(a)] PREV:[w(a)]
r(3) NEXT:[r(4)] PREV:[w(a)] r(a) NEXT:[r(10)] PREV:[r(3)]
r(4) NEXT:[r(10)] PREV:[r(3)] r(10) NEXT:[r(4)] PREV:[r(a)]
r(10) NEXT:[r(a)] PREV:[r(4)] r(4) NEXT:[call(a[10], set)] PREV:[r(10)]
r(a) NEXT:[r(=)] PREV:[r(10)] call(a[10], set) NEXT:[r(2)] PREV:[r(4)]
r(=) NEXT:[w(a[10])] PREV:[r(a)] r(2) NEXT:[r(a)] PREV:[call(a[10], set)]
w(a[10]) NEXT:[r(2)] PREV:[r(=)] r(a) NEXT:[r(10)] PREV:[r(2)]
r(2) NEXT:[r(10)] PREV:[w(a[10])] r(10) NEXT:[call(a[10], get)] PREV:[r(a)]
r(10) NEXT:[r(a)] PREV:[r(2)] call(a[10], get) NEXT:[r(100)] PREV:[r(10)]
r(a) NEXT:[r(a[10])] PREV:[r(10)] r(100) NEXT:[r(a)] PREV:[call(a[10], get)]
r(a[10]) NEXT:[r(100)] PREV:[r(a)] r(a) NEXT:[r(10)] PREV:[r(100)]
r(100) NEXT:[r(10)] PREV:[r(a[10])] r(10) NEXT:[call(a[10], get)] PREV:[r(a)]
r(10) NEXT:[r(a)] PREV:[r(100)] call(a[10], get) NEXT:[r(1)] PREV:[r(10)]
r(a) NEXT:[r(a[10])] PREV:[r(10)] r(1) NEXT:[call(+=, plus)] PREV:[call(a[10], get)]
r(a[10]) NEXT:[r(1)] PREV:[r(a)] call(+=, plus) NEXT:[r(a)] PREV:[r(1)]
r(1) NEXT:[r(+=)] PREV:[r(a[10])] r(a) NEXT:[r(10)] PREV:[call(+=, plus)]
r(+=) NEXT:[w(a[10])] PREV:[r(1)] r(10) NEXT:[call(a[10], set)] PREV:[r(a)]
w(a[10]) NEXT:[<END>] PREV:[r(+=)] call(a[10], get) NEXT:[<END>] PREV:[r(10)]
L1: L1:
<END> NEXT:[<SINK>] PREV:[w(a[10])] <END> NEXT:[<SINK>] PREV:[call(a[10], get)]
error: error:
<ERROR> NEXT:[<SINK>] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
@@ -0,0 +1,20 @@
== foo ==
fun foo(a: Array<Int>) {
a[1] = 2
}
---------------------
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(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:[<END>] PREV:[r(2)]
L1:
<END> NEXT:[<SINK>] PREV:[call(a[1], set)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
+3
View File
@@ -0,0 +1,3 @@
fun foo(a: Array<Int>) {
a[1] = 2
}
@@ -51,6 +51,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
doTest("compiler/testData/cfg/arrayAccessExpression.kt"); doTest("compiler/testData/cfg/arrayAccessExpression.kt");
} }
@TestMetadata("arraySet.kt")
public void testArraySet() throws Exception {
doTest("compiler/testData/cfg/arraySet.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");