From 77bbf8f73b1f867d0dc1f000e3264c87d62dbb26 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 23 Jul 2014 12:56:21 +0400 Subject: [PATCH] Pseudocode: Generate fake values for Unit/Nothing-typed expressions --- .../jet/lang/cfg/JetControlFlowBuilder.java | 2 + .../cfg/JetControlFlowBuilderAdapter.java | 6 + .../jet/lang/cfg/JetControlFlowProcessor.java | 24 +- .../JetControlFlowInstructionsGenerator.java | 8 +- .../jet/lang/cfg/pseudocode/PseudoValue.kt | 4 +- .../lang/cfg/pseudocode/PseudoValueImpl.kt | 6 +- .../jet/lang/cfg/pseudocode/pseudocodeUtil.kt | 6 +- .../basic/IfWithUninitialized.instructions | 23 +- .../basic/IfWithUninitialized.values | 20 +- .../basic/InitializedNotDeclared.values | 6 +- .../basic/UsageInFunctionLiteral.values | 2 +- .../cfg-variables/basic/VariablesUsage.values | 4 +- .../bugs/varInitializationInIf.instructions | 11 +- .../bugs/varInitializationInIf.values | 22 +- .../varInitializationInIfInCycle.instructions | 9 +- .../bugs/varInitializationInIfInCycle.values | 29 +- .../lexicalScopes/doWhileScope.values | 14 +- .../lexicalScopes/forScope.values | 14 +- .../lexicalScopes/functionLiteralScope.values | 14 +- .../lexicalScopes/ifScope.instructions | 23 +- .../lexicalScopes/ifScope.values | 17 +- .../lexicalScopes/localClass.values | 12 +- .../lexicalScopes/localFunctionScope.values | 12 +- .../lexicalScopes/localObject.values | 8 +- .../lexicalScopes/objectLiteralScope.values | 10 +- .../propertyAccessorScope.values | 14 +- .../lexicalScopes/tryScope.instructions | 5 +- .../lexicalScopes/tryScope.values | 19 +- .../lexicalScopes/whileScope.instructions | 4 +- .../lexicalScopes/whileScope.values | 4 +- .../cfg/bugs/jumpToOuterScope.instructions | 9 +- .../testData/cfg/bugs/jumpToOuterScope.values | 14 +- .../controlStructures/Finally.instructions | 156 +++++----- .../cfg/controlStructures/Finally.values | 294 +++++++++++------- .../FinallyTestCopy.instructions | 58 ++-- .../controlStructures/FinallyTestCopy.values | 49 +-- .../testData/cfg/controlStructures/For.values | 16 +- .../cfg/controlStructures/If.instructions | 43 +-- .../testData/cfg/controlStructures/If.values | 51 +-- .../OnlyWhileInFunctionBody.instructions | 8 +- .../OnlyWhileInFunctionBody.values | 22 +- .../controlStructures/returnsInWhen.values | 11 +- .../controlStructures/whenConditions.values | 2 +- .../testData/cfg/conventions/equals.values | 13 +- .../testData/cfg/conventions/notEqual.values | 13 +- .../cfg/deadCode/returnInElvis.instructions | 17 +- .../cfg/deadCode/returnInElvis.values | 7 +- .../cfg/deadCode/stringTemplate.instructions | 12 +- .../cfg/deadCode/stringTemplate.values | 9 +- .../AnonymousInitializers.instructions | 6 +- .../AnonymousInitializers.values | 14 +- .../functions/FailFunction.values | 6 +- .../local/LocalDeclarations.instructions | 16 +- .../local/LocalDeclarations.values | 42 ++- .../local/ObjectExpression.values | 16 +- .../declarations/local/localProperty.values | 4 +- .../ReturnFromExpression.instructions | 12 +- .../expressions/ReturnFromExpression.values | 10 +- .../cfg/expressions/nothingExpr.instructions | 2 +- .../cfg/expressions/nothingExpr.values | 15 +- .../expressions/thisExpression.instructions | 8 +- .../cfg/expressions/thisExpression.values | 8 +- .../expressions/unresolvedCall.instructions | 8 +- .../cfg/expressions/unresolvedCall.values | 11 +- .../testData/cfg/tailCalls/finally.values | 9 +- .../cfg/tailCalls/finallyWithReturn.values | 9 +- .../testData/cfg/tailCalls/sum.instructions | 20 +- compiler/testData/cfg/tailCalls/sum.values | 34 +- .../testData/cfg/tailCalls/try.instructions | 21 +- compiler/testData/cfg/tailCalls/try.values | 9 +- .../return/LocalReturnHasTypeNothing.kt | 2 +- .../jet/cfg/AbstractPseudoValueTest.kt | 5 +- 72 files changed, 851 insertions(+), 592 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index b67b07c2f58..aba297f4f63 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -98,6 +98,8 @@ public interface JetControlFlowBuilder { @Nullable PseudoValue getBoundValue(@Nullable JetElement element); void bindValue(@NotNull PseudoValue value, @NotNull JetElement element); + @NotNull + PseudoValue newValue(@Nullable JetElement element); void loadUnit(@NotNull JetExpression expression); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index d2dae8c717d..75ecb2361a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -288,6 +288,12 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil getDelegateBuilder().bindValue(value, element); } + @NotNull + @Override + public PseudoValue newValue(@Nullable JetElement element) { + return getDelegateBuilder().newValue(element); + } + @Override public void enterLexicalScope(@NotNull JetElement element) { getDelegateBuilder().enterLexicalScope(element); 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 ee9b72f2926..ea5f9f7904d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -22,7 +22,6 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.SmartFMap; import com.intellij.util.containers.ContainerUtil; -import jet.runtime.typeinfo.JetValueParameter; import kotlin.Function0; import kotlin.Function1; import kotlin.KotlinPackage; @@ -235,12 +234,20 @@ public class JetControlFlowProcessor { } private void copyValue(@Nullable JetElement from, @NotNull JetElement to) { - PseudoValue value = builder.getBoundValue(from); + PseudoValue value = getBoundOrUnreachableValue(from); if (value != null) { builder.bindValue(value, to); } } + @Nullable + private PseudoValue getBoundOrUnreachableValue(@Nullable JetElement element) { + if (element == null) return null; + + PseudoValue value = builder.getBoundValue(element); + return value != null || element instanceof JetDeclaration ? value : builder.newValue(element); + } + private List elementsToValues(List from) { if (from.isEmpty()) return Collections.emptyList(); return KotlinPackage.filterNotNull( @@ -249,7 +256,7 @@ public class JetControlFlowProcessor { new Function1() { @Override public PseudoValue invoke(JetElement element) { - return builder.getBoundValue(element); + return getBoundOrUnreachableValue(element); } } ) @@ -427,7 +434,7 @@ public class JetControlFlowProcessor { @Override public PseudoValue invoke() { generateInstructions(expression); - return builder.getBoundValue(expression); + return getBoundOrUnreachableValue(expression); } }; } @@ -1234,7 +1241,7 @@ public class JetControlFlowProcessor { JetExpression left = expression.getLeft(); if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { generateInstructions(left); - if (builder.getBoundValue(left) != null) { + if (getBoundOrUnreachableValue(left) != null) { createNonSyntheticValue(expression, MagicKind.CAST, left); } } @@ -1428,7 +1435,8 @@ public class JetControlFlowProcessor { List arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression())); JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference()); TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$; - builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER); + builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), + MagicKind.VALUE_CONSUMER); } @Override @@ -1539,7 +1547,7 @@ public class JetControlFlowProcessor { generateInstructions(expression); } - PseudoValue receiverPseudoValue = builder.getBoundValue(expression); + PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression); if (receiverPseudoValue != null) { receiverValues = receiverValues.plus(receiverPseudoValue, receiver); } @@ -1578,7 +1586,7 @@ public class JetControlFlowProcessor { generateInstructions(expression); } - PseudoValue argValue = builder.getBoundValue(expression); + PseudoValue argValue = getBoundOrUnreachableValue(expression); if (argValue != null) { parameterValues = parameterValues.plus(argValue, parameterDescriptor); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 3f229c14ac1..5c3a00b225f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -106,7 +106,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd private final PseudoValueFactory valueFactory = new PseudoValueFactoryImpl() { @NotNull @Override - public PseudoValue newValue(@Nullable JetElement element, @NotNull InstructionWithValue instruction) { + public PseudoValue newValue(@Nullable JetElement element, @Nullable InstructionWithValue instruction) { PseudoValue value = super.newValue(element, instruction); if (element != null) { bindValue(value, element); @@ -283,6 +283,12 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd pseudocode.bindElementToValue(element, value); } + @NotNull + @Override + public PseudoValue newValue(@Nullable JetElement element) { + return valueFactory.newValue(element, null); + } + @Override public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) { Label exitPoint = getExitPoint(subroutine); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValue.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValue.kt index 95a4e2976c7..fd5042e7ee6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValue.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValue.kt @@ -22,9 +22,9 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa public trait PseudoValue { public val debugName: String public val element: JetElement? - public val createdAt: InstructionWithValue + public val createdAt: InstructionWithValue? } public trait PseudoValueFactory { - public fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue + public fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValueImpl.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValueImpl.kt index 6f9eb0f6d5a..0cb72ac355d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValueImpl.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudoValueImpl.kt @@ -22,7 +22,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa class PseudoValueImpl( override val debugName: String, override val element: JetElement?, - override val createdAt: InstructionWithValue + override val createdAt: InstructionWithValue? ) : PseudoValue { override fun toString(): String = debugName } @@ -30,7 +30,7 @@ class PseudoValueImpl( open class PseudoValueFactoryImpl: PseudoValueFactory { private var lastIndex: Int = 0 - override fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue { - return PseudoValueImpl("", element, instruction) + override fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue { + return PseudoValueImpl((instruction?.let { "" } ?: "!") + "", element, instruction) } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt index ccd40fad9ed..2cc1a11f002 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt @@ -54,7 +54,9 @@ fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: Recei } fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext): TypePredicate { - val pseudocode = value.createdAt.owner + val pseudocode = value.createdAt?.owner + if (pseudocode == null) return AllTypes + val typePredicates = LinkedHashSet() fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate()) @@ -66,7 +68,7 @@ fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext) val returnElement = it.element val functionDescriptor = when(returnElement) { is JetReturnExpression -> returnElement.getTargetFunctionDescriptor(bindingContext) - else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, value.createdAt.owner.getCorrespondingElement()] + else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, pseudocode.getCorrespondingElement()] } addSubtypesOf((functionDescriptor as? CallableDescriptor)?.getReturnType()) } diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions index d1872a64736..960c0705739 100644 --- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions +++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions @@ -10,31 +10,32 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} USE: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } }) - v(val b: Boolean) INIT: in: {} out: {b=D} - mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D} + v(val b: Boolean) INIT: in: {} out: {b=D} + mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D} r(1) -> r(2) -> mark(1 < 2) call(1 < 2, compareTo|, ) -> jf(L2|) - 3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ} - r(b) -> USE: in: {} out: {b=READ} + 3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ} + r(b) -> USE: in: {} out: {b=READ} mark(use(b)) call(use(b), use|) -> - 2 jmp(L3) USE: in: {} out: {} + 2 jmp(L3) USE: in: {} out: {} L2: 3 mark({ b = true }) - r(true) -> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ} - w(b|) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} -L1: + r(true) -> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ} + w(b|) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} L3: - 1 INIT: in: {} out: {} + 2 merge(if (1 < 2) { use(b) } else { b = true }|, !) -> INIT: in: {b=D} out: {b=D} +L1: + 1 INIT: in: {} out: {} error: sink: - USE: in: {} out: {} + USE: in: {} out: {} ===================== == use == fun use(vararg a: Any?) = a diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values index 4c96c9f62f3..3b520035ad9 100644 --- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values +++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values @@ -9,15 +9,17 @@ fun foo() { } } --------------------- -1 : {<: Comparable} NEW: r(1) -> -2 : Int NEW: r(2) -> -1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> -b : * NEW: r(b) -> -use(b) : * NEW: call(use(b), use|) -> -{ use(b) } : * COPY -true : Boolean NEW: r(true) -> -if (1 < 2) { use(b) } else { b = true } : * COPY -{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } : * COPY +1 : {<: Comparable} NEW: r(1) -> +2 : Int NEW: r(2) -> +1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> +b : * NEW: r(b) -> +use(b) : * NEW: call(use(b), use|) -> +{ use(b) } : * COPY +true : Boolean NEW: r(true) -> +b = true !: * +{ b = true } !: * COPY +if (1 < 2) { use(b) } else { b = true } : * NEW: merge(if (1 < 2) { use(b) } else { b = true }|, !) -> +{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } : * COPY ===================== == use == fun use(vararg a: Any?) = a diff --git a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values index 179980fa687..e1c759fdbd2 100644 --- a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values +++ b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values @@ -6,6 +6,8 @@ class A { val x: Int } --------------------- - : A NEW: magic[IMPLICIT_RECEIVER](x) -> -1 : Int NEW: r(1) -> + : A NEW: magic[IMPLICIT_RECEIVER](x) -> +1 : Int NEW: r(1) -> +x = 1 !: * +{ x = 1 } !: * COPY ===================== diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values index 033d91cd500..8c892930432 100644 --- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values +++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values @@ -20,7 +20,7 @@ fun foo() { x : Int NEW: r(x) -> a : Int NEW: r(a) -> x + a : Int NEW: call(x + a, plus|, ) -> -a : * NEW: r(a) -> +a : * NEW: r(a) -> use(a) : {<: Array} NEW: call(use(a), use|) -> val y = x + a use(a) : {<: Array} COPY ===================== diff --git a/compiler/testData/cfg-variables/basic/VariablesUsage.values b/compiler/testData/cfg-variables/basic/VariablesUsage.values index 47262113ddc..9c42af33508 100644 --- a/compiler/testData/cfg-variables/basic/VariablesUsage.values +++ b/compiler/testData/cfg-variables/basic/VariablesUsage.values @@ -20,7 +20,9 @@ fun bar() { b = 3 } --------------------- -3 : Int NEW: r(3) -> +3 : Int NEW: r(3) -> +b = 3 !: * +{ val b: Int b = 3 } !: * COPY ===================== == use == fun use(a: Int) = a diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions b/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions index 39cc786188f..485f53b0b25 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions @@ -26,14 +26,15 @@ L0: 2 jmp(L3) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ} L2: 3 mark({ b = true }) INIT: in: {b=D} out: {b=D} - r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} - w(b|) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} + r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} + w(b|) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} L3: - 2 error(use(b), No resolved call) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ} - r(b) -> USE: in: {} out: {b=READ} + 2 merge(if (1 < 2) { b = false } else { b = true }|!, !) -> INIT: in: {b=ID} out: {b=ID} + error(use(b), No resolved call) USE: in: {b=READ} out: {b=READ} + r(b) -> USE: in: {} out: {b=READ} error(use, No resolved call) mark(use(b)) - magic[UNRESOLVED_CALL](use(b)|) -> + magic[UNRESOLVED_CALL](use(b)|, !) -> L1: 1 INIT: in: {} out: {} error: diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIf.values b/compiler/testData/cfg-variables/bugs/varInitializationInIf.values index 09bdf63c937..b5866c02d04 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIf.values +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIf.values @@ -10,12 +10,18 @@ fun foo() { use(b) } --------------------- -1 : {<: Comparable} NEW: r(1) -> -2 : Int NEW: r(2) -> -1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> -false : Boolean NEW: r(false) -> -true : Boolean NEW: r(true) -> -b : * NEW: r(b) -> -use(b) : * NEW: magic[UNRESOLVED_CALL](use(b)|) -> -{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } : * COPY +1 : {<: Comparable} NEW: r(1) -> +2 : Int NEW: r(2) -> +1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> +false : Boolean NEW: r(false) -> +b = false !: * +{ b = false } !: * COPY +true : Boolean NEW: r(true) -> +b = true !: * +{ b = true } !: * COPY +if (1 < 2) { b = false } else { b = true } : * NEW: merge(if (1 < 2) { b = false } else { b = true }|!, !) -> +use !: * +b : * NEW: r(b) -> +use(b) : * NEW: magic[UNRESOLVED_CALL](use(b)|, !) -> +{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions index c679f62e540..26c0aac16aa 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions @@ -42,12 +42,13 @@ L5 [body entry point]: 4 jmp(L7) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ} L6: 5 mark({ b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID} - r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} - w(b|) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} + r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} + w(b|) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} L7: - 4 r(b) -> INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {} out: {b=READ} + 4 merge(if (1 < 2) { b = false } else { b = true }|!, !) -> INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ} + r(b) -> USE: in: {} out: {b=READ} mark(use(b)) - call(use(b), use|) -> + call(use(b), use|) -> jmp(L4 [loop entry point]) USE: in: {} out: {} - 3 jmp?(L4 [loop entry point]) L2: diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values index 68ccdba7801..2133ae845e2 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values @@ -13,16 +13,25 @@ fun foo(numbers: Collection) { } } --------------------- - : {<: Collection} NEW: magic[FAKE_INITIALIZER](numbers: Collection) -> - : Int NEW: magic[LOOP_RANGE_ITERATION](numbers|) -> -numbers : {<: Iterable} NEW: r(numbers) -> -1 : {<: Comparable} NEW: r(1) -> -2 : Int NEW: r(2) -> -1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> -false : Boolean NEW: r(false) -> -true : Boolean NEW: r(true) -> -b : * NEW: r(b) -> -use(b) : * NEW: call(use(b), use|) -> + : {<: Collection} NEW: magic[FAKE_INITIALIZER](numbers: Collection) -> + : Int NEW: magic[LOOP_RANGE_ITERATION](numbers|) -> +numbers : {<: Iterable} NEW: r(numbers) -> +1 : {<: Comparable} NEW: r(1) -> +2 : Int NEW: r(2) -> +1 < 2 : Boolean NEW: call(1 < 2, compareTo|, ) -> +false : Boolean NEW: r(false) -> +b = false !: * +{ b = false } !: * COPY +true : Boolean NEW: r(true) -> +b = true !: * +{ b = true } !: * COPY +if (1 < 2) { b = false } else { b = true } : * NEW: merge(if (1 < 2) { b = false } else { b = true }|!, !) -> +b : * NEW: r(b) -> +use(b) : * NEW: call(use(b), use|) -> +continue !: * +{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } !: * COPY +for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } !: * +{ for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } } !: * COPY ===================== == use == fun use(vararg a: Any?) = a diff --git a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values index 8c988d099c5..2ac12bd90b1 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values @@ -7,11 +7,11 @@ fun foo() { "after" } --------------------- -"before" : * NEW: r("before") -> -2 : Int NEW: r(2) -> -a : {<: Comparable} NEW: r(a) -> -0 : Int NEW: r(0) -> +"before" : * NEW: r("before") -> +2 : Int NEW: r(2) -> +a : {<: Comparable} NEW: r(a) -> +0 : Int NEW: r(0) -> a > 0 : Boolean NEW: call(a > 0, compareTo|, ) -> -"after" : * NEW: r("after") -> -{ "before" do { var a = 2 } while (a > 0) "after" } : * COPY -===================== \ No newline at end of file +"after" : * NEW: r("after") -> +{ "before" do { var a = 2 } while (a > 0) "after" } : * COPY +===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/forScope.values b/compiler/testData/cfg-variables/lexicalScopes/forScope.values index 943aebfa307..a291ce38e85 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/forScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/forScope.values @@ -8,11 +8,11 @@ fun foo() { } --------------------- : Int NEW: magic[LOOP_RANGE_ITERATION](1..10|) -> -"before" : * NEW: r("before") -> -1 : Int NEW: r(1) -> -10 : Int NEW: r(10) -> -1..10 : {<: Iterable} NEW: call(1..10, rangeTo|, ) -> -i : Int NEW: r(i) -> -"after" : * NEW: r("after") -> -{ "before" for (i in 1..10) { val a = i } "after" } : * COPY +"before" : * NEW: r("before") -> +1 : Int NEW: r(1) -> +10 : Int NEW: r(10) -> +1..10 : {<: Iterable} NEW: call(1..10, rangeTo|, ) -> +i : Int NEW: r(i) -> +"after" : * NEW: r("after") -> +{ "before" for (i in 1..10) { val a = i } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values index da85f01af2c..80ae74bf62a 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values @@ -8,11 +8,11 @@ fun foo() { "after" } --------------------- -"before" : * NEW: r("before") -> -1 : Int NEW: r(1) -> +"before" : * NEW: r("before") -> +1 : Int NEW: r(1) -> { (x: Int) -> val a = x + b } : {<: (Int) -> Unit} NEW: r({ (x: Int) -> val a = x + b }) -> -"after" : * NEW: r("after") -> -{ "before" val b = 1 val f = { (x: Int) -> val a = x + b } "after" } : * COPY +"after" : * NEW: r("after") -> +{ "before" val b = 1 val f = { (x: Int) -> val a = x + b } "after" } : * COPY ===================== == anonymous_0 == { (x: Int) -> @@ -20,7 +20,7 @@ fun foo() { } --------------------- : Int NEW: magic[FAKE_INITIALIZER](x: Int) -> -x : Int NEW: r(x) -> -b : Int NEW: r(b) -> -x + b : Int NEW: call(x + b, plus|, ) -> +x : Int NEW: r(x) -> +b : Int NEW: r(b) -> +x + b : Int NEW: call(x + b, plus|, ) -> ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions index 9f1a87a1366..5a83b19d785 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions @@ -11,7 +11,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} 2 mark({ "before" if (true) { val a = 1 } else { val b = 2 } "after" }) mark("before") r("before") -> @@ -19,22 +19,23 @@ L0: r(true) -> jf(L2|) 3 mark({ val a = 1 }) - v(val a = 1) INIT: in: {} out: {a=D} - r(1) -> INIT: in: {a=D} out: {a=D} - w(a|) INIT: in: {a=D} out: {a=ID} - 2 jmp(L3) INIT: in: {} out: {} + v(val a = 1) INIT: in: {} out: {a=D} + r(1) -> INIT: in: {a=D} out: {a=D} + w(a|) INIT: in: {a=D} out: {a=ID} + 2 jmp(L3) INIT: in: {} out: {} L2: 3 mark({ val b = 2 }) - v(val b = 2) INIT: in: {} out: {b=D} - r(2) -> INIT: in: {b=D} out: {b=D} - w(b|) INIT: in: {b=D} out: {b=ID} + v(val b = 2) INIT: in: {} out: {b=D} + r(2) -> INIT: in: {b=D} out: {b=D} + w(b|) INIT: in: {b=D} out: {b=ID} L3: - 2 mark("after") INIT: in: {} out: {} - r("after") -> + 2 merge(if (true) { val a = 1 } else { val b = 2 }|!, !) -> INIT: in: {} out: {} + mark("after") + r("after") -> L1: 1 error: sink: - USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/ifScope.values b/compiler/testData/cfg-variables/lexicalScopes/ifScope.values index 17731824208..07eaa5e5a1c 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/ifScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/ifScope.values @@ -10,10 +10,13 @@ fun foo() { "after" } --------------------- -"before" : * NEW: r("before") -> -true : Boolean NEW: r(true) -> -1 : Int NEW: r(1) -> -2 : Int NEW: r(2) -> -"after" : * NEW: r("after") -> -{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } : * COPY -===================== \ No newline at end of file +"before" : * NEW: r("before") -> +true : Boolean NEW: r(true) -> +1 : Int NEW: r(1) -> +{ val a = 1 } !: * +2 : Int NEW: r(2) -> +{ val b = 2 } !: * +if (true) { val a = 1 } else { val b = 2 } : * NEW: merge(if (true) { val a = 1 } else { val b = 2 }|!, !) -> +"after" : * NEW: r("after") -> +{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } : * COPY +===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localClass.values b/compiler/testData/cfg-variables/lexicalScopes/localClass.values index 4e98c3faac9..0bbe02c2ee8 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localClass.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localClass.values @@ -13,11 +13,11 @@ fun foo() { } --------------------- : Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> - : A NEW: magic[IMPLICIT_RECEIVER](x) -> -"before" : * NEW: r("before") -> -x : Int NEW: r(x|) -> -"after" : * NEW: r("after") -> -{ "before" class A(val x: Int) { { val a = x } fun foo() { val b = x } } "after" } : * COPY + : A NEW: magic[IMPLICIT_RECEIVER](x) -> +"before" : * NEW: r("before") -> +x : Int NEW: r(x|) -> +"after" : * NEW: r("after") -> +{ "before" class A(val x: Int) { { val a = x } fun foo() { val b = x } } "after" } : * COPY ===================== == foo == fun foo() { @@ -25,5 +25,5 @@ fun foo() { } --------------------- : A NEW: magic[IMPLICIT_RECEIVER](x) -> -x : Int NEW: r(x|) -> +x : Int NEW: r(x|) -> ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values index 0f06024c3db..68804930317 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values @@ -9,9 +9,9 @@ fun foo() { } --------------------- "before" : * NEW: r("before") -> -1 : Int NEW: r(1) -> -"after" : * NEW: r("after") -> -{ "before" val b = 1 fun local(x: Int) { val a = x + b } "after" } : * COPY +1 : Int NEW: r(1) -> +"after" : * NEW: r("after") -> +{ "before" val b = 1 fun local(x: Int) { val a = x + b } "after" } : * COPY ===================== == local == fun local(x: Int) { @@ -19,7 +19,7 @@ fun local(x: Int) { } --------------------- : Int NEW: magic[FAKE_INITIALIZER](x: Int) -> -x : Int NEW: r(x) -> -b : Int NEW: r(b) -> -x + b : Int NEW: call(x + b, plus|, ) -> +x : Int NEW: r(x) -> +b : Int NEW: r(b) -> +x + b : Int NEW: call(x + b, plus|, ) -> ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localObject.values b/compiler/testData/cfg-variables/lexicalScopes/localObject.values index 32867834b21..f1d5201cf33 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localObject.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localObject.values @@ -13,9 +13,9 @@ fun foo() { } --------------------- "before" : * NEW: r("before") -> -1 : Int NEW: r(1) -> -"after" : * NEW: r("after") -> -{ "before" object A { { val a = 1 } fun foo() { val b = 2 } } "after" } : * COPY +1 : Int NEW: r(1) -> +"after" : * NEW: r("after") -> +{ "before" object A { { val a = 1 } fun foo() { val b = 2 } } "after" } : * COPY ===================== == foo == fun foo() { @@ -23,4 +23,4 @@ fun foo() { } --------------------- 2 : Int NEW: r(2) -> -===================== \ No newline at end of file +===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values index 4e17237c7ca..d27c79aa726 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values @@ -12,11 +12,11 @@ fun foo() { "after" } --------------------- -"before" : * NEW: r("before") -> -1 : Int NEW: r(1) -> +"before" : * NEW: r("before") -> +1 : Int NEW: r(1) -> object { { val x = 1 } fun foo() { val a = 2 } } : NEW: r(object { { val x = 1 } fun foo() { val a = 2 } }) -> -"after" : * NEW: r("after") -> -{ "before" val bar = object { { val x = 1 } fun foo() { val a = 2 } } "after" } : * COPY +"after" : * NEW: r("after") -> +{ "before" val bar = object { { val x = 1 } fun foo() { val a = 2 } } "after" } : * COPY ===================== == foo == fun foo() { @@ -24,4 +24,4 @@ fun foo() { } --------------------- 2 : Int NEW: r(2) -> -===================== \ No newline at end of file +===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values b/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values index 16d26ec0c7c..42b73d35184 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values @@ -17,15 +17,19 @@ get() { return $a } --------------------- - : A NEW: magic[IMPLICIT_RECEIVER]($a) -> -$a : Int NEW: r($a|) -> + : A NEW: magic[IMPLICIT_RECEIVER]($a) -> +$a : Int NEW: r($a|) -> +return $a !: * +{ return $a } !: * COPY ===================== == set_a == set(v: Int) { $a = v } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](v: Int) -> - : A NEW: magic[IMPLICIT_RECEIVER]($a) -> -v : Int NEW: r(v) -> + : Int NEW: magic[FAKE_INITIALIZER](v: Int) -> + : A NEW: magic[IMPLICIT_RECEIVER]($a) -> +v : Int NEW: r(v) -> +$a = v !: * +{ $a = v } !: * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions index ee3f1acca74..8b2f83a5577 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions @@ -49,8 +49,9 @@ L5 [skipFinallyToErrorBlock]: v(val a = 1) INIT: in: {} out: {a=D} r(1) -> INIT: in: {a=D} out: {a=D} w(a|) INIT: in: {a=D} out: {a=ID} - 2 mark("after") INIT: in: {} out: {} - r("after") -> + 2 merge(try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 }|, !) -> INIT: in: {} out: {} + mark("after") + r("after") -> L1: 1 error: diff --git a/compiler/testData/cfg-variables/lexicalScopes/tryScope.values b/compiler/testData/cfg-variables/lexicalScopes/tryScope.values index 76ef8379d2e..5a15f3baf77 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/tryScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/tryScope.values @@ -13,13 +13,14 @@ fun foo() { "after" } --------------------- - : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> -"before" : * NEW: r("before") -> -foo() : * NEW: call(foo(), foo) -> -{ foo() } : * COPY -e : {<: Exception} NEW: r(e) -> -1 : Int NEW: r(1) -> -try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } : * COPY -"after" : * NEW: r("after") -> -{ "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } : * COPY + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> +"before" : * NEW: r("before") -> +foo() : * NEW: call(foo(), foo) -> +{ foo() } : * COPY +e : {<: Exception} NEW: r(e) -> +{ val a = e } !: * +1 : Int NEW: r(1) -> +try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } : * NEW: merge(try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 }|, !) -> +"after" : * NEW: r("after") -> +{ "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions index 08521566d7a..d6d9bed4816 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions @@ -22,9 +22,9 @@ L4 [body entry point]: v(val a: Int) INIT: in: {} out: {a=D} 2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {} L3 [loop exit point]: -- read (Unit) -> +- read (Unit) - mark("after") -- r("after") -> +- r("after") -> L1: 1 INIT: in: {} out: {} error: diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values index c11056bc64a..73b6bb223ae 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values @@ -10,6 +10,6 @@ fun foo() { : * NEW: magic[VALUE_CONSUMER](true|) -> "before" : * NEW: r("before") -> true : Boolean NEW: r(true) -> -"after" : * NEW: r("after") -> -{ "before" while (true) { val a: Int } "after" } : * COPY +"after" : * NEW: r("after") -> +{ "before" while (true) { val a: Int } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg/bugs/jumpToOuterScope.instructions b/compiler/testData/cfg/bugs/jumpToOuterScope.instructions index 1e8977e579e..b3bed52a215 100644 --- a/compiler/testData/cfg/bugs/jumpToOuterScope.instructions +++ b/compiler/testData/cfg/bugs/jumpToOuterScope.instructions @@ -46,11 +46,12 @@ sink: L7: 5 6 mark(break) - jmp(L2) NEXT:[read (Unit)] + jmp(L2) NEXT:[read (Unit)] +- 5 ret(*|!) L8 PREV:[] L8: - 5 NEXT:[] PREV:[] + NEXT:[] PREV:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/bugs/jumpToOuterScope.values b/compiler/testData/cfg/bugs/jumpToOuterScope.values index b0a3ca9ea68..85d73202db1 100644 --- a/compiler/testData/cfg/bugs/jumpToOuterScope.values +++ b/compiler/testData/cfg/bugs/jumpToOuterScope.values @@ -7,15 +7,19 @@ fun foo(c: Collection) { } } --------------------- - : {<: Collection} NEW: magic[FAKE_INITIALIZER](c: Collection) -> - : Int NEW: magic[LOOP_RANGE_ITERATION](c|) -> -c : {<: Iterable} NEW: r(c) -> -{ break } : * NEW: r({ break }) -> -{ { break } } : * COPY + : {<: Collection} NEW: magic[FAKE_INITIALIZER](c: Collection) -> + : Int NEW: magic[LOOP_RANGE_ITERATION](c|) -> +c : {<: Iterable} NEW: r(c) -> +{ break } : * NEW: r({ break }) -> +{ { break } } : * COPY +for (e in c) { { break } } !: * +{ for (e in c) { { break } } } !: * COPY ===================== == anonymous_0 == { break } --------------------- +break !: * +break !: * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/Finally.instructions b/compiler/testData/cfg/controlStructures/Finally.instructions index d5d1797d6af..9fd97fcc5e0 100644 --- a/compiler/testData/cfg/controlStructures/Finally.instructions +++ b/compiler/testData/cfg/controlStructures/Finally.instructions @@ -143,12 +143,13 @@ L4: jf(L6|) NEXT:[read (Unit), mark({ return@l })] 6 mark({ return@l }) ret L5 NEXT:[] -- 5 jmp(L7) NEXT:[] PREV:[] +- 5 jmp(L7) NEXT:[ret(*|!) L5] PREV:[] L6: read (Unit) PREV:[jf(L6|)] -L5: L7: - 4 NEXT:[] PREV:[ret L5, read (Unit)] + 4 ret(*|!) L5 +L5: + NEXT:[] PREV:[ret L5, ret(*|!) L5] error: PREV:[] sink: @@ -227,8 +228,9 @@ L5 [onExceptionToFinallyBlock]: L10 [skipFinallyToErrorBlock]: 7 mark({ 2 }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] r(2) -> + 3 ret(*|!) L4 L4: - 3 NEXT:[] PREV:[ret L4, r(2) -> ] + NEXT:[] PREV:[ret L4, ret(*|!) L4] error: PREV:[jmp(error)] sink: @@ -342,17 +344,17 @@ L8: 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> ] L4 [loop exit point]: read (Unit) PREV:[jmp(L4 [loop exit point])] - r(5) -> + r(5) -> 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: @@ -408,12 +410,12 @@ L4 [loop exit point]: L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: @@ -547,17 +549,17 @@ L8: 4 jmp?(L5 [loop entry point]) NEXT:[magic[LOOP_RANGE_ITERATION](1..a|) -> , read (Unit)] L3: read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])] - 3 r(5) -> + 3 r(5) -> 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: @@ -622,12 +624,12 @@ L3: L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: @@ -735,8 +737,8 @@ L0: 1 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } }) mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }) - jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] - jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] + jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] + jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] 3 mark({ return 1 }) r(1) -> L4 [start finally]: @@ -745,36 +747,37 @@ L4 [start finally]: mark(doSmth(3)) call(doSmth(3), doSmth|) -> L5 [finish finally]: - 3 ret(*|) L1 NEXT:[] -- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] + 3 ret(*|) L1 NEXT:[] +- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] L2 [onException]: - 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] - magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> - w(e|) + 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] + magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> + w(e|) 4 mark({ doSmth(2) }) - r(2) -> + r(2) -> mark(doSmth(2)) - call(doSmth(2), doSmth|) -> + call(doSmth(2), doSmth|) -> 3 jmp(L6 [afterCatches]) L6 [afterCatches]: - 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] + 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] L3 [onExceptionToFinallyBlock]: - 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] + 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> - 2 jmp(error) NEXT:[] + 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: - 4 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] + 4 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> + 2 merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!, ) -> L1: - 1 NEXT:[] PREV:[ret(*|) L1, call(doSmth(3), doSmth|) -> ] + 1 NEXT:[] PREV:[ret(*|) L1, merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!, ) -> ] error: - PREV:[jmp(error)] + PREV:[jmp(error)] sink: - PREV:[, ] + PREV:[, ] ===================== == t14 == fun t14() : Int { @@ -790,27 +793,28 @@ L0: 1 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } }) mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }) - jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), mark({ return 1 })] + jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), mark({ return 1 })] 3 mark({ return 1 }) r(1) -> - ret(*|) L1 NEXT:[] -- 2 jmp(L3 [afterCatches]) NEXT:[] PREV:[] + ret(*|) L1 NEXT:[] +- 2 jmp(L3 [afterCatches]) NEXT:[merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!, ) -> ] PREV:[] L2 [onException]: - 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] - magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> - w(e|) + 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] + magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> + w(e|) 4 mark({ doSmth(2) }) - r(2) -> + r(2) -> mark(doSmth(2)) - call(doSmth(2), doSmth|) -> + call(doSmth(2), doSmth|) -> 3 jmp(L3 [afterCatches]) -L1: L3 [afterCatches]: - 1 NEXT:[] PREV:[ret(*|) L1, jmp(L3 [afterCatches])] + 2 merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!, ) -> +L1: + 1 NEXT:[] PREV:[ret(*|) L1, merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!, ) -> ] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== == t15 == fun t15() : Int { @@ -829,8 +833,8 @@ L0: 1 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } }) mark(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }) - jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] - jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] + jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] + jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] 3 mark({ return 1 }) r(1) -> L4 [start finally]: @@ -839,39 +843,40 @@ L4 [start finally]: mark(doSmth(3)) call(doSmth(3), doSmth|) -> L5 [finish finally]: - 3 ret(*|) L1 NEXT:[] -- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] + 3 ret(*|) L1 NEXT:[] +- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] L2 [onException]: - 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] - magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> - w(e|) + 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] + magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> + w(e|) 4 mark({ return 2 }) - r(2) -> + r(2) -> mark({ doSmth(3) }) r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> - ret(*|) L1 NEXT:[] -- 3 jmp(L6 [afterCatches]) PREV:[] + ret(*|) L1 NEXT:[] +- 3 jmp(L6 [afterCatches]) PREV:[] L6 [afterCatches]: -- 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[] +- 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[] L3 [onExceptionToFinallyBlock]: - 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] + 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> - 2 jmp(error) NEXT:[] + 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: -- 4 mark({ doSmth(3) }) PREV:[] -- r(3) -> PREV:[] -- mark(doSmth(3)) PREV:[] -- call(doSmth(3), doSmth|) -> PREV:[] +- 4 mark({ doSmth(3) }) PREV:[] +- r(3) -> PREV:[] +- mark(doSmth(3)) PREV:[] +- call(doSmth(3), doSmth|) -> PREV:[] +- 2 merge(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|!, !) -> PREV:[] L1: - 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] + 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] error: - PREV:[jmp(error)] + PREV:[jmp(error)] sink: - PREV:[, ] + PREV:[, ] ===================== == t16 == fun t16() : Int { @@ -890,15 +895,15 @@ L0: 1 2 mark({ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } }) mark(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }) - jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] - jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ doSmth(1) })] + jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] + jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ doSmth(1) })] 3 mark({ doSmth(1) }) r(1) -> mark(doSmth(1)) call(doSmth(1), doSmth|) -> - 2 jmp(L4 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] + 2 jmp(L4 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] L2 [onException]: - 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] + 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> w(e|) 4 mark({ return 2 }) @@ -909,27 +914,28 @@ L5 [start finally]: mark(doSmth(3)) call(doSmth(3), doSmth|) -> L6 [finish finally]: - 4 ret(*|) L1 NEXT:[] -- 3 jmp(L4 [afterCatches]) PREV:[] + 4 ret(*|) L1 NEXT:[] +- 3 jmp(L4 [afterCatches]) PREV:[] L4 [afterCatches]: - 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4 [afterCatches])] + 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4 [afterCatches])] L3 [onExceptionToFinallyBlock]: - 5 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] + 5 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> - 2 jmp(error) NEXT:[] + 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: - 5 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] + 5 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] r(3) -> mark(doSmth(3)) call(doSmth(3), doSmth|) -> + 2 merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|, !) -> L1: - 1 NEXT:[] PREV:[ret(*|) L1, call(doSmth(3), doSmth|) -> ] + 1 NEXT:[] PREV:[ret(*|) L1, merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|, !) -> ] error: - PREV:[jmp(error)] + PREV:[jmp(error)] sink: - PREV:[, ] + PREV:[, ] ===================== == doSmth == fun doSmth(i: Int) { diff --git a/compiler/testData/cfg/controlStructures/Finally.values b/compiler/testData/cfg/controlStructures/Finally.values index 4fbfca31178..52b9de59dd0 100644 --- a/compiler/testData/cfg/controlStructures/Finally.values +++ b/compiler/testData/cfg/controlStructures/Finally.values @@ -26,12 +26,18 @@ fun t2() { } } --------------------- -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +return !: * +{ return } !: * COPY +if (2 > 3) { return } !: * COPY +{ 1 if (2 > 3) { return } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { 1 if (2 > 3) { return } } finally { 2 } !: * COPY +{ try { 1 if (2 > 3) { return } } finally { 2 } } !: * COPY ===================== == t3 == fun t3() { @@ -63,9 +69,13 @@ try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } : * COPY } } --------------------- -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +return@l !: * +{ return@l } !: * COPY +if (2 > 3) { return@l } !: * COPY +if (2 > 3) { return@l } !: * COPY ===================== == t4 == fun t4() { @@ -97,12 +107,18 @@ fun t4() { } } --------------------- -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +return@l !: * +{ return@l } !: * COPY +if (2 > 3) { return@l } !: * COPY +{ 1 if (2 > 3) { return@l } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { 1 if (2 > 3) { return@l } } finally { 2 } !: * COPY +try { 1 if (2 > 3) { return@l } } finally { 2 } !: * COPY ===================== == t5 == fun t5() { @@ -118,14 +134,23 @@ fun t5() { } } --------------------- - : * NEW: magic[VALUE_CONSUMER](true|) -> -true : Boolean NEW: r(true) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +true : Boolean NEW: r(true) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +break @l !: * +{ break @l } !: * COPY +if (2 > 3) { break @l } !: * COPY +{ 1 if (2 > 3) { break @l } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { 1 if (2 > 3) { break @l } } finally { 2 } !: * COPY +{ try { 1 if (2 > 3) { break @l } } finally { 2 } } !: * COPY +while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } !: * +@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } !: * COPY +{ @l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } } !: * COPY ===================== == t6 == fun t6() { @@ -148,12 +173,18 @@ true : 2 : {<: Comparable} NEW: r(2) -> 3 : Int NEW: r(3) -> 2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -5 : * NEW: r(5) -> -{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } : * COPY -2 : * NEW: r(2) -> -{ 2 } : * COPY -try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } : * COPY -{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } : * COPY +break @l !: * +{ break @l } !: * COPY +if (2 > 3) { break @l } !: * COPY +{ 1 if (2 > 3) { break @l } } !: * COPY +while(true) { 1 if (2 > 3) { break @l } } !: * +@l while(true) { 1 if (2 > 3) { break @l } } !: * COPY +5 : * NEW: r(5) -> +{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } : * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } : * COPY +{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } : * COPY ===================== == t7 == fun t7() { @@ -169,14 +200,23 @@ fun t7() { } } --------------------- - : * NEW: magic[VALUE_CONSUMER](true|) -> -true : Boolean NEW: r(true) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +true : Boolean NEW: r(true) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +break @l !: * +{ break @l } !: * COPY +if (2 > 3) { break @l } !: * COPY +{ 1 if (2 > 3) { break @l } } !: * COPY +while(true) { 1 if (2 > 3) { break @l } } !: * +@l while(true) { 1 if (2 > 3) { break @l } } !: * COPY +{ @l while(true) { 1 if (2 > 3) { break @l } } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { @l while(true) { 1 if (2 > 3) { break @l } } } finally { 2 } !: * COPY +{ try { @l while(true) { 1 if (2 > 3) { break @l } } } finally { 2 } } !: * COPY ===================== == t8 == fun t8(a : Int) { @@ -192,17 +232,26 @@ fun t8(a : Int) { } } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](a : Int) -> - : Int NEW: magic[LOOP_RANGE_ITERATION](1..a|) -> -1 : Int NEW: r(1) -> -a : Int NEW: r(a) -> -1..a : {<: Iterable} NEW: call(1..a, rangeTo|, ) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : Int NEW: magic[FAKE_INITIALIZER](a : Int) -> + : Int NEW: magic[LOOP_RANGE_ITERATION](1..a|) -> +1 : Int NEW: r(1) -> +a : Int NEW: r(a) -> +1..a : {<: Iterable} NEW: call(1..a, rangeTo|, ) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +continue @l !: * +{ continue @l } !: * COPY +if (2 > 3) { continue @l } !: * COPY +{ 1 if (2 > 3) { continue @l } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { 1 if (2 > 3) { continue @l } } finally { 2 } !: * COPY +{ try { 1 if (2 > 3) { continue @l } } finally { 2 } } !: * COPY +for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } !: * +@l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } !: * COPY +{ @l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } } !: * COPY ===================== == t9 == fun t9(a : Int) { @@ -228,12 +277,18 @@ a 2 : {<: Comparable} NEW: r(2) -> 3 : Int NEW: r(3) -> 2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -5 : * NEW: r(5) -> -{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } : * COPY -2 : * NEW: r(2) -> -{ 2 } : * COPY -try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } : * COPY -{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } : * COPY +continue @l !: * +{ continue @l } !: * COPY +if (2 > 3) { continue @l } !: * COPY +{ 1 if (2 > 3) { continue @l } } !: * COPY +for (i in 1..a) { 1 if (2 > 3) { continue @l } } !: * +@l for (i in 1..a) { 1 if (2 > 3) { continue @l } } !: * COPY +5 : * NEW: r(5) -> +{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } : * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } : * COPY +{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } : * COPY ===================== == t10 == fun t10(a : Int) { @@ -249,17 +304,26 @@ fun t10(a : Int) { } } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](a : Int) -> - : Int NEW: magic[LOOP_RANGE_ITERATION](1..a|) -> -1 : Int NEW: r(1) -> -a : Int NEW: r(a) -> -1..a : {<: Iterable} NEW: call(1..a, rangeTo|, ) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : Int NEW: magic[FAKE_INITIALIZER](a : Int) -> + : Int NEW: magic[LOOP_RANGE_ITERATION](1..a|) -> +1 : Int NEW: r(1) -> +a : Int NEW: r(a) -> +1..a : {<: Iterable} NEW: call(1..a, rangeTo|, ) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +continue @l !: * +{ continue @l } !: * COPY +if (2 > 3) { continue @l } !: * COPY +{ 1 if (2 > 3) { continue @l } } !: * COPY +for (i in 1..a) { 1 if (2 > 3) { continue @l } } !: * +@l for (i in 1..a) { 1 if (2 > 3) { continue @l } } !: * COPY +{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } !: * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } finally { 2 } !: * COPY +{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } finally { 2 } } !: * COPY ===================== == t11 == fun t11() { @@ -271,8 +335,14 @@ fun t11() { } } --------------------- -1 : {<: Unit} NEW: r(1) -> -2 : {<: Unit} NEW: r(2) -> +1 : Unit NEW: r(1) -> +return 1 !: * +{ return 1 } !: * COPY +2 : Unit NEW: r(2) -> +return 2 !: * +{ return 2 } !: * COPY +try { return 1 } finally { return 2 } !: * COPY +{ try { return 1 } finally { return 2 } } !: * COPY ===================== == t12 == fun t12() : Int { @@ -284,10 +354,14 @@ fun t12() : Int { } } --------------------- -1 : Int NEW: r(1) -> -3 : Int NEW: r(3) -> -doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> -{ doSmth(3) } : * COPY +1 : Int NEW: r(1) -> +return 1 !: * +{ return 1 } !: * COPY +3 : Int NEW: r(3) -> +doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> +{ doSmth(3) } : * COPY +try { return 1 } finally { doSmth(3) } !: * COPY +{ try { return 1 } finally { doSmth(3) } } !: * COPY ===================== == t13 == fun t13() : Int { @@ -302,16 +376,18 @@ fun t13() : Int { } } --------------------- - : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> -1 : Int NEW: r(1) -> -2 : Int NEW: r(2) -> -doSmth(2) : * NEW: call(doSmth(2), doSmth|) -> -{ doSmth(2) } : * COPY -3 : Int NEW: r(3) -> -doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> -{ doSmth(3) } : * COPY -try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } : * COPY -{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } : * COPY + : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> +1 : Int NEW: r(1) -> +return 1 !: * +{ return 1 } !: * COPY +2 : Int NEW: r(2) -> +doSmth(2) : * NEW: call(doSmth(2), doSmth|) -> +{ doSmth(2) } : * COPY +3 : Int NEW: r(3) -> +doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> +{ doSmth(3) } : * COPY +try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } : * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!, ) -> +{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } : * COPY ===================== == t14 == fun t14() : Int { @@ -323,13 +399,15 @@ fun t14() : Int { } } --------------------- - : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> -1 : Int NEW: r(1) -> -2 : Int NEW: r(2) -> -doSmth(2) : * NEW: call(doSmth(2), doSmth|) -> -{ doSmth(2) } : * COPY -try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } : * COPY -{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } : * COPY + : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> +1 : Int NEW: r(1) -> +return 1 !: * +{ return 1 } !: * COPY +2 : Int NEW: r(2) -> +doSmth(2) : * NEW: call(doSmth(2), doSmth|) -> +{ doSmth(2) } : * COPY +try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } : * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!, ) -> +{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } : * COPY ===================== == t15 == fun t15() : Int { @@ -344,12 +422,18 @@ fun t15() : Int { } } --------------------- - : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> -1 : Int NEW: r(1) -> -2 : Int NEW: r(2) -> -3 : Int NEW: r(3) -> -doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> -{ doSmth(3) } : * COPY + : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> +1 : Int NEW: r(1) -> +return 1 !: * +{ return 1 } !: * COPY +2 : Int NEW: r(2) -> +return 2 !: * +{ return 2 } !: * COPY +3 : Int NEW: r(3) -> +doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> +{ doSmth(3) } : * COPY +try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } : * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|!, !) -> +{ try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } : * COPY ===================== == t16 == fun t16() : Int { @@ -364,16 +448,18 @@ fun t16() : Int { } } --------------------- - : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> -1 : Int NEW: r(1) -> -doSmth(1) : * NEW: call(doSmth(1), doSmth|) -> -{ doSmth(1) } : * COPY -2 : Int NEW: r(2) -> -3 : Int NEW: r(3) -> -doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> -{ doSmth(3) } : * COPY -try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } : * COPY -{ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } : * COPY + : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> +1 : Int NEW: r(1) -> +doSmth(1) : * NEW: call(doSmth(1), doSmth|) -> +{ doSmth(1) } : * COPY +2 : Int NEW: r(2) -> +return 2 !: * +{ return 2 } !: * COPY +3 : Int NEW: r(3) -> +doSmth(3) : * NEW: call(doSmth(3), doSmth|) -> +{ doSmth(3) } : * COPY +try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } : * NEW: merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|, !) -> +{ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } : * COPY ===================== == doSmth == fun doSmth(i: Int) { diff --git a/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions b/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions index 292c4442875..ac3d418a18f 100644 --- a/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions +++ b/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions @@ -110,7 +110,7 @@ L6 [skipFinallyToErrorBlock]: 3 mark({ return 1 }) PREV:[jmp(L6 [skipFinallyToErrorBlock])] r(1) -> ret(*|) L1 NEXT:[] -- 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|, , ) -> PREV:[] +- 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|, , ) -> PREV:[] L1: 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] error: @@ -142,30 +142,30 @@ L0: 2 mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }) L2 [loop entry point]: L5 [condition entry point]: - mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] + mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] call(cond(), cond) -> mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) - jf(L3 [loop exit point]|) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })] + jf(L3 [loop exit point]|) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })] L4 [body entry point]: 3 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }) - jmp?(L6 [onException]) NEXT:[jmp?(L9 [catch 0]), jmp?(L7 [onExceptionToFinallyBlock])] - jmp?(L7 [onExceptionToFinallyBlock]) NEXT:[mark({ if (cond()) return else continue }), mark({ doSmth() })] + jmp?(L6 [onException]) NEXT:[jmp?(L9 [catch 0]), jmp?(L7 [onExceptionToFinallyBlock])] + jmp?(L7 [onExceptionToFinallyBlock]) NEXT:[mark({ if (cond()) return else continue }), mark({ doSmth() })] 4 mark({ doSmth() }) mark(doSmth()) call(doSmth(), doSmth) -> - 3 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] + 3 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] L6 [onException]: - jmp?(L9 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L6 [onException])] + jmp?(L9 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L6 [onException])] 4 v(e: NullPointerException) magic[FAKE_INITIALIZER](e: NullPointerException) -> w(e|) 5 mark({ doSmth1() }) mark(doSmth1()) call(doSmth1(), doSmth1) -> - 4 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] + 4 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] L9 [catch 0]: - v(e: Exception) PREV:[jmp?(L9 [catch 0])] + v(e: Exception) PREV:[jmp?(L9 [catch 0])] magic[FAKE_INITIALIZER](e: Exception) -> w(e|) 5 mark({ doSmth2() }) @@ -173,40 +173,42 @@ L9 [catch 0]: call(doSmth2(), doSmth2) -> 4 jmp(L8 [afterCatches]) L8 [afterCatches]: - 3 jmp(L10 [skipFinallyToErrorBlock]) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L8 [afterCatches]), jmp(L8 [afterCatches]), jmp(L8 [afterCatches])] + 3 jmp(L10 [skipFinallyToErrorBlock]) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L8 [afterCatches]), jmp(L8 [afterCatches]), jmp(L8 [afterCatches])] L7 [onExceptionToFinallyBlock]: L11 [start finally]: - 4 mark({ if (cond()) return else continue }) PREV:[jmp?(L7 [onExceptionToFinallyBlock])] + 4 mark({ if (cond()) return else continue }) PREV:[jmp?(L7 [onExceptionToFinallyBlock])] mark(if (cond()) return else continue) mark(cond()) call(cond(), cond) -> - jf(L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] - ret L1 NEXT:[] -- jmp(L13) NEXT:[jmp(error)] PREV:[] + jf(L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] + ret L1 NEXT:[] +- jmp(L13) NEXT:[merge(if (cond()) return else continue|!, !) -> ] PREV:[] L12: - jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(L12|)] + jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(L12|)] L13: +- merge(if (cond()) return else continue|!, !) -> PREV:[] L14 [finish finally]: -- 3 jmp(error) NEXT:[] PREV:[] +- 3 jmp(error) NEXT:[] PREV:[] L10 [skipFinallyToErrorBlock]: - 4 mark({ if (cond()) return else continue }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] + 4 mark({ if (cond()) return else continue }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] mark(if (cond()) return else continue) mark(cond()) call(cond(), cond) -> - jf(copy L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] - ret L1 NEXT:[] -- jmp(copy L13) NEXT:[merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> ] PREV:[] - jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(copy L12|)] -- 3 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> PREV:[] -- 2 jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[] + jf(copy L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] + ret L1 NEXT:[] +- jmp(copy L13) NEXT:[merge(if (cond()) return else continue|!, !) -> ] PREV:[] + jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(copy L12|)] +- merge(if (cond()) return else continue|!, !) -> PREV:[] +- 3 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> PREV:[] +- 2 jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[] L3 [loop exit point]: - read (Unit) PREV:[jf(L3 [loop exit point]|)] + read (Unit) PREV:[jf(L3 [loop exit point]|)] L1: - 1 NEXT:[] PREV:[ret L1, ret L1, read (Unit)] + 1 NEXT:[] PREV:[ret L1, ret L1, read (Unit)] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== == testCopy3 == fun testCopy3() { @@ -276,7 +278,7 @@ L6 [skipFinallyToErrorBlock]: jf(copy L9 [loop exit point]|) NEXT:[read (Unit), jmp(copy L8 [loop entry point])] jmp(copy L8 [loop entry point]) NEXT:[mark(cond())] read (Unit) PREV:[jf(copy L9 [loop exit point]|)] - 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|, , ) -> + 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|, , ) -> L1: 1 NEXT:[] error: diff --git a/compiler/testData/cfg/controlStructures/FinallyTestCopy.values b/compiler/testData/cfg/controlStructures/FinallyTestCopy.values index b65a79dad80..710b3c5e900 100644 --- a/compiler/testData/cfg/controlStructures/FinallyTestCopy.values +++ b/compiler/testData/cfg/controlStructures/FinallyTestCopy.values @@ -39,8 +39,10 @@ doSmth1() doSmth2() : * NEW: call(doSmth2(), doSmth2) -> { doSmth2() } : * COPY 1 : Int NEW: r(1) -> -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|, , ) -> -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } : * COPY +return 1 !: * +{ return 1 } !: * COPY +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|, , ) -> +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } : * COPY ===================== == testCopy2 == fun testCopy2() { @@ -61,18 +63,24 @@ fun testCopy2() { } } --------------------- - : {<: NullPointerException} NEW: magic[FAKE_INITIALIZER](e: NullPointerException) -> - : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> -cond() : Boolean NEW: call(cond(), cond) -> -doSmth() : * NEW: call(doSmth(), doSmth) -> -{ doSmth() } : * COPY -doSmth1() : * NEW: call(doSmth1(), doSmth1) -> -{ doSmth1() } : * COPY -doSmth2() : * NEW: call(doSmth2(), doSmth2) -> -{ doSmth2() } : * COPY -cond() : Boolean NEW: call(cond(), cond) -> -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } : * COPY + : {<: NullPointerException} NEW: magic[FAKE_INITIALIZER](e: NullPointerException) -> + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> +cond() : Boolean NEW: call(cond(), cond) -> +doSmth() : * NEW: call(doSmth(), doSmth) -> +{ doSmth() } : * COPY +doSmth1() : * NEW: call(doSmth1(), doSmth1) -> +{ doSmth1() } : * COPY +doSmth2() : * NEW: call(doSmth2(), doSmth2) -> +{ doSmth2() } : * COPY +cond() : Boolean NEW: call(cond(), cond) -> +return !: * +continue !: * +if (cond()) return else continue : * NEW: merge(if (cond()) return else continue|!, !) -> +{ if (cond()) return else continue } : * COPY +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } : * COPY +while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } !: * +{ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } } !: * COPY ===================== == testCopy3 == fun testCopy3() { @@ -99,8 +107,10 @@ doSmth1() doSmth2() : * NEW: call(doSmth2(), doSmth2) -> { doSmth2() } : * COPY cond() : Boolean NEW: call(cond(), cond) -> -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|, , ) -> -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } : * COPY +while (cond()) !: * +{ while (cond()); } !: * COPY +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } : * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|, , ) -> +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } : * COPY ===================== == doTestCopy4 == fun doTestCopy4(list: List?) : Int { @@ -116,9 +126,12 @@ fun doTestCopy4(list: List?) : Int { : {<: List?} NEW: magic[FAKE_INITIALIZER](list: List?) -> doSmth() : * NEW: call(doSmth(), doSmth) -> { doSmth() } : * COPY -list : * NEW: r(list) -> -null : * NEW: r(null) -> +list : * NEW: r(list) -> +null : * NEW: r(null) -> list != null : Boolean NEW: call(list != null, equals|, ) -> +{ } !: * +if(list != null) { } !: * COPY +{ if(list != null) { } } !: * COPY try { doSmth() } finally { if(list != null) { } } : * COPY { try { doSmth() } finally { if(list != null) { } } } : * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/For.values b/compiler/testData/cfg/controlStructures/For.values index eabbcdce3a8..ad69b1e1003 100644 --- a/compiler/testData/cfg/controlStructures/For.values +++ b/compiler/testData/cfg/controlStructures/For.values @@ -5,13 +5,15 @@ fun t1() { } } --------------------- - : Int NEW: magic[LOOP_RANGE_ITERATION](1..2|) -> -1 : Int NEW: r(1) -> -2 : Int NEW: r(2) -> -1..2 : {<: Iterable} NEW: call(1..2, rangeTo|, ) -> -i : Int NEW: r(i) -> -doSmth(i) : * NEW: call(doSmth(i), doSmth|) -> -{ doSmth(i) } : * COPY + : Int NEW: magic[LOOP_RANGE_ITERATION](1..2|) -> +1 : Int NEW: r(1) -> +2 : Int NEW: r(2) -> +1..2 : {<: Iterable} NEW: call(1..2, rangeTo|, ) -> +i : Int NEW: r(i) -> +doSmth(i) : * NEW: call(doSmth(i), doSmth|) -> +{ doSmth(i) } : * COPY +for (i in 1..2) { doSmth(i) } !: * +{ for (i in 1..2) { doSmth(i) } } !: * COPY ===================== == doSmth == fun doSmth(i: Int) {} diff --git a/compiler/testData/cfg/controlStructures/If.instructions b/compiler/testData/cfg/controlStructures/If.instructions index 31c9de62812..4da8eeabc17 100644 --- a/compiler/testData/cfg/controlStructures/If.instructions +++ b/compiler/testData/cfg/controlStructures/If.instructions @@ -30,31 +30,32 @@ L0: mark("s") r("s") -> w(u|) - 2 jmp(L3) NEXT:[r(u) -> ] + 2 jmp(L3) NEXT:[r(u) -> ] L2: read (Unit) PREV:[jf(L2|)] L3: - r(u) -> PREV:[jmp(L3), read (Unit)] + r(u) -> PREV:[jmp(L3), read (Unit)] mark(doSmth(u)) - call(doSmth(u), doSmth|) -> + call(doSmth(u), doSmth|) -> v(var r: String) mark(if (b) { r = "s" } else { r = "t" }) - r(b) -> - jf(L4|) NEXT:[mark({ r = "t" }), mark({ r = "s" })] + r(b) -> + jf(L4|) NEXT:[mark({ r = "t" }), mark({ r = "s" })] 3 mark({ r = "s" }) mark("s") - r("s") -> - w(r|) - 2 jmp(L5) NEXT:[r(r) -> ] -L4: - 3 mark({ r = "t" }) PREV:[jf(L4|)] - mark("t") - r("t") -> + r("s") -> w(r|) + 2 jmp(L5) NEXT:[merge(if (b) { r = "s" } else { r = "t" }|!, !) -> ] +L4: + 3 mark({ r = "t" }) PREV:[jf(L4|)] + mark("t") + r("t") -> + w(r|) L5: - 2 r(r) -> PREV:[jmp(L5), w(r|)] + 2 merge(if (b) { r = "s" } else { r = "t" }|!, !) -> PREV:[jmp(L5), w(r|)] + r(r) -> mark(doSmth(r)) - call(doSmth(r), doSmth|) -> + call(doSmth(r), doSmth|) -> L1: 1 NEXT:[] error: @@ -88,23 +89,23 @@ L0: jf(L2|) NEXT:[read (Unit), mark({ return; })] 3 mark({ return; }) ret L1 NEXT:[] -- 2 jmp(L3) NEXT:[r(i) -> ] PREV:[] +- 2 jmp(L3) NEXT:[r(i) -> ] PREV:[] L2: read (Unit) PREV:[jf(L2|)] L3: - r(i) -> + r(i) -> mark(doSmth(i)) - call(doSmth(i), doSmth|) -> + call(doSmth(i), doSmth|) -> mark(if (i is Int) { return; }) mark(i is Int) - r(i) -> - magic[IS](i is Int|) -> - jf(L4|) NEXT:[read (Unit), mark({ return; })] + r(i) -> + magic[IS](i is Int|) -> + jf(L4|) NEXT:[read (Unit), mark({ return; })] 3 mark({ return; }) ret L1 NEXT:[] - 2 jmp(L5) NEXT:[] PREV:[] L4: - read (Unit) PREV:[jf(L4|)] + read (Unit) PREV:[jf(L4|)] L1: L5: 1 NEXT:[] PREV:[ret L1, ret L1, read (Unit)] diff --git a/compiler/testData/cfg/controlStructures/If.values b/compiler/testData/cfg/controlStructures/If.values index 8c29d25273c..e1c083d49fb 100644 --- a/compiler/testData/cfg/controlStructures/If.values +++ b/compiler/testData/cfg/controlStructures/If.values @@ -16,17 +16,25 @@ fun t1(b: Boolean) { doSmth(r) } --------------------- - : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> -b : Boolean NEW: r(b) -> -"s" : String NEW: r("s") -> -u : String NEW: r(u) -> -doSmth(u) : * NEW: call(doSmth(u), doSmth|) -> -b : Boolean NEW: r(b) -> -"s" : String NEW: r("s") -> -"t" : String NEW: r("t") -> -r : String NEW: r(r) -> -doSmth(r) : * NEW: call(doSmth(r), doSmth|) -> -{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } : * COPY + : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> +b : Boolean NEW: r(b) -> +"s" : String NEW: r("s") -> +u = "s" !: * +{ u = "s" } !: * COPY +if (b) { u = "s" } !: * COPY +u : String NEW: r(u) -> +doSmth(u) : * NEW: call(doSmth(u), doSmth|) -> +b : Boolean NEW: r(b) -> +"s" : String NEW: r("s") -> +r = "s" !: * +{ r = "s" } !: * COPY +"t" : String NEW: r("t") -> +r = "t" !: * +{ r = "t" } !: * COPY +if (b) { r = "s" } else { r = "t" } : * NEW: merge(if (b) { r = "s" } else { r = "t" }|!, !) -> +r : String NEW: r(r) -> +doSmth(r) : * NEW: call(doSmth(r), doSmth|) -> +{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } : * COPY ===================== == t2 == fun t2(b: Boolean) { @@ -40,13 +48,20 @@ fun t2(b: Boolean) { } } --------------------- - : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> -3 : Int NEW: r(3) -> -b : Boolean NEW: r(b) -> -i : String NEW: r(i) -> -doSmth(i) : * NEW: call(doSmth(i), doSmth|) -> -i : * NEW: r(i) -> -i is Int : Boolean NEW: magic[IS](i is Int|) -> + : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> +3 : Int NEW: r(3) -> +b : Boolean NEW: r(b) -> +return !: * +{ return; } !: * COPY +if (b) { return; } !: * COPY +i : String NEW: r(i) -> +doSmth(i) : * NEW: call(doSmth(i), doSmth|) -> +i : * NEW: r(i) -> +i is Int : Boolean NEW: magic[IS](i is Int|) -> +return !: * +{ return; } !: * COPY +if (i is Int) { return; } !: * COPY +{ val i = 3 if (b) { return; } doSmth(i) if (i is Int) { return; } } !: * COPY ===================== == doSmth == fun doSmth(s: String) {} diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions index 0955b072dec..17ffead681c 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions @@ -44,11 +44,11 @@ L4 [body entry point]: mark({return}) ret L1 NEXT:[] L5 [condition entry point]: -- r(0) -> PREV:[] -- r(1) -> PREV:[] +- r(0) -> PREV:[] +- r(1) -> PREV:[] - mark(0 > 1) PREV:[] -- call(0 > 1, compareTo|, ) -> PREV:[] -- jt(L2 [loop entry point]|) NEXT:[read (Unit), mark({return})] PREV:[] +- call(0 > 1, compareTo|, ) -> PREV:[] +- jt(L2 [loop entry point]|) NEXT:[read (Unit), mark({return})] PREV:[] L3 [loop exit point]: - read (Unit) PREV:[] L1: diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values index 27bf2cc3078..db9d72033f0 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values @@ -5,11 +5,13 @@ fun main() { } } --------------------- -0 : {<: Comparable} NEW: r(0) -> -1 : Int NEW: r(1) -> -0 > 1 : Boolean NEW: call(0 > 1, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY +0 : {<: Comparable} NEW: r(0) -> +1 : Int NEW: r(1) -> +0 > 1 : Boolean NEW: call(0 > 1, compareTo|, ) -> +2 : * NEW: r(2) -> +{ 2 } : * COPY +while(0 > 1) { 2 } !: * +{ while(0 > 1) { 2 } } !: * COPY ===================== == dowhile == fun dowhile() { @@ -17,7 +19,11 @@ fun dowhile() { while(0 > 1) } --------------------- -0 : {<: Comparable} NEW: r(0) -> -1 : Int NEW: r(1) -> -0 > 1 : Boolean NEW: call(0 > 1, compareTo|, ) -> +return !: * +{return} !: * COPY +0 : {<: Comparable} NEW: r(0) -> +1 : Int NEW: r(1) -> +0 > 1 : Boolean NEW: call(0 > 1, compareTo|, ) -> +do {return} while(0 > 1) !: * +{ do {return} while(0 > 1) } !: * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/returnsInWhen.values b/compiler/testData/cfg/controlStructures/returnsInWhen.values index f322b917ae6..5d175b30015 100644 --- a/compiler/testData/cfg/controlStructures/returnsInWhen.values +++ b/compiler/testData/cfg/controlStructures/returnsInWhen.values @@ -5,8 +5,11 @@ fun illegalWhenBlock(a: Any): Any { } } --------------------- - : {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> -a : * NEW: r(a) -> -is Int : * NEW: magic[IS](is Int|) -> -a : {<: Any} NEW: r(a) -> + : {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> +a : * NEW: r(a) -> +is Int : * NEW: magic[IS](is Int|) -> +a : {<: Any} NEW: r(a) -> +return a !: * +when(a) { is Int -> return a } !: * COPY +{ when(a) { is Int -> return a } } !: * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/whenConditions.values b/compiler/testData/cfg/controlStructures/whenConditions.values index f50dcb47443..9dc67202b46 100644 --- a/compiler/testData/cfg/controlStructures/whenConditions.values +++ b/compiler/testData/cfg/controlStructures/whenConditions.values @@ -11,7 +11,7 @@ fun foo(a: Number) { } --------------------- : {<: Number} NEW: magic[FAKE_INITIALIZER](a: Number) -> -a : * NEW: r(a) -> +a : * NEW: r(a) -> 1 : * NEW: r(1) -> 1 : * NEW: magic[EQUALS_IN_WHEN_CONDITION](1|, ) -> "1" : {<: String?} NEW: r("1") -> diff --git a/compiler/testData/cfg/conventions/equals.values b/compiler/testData/cfg/conventions/equals.values index 8a51f921331..4445c376026 100644 --- a/compiler/testData/cfg/conventions/equals.values +++ b/compiler/testData/cfg/conventions/equals.values @@ -4,9 +4,12 @@ fun foo(a: Int, b: Int) { } } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> - : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> -a : OR{{<: Any}, {<: Any}} NEW: r(a) -> -b : * NEW: r(b) -> -a == b : Boolean NEW: call(a == b, equals|, ) -> + : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> + : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> +a : OR{{<: Any}, {<: Any}} NEW: r(a) -> +b : * NEW: r(b) -> +a == b : Boolean NEW: call(a == b, equals|, ) -> +{ } !: * +if (a == b) { } !: * COPY +{ if (a == b) { } } !: * COPY ===================== diff --git a/compiler/testData/cfg/conventions/notEqual.values b/compiler/testData/cfg/conventions/notEqual.values index c2890278034..a563c288b74 100644 --- a/compiler/testData/cfg/conventions/notEqual.values +++ b/compiler/testData/cfg/conventions/notEqual.values @@ -3,9 +3,12 @@ fun neq(a: Int, b: Int) { if (a != b) {} } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> - : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> -a : OR{{<: Any}, {<: Any}} NEW: r(a) -> -b : * NEW: r(b) -> -a != b : Boolean NEW: call(a != b, equals|, ) -> + : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> + : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> +a : OR{{<: Any}, {<: Any}} NEW: r(a) -> +b : * NEW: r(b) -> +a != b : Boolean NEW: call(a != b, equals|, ) -> +{} !: * +if (a != b) {} !: * COPY +{ if (a != b) {} } !: * COPY ===================== diff --git a/compiler/testData/cfg/deadCode/returnInElvis.instructions b/compiler/testData/cfg/deadCode/returnInElvis.instructions index a8837e2cd21..718d200f40d 100644 --- a/compiler/testData/cfg/deadCode/returnInElvis.instructions +++ b/compiler/testData/cfg/deadCode/returnInElvis.instructions @@ -6,15 +6,16 @@ fun foo() { L0: 1 2 mark({ return ?: null }) - ret L1 NEXT:[] -- mark(return ?: null) PREV:[] -- jt(L2) NEXT:[r(null) -> , ] PREV:[] -- r(null) -> PREV:[] -L1: + ret L1 NEXT:[] +- mark(return ?: null) PREV:[] +- jt(L2) NEXT:[r(null) -> , merge(return ?: null|!, ) -> ] PREV:[] +- r(null) -> PREV:[] L2: - 1 NEXT:[] PREV:[ret L1] +- merge(return ?: null|!, ) -> PREV:[] +L1: + 1 NEXT:[] PREV:[ret L1] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/deadCode/returnInElvis.values b/compiler/testData/cfg/deadCode/returnInElvis.values index 85d0877ad46..bfc914e2745 100644 --- a/compiler/testData/cfg/deadCode/returnInElvis.values +++ b/compiler/testData/cfg/deadCode/returnInElvis.values @@ -3,7 +3,8 @@ fun foo() { return ?: null } --------------------- -null : * NEW: r(null) -> -return ?: null : * COPY -{ return ?: null } : * COPY +return !: * +null : * NEW: r(null) -> +return ?: null : * NEW: merge(return ?: null|!, ) -> +{ return ?: null } : * COPY ===================== diff --git a/compiler/testData/cfg/deadCode/stringTemplate.instructions b/compiler/testData/cfg/deadCode/stringTemplate.instructions index fa210184da3..2ecdd940ba3 100644 --- a/compiler/testData/cfg/deadCode/stringTemplate.instructions +++ b/compiler/testData/cfg/deadCode/stringTemplate.instructions @@ -10,13 +10,13 @@ L0: mark(throw Exception()) mark(Exception()) call(Exception(), ) -> - throw (throw Exception()|) NEXT:[] -- r(1) -> PREV:[] -- magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|) -> PREV:[] + throw (throw Exception()|) NEXT:[] +- r(1) -> PREV:[] +- magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|!, ) -> PREV:[] L1: - 1 NEXT:[] PREV:[] + 1 NEXT:[] PREV:[] error: - PREV:[throw (throw Exception()|)] + PREV:[throw (throw Exception()|)] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/deadCode/stringTemplate.values b/compiler/testData/cfg/deadCode/stringTemplate.values index 4f1ba9aa6a9..d5496063a02 100644 --- a/compiler/testData/cfg/deadCode/stringTemplate.values +++ b/compiler/testData/cfg/deadCode/stringTemplate.values @@ -3,8 +3,9 @@ fun test() { "${throw Exception()} ${1}" } --------------------- -Exception() : {<: Throwable} NEW: call(Exception(), ) -> -1 : * NEW: r(1) -> -"${throw Exception()} ${1}" : * NEW: magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|) -> -{ "${throw Exception()} ${1}" } : * COPY +Exception() : {<: Throwable} NEW: call(Exception(), ) -> +throw Exception() !: * +1 : * NEW: r(1) -> +"${throw Exception()} ${1}" : * NEW: magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|!, ) -> +{ "${throw Exception()} ${1}" } : * COPY ===================== diff --git a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.instructions b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.instructions index 6818d2f4a2e..5033d258a64 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.instructions +++ b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.instructions @@ -27,9 +27,9 @@ L0: w($i|, ) 1 v(val j: Int get() = 20) 2 mark({ $i = 13 }) - magic[IMPLICIT_RECEIVER]($i) -> - r(13) -> - w($i|, ) + magic[IMPLICIT_RECEIVER]($i) -> + r(13) -> + w($i|, ) L1: 1 NEXT:[] error: diff --git a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values index 22fa9870f2c..c777cf4c0fb 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values +++ b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values @@ -15,9 +15,13 @@ class AnonymousInitializers() { } } --------------------- - : AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> - : AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> -34 : Int NEW: r(34) -> -12 : Int NEW: r(12) -> -13 : Int NEW: r(13) -> + : AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> + : AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> +34 : Int NEW: r(34) -> +12 : Int NEW: r(12) -> +$i = 12 !: * +{ $i = 12 } !: * COPY +13 : Int NEW: r(13) -> +$i = 13 !: * +{ $i = 13 } !: * COPY ===================== diff --git a/compiler/testData/cfg/declarations/functions/FailFunction.values b/compiler/testData/cfg/declarations/functions/FailFunction.values index f92e648ea4d..24109c1db5f 100644 --- a/compiler/testData/cfg/declarations/functions/FailFunction.values +++ b/compiler/testData/cfg/declarations/functions/FailFunction.values @@ -3,6 +3,8 @@ fun fail() : Nothing { throw java.lang.RuntimeException() } --------------------- -RuntimeException() : {<: Throwable} NEW: call(RuntimeException(), ) -> -java.lang.RuntimeException() : {<: Throwable} COPY +RuntimeException() : {<: Throwable} NEW: call(RuntimeException(), ) -> +java.lang.RuntimeException() : {<: Throwable} COPY +throw java.lang.RuntimeException() !: * +{ throw java.lang.RuntimeException() } !: * COPY ===================== diff --git a/compiler/testData/cfg/declarations/local/LocalDeclarations.instructions b/compiler/testData/cfg/declarations/local/LocalDeclarations.instructions index efb6b2b5137..6a3e4a0b35c 100644 --- a/compiler/testData/cfg/declarations/local/LocalDeclarations.instructions +++ b/compiler/testData/cfg/declarations/local/LocalDeclarations.instructions @@ -66,8 +66,8 @@ L0: magic[IMPLICIT_RECEIVER]($x) -> r(1) -> w($x|, ) - 2 r(object { val x : Int { $x = 1 } }) -> - w(a|) + 2 r(object { val x : Int { $x = 1 } }) -> + w(a|) L1: 1 NEXT:[] error: @@ -196,11 +196,11 @@ L0: magic[IMPLICIT_RECEIVER]($x) -> r(1) -> w($x|, ) - 2 jmp?(L2) NEXT:[r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> , d(fun ggg() { y = 10 })] + 2 jmp?(L2) NEXT:[r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> , d(fun ggg() { y = 10 })] d(fun ggg() { y = 10 }) NEXT:[] L2: - r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> PREV:[jmp?(L2)] - w(a|) + r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> PREV:[jmp?(L2)] + w(a|) L1: 1 NEXT:[] error: @@ -257,11 +257,11 @@ L0: 2 jmp?(L2) NEXT:[jmp?(L5), d(fun foo() { x = 3 })] d(fun foo() { x = 3 }) NEXT:[] L2: - jmp?(L5) NEXT:[r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> , d(fun bar() { x = 4 })] PREV:[jmp?(L2)] + jmp?(L5) NEXT:[r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> , d(fun bar() { x = 4 })] PREV:[jmp?(L2)] d(fun bar() { x = 4 }) NEXT:[] L5: - r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> PREV:[jmp?(L5)] - w(a|) + r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> PREV:[jmp?(L5)] + w(a|) L1: 1 NEXT:[] error: diff --git a/compiler/testData/cfg/declarations/local/LocalDeclarations.values b/compiler/testData/cfg/declarations/local/LocalDeclarations.values index b44de686959..db48c8297c5 100644 --- a/compiler/testData/cfg/declarations/local/LocalDeclarations.values +++ b/compiler/testData/cfg/declarations/local/LocalDeclarations.values @@ -36,7 +36,9 @@ fun test1() { --------------------- : NEW: magic[IMPLICIT_RECEIVER]($x) -> 1 : Int NEW: r(1) -> -object { val x : Int { $x = 1 } } : NEW: r(object { val x : Int { $x = 1 } }) -> +$x = 1 !: * +{ $x = 1 } !: * COPY +object { val x : Int { $x = 1 } } : NEW: r(object { val x : Int { $x = 1 } }) -> ===================== == O == object O { @@ -46,8 +48,10 @@ object O { } } --------------------- - : O NEW: magic[IMPLICIT_RECEIVER]($x) -> -1 : Int NEW: r(1) -> + : O NEW: magic[IMPLICIT_RECEIVER]($x) -> +1 : Int NEW: r(1) -> +$x = 1 !: * +{ $x = 1 } !: * COPY ===================== == test2 == fun test2() { @@ -78,8 +82,10 @@ fun inner_bar() { y = 10 } --------------------- - : NEW: magic[IMPLICIT_RECEIVER](y) -> -10 : Int NEW: r(10) -> + : NEW: magic[IMPLICIT_RECEIVER](y) -> +10 : Int NEW: r(10) -> +y = 10 !: * +{ y = 10 } !: * COPY ===================== == test4 == fun test4() { @@ -97,15 +103,19 @@ fun test4() { --------------------- : NEW: magic[IMPLICIT_RECEIVER]($x) -> 1 : Int NEW: r(1) -> -object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } : NEW: r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> +$x = 1 !: * +{ $x = 1 } !: * COPY +object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } : NEW: r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> ===================== == ggg == fun ggg() { y = 10 } --------------------- - : NEW: magic[IMPLICIT_RECEIVER](y) -> -10 : Int NEW: r(10) -> + : NEW: magic[IMPLICIT_RECEIVER](y) -> +10 : Int NEW: r(10) -> +y = 10 !: * +{ y = 10 } !: * COPY ===================== == test5 == fun test5() { @@ -126,21 +136,27 @@ fun test5() { : NEW: magic[IMPLICIT_RECEIVER]($x) -> 1 : Int NEW: r(1) -> 2 : Int NEW: r(2) -> -object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } : NEW: r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> +$x = 2 !: * +{ $x = 2 } !: * COPY +object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } : NEW: r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> ===================== == foo == fun foo() { x = 3 } --------------------- - : NEW: magic[IMPLICIT_RECEIVER](x) -> -3 : Int NEW: r(3) -> + : NEW: magic[IMPLICIT_RECEIVER](x) -> +3 : Int NEW: r(3) -> +x = 3 !: * +{ x = 3 } !: * COPY ===================== == bar == fun bar() { x = 4 } --------------------- - : NEW: magic[IMPLICIT_RECEIVER](x) -> -4 : Int NEW: r(4) -> + : NEW: magic[IMPLICIT_RECEIVER](x) -> +4 : Int NEW: r(4) -> +x = 4 !: * +{ x = 4 } !: * COPY ===================== diff --git a/compiler/testData/cfg/declarations/local/ObjectExpression.values b/compiler/testData/cfg/declarations/local/ObjectExpression.values index d4fa5d403d2..9f3d26b4b75 100644 --- a/compiler/testData/cfg/declarations/local/ObjectExpression.values +++ b/compiler/testData/cfg/declarations/local/ObjectExpression.values @@ -25,11 +25,13 @@ fun foo(b: B) : Int { return o.foo() } --------------------- - : B NEW: magic[FAKE_INITIALIZER](b: B) -> - : * NEW: magic[VALUE_CONSUMER](A by b|) -> -b : {<: A} NEW: r(b) -> -object : A by b {} : NEW: r(object : A by b {}) -> -o : {<: A} NEW: r(o) -> -foo() : Int NEW: call(foo(), foo|) -> -o.foo() : Int COPY + : B NEW: magic[FAKE_INITIALIZER](b: B) -> + : * NEW: magic[VALUE_CONSUMER](A by b|) -> +b : {<: A} NEW: r(b) -> +object : A by b {} : NEW: r(object : A by b {}) -> +o : {<: A} NEW: r(o) -> +foo() : Int NEW: call(foo(), foo|) -> +o.foo() : Int COPY +return o.foo() !: * +{ val o = object : A by b {} return o.foo() } !: * COPY ===================== diff --git a/compiler/testData/cfg/declarations/local/localProperty.values b/compiler/testData/cfg/declarations/local/localProperty.values index 096cc6d25a8..5c3a27f7ed9 100644 --- a/compiler/testData/cfg/declarations/local/localProperty.values +++ b/compiler/testData/cfg/declarations/local/localProperty.values @@ -16,5 +16,7 @@ get() { return b } --------------------- -b : Int NEW: r(b) -> +b : Int NEW: r(b) -> +return b !: * +{ val b: Int return b } !: * COPY ===================== diff --git a/compiler/testData/cfg/expressions/ReturnFromExpression.instructions b/compiler/testData/cfg/expressions/ReturnFromExpression.instructions index a1b6af0c54c..7159e92e1e3 100644 --- a/compiler/testData/cfg/expressions/ReturnFromExpression.instructions +++ b/compiler/testData/cfg/expressions/ReturnFromExpression.instructions @@ -7,16 +7,16 @@ L0: 1 2 mark({ false || (return false) }) r(false) -> - jt(L2|) NEXT:[mark((return false)), magic[OR](false || (return false)|) -> ] + jt(L2|) NEXT:[mark((return false)), magic[OR](false || (return false)|, !) -> ] mark((return false)) r(false) -> - ret(*|) L1 NEXT:[] + ret(*|) L1 NEXT:[] L2: - magic[OR](false || (return false)|) -> PREV:[jt(L2|)] + magic[OR](false || (return false)|, !) -> PREV:[jt(L2|)] L1: - 1 NEXT:[] PREV:[ret(*|) L1, magic[OR](false || (return false)|) -> ] + 1 NEXT:[] PREV:[ret(*|) L1, magic[OR](false || (return false)|, !) -> ] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/expressions/ReturnFromExpression.values b/compiler/testData/cfg/expressions/ReturnFromExpression.values index 9b44fda7670..65d2f3e1972 100644 --- a/compiler/testData/cfg/expressions/ReturnFromExpression.values +++ b/compiler/testData/cfg/expressions/ReturnFromExpression.values @@ -3,8 +3,10 @@ fun blockAndAndMismatch() : Boolean { false || (return false) } --------------------- -false : Boolean NEW: r(false) -> -false : Boolean NEW: r(false) -> -false || (return false) : * NEW: magic[OR](false || (return false)|) -> -{ false || (return false) } : * COPY +false : Boolean NEW: r(false) -> +false : Boolean NEW: r(false) -> +return false !: * +(return false) !: * COPY +false || (return false) : * NEW: magic[OR](false || (return false)|, !) -> +{ false || (return false) } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/nothingExpr.instructions b/compiler/testData/cfg/expressions/nothingExpr.instructions index a350371841a..affca21e352 100644 --- a/compiler/testData/cfg/expressions/nothingExpr.instructions +++ b/compiler/testData/cfg/expressions/nothingExpr.instructions @@ -48,7 +48,7 @@ L0: - call(bar(), bar) PREV:[] - jmp(error) NEXT:[] PREV:[] - mark(doSomething) PREV:[] -- call(doSomething, doSomething) -> PREV:[] +- call(doSomething, doSomething|!) -> PREV:[] L1: 1 NEXT:[] PREV:[] error: diff --git a/compiler/testData/cfg/expressions/nothingExpr.values b/compiler/testData/cfg/expressions/nothingExpr.values index 5e0fcd71602..06e11515d56 100644 --- a/compiler/testData/cfg/expressions/nothingExpr.values +++ b/compiler/testData/cfg/expressions/nothingExpr.values @@ -13,11 +13,12 @@ fun foo() { bar().doSomething } --------------------- -null : * NEW: r(null) -> -null!! : * NEW: magic[NOT_NULL_ASSERTION](null!!|) -> -doSomething() : * NEW: call(doSomething(), doSomething|) -> -null!!.doSomething() : * COPY -doSomething : * NEW: call(doSomething, doSomething) -> -bar().doSomething : * COPY -{ null!!.doSomething() bar().doSomething } : * COPY +null : * NEW: r(null) -> +null!! : * NEW: magic[NOT_NULL_ASSERTION](null!!|) -> +doSomething() : * NEW: call(doSomething(), doSomething|) -> +null!!.doSomething() : * COPY +bar() !: * +doSomething : * NEW: call(doSomething, doSomething|!) -> +bar().doSomething : * COPY +{ null!!.doSomething() bar().doSomething } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/thisExpression.instructions b/compiler/testData/cfg/expressions/thisExpression.instructions index f28883915d4..14075064b94 100644 --- a/compiler/testData/cfg/expressions/thisExpression.instructions +++ b/compiler/testData/cfg/expressions/thisExpression.instructions @@ -7,11 +7,11 @@ L0: 1 2 mark({ this() }) mark(this()) - call(this(), invoke) -> + call(this(), invoke|!) -> L1: - 1 NEXT:[] + 1 NEXT:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/expressions/thisExpression.values b/compiler/testData/cfg/expressions/thisExpression.values index e4b94c8616b..a80b193fcdb 100644 --- a/compiler/testData/cfg/expressions/thisExpression.values +++ b/compiler/testData/cfg/expressions/thisExpression.values @@ -3,6 +3,8 @@ fun Function0.foo() { this() } --------------------- -this() : * NEW: call(this(), invoke) -> -{ this() } : * COPY -===================== \ No newline at end of file +this !: * COPY +this !: * +this() : * NEW: call(this(), invoke|!) -> +{ this() } : * COPY +===================== diff --git a/compiler/testData/cfg/expressions/unresolvedCall.instructions b/compiler/testData/cfg/expressions/unresolvedCall.instructions index 998afd3ea14..d4dfb765cb0 100644 --- a/compiler/testData/cfg/expressions/unresolvedCall.instructions +++ b/compiler/testData/cfg/expressions/unresolvedCall.instructions @@ -14,11 +14,11 @@ L0: error(foo, No resolved call) r(a) -> mark(foo()) - magic[UNRESOLVED_CALL](foo()|) -> + magic[UNRESOLVED_CALL](foo()|!, ) -> L1: - 1 NEXT:[] + 1 NEXT:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/expressions/unresolvedCall.values b/compiler/testData/cfg/expressions/unresolvedCall.values index 7975e28a21a..c274a8d81d6 100644 --- a/compiler/testData/cfg/expressions/unresolvedCall.values +++ b/compiler/testData/cfg/expressions/unresolvedCall.values @@ -3,9 +3,10 @@ fun test(a: Any) { a.foo() } --------------------- - : {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> -a : * NEW: r(a) -> -foo() : * NEW: magic[UNRESOLVED_CALL](foo()|) -> -a.foo() : * COPY -{ a.foo() } : * COPY + : {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> +a : * NEW: r(a) -> +foo !: * +foo() : * NEW: magic[UNRESOLVED_CALL](foo()|!, ) -> +a.foo() : * COPY +{ a.foo() } : * COPY ===================== diff --git a/compiler/testData/cfg/tailCalls/finally.values b/compiler/testData/cfg/tailCalls/finally.values index 07aceec2f25..02f1d56b8e4 100644 --- a/compiler/testData/cfg/tailCalls/finally.values +++ b/compiler/testData/cfg/tailCalls/finally.values @@ -7,6 +7,9 @@ tailRecursive fun test() : Int { } } --------------------- -test() : * NEW: call(test(), test) -> -{ test() } : * COPY -===================== \ No newline at end of file +{ // do nothing } !: * +test() : * NEW: call(test(), test) -> +{ test() } : * COPY +try { // do nothing } finally { test() } !: * COPY +{ try { // do nothing } finally { test() } } !: * COPY +===================== diff --git a/compiler/testData/cfg/tailCalls/finallyWithReturn.values b/compiler/testData/cfg/tailCalls/finallyWithReturn.values index 8b8a35f46d7..ad604deb3b5 100644 --- a/compiler/testData/cfg/tailCalls/finallyWithReturn.values +++ b/compiler/testData/cfg/tailCalls/finallyWithReturn.values @@ -7,5 +7,10 @@ tailRecursive fun test() : Int { } } --------------------- -test() : Int NEW: call(test(), test) -> -===================== \ No newline at end of file +{ // do nothing } !: * +test() : Int NEW: call(test(), test) -> +return test() !: * +{ return test() } !: * COPY +try { // do nothing } finally { return test() } !: * COPY +{ try { // do nothing } finally { return test() } } !: * COPY +===================== diff --git a/compiler/testData/cfg/tailCalls/sum.instructions b/compiler/testData/cfg/tailCalls/sum.instructions index a1a4b846c47..c76d8ace6fb 100644 --- a/compiler/testData/cfg/tailCalls/sum.instructions +++ b/compiler/testData/cfg/tailCalls/sum.instructions @@ -24,23 +24,23 @@ L0: jf(L2|) NEXT:[read (Unit), r(sum) -> ] r(sum) -> ret(*|) L1 NEXT:[] -- jmp(L3) NEXT:[r(x) -> ] PREV:[] +- jmp(L3) NEXT:[r(x) -> ] PREV:[] L2: read (Unit) PREV:[jf(L2|)] L3: - r(x) -> - r(1) -> + r(x) -> + r(1) -> mark(x - 1) - call(x - 1, minus|, ) -> - r(sum) -> - r(x) -> + call(x - 1, minus|, ) -> + r(sum) -> + r(x) -> mark(sum + x) - call(sum + x, plus|, ) -> + call(sum + x, plus|, ) -> mark(sum(x - 1, sum + x)) - call(sum(x - 1, sum + x), sum|, ) -> - ret(*|) L1 + call(sum(x - 1, sum + x), sum|, ) -> + ret(*|) L1 L1: - 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] + 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] error: PREV:[] sink: diff --git a/compiler/testData/cfg/tailCalls/sum.values b/compiler/testData/cfg/tailCalls/sum.values index ccfbb5d4aaa..6da2309f8f5 100644 --- a/compiler/testData/cfg/tailCalls/sum.values +++ b/compiler/testData/cfg/tailCalls/sum.values @@ -4,19 +4,23 @@ tailRecursive fun sum(x: Long, sum: Long): Long { return sum(x - 1, sum + x) } --------------------- - : Long NEW: magic[FAKE_INITIALIZER](x: Long) -> - : Long NEW: magic[FAKE_INITIALIZER](sum: Long) -> -x : OR{{<: Any}, {<: Any}} NEW: r(x) -> -0 : {<: Number} NEW: r(0) -> -toLong() : * NEW: call(toLong(), toLong|) -> -0.toLong() : * COPY -x == 0.toLong() : Boolean NEW: call(x == 0.toLong(), equals|, ) -> -sum : Long NEW: r(sum) -> -x : Long NEW: r(x) -> -1 : Int NEW: r(1) -> -x - 1 : Long NEW: call(x - 1, minus|, ) -> -sum : Long NEW: r(sum) -> -x : Long NEW: r(x) -> -sum + x : Long NEW: call(sum + x, plus|, ) -> -sum(x - 1, sum + x) : Long NEW: call(sum(x - 1, sum + x), sum|, ) -> + : Long NEW: magic[FAKE_INITIALIZER](x: Long) -> + : Long NEW: magic[FAKE_INITIALIZER](sum: Long) -> +x : OR{{<: Any}, {<: Any}} NEW: r(x) -> +0 : {<: Number} NEW: r(0) -> +toLong() : * NEW: call(toLong(), toLong|) -> +0.toLong() : * COPY +x == 0.toLong() : Boolean NEW: call(x == 0.toLong(), equals|, ) -> +sum : Long NEW: r(sum) -> +return sum !: * +if (x == 0.toLong()) return sum !: * COPY +x : Long NEW: r(x) -> +1 : Int NEW: r(1) -> +x - 1 : Long NEW: call(x - 1, minus|, ) -> +sum : Long NEW: r(sum) -> +x : Long NEW: r(x) -> +sum + x : Long NEW: call(sum + x, plus|, ) -> +sum(x - 1, sum + x) : Long NEW: call(sum(x - 1, sum + x), sum|, ) -> +return sum(x - 1, sum + x) !: * +{ if (x == 0.toLong()) return sum return sum(x - 1, sum + x) } !: * COPY ===================== diff --git a/compiler/testData/cfg/tailCalls/try.instructions b/compiler/testData/cfg/tailCalls/try.instructions index 5d1655718d4..f850733ee47 100644 --- a/compiler/testData/cfg/tailCalls/try.instructions +++ b/compiler/testData/cfg/tailCalls/try.instructions @@ -11,24 +11,25 @@ L0: 1 2 mark({ try { return foo() } catch (e: Throwable) { } }) mark(try { return foo() } catch (e: Throwable) { }) - jmp?(L2 [onException]) NEXT:[v(e: Throwable), mark({ return foo() })] + jmp?(L2 [onException]) NEXT:[v(e: Throwable), mark({ return foo() })] 3 mark({ return foo() }) mark(foo()) call(foo(), foo) -> - ret(*|) L1 NEXT:[] -- 2 jmp(L3 [afterCatches]) NEXT:[] PREV:[] + ret(*|) L1 NEXT:[] +- 2 jmp(L3 [afterCatches]) NEXT:[merge(try { return foo() } catch (e: Throwable) { }|!, !) -> ] PREV:[] L2 [onException]: - 3 v(e: Throwable) PREV:[jmp?(L2 [onException])] - magic[FAKE_INITIALIZER](e: Throwable) -> - w(e|) + 3 v(e: Throwable) PREV:[jmp?(L2 [onException])] + magic[FAKE_INITIALIZER](e: Throwable) -> + w(e|) 4 mark({ }) read (Unit) 3 jmp(L3 [afterCatches]) -L1: L3 [afterCatches]: - 1 NEXT:[] PREV:[ret(*|) L1, jmp(L3 [afterCatches])] + 2 merge(try { return foo() } catch (e: Throwable) { }|!, !) -> +L1: + 1 NEXT:[] PREV:[ret(*|) L1, merge(try { return foo() } catch (e: Throwable) { }|!, !) -> ] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/tailCalls/try.values b/compiler/testData/cfg/tailCalls/try.values index 3270934a9e1..fe7782aa584 100644 --- a/compiler/testData/cfg/tailCalls/try.values +++ b/compiler/testData/cfg/tailCalls/try.values @@ -7,6 +7,11 @@ tailRecursive fun foo() { } } --------------------- - : {<: Throwable} NEW: magic[FAKE_INITIALIZER](e: Throwable) -> -foo() : Unit NEW: call(foo(), foo) -> + : {<: Throwable} NEW: magic[FAKE_INITIALIZER](e: Throwable) -> +foo() : Unit NEW: call(foo(), foo) -> +return foo() !: * +{ return foo() } !: * COPY +{ } !: * +try { return foo() } catch (e: Throwable) { } : * NEW: merge(try { return foo() } catch (e: Throwable) { }|!, !) -> +{ try { return foo() } catch (e: Throwable) { } } : * COPY ===================== diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnHasTypeNothing.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnHasTypeNothing.kt index 58d855b0c29..28e17358fd5 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnHasTypeNothing.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/LocalReturnHasTypeNothing.kt @@ -1,6 +1,6 @@ fun test() { run1 @f{(): Int -> - (return@f 1): Nothing + (return@f 1): Nothing } } diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt index c78d6642cc2..3fb6c0a5e86 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt @@ -54,7 +54,10 @@ public abstract class AbstractPseudoValueTest : AbstractPseudocodeTest() { } fun valueDescription(element: JetElement?, value: PseudoValue): String { - return if (value.element != element) "COPY" else "NEW: ${value.createdAt}" + return when { + value.element != element -> "COPY" + else -> value.createdAt?.let { "NEW: $it" } ?: "" + } } val elementToValues = getElementToValueMap(pseudocode)