KT-2166 Control flow analysis doesn't detect that a 'while(true)' loop never terminates
KT-2103 Compiler requires return statement after loop which never exits #KT-2166 Fixed #KT-2103 Fixed
This commit is contained in:
@@ -30,9 +30,13 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.constants.BooleanValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -477,7 +481,15 @@ public class JetControlFlowProcessor {
|
||||
if (condition != null) {
|
||||
value(condition, true);
|
||||
}
|
||||
builder.jumpOnFalse(loopInfo.getExitPoint());
|
||||
boolean conditionIsTrueConstant = false;
|
||||
if (condition instanceof JetConstantExpression && condition.getNode().getElementType() == JetNodeTypes.BOOLEAN_CONSTANT) {
|
||||
if (BooleanValue.TRUE == new CompileTimeConstantResolver().getBooleanValue(condition.getText(), JetStandardLibrary.getInstance().getBooleanType())) {
|
||||
conditionIsTrueConstant = true;
|
||||
}
|
||||
}
|
||||
if (!conditionIsTrueConstant) {
|
||||
builder.jumpOnFalse(loopInfo.getExitPoint());
|
||||
}
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
|
||||
+1
-3
@@ -38,11 +38,9 @@ public class CompileTimeConstantResolver {
|
||||
public static final ErrorValue OUT_OF_RANGE = new ErrorValue("The value is out of range");
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final BindingTrace trace;
|
||||
|
||||
public CompileTimeConstantResolver(@NotNull BindingTrace trace) {
|
||||
public CompileTimeConstantResolver() {
|
||||
this.standardLibrary = JetStandardLibrary.getInstance();
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ public class ExpressionTypingContext {
|
||||
|
||||
public CompileTimeConstantResolver getCompileTimeConstantResolver() {
|
||||
if (compileTimeConstantResolver == null) {
|
||||
compileTimeConstantResolver = new CompileTimeConstantResolver(trace);
|
||||
compileTimeConstantResolver = new CompileTimeConstantResolver();
|
||||
}
|
||||
return compileTimeConstantResolver;
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ fun t5() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[r(while(true) { try { 1 if (..)] PREV:[]
|
||||
<START> NEXT:[r(while(true) { try { 1 if (..)] PREV:[]
|
||||
r(while(true) {
|
||||
try {
|
||||
1
|
||||
@@ -311,11 +311,10 @@ l0:
|
||||
} finally {
|
||||
2
|
||||
}
|
||||
}) NEXT:[r(true)] PREV:[<START>]
|
||||
}) NEXT:[r(true)] PREV:[<START>]
|
||||
l2:
|
||||
l5:
|
||||
r(true) NEXT:[jf(l3)] PREV:[r(while(true) { try { 1 if (..), jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(try { 1 if (2 > 3) { break..)] PREV:[r(true)]
|
||||
r(true) NEXT:[r(try { 1 if (2 > 3) { break..)] PREV:[r(while(true) { try { 1 if (..), jmp(l2)]
|
||||
l4:
|
||||
r(try {
|
||||
1
|
||||
@@ -324,31 +323,31 @@ l4:
|
||||
}
|
||||
} finally {
|
||||
2
|
||||
}) NEXT:[r(1)] PREV:[jf(l3)]
|
||||
r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { break..)]
|
||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[jmp(l3)] PREV:[jf(l6)]
|
||||
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
|
||||
- jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
}) NEXT:[r(1)] PREV:[r(true)]
|
||||
r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { break..)]
|
||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[jmp(l3)] PREV:[jf(l6)]
|
||||
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
|
||||
- jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
l7:
|
||||
l8:
|
||||
r(2) NEXT:[jmp(l2)] PREV:[read (Unit)]
|
||||
r(2) NEXT:[jmp(l2)] PREV:[read (Unit)]
|
||||
l9:
|
||||
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
||||
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
||||
l3:
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jmp(l3)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t6 ==
|
||||
fun t6() {
|
||||
@@ -386,10 +385,9 @@ l0:
|
||||
}) NEXT:[r(true)] PREV:[r(try { @ while(true) { 1 if..)]
|
||||
l2:
|
||||
l5:
|
||||
r(true) NEXT:[jf(l3)] PREV:[r(while(true) { 1 if (2 > 3)..), jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
r(true) NEXT:[r(1)] PREV:[r(while(true) { 1 if (2 > 3)..), jmp(l2)]
|
||||
l4:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
r(1) NEXT:[r(2)] PREV:[r(true)]
|
||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
@@ -402,7 +400,7 @@ l6:
|
||||
l7:
|
||||
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(5)] PREV:[jf(l3), jmp(l3)]
|
||||
read (Unit) NEXT:[r(5)] PREV:[jmp(l3)]
|
||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||
l8:
|
||||
r(2) NEXT:[<END>] PREV:[r(5)]
|
||||
@@ -448,10 +446,9 @@ l0:
|
||||
}) NEXT:[r(true)] PREV:[r(try { @ while(true) { 1 if..)]
|
||||
l2:
|
||||
l5:
|
||||
r(true) NEXT:[jf(l3)] PREV:[r(while(true) { 1 if (2 > 3)..), jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
r(true) NEXT:[r(1)] PREV:[r(while(true) { 1 if (2 > 3)..), jmp(l2)]
|
||||
l4:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
r(1) NEXT:[r(2)] PREV:[r(true)]
|
||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
@@ -464,7 +461,7 @@ l6:
|
||||
l7:
|
||||
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l3), jmp(l3)]
|
||||
read (Unit) NEXT:[r(2)] PREV:[jmp(l3)]
|
||||
l8:
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l1:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package a
|
||||
|
||||
//KT-2166 Control flow analysis doesn't detect that a 'while(true)' loop never terminates
|
||||
fun foo(): Int {
|
||||
while (true) {
|
||||
}
|
||||
}
|
||||
|
||||
//KT-2103 Compiler requires return statement after loop which never exits
|
||||
fun foo1() : Boolean{
|
||||
while(true){
|
||||
if (bar()) continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fun bar() : Boolean = true
|
||||
+5
-2
@@ -118,8 +118,11 @@ fun bar(<!UNUSED_PARAMETER!>a<!>: Unit) {}
|
||||
fun testStatementInExpressionContext() {
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 34
|
||||
val <!UNUSED_VARIABLE!>a1<!>: Unit = <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>334<!><!>
|
||||
val <!UNUSED_VARIABLE!>a2<!>: Unit = <!EXPRESSION_EXPECTED!>while(true) {}<!>
|
||||
val <!UNUSED_VARIABLE!>f<!> = <!EXPRESSION_EXPECTED!>for (i in 1..10) {}<!>
|
||||
if (true) return <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>34<!><!>
|
||||
return <!EXPRESSION_EXPECTED!>while (true) {}<!>
|
||||
<!UNREACHABLE_CODE!>return <!EXPRESSION_EXPECTED!>while (true) {}<!><!>
|
||||
}
|
||||
|
||||
fun testStatementInExpressionContext2() {
|
||||
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>a2<!>: Unit = <!EXPRESSION_EXPECTED!>while(true) {}<!><!>
|
||||
}
|
||||
Reference in New Issue
Block a user