From b5ae3adf773a3c9ef909fcacab810bc454d75c9f Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 2 Dec 2013 22:12:43 +0400 Subject: [PATCH] Proper resolved calls for '==' --- .../jet/lang/cfg/JetControlFlowProcessor.java | 38 +++++++++++++++++-- compiler/testData/cfg/equals.instructions | 28 ++++++++++++++ compiler/testData/cfg/equals.kt | 4 ++ compiler/testData/cfg/notEqual.instructions | 27 +++++++++++++ compiler/testData/cfg/notEqual.kt | 3 ++ .../jet/cfg/ControlFlowTestGenerated.java | 10 +++++ 6 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/cfg/equals.instructions create mode 100644 compiler/testData/cfg/equals.kt create mode 100644 compiler/testData/cfg/notEqual.instructions create mode 100644 compiler/testData/cfg/notEqual.kt 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 6c926a10170..c153b2ad5df 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -32,10 +32,12 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; -import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.*; +import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate; +import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy; +import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; import org.jetbrains.jet.lang.resolve.constants.BooleanValue; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; @@ -285,6 +287,36 @@ public class JetControlFlowProcessor { } builder.bindLabel(afterElvis); } + else if (operationType == JetTokens.EQEQ || operationType == JetTokens.EXCLEQ) { + // Equals is resolved on a fake argument, to ensure "Any?" in the signature, so we have to read the right argument manually + @SuppressWarnings("unchecked") + ResolvedCall resolvedCall = (ResolvedCall) getResolvedCall(operationReference); + if (resolvedCall != null && !resolvedCall.getValueArguments().isEmpty() && right != null) { + ResolvedCallImpl fakeCall = ResolvedCallImpl.create( + ResolutionCandidate.create( + resolvedCall.getCandidateDescriptor(), + resolvedCall.getThisObject(), + resolvedCall.getReceiverArgument(), + resolvedCall.getExplicitReceiverKind(), + resolvedCall.isSafeCall() + ), + new DelegatingBindingTrace(BindingContext.EMPTY, "Fake call for =="), + TracingStrategy.EMPTY, + MutableDataFlowInfoForArguments.WITHOUT_ARGUMENTS_CHECK + ); + + ValueParameterDescriptor parameterDescriptor = resolvedCall.getValueArguments().keySet().iterator().next(); + fakeCall.recordValueArgument( + parameterDescriptor, + new ExpressionValueArgument(CallMaker.makeValueArgument(right)) + ); + fakeCall.setStatusToSuccess(); + generateCall(expression, fakeCall); + } + else { + generateBothArguments(expression); + } + } else { if (!generateCall(operationReference)) { generateBothArguments(expression); diff --git a/compiler/testData/cfg/equals.instructions b/compiler/testData/cfg/equals.instructions new file mode 100644 index 00000000000..76b512f416b --- /dev/null +++ b/compiler/testData/cfg/equals.instructions @@ -0,0 +1,28 @@ +== foo == +fun foo(a: Int, b: Int) { + if (a == b) { + } +} +--------------------- +L0: + NEXT:[v(a: Int)] PREV:[] + v(a: Int) NEXT:[w(a)] PREV:[] + w(a) NEXT:[v(b: Int)] PREV:[v(a: Int)] + v(b: Int) NEXT:[w(b)] PREV:[w(a)] + w(b) NEXT:[r(a)] PREV:[v(b: Int)] + r(a) NEXT:[r(b)] PREV:[w(b)] + r(b) NEXT:[call(a == b, equals)] PREV:[r(a)] + call(a == b, equals) NEXT:[jf(L2)] PREV:[r(b)] + jf(L2) NEXT:[read (Unit), read (Unit)] PREV:[call(a == b, equals)] + read (Unit) NEXT:[jmp(L3)] PREV:[jf(L2)] + jmp(L3) NEXT:[] PREV:[read (Unit)] +L2: + read (Unit) NEXT:[] PREV:[jf(L2)] +L1: +L3: + NEXT:[] PREV:[jmp(L3), read (Unit)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== diff --git a/compiler/testData/cfg/equals.kt b/compiler/testData/cfg/equals.kt new file mode 100644 index 00000000000..0b2dd4f6cad --- /dev/null +++ b/compiler/testData/cfg/equals.kt @@ -0,0 +1,4 @@ +fun foo(a: Int, b: Int) { + if (a == b) { + } +} \ No newline at end of file diff --git a/compiler/testData/cfg/notEqual.instructions b/compiler/testData/cfg/notEqual.instructions new file mode 100644 index 00000000000..baab4fedf3c --- /dev/null +++ b/compiler/testData/cfg/notEqual.instructions @@ -0,0 +1,27 @@ +== neq == +fun neq(a: Int, b: Int) { + if (a != b) {} +} +--------------------- +L0: + NEXT:[v(a: Int)] PREV:[] + v(a: Int) NEXT:[w(a)] PREV:[] + w(a) NEXT:[v(b: Int)] PREV:[v(a: Int)] + v(b: Int) NEXT:[w(b)] PREV:[w(a)] + w(b) NEXT:[r(a)] PREV:[v(b: Int)] + r(a) NEXT:[r(b)] PREV:[w(b)] + r(b) NEXT:[call(a != b, equals)] PREV:[r(a)] + call(a != b, equals) NEXT:[jf(L2)] PREV:[r(b)] + jf(L2) NEXT:[read (Unit), read (Unit)] PREV:[call(a != b, equals)] + read (Unit) NEXT:[jmp(L3)] PREV:[jf(L2)] + jmp(L3) NEXT:[] PREV:[read (Unit)] +L2: + read (Unit) NEXT:[] PREV:[jf(L2)] +L1: +L3: + NEXT:[] PREV:[jmp(L3), read (Unit)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== diff --git a/compiler/testData/cfg/notEqual.kt b/compiler/testData/cfg/notEqual.kt new file mode 100644 index 00000000000..0f367529462 --- /dev/null +++ b/compiler/testData/cfg/notEqual.kt @@ -0,0 +1,3 @@ +fun neq(a: Int, b: Int) { + if (a != b) {} +} \ 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 9bb99d23851..78be8557aa0 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java @@ -81,6 +81,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { doTest("compiler/testData/cfg/EmptyFunction.kt"); } + @TestMetadata("equals.kt") + public void testEquals() throws Exception { + doTest("compiler/testData/cfg/equals.kt"); + } + @TestMetadata("FailFunction.kt") public void testFailFunction() throws Exception { doTest("compiler/testData/cfg/FailFunction.kt"); @@ -136,6 +141,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { doTest("compiler/testData/cfg/multiDeclarationWithError.kt"); } + @TestMetadata("notEqual.kt") + public void testNotEqual() throws Exception { + doTest("compiler/testData/cfg/notEqual.kt"); + } + @TestMetadata("ObjectExpression.kt") public void testObjectExpression() throws Exception { doTest("compiler/testData/cfg/ObjectExpression.kt");