Pseudocode: Generate additional returns for implicit return values (lambdas, functions with expression bodies)
This commit is contained in:
@@ -74,7 +74,7 @@ public interface JetControlFlowBuilder {
|
|||||||
void nondeterministicJump(@NotNull List<Label> label, @NotNull JetElement element);
|
void nondeterministicJump(@NotNull List<Label> label, @NotNull JetElement element);
|
||||||
void jumpToError(@NotNull JetElement element);
|
void jumpToError(@NotNull JetElement element);
|
||||||
|
|
||||||
void returnValue(@NotNull JetReturnExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine);
|
void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine);
|
||||||
void returnNoValue(@NotNull JetReturnExpression returnExpression, @NotNull JetElement subroutine);
|
void returnNoValue(@NotNull JetReturnExpression returnExpression, @NotNull JetElement subroutine);
|
||||||
|
|
||||||
void throwException(@NotNull JetThrowExpression throwExpression, @NotNull PseudoValue thrownValue);
|
void throwException(@NotNull JetThrowExpression throwExpression, @NotNull PseudoValue thrownValue);
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void returnValue(@NotNull JetReturnExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) {
|
public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) {
|
||||||
getDelegateBuilder().returnValue(returnExpression, returnValue, subroutine);
|
getDelegateBuilder().returnValue(returnExpression, returnValue, subroutine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ public class JetControlFlowProcessor {
|
|||||||
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
|
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
|
||||||
if (bodyExpression != null) {
|
if (bodyExpression != null) {
|
||||||
cfpVisitor.generateInstructions(bodyExpression);
|
cfpVisitor.generateInstructions(bodyExpression);
|
||||||
|
if (!declarationWithBody.hasBlockBody()) {
|
||||||
|
generateImplicitReturnValue(bodyExpression, subroutine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cfpVisitor.generateInstructions(subroutine);
|
cfpVisitor.generateInstructions(subroutine);
|
||||||
@@ -94,6 +97,13 @@ public class JetControlFlowProcessor {
|
|||||||
return builder.exitSubroutine(subroutine);
|
return builder.exitSubroutine(subroutine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateImplicitReturnValue(@NotNull JetExpression bodyExpression, @NotNull JetElement subroutine) {
|
||||||
|
PseudoValue returnValue = builder.getBoundValue(bodyExpression);
|
||||||
|
if (returnValue == null) return;
|
||||||
|
|
||||||
|
builder.returnValue(bodyExpression, returnValue, subroutine);
|
||||||
|
}
|
||||||
|
|
||||||
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
|
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
|
||||||
JetElement parent = PsiTreeUtil.getParentOfType(subroutine, JetElement.class);
|
JetElement parent = PsiTreeUtil.getParentOfType(subroutine, JetElement.class);
|
||||||
assert parent != null;
|
assert parent != null;
|
||||||
|
|||||||
+1
-3
@@ -284,9 +284,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void returnValue(
|
public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) {
|
||||||
@NotNull JetReturnExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine
|
|
||||||
) {
|
|
||||||
Label exitPoint = getExitPoint(subroutine);
|
Label exitPoint = getExitPoint(subroutine);
|
||||||
handleJumpInsideTryFinally(exitPoint);
|
handleJumpInsideTryFinally(exitPoint);
|
||||||
add(new ReturnValueInstruction(returnExpression, getCurrentScope(), exitPoint, returnValue));
|
add(new ReturnValueInstruction(returnExpression, getCurrentScope(), exitPoint, returnValue));
|
||||||
|
|||||||
+5
@@ -23,6 +23,7 @@ import java.util.Collections
|
|||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReturnExpression
|
||||||
|
|
||||||
public class ReturnValueInstruction(
|
public class ReturnValueInstruction(
|
||||||
returnExpression: JetExpression,
|
returnExpression: JetExpression,
|
||||||
@@ -47,4 +48,8 @@ public class ReturnValueInstruction(
|
|||||||
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction {
|
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction {
|
||||||
return ReturnValueInstruction((element as JetExpression), lexicalScope, newLabel, returnedValue)
|
return ReturnValueInstruction((element as JetExpression), lexicalScope, newLabel, returnedValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public val resultExpression: JetExpression =
|
||||||
|
element.let{ if (it is JetReturnExpression) it.getReturnedExpression()!! else element as JetExpression }
|
||||||
|
public val returnExpressionIfAny: JetReturnExpression? = element as? JetReturnExpression
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,37 +32,8 @@ import org.jetbrains.jet.lang.resolve.OverridingUtil
|
|||||||
import org.jetbrains.jet.lang.types.TypeUtils
|
import org.jetbrains.jet.lang.types.TypeUtils
|
||||||
import org.jetbrains.jet.lang.types.JetType
|
import org.jetbrains.jet.lang.types.JetType
|
||||||
|
|
||||||
fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
|
fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean =
|
||||||
val value = pseudocode.getElementValue(this);
|
pseudocode.getUsages(pseudocode.getElementValue(this)).isEmpty()
|
||||||
if (value == null) return true
|
|
||||||
|
|
||||||
fun considerUsedIfCreatedBeforeExit(): Boolean {
|
|
||||||
return when {
|
|
||||||
(getParent() as? JetFunction)?.getBodyExpression() == this ->
|
|
||||||
true
|
|
||||||
value.implicitReturnValue ->
|
|
||||||
true
|
|
||||||
else ->
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val instruction = value.createdAt
|
|
||||||
if (considerUsedIfCreatedBeforeExit() && instruction.nextInstructions.any { it == pseudocode.getExitInstruction() }) return false
|
|
||||||
return pseudocode.getUsages(pseudocode.getElementValue(this)).isEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
val PseudoValue.implicitReturnValue: Boolean
|
|
||||||
get() {
|
|
||||||
val pseudocode = createdAt.owner
|
|
||||||
|
|
||||||
val function = pseudocode.getCorrespondingElement() as? JetDeclarationWithBody
|
|
||||||
|
|
||||||
if (function is JetFunctionLiteral || (function != null && !function.hasBlockBody())) {
|
|
||||||
return pseudocode.getElementValue(function.getBodyExpression()) == this
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: ReceiverValue): TypePredicate? {
|
fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: ReceiverValue): TypePredicate? {
|
||||||
val callableDescriptor = resolvedCall.getResultingDescriptor()
|
val callableDescriptor = resolvedCall.getResultingDescriptor()
|
||||||
@@ -91,17 +62,15 @@ fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext)
|
|||||||
fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
|
fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
|
||||||
|
|
||||||
fun addTypePredicates(value: PseudoValue) {
|
fun addTypePredicates(value: PseudoValue) {
|
||||||
if (value.implicitReturnValue) {
|
|
||||||
val function = value.createdAt.owner.getCorrespondingElement() as? JetDeclarationWithBody
|
|
||||||
val functionDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor
|
|
||||||
addSubtypesOf(functionDescriptor?.getReturnType())
|
|
||||||
}
|
|
||||||
|
|
||||||
pseudocode.getUsages(value).forEach {
|
pseudocode.getUsages(value).forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is ReturnValueInstruction -> {
|
is ReturnValueInstruction -> {
|
||||||
val functionDescriptor = (it.element as JetReturnExpression).getTargetFunctionDescriptor(bindingContext)
|
val returnElement = it.element
|
||||||
addSubtypesOf(functionDescriptor?.getReturnType())
|
val functionDescriptor = when(returnElement) {
|
||||||
|
is JetReturnExpression -> returnElement.getTargetFunctionDescriptor(bindingContext)
|
||||||
|
else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, value.createdAt.owner.getCorrespondingElement()]
|
||||||
|
}
|
||||||
|
addSubtypesOf((functionDescriptor as? CallableDescriptor)?.getReturnType())
|
||||||
}
|
}
|
||||||
|
|
||||||
is ConditionalJumpInstruction ->
|
is ConditionalJumpInstruction ->
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ L0:
|
|||||||
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
||||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||||
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
||||||
|
ret(*|<v1>) L1
|
||||||
L1:
|
L1:
|
||||||
<END>
|
<END>
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ L3:
|
|||||||
r(a) -> <v4> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ}
|
r(a) -> <v4> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ}
|
||||||
mark(use(a))
|
mark(use(a))
|
||||||
call(use(a), use|<v4>) -> <v5>
|
call(use(a), use|<v4>) -> <v5>
|
||||||
|
3 ret(*|<v5>) L4 INIT: in: {x=ID} out: {x=ID}
|
||||||
L4:
|
L4:
|
||||||
3 <END> INIT: in: {x=ID} out: {x=ID}
|
<END>
|
||||||
error:
|
error:
|
||||||
<ERROR> INIT: in: {} out: {}
|
<ERROR> INIT: in: {} out: {}
|
||||||
sink:
|
sink:
|
||||||
@@ -64,6 +65,7 @@ L0:
|
|||||||
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
||||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||||
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
||||||
|
ret(*|<v1>) L1
|
||||||
L1:
|
L1:
|
||||||
<END>
|
<END>
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ L0:
|
|||||||
magic(a: Int) -> <v0> INIT: in: {a=D} out: {a=D}
|
magic(a: Int) -> <v0> INIT: in: {a=D} out: {a=D}
|
||||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||||
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
||||||
|
ret(*|<v1>) L1
|
||||||
L1:
|
L1:
|
||||||
<END>
|
<END>
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ L3:
|
|||||||
r(x) -> <v7> USE: in: {} out: {x=READ}
|
r(x) -> <v7> USE: in: {} out: {x=READ}
|
||||||
mark(sum(x - 1) + x)
|
mark(sum(x - 1) + x)
|
||||||
call(sum(x - 1) + x, plus|<v6>, <v7>) -> <v8>
|
call(sum(x - 1) + x, plus|<v6>, <v7>) -> <v8>
|
||||||
|
2 ret(*|<v8>) L4
|
||||||
L4:
|
L4:
|
||||||
2 <END>
|
<END>
|
||||||
error:
|
error:
|
||||||
<ERROR> INIT: in: {} out: {}
|
<ERROR> INIT: in: {} out: {}
|
||||||
sink:
|
sink:
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ L0:
|
|||||||
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
magic(vararg a: Any?) -> <v0> INIT: in: {a=D} out: {a=D}
|
||||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||||
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {a=READ}
|
||||||
|
ret(*|<v1>) L1
|
||||||
L1:
|
L1:
|
||||||
<END>
|
<END>
|
||||||
error:
|
error:
|
||||||
|
|||||||
+1
@@ -38,6 +38,7 @@ L3:
|
|||||||
r(b) -> <v2> USE: in: {} out: {b=READ}
|
r(b) -> <v2> USE: in: {} out: {b=READ}
|
||||||
mark(x + b)
|
mark(x + b)
|
||||||
call(x + b, plus|<v1>, <v2>) -> <v3>
|
call(x + b, plus|<v1>, <v2>) -> <v3>
|
||||||
|
ret(*|<v3>) L4
|
||||||
L4:
|
L4:
|
||||||
<END>
|
<END>
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -79,12 +79,13 @@ L3:
|
|||||||
3 <START>
|
3 <START>
|
||||||
4 mark(1)
|
4 mark(1)
|
||||||
r(1) -> <v0>
|
r(1) -> <v0>
|
||||||
|
3 ret(*|<v0>) L4
|
||||||
L4:
|
L4:
|
||||||
3 <END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
== foo ==
|
== foo ==
|
||||||
fun foo(a : Boolean, b : Int) : Unit {}
|
fun foo(a : Boolean, b : Int) : Unit {}
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ fun short() = 1
|
|||||||
L0:
|
L0:
|
||||||
1 <START>
|
1 <START>
|
||||||
r(1) -> <v0>
|
r(1) -> <v0>
|
||||||
|
ret(*|<v0>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
@@ -45,12 +45,13 @@ override fun foo() = 10
|
|||||||
L0:
|
L0:
|
||||||
1 <START>
|
1 <START>
|
||||||
r(10) -> <v0>
|
r(10) -> <v0>
|
||||||
|
ret(*|<v0>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
== foo ==
|
== foo ==
|
||||||
fun foo(b: B) : Int {
|
fun foo(b: B) : Int {
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ fun component1() = 1
|
|||||||
L0:
|
L0:
|
||||||
1 <START>
|
1 <START>
|
||||||
r(1) -> <v0>
|
r(1) -> <v0>
|
||||||
|
ret(*|<v0>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
== component2 ==
|
== component2 ==
|
||||||
fun component2() = 2
|
fun component2() = 2
|
||||||
@@ -32,12 +33,13 @@ fun component2() = 2
|
|||||||
L0:
|
L0:
|
||||||
1 <START>
|
1 <START>
|
||||||
r(2) -> <v0>
|
r(2) -> <v0>
|
||||||
|
ret(*|<v0>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
== test ==
|
== test ==
|
||||||
fun test(c: C) {
|
fun test(c: C) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ L0:
|
|||||||
magic(p: PropertyMetadata) -> <v1>
|
magic(p: PropertyMetadata) -> <v1>
|
||||||
w(p|<v1>)
|
w(p|<v1>)
|
||||||
r(0) -> <v2>
|
r(0) -> <v2>
|
||||||
|
ret(*|<v2>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
|
|||||||
+1
@@ -26,6 +26,7 @@ L0:
|
|||||||
r($bar|<v1>) -> <v2>
|
r($bar|<v1>) -> <v2>
|
||||||
mark("foo" + this.$bar)
|
mark("foo" + this.$bar)
|
||||||
call("foo" + this.$bar, plus|<v0>, <v2>) -> <v3>
|
call("foo" + this.$bar, plus|<v0>, <v2>) -> <v3>
|
||||||
|
ret(*|<v3>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ L2 [after default value for parameter i]:
|
|||||||
r(j) -> <v5>
|
r(j) -> <v5>
|
||||||
mark(i + j)
|
mark(i + j)
|
||||||
call(i + j, plus|<v4>, <v5>) -> <v6>
|
call(i + j, plus|<v4>, <v5>) -> <v6>
|
||||||
|
ret(*|<v6>) L1
|
||||||
L1:
|
L1:
|
||||||
<END> NEXT:[<SINK>]
|
<END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -16,14 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.cfg;
|
package org.jetbrains.jet.cfg;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
import java.io.File;
|
import org.jetbrains.jet.cfg.AbstractPseudoValueTest;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
|
|||||||
+10
-5
@@ -90,7 +90,7 @@ private fun List<Instruction>.getResultType(
|
|||||||
fun instructionToType(instruction: Instruction): JetType? {
|
fun instructionToType(instruction: Instruction): JetType? {
|
||||||
val expression = when (instruction) {
|
val expression = when (instruction) {
|
||||||
is ReturnValueInstruction ->
|
is ReturnValueInstruction ->
|
||||||
(instruction.element as JetReturnExpression).getReturnedExpression()
|
instruction.resultExpression
|
||||||
is InstructionWithValue ->
|
is InstructionWithValue ->
|
||||||
instruction.outputValue?.element as? JetExpression
|
instruction.outputValue?.element as? JetExpression
|
||||||
else -> null
|
else -> null
|
||||||
@@ -145,10 +145,15 @@ private fun List<Instruction>.analyzeControlFlow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (insn) {
|
when (insn) {
|
||||||
is ReturnValueInstruction ->
|
is ReturnValueInstruction -> {
|
||||||
if (isCurrentFunctionReturn(insn.element as JetReturnExpression)) {
|
val returnExpression = insn.returnExpressionIfAny
|
||||||
valuedReturnExits.add(insn)
|
if (returnExpression == null) {
|
||||||
}
|
defaultExits.add(insn)
|
||||||
|
}
|
||||||
|
else if (isCurrentFunctionReturn(returnExpression)) {
|
||||||
|
valuedReturnExits.add(insn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is AbstractJumpInstruction -> {
|
is AbstractJumpInstruction -> {
|
||||||
val element = insn.element
|
val element = insn.element
|
||||||
|
|||||||
Reference in New Issue
Block a user