generate pseudocode for property accessor only if the property is local
otherwise check it independently like a function
This commit is contained in:
@@ -792,8 +792,10 @@ public class JetControlFlowProcessor {
|
||||
if (delegate != null) {
|
||||
generateInstructions(delegate, NOT_IN_CONDITION);
|
||||
}
|
||||
for (JetPropertyAccessor accessor : property.getAccessors()) {
|
||||
generateInstructions(accessor, NOT_IN_CONDITION);
|
||||
if (JetPsiUtil.isLocal(property)) {
|
||||
for (JetPropertyAccessor accessor : property.getAccessors()) {
|
||||
generateInstructions(accessor, NOT_IN_CONDITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,20 +96,14 @@ public class JetFlowInformationProvider {
|
||||
@NotNull JetType expectedReturnType,
|
||||
boolean isLocalObject
|
||||
) {
|
||||
boolean isPropertyAccessor = function instanceof JetPropertyAccessor;
|
||||
if (!isPropertyAccessor) {
|
||||
recordInitializedVariables();
|
||||
}
|
||||
recordInitializedVariables();
|
||||
|
||||
checkDefiniteReturn(expectedReturnType);
|
||||
checkLocalFunctions();
|
||||
|
||||
if (isLocalObject) return;
|
||||
|
||||
if (!isPropertyAccessor) {
|
||||
// Property accessor is checked through initialization of a class/object or package properties (at 'checkDeclarationContainer')
|
||||
markUninitializedVariables();
|
||||
}
|
||||
markUninitializedVariables();
|
||||
|
||||
markUnusedVariables();
|
||||
|
||||
|
||||
@@ -25,10 +25,7 @@ L0:
|
||||
r(12)
|
||||
w($i)
|
||||
v(val j: Int get() = 20)
|
||||
jmp?(L2) NEXT:[mark({ $i = 13 }), d(get() = 20)]
|
||||
d(get() = 20) NEXT:[<SINK>]
|
||||
L2:
|
||||
mark({ $i = 13 }) PREV:[jmp?(L2)]
|
||||
mark({ $i = 13 })
|
||||
r(13)
|
||||
w($i)
|
||||
L1:
|
||||
@@ -36,27 +33,5 @@ L1:
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>, d(get() = 20)]
|
||||
L3:
|
||||
<START>
|
||||
r(20)
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== get_j ==
|
||||
get() = 20
|
||||
---------------------
|
||||
L3:
|
||||
<START>
|
||||
r(20)
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -11,37 +11,12 @@ class C {
|
||||
L0:
|
||||
<START>
|
||||
v(val a: Int get() = 1)
|
||||
jmp?(L2) NEXT:[mark({ $a }), d(get() = 1)]
|
||||
d(get() = 1) NEXT:[<SINK>]
|
||||
L2:
|
||||
mark({ $a }) PREV:[jmp?(L2)]
|
||||
mark({ $a })
|
||||
r($a)
|
||||
L1:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>, d(get() = 1)]
|
||||
L3:
|
||||
<START>
|
||||
r(1)
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== get_a ==
|
||||
get() = 1
|
||||
---------------------
|
||||
L3:
|
||||
<START>
|
||||
r(1)
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
== foo ==
|
||||
fun foo() {
|
||||
class B {
|
||||
val a: Int
|
||||
get() {
|
||||
val b: Int
|
||||
return b
|
||||
}
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START>
|
||||
mark({ class B { val a: Int get() { val b: Int return b } } })
|
||||
v(val a: Int get() { val b: Int return b })
|
||||
jmp?(L2) NEXT:[<END>, d(get() { val b: Int return b })]
|
||||
d(get() { val b: Int return b }) NEXT:[<SINK>]
|
||||
L1:
|
||||
L2:
|
||||
<END> NEXT:[<SINK>] PREV:[jmp?(L2)]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>, d(get() { val b: Int return b })]
|
||||
L3:
|
||||
<START>
|
||||
mark({ val b: Int return b })
|
||||
v(val b: Int)
|
||||
r(b)
|
||||
ret(*) L4
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== get_a ==
|
||||
get() {
|
||||
val b: Int
|
||||
return b
|
||||
}
|
||||
---------------------
|
||||
L3:
|
||||
<START>
|
||||
mark({ val b: Int return b })
|
||||
v(val b: Int)
|
||||
r(b)
|
||||
ret(*) L4
|
||||
L4:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo() {
|
||||
class B {
|
||||
val a: Int
|
||||
get() {
|
||||
val b: Int
|
||||
return b
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package d
|
||||
|
||||
val a: Int
|
||||
get() {
|
||||
val b: Int
|
||||
val <!UNUSED_VARIABLE!>c<!>: Int
|
||||
<!UNUSED_EXPRESSION!>42<!>
|
||||
|
||||
fun bar(): Int {
|
||||
val d: Int
|
||||
<!UNUSED_EXPRESSION!>42<!>
|
||||
return <!UNINITIALIZED_VARIABLE!>d<!>
|
||||
}
|
||||
|
||||
return <!UNINITIALIZED_VARIABLE!>b<!>
|
||||
}
|
||||
|
||||
class A {
|
||||
val a: Int
|
||||
get() {
|
||||
val b: Int
|
||||
val <!UNUSED_VARIABLE!>c<!>: Int
|
||||
<!UNUSED_EXPRESSION!>42<!>
|
||||
return <!UNINITIALIZED_VARIABLE!>b<!>
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
class B {
|
||||
val a: Int
|
||||
get() {
|
||||
val b: Int
|
||||
val <!UNUSED_VARIABLE!>c<!>: Int
|
||||
<!UNUSED_EXPRESSION!>42<!>
|
||||
return <!UNINITIALIZED_VARIABLE!>b<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/LocalDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localProperty.kt")
|
||||
public void testLocalProperty() throws Exception {
|
||||
doTest("compiler/testData/cfg/localProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("MultiDecl.kt")
|
||||
public void testMultiDecl() throws Exception {
|
||||
doTest("compiler/testData/cfg/MultiDecl.kt");
|
||||
|
||||
@@ -1493,6 +1493,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkPropertyAccessor.kt")
|
||||
public void testCheckPropertyAccessor() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/checkPropertyAccessor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DeadCode.kt")
|
||||
public void testDeadCode() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt");
|
||||
|
||||
Reference in New Issue
Block a user