Jump after 'for' cycle to loop parameter change.
Not to the cycle body.
This commit is contained in:
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -608,14 +607,7 @@ public class JetControlFlowProcessor {
|
||||
if (loopRange != null) {
|
||||
generateInstructions(loopRange, NOT_IN_CONDITION);
|
||||
}
|
||||
JetParameter loopParameter = expression.getLoopParameter();
|
||||
if (loopParameter != null) {
|
||||
generateInstructions(loopParameter, context);
|
||||
}
|
||||
else {
|
||||
JetMultiDeclaration multiParameter = expression.getMultiParameter();
|
||||
generateInstructions(multiParameter, context);
|
||||
}
|
||||
declareLoopParameter(expression);
|
||||
|
||||
// TODO : primitive cases
|
||||
Label loopExitPoint = builder.createUnboundLabel();
|
||||
@@ -627,6 +619,8 @@ public class JetControlFlowProcessor {
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
writeLoopParameterAssignment(expression);
|
||||
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
generateInstructions(body, NOT_IN_CONDITION);
|
||||
@@ -638,6 +632,30 @@ public class JetControlFlowProcessor {
|
||||
builder.exitLexicalScope(expression);
|
||||
}
|
||||
|
||||
private void declareLoopParameter(JetForExpression expression) {
|
||||
JetParameter loopParameter = expression.getLoopParameter();
|
||||
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
|
||||
if (loopParameter != null) {
|
||||
builder.declareParameter(loopParameter);
|
||||
}
|
||||
else if (multiDeclaration != null) {
|
||||
visitMultiDeclaration(multiDeclaration, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLoopParameterAssignment(JetForExpression expression) {
|
||||
JetParameter loopParameter = expression.getLoopParameter();
|
||||
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
|
||||
if (loopParameter != null) {
|
||||
builder.write(loopParameter, loopParameter);
|
||||
}
|
||||
else if (multiDeclaration != null) {
|
||||
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
builder.write(entry, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreakExpressionVoid(@NotNull JetBreakExpression expression, CFPContext context) {
|
||||
JetElement loop = getCorrespondingLoop(expression);
|
||||
@@ -832,18 +850,21 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitMultiDeclarationVoid(@NotNull JetMultiDeclaration declaration, CFPContext context) {
|
||||
JetExpression initializer = declaration.getInitializer();
|
||||
if (initializer != null) {
|
||||
generateInstructions(initializer, NOT_IN_CONDITION);
|
||||
}
|
||||
List<JetMultiDeclarationEntry> entries = declaration.getEntries();
|
||||
for (JetMultiDeclarationEntry entry : entries) {
|
||||
visitMultiDeclaration(declaration, true);
|
||||
}
|
||||
|
||||
private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) {
|
||||
generateInstructions(declaration.getInitializer(), NOT_IN_CONDITION);
|
||||
|
||||
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
|
||||
builder.declareVariable(entry);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
|
||||
if (resolvedCall != null) {
|
||||
builder.call(entry, resolvedCall);
|
||||
}
|
||||
builder.write(entry, entry);
|
||||
if (generateWriteForEntries) {
|
||||
builder.write(entry, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@ L0:
|
||||
3 mark(for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) USE: in: {numbers=READ} out: {numbers=READ}
|
||||
r(numbers) USE: in: {} out: {numbers=READ}
|
||||
v(i) INIT: in: {numbers=ID} out: {i=D, numbers=ID}
|
||||
w(i) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID}
|
||||
L3:
|
||||
jmp?(L2) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {}
|
||||
jmp?(L2) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
|
||||
L4 [loop entry point]:
|
||||
L5 [body entry point]:
|
||||
4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID}
|
||||
v(val b: Boolean)
|
||||
mark(if (1 < 2) { b = false } else { b = true })
|
||||
w(i) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {}
|
||||
4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID}
|
||||
v(val b: Boolean) INIT: in: {i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
|
||||
mark(if (1 < 2) { b = false } else { b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
|
||||
mark(1 < 2)
|
||||
r(1)
|
||||
r(2)
|
||||
@@ -36,20 +36,20 @@ L5 [body entry point]:
|
||||
jf(L6)
|
||||
5 mark({ b = false })
|
||||
r(false) USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
|
||||
w(b) USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
|
||||
4 jmp(L7) USE: in: {b=READ} out: {b=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}
|
||||
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 })
|
||||
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) USE: in: {b=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 mark(use(b)) USE: in: {b=READ} out: {b=READ}
|
||||
r(b) USE: in: {b=WRITTEN_AFTER_READ} out: {b=READ}
|
||||
4 mark(use(b)) 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}
|
||||
call(use, use)
|
||||
jmp(L4 [loop entry point]) USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
|
||||
jmp(L4 [loop entry point]) USE: in: {} out: {}
|
||||
- 3 jmp?(L4 [loop entry point])
|
||||
L2:
|
||||
read (Unit) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID}
|
||||
read (Unit) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
|
||||
L1:
|
||||
1 <END> INIT: in: {numbers=ID} out: {numbers=ID}
|
||||
error:
|
||||
|
||||
@@ -18,18 +18,18 @@ L0:
|
||||
r(10)
|
||||
call(.., rangeTo)
|
||||
v(i) INIT: in: {} out: {i=D}
|
||||
w(i) INIT: in: {i=D} out: {i=ID}
|
||||
L3:
|
||||
jmp?(L2) INIT: in: {i=ID} out: {i=ID}
|
||||
jmp?(L2) INIT: in: {i=D} out: {i=D}
|
||||
L4 [loop entry point]:
|
||||
L5 [body entry point]:
|
||||
4 mark({ val a = i })
|
||||
w(i) INIT: in: {i=D} out: {i=ID}
|
||||
4 mark({ val a = i }) INIT: in: {i=ID} out: {i=ID}
|
||||
v(val a = i) INIT: in: {i=ID} out: {a=D, i=ID}
|
||||
r(i) INIT: in: {a=D, i=ID} out: {a=D, i=ID}
|
||||
w(a) INIT: in: {a=D, i=ID} out: {a=ID, i=ID}
|
||||
3 jmp?(L4 [loop entry point]) INIT: in: {i=ID} out: {i=ID} USE: in: {i=READ} out: {i=READ}
|
||||
L2:
|
||||
read (Unit)
|
||||
read (Unit) INIT: in: {i=D} out: {i=D}
|
||||
2 mark("after") INIT: in: {} out: {}
|
||||
r("after")
|
||||
L1:
|
||||
|
||||
@@ -444,12 +444,12 @@ L0:
|
||||
r(a)
|
||||
call(.., rangeTo)
|
||||
v(i)
|
||||
w(i)
|
||||
L3:
|
||||
jmp?(L2) NEXT:[read (Unit), mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })]
|
||||
jmp?(L2) NEXT:[read (Unit), w(i)]
|
||||
L4 [loop entry point]:
|
||||
L5 [body entry point]:
|
||||
4 mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } }) PREV:[jmp?(L2), jmp(L4 [loop entry point]), jmp?(L4 [loop entry point])]
|
||||
w(i) PREV:[jmp?(L2), jmp(L4 [loop entry point]), jmp?(L4 [loop entry point])]
|
||||
4 mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })
|
||||
mark(try { 1 if (2 > 3) { continue @ } } finally { 2 })
|
||||
jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { continue @ } })]
|
||||
5 mark({ 1 if (2 > 3) { continue @ } })
|
||||
@@ -465,7 +465,7 @@ L8 [start finally]:
|
||||
7 mark({ 2 })
|
||||
r(2)
|
||||
L9 [finish finally]:
|
||||
6 jmp(L4 [loop entry point]) NEXT:[mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })]
|
||||
6 jmp(L4 [loop entry point]) NEXT:[w(i)]
|
||||
- 5 jmp(L10) NEXT:[jmp(L11 [skipFinallyToErrorBlock])] PREV:[]
|
||||
L7:
|
||||
read (Unit) PREV:[jf(L7)]
|
||||
@@ -478,7 +478,7 @@ L6 [onExceptionToFinallyBlock]:
|
||||
L11 [skipFinallyToErrorBlock]:
|
||||
7 mark({ 2 }) PREV:[jmp(L11 [skipFinallyToErrorBlock])]
|
||||
r(2)
|
||||
3 jmp?(L4 [loop entry point]) NEXT:[mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } }), read (Unit)]
|
||||
3 jmp?(L4 [loop entry point]) NEXT:[w(i), read (Unit)]
|
||||
L2:
|
||||
read (Unit) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
|
||||
L1:
|
||||
@@ -518,12 +518,12 @@ L0:
|
||||
r(a)
|
||||
call(.., rangeTo)
|
||||
v(i)
|
||||
w(i)
|
||||
L4:
|
||||
jmp?(L3) NEXT:[read (Unit), mark({ 1 if (2 > 3) { continue @ } })]
|
||||
jmp?(L3) NEXT:[read (Unit), w(i)]
|
||||
L5 [loop entry point]:
|
||||
L6 [body entry point]:
|
||||
5 mark({ 1 if (2 > 3) { continue @ } }) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
|
||||
w(i) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
|
||||
5 mark({ 1 if (2 > 3) { continue @ } })
|
||||
r(1)
|
||||
mark(if (2 > 3) { continue @ })
|
||||
mark(2 > 3)
|
||||
@@ -532,12 +532,12 @@ L6 [body entry point]:
|
||||
call(>, compareTo)
|
||||
jf(L7) NEXT:[read (Unit), mark({ continue @ })]
|
||||
6 mark({ continue @ })
|
||||
jmp(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } })]
|
||||
jmp(L5 [loop entry point]) NEXT:[w(i)]
|
||||
- 5 jmp(L8) NEXT:[jmp?(L5 [loop entry point])] PREV:[]
|
||||
L7:
|
||||
read (Unit) PREV:[jf(L7)]
|
||||
L8:
|
||||
4 jmp?(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } }), read (Unit)]
|
||||
4 jmp?(L5 [loop entry point]) NEXT:[w(i), read (Unit)]
|
||||
L3:
|
||||
read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])]
|
||||
3 r(5)
|
||||
@@ -587,12 +587,12 @@ L0:
|
||||
r(a)
|
||||
call(.., rangeTo)
|
||||
v(i)
|
||||
w(i)
|
||||
L4:
|
||||
jmp?(L3) NEXT:[read (Unit), mark({ 1 if (2 > 3) { continue @ } })]
|
||||
jmp?(L3) NEXT:[read (Unit), w(i)]
|
||||
L5 [loop entry point]:
|
||||
L6 [body entry point]:
|
||||
5 mark({ 1 if (2 > 3) { continue @ } }) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
|
||||
w(i) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
|
||||
5 mark({ 1 if (2 > 3) { continue @ } })
|
||||
r(1)
|
||||
mark(if (2 > 3) { continue @ })
|
||||
mark(2 > 3)
|
||||
@@ -601,12 +601,12 @@ L6 [body entry point]:
|
||||
call(>, compareTo)
|
||||
jf(L7) NEXT:[read (Unit), mark({ continue @ })]
|
||||
6 mark({ continue @ })
|
||||
jmp(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } })]
|
||||
jmp(L5 [loop entry point]) NEXT:[w(i)]
|
||||
- 5 jmp(L8) NEXT:[jmp?(L5 [loop entry point])] PREV:[]
|
||||
L7:
|
||||
read (Unit) PREV:[jf(L7)]
|
||||
L8:
|
||||
4 jmp?(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } }), read (Unit)]
|
||||
4 jmp?(L5 [loop entry point]) NEXT:[w(i), read (Unit)]
|
||||
L3:
|
||||
read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])]
|
||||
2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
|
||||
|
||||
@@ -14,16 +14,16 @@ L0:
|
||||
r(2)
|
||||
call(.., rangeTo)
|
||||
v(i)
|
||||
w(i)
|
||||
L3:
|
||||
jmp?(L2) NEXT:[read (Unit), mark({ doSmth(i) })]
|
||||
jmp?(L2) NEXT:[read (Unit), w(i)]
|
||||
L4 [loop entry point]:
|
||||
L5 [body entry point]:
|
||||
4 mark({ doSmth(i) }) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
|
||||
w(i) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
|
||||
4 mark({ doSmth(i) })
|
||||
mark(doSmth(i))
|
||||
r(i)
|
||||
call(doSmth, doSmth)
|
||||
3 jmp?(L4 [loop entry point]) NEXT:[mark({ doSmth(i) }), read (Unit)]
|
||||
3 jmp?(L4 [loop entry point]) NEXT:[w(i), read (Unit)]
|
||||
L2:
|
||||
read (Unit) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
|
||||
L1:
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
fun foo(numbers: Collection<Int>) {
|
||||
for (i in numbers) {
|
||||
val b: Boolean
|
||||
if (1 < 2) {
|
||||
b = false
|
||||
}
|
||||
else {
|
||||
b = true
|
||||
}
|
||||
use(b)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fun use(vararg a: Any?) = a
|
||||
@@ -1688,6 +1688,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("varInitializationInIfInCycle.kt")
|
||||
public void testVarInitializationInIfInCycle() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/varInitializationInIfInCycle.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturn")
|
||||
public static class DefiniteReturn extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInDefiniteReturn() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user