From 25eefdb6ec396aa5f93ad027c63b9bfacd14e894 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 24 Aug 2016 15:14:10 +0300 Subject: [PATCH] Pseudocode label now cannot be bound to a non-owning pseudocode #KT-13555 Fixed Also EA-77641 Fixed (cherry picked from commit 07643ce) --- .../kotlin/cfg/pseudocode/PseudocodeImpl.kt | 7 +++++- .../kotlin/cfg/pseudocode/PseudocodeLabel.kt | 4 ++-- ...AndNonlocalReturnsWithFinally.instructions | 22 +++++++++---------- .../nonLocalReturnWithFinally.kt | 10 +++++++++ .../nonLocalReturnWithFinally.txt | 3 +++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ 6 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeImpl.kt index acf24c6330e..bbfea60527c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeImpl.kt @@ -192,6 +192,11 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode } fun bindLabel(label: PseudocodeLabel) { + assert(this == label.pseudocode) { + "Attempt to bind label $label to instruction from different pseudocode: " + + "\nowner pseudocode = ${label.pseudocode.mutableInstructionList}, " + + "\nbound pseudocode = ${this.mutableInstructionList}" + } label.targetInstructionIndex = mutableInstructionList.size } @@ -380,7 +385,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement) : Pseudocode if (label === startLabel || label === finishLabel) continue if (startIndex <= index && index <= finishIndex) { - originalToCopy.put(label, label.copy(labelCount++)) + originalToCopy.put(label, label.copy(this, labelCount++)) originalLabelsForInstruction.put(getJumpTarget(label), label) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeLabel.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeLabel.kt index 9fdcb205f9b..78af5f2b1ff 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeLabel.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeLabel.kt @@ -43,7 +43,7 @@ class PseudocodeLabel internal constructor( return instructionList[index] } - fun copy(newLabelIndex: Int): PseudocodeLabel { - return PseudocodeLabel(pseudocode, "L" + newLabelIndex, "copy of $name, $comment") + fun copy(newPseudocode: PseudocodeImpl, newLabelIndex: Int): PseudocodeLabel { + return PseudocodeLabel(newPseudocode, "L" + newLabelIndex, "copy of $name, $comment") } } diff --git a/compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.instructions b/compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.instructions index cf9317bcf07..3ad142a6297 100644 --- a/compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.instructions +++ b/compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.instructions @@ -54,7 +54,7 @@ L0: jmp?(L2) NEXT:[mark({ for (i in 1..2) { } return bar() }), mark({ if (n < 0) return 0 n.let { return it } })] 3 mark({ if (n < 0) return 0 n.let { return it } }) mark(if (n < 0) return 0) - r(n) -> PREV:[mark(if (n < 0) return 0), jmp(L15)] + r(n) -> r(0) -> mark(n < 0) call(n < 0, compareTo|, ) -> @@ -62,7 +62,7 @@ L0: r(0) -> L4 [start finally]: 4 mark({ for (i in 1..2) { } return bar() }) - 5 r(1) -> PREV:[mark({ for (i in 1..2) { } return bar() }), jmp?(L16)] + 5 r(1) -> r(2) -> mark(1..2) call(1..2, rangeTo|, ) -> @@ -149,7 +149,7 @@ L29 [copy of L8, body exit point]: ret(*|) L1 NEXT:[] - 2 merge(try { if (n < 0) return 0 n.let { return it } } finally { for (i in 1..2) { } return bar() }|) -> PREV:[] L1: - 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1, ret(*|) L1] + 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1, ret(*|) L1, ret(*|) L1] error: PREV:[] sink: @@ -170,24 +170,24 @@ L13: v(i) L15 [copy of L5, loop entry point]: L19 [copy of L9, condition entry point]: - jmp?(L16) NEXT:[r(1) -> , magic[LOOP_RANGE_ITERATION](1..2|) -> ] + jmp?(L16) NEXT:[read (Unit), magic[LOOP_RANGE_ITERATION](1..2|) -> ] PREV:[v(i), jmp(L15)] magic[LOOP_RANGE_ITERATION](1..2|) -> w(i|) mark(for (i in 1..2) { }) L17 [copy of L7, body entry point]: 6 mark({ }) read (Unit) - 5 jmp(L15) NEXT:[r(n) -> ] + 5 jmp(L15) NEXT:[jmp?(L16)] L16 [copy of L6, loop exit point]: L18 [copy of L8, body exit point]: -- read (Unit) PREV:[] -- 4 mark(bar()) PREV:[] -- call(bar(), bar) -> PREV:[] -- ret(*|) L1 NEXT:[] PREV:[] -- 5 ret(*|) L1 NEXT:[] PREV:[] + read (Unit) PREV:[jmp?(L16)] + 4 mark(bar()) + call(bar(), bar) -> + ret(*|) L1 NEXT:[] +- 5 ret(*|) L1 NEXT:[] PREV:[] - 4 ret(*|!) L14 PREV:[] L14: - NEXT:[] PREV:[] + NEXT:[] PREV:[] error: PREV:[] sink: diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.kt new file mode 100644 index 00000000000..37c23610960 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.kt @@ -0,0 +1,10 @@ +fun test(name: String?) { + try { + name?.let { + return + } + } + finally { + name?.hashCode() + } +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.txt new file mode 100644 index 00000000000..8907f18b668 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.txt @@ -0,0 +1,3 @@ +package + +public fun test(/*0*/ name: kotlin.String?): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index a60140aedb6..20ec31a4f62 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3564,6 +3564,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("nonLocalReturnWithFinally.kt") + public void testNonLocalReturnWithFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/nonLocalReturnWithFinally.kt"); + doTest(fileName); + } + @TestMetadata("privateSetter.kt") public void testPrivateSetter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.kt");