Proper resolved calls for '=='

This commit is contained in:
Andrey Breslav
2013-12-02 22:12:43 +04:00
parent 87b6ec4990
commit b5ae3adf77
6 changed files with 107 additions and 3 deletions
@@ -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<FunctionDescriptor> resolvedCall = (ResolvedCall<FunctionDescriptor>) getResolvedCall(operationReference);
if (resolvedCall != null && !resolvedCall.getValueArguments().isEmpty() && right != null) {
ResolvedCallImpl<FunctionDescriptor> 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);
+28
View File
@@ -0,0 +1,28 @@
== foo ==
fun foo(a: Int, b: Int) {
if (a == b) {
}
}
---------------------
L0:
<START> NEXT:[v(a: Int)] PREV:[]
v(a: Int) NEXT:[w(a)] PREV:[<START>]
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:[<END>] PREV:[read (Unit)]
L2:
read (Unit) NEXT:[<END>] PREV:[jf(L2)]
L1:
L3:
<END> NEXT:[<SINK>] PREV:[jmp(L3), read (Unit)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
+4
View File
@@ -0,0 +1,4 @@
fun foo(a: Int, b: Int) {
if (a == b) {
}
}
@@ -0,0 +1,27 @@
== neq ==
fun neq(a: Int, b: Int) {
if (a != b) {}
}
---------------------
L0:
<START> NEXT:[v(a: Int)] PREV:[]
v(a: Int) NEXT:[w(a)] PREV:[<START>]
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:[<END>] PREV:[read (Unit)]
L2:
read (Unit) NEXT:[<END>] PREV:[jf(L2)]
L1:
L3:
<END> NEXT:[<SINK>] PREV:[jmp(L3), read (Unit)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
+3
View File
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a != b) {}
}
@@ -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");