FIR CFG: add more uncaught exception paths
This commit is contained in:
committed by
teamcityserver
parent
7b06885348
commit
440cf78884
@@ -159,7 +159,8 @@ digraph complex_kt {
|
|||||||
28 -> {29};
|
28 -> {29};
|
||||||
29 -> {30};
|
29 -> {30};
|
||||||
30 -> {38 31};
|
30 -> {38 31};
|
||||||
31 -> {54 32};
|
31 -> {32};
|
||||||
|
31 -> {54} [label=onUncaughtException];
|
||||||
32 -> {33};
|
32 -> {33};
|
||||||
33 -> {34};
|
33 -> {34};
|
||||||
34 -> {35};
|
34 -> {35};
|
||||||
|
|||||||
+2
-1
@@ -177,7 +177,8 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
|
|||||||
44 -> {45};
|
44 -> {45};
|
||||||
45 -> {46};
|
45 -> {46};
|
||||||
46 -> {52 47};
|
46 -> {52 47};
|
||||||
47 -> {56 48};
|
47 -> {48};
|
||||||
|
47 -> {56} [label=onUncaughtException];
|
||||||
48 -> {49};
|
48 -> {49};
|
||||||
49 -> {50};
|
49 -> {50};
|
||||||
50 -> {51};
|
50 -> {51};
|
||||||
|
|||||||
+2
-1
@@ -315,7 +315,8 @@ digraph propertiesAndInitBlocks_kt {
|
|||||||
88 -> {89};
|
88 -> {89};
|
||||||
89 -> {90};
|
89 -> {90};
|
||||||
90 -> {96 91};
|
90 -> {96 91};
|
||||||
91 -> {102 92};
|
91 -> {92};
|
||||||
|
91 -> {96} [label=onUncaughtException];
|
||||||
92 -> {93};
|
92 -> {93};
|
||||||
93 -> {94};
|
93 -> {94};
|
||||||
94 -> {95};
|
94 -> {95};
|
||||||
|
|||||||
@@ -63,13 +63,15 @@ digraph tryCatch_kt {
|
|||||||
6 -> {7};
|
6 -> {7};
|
||||||
7 -> {8};
|
7 -> {8};
|
||||||
8 -> {21 15 9};
|
8 -> {21 15 9};
|
||||||
9 -> {23 10};
|
9 -> {10};
|
||||||
|
9 -> {23} [label=onUncaughtException];
|
||||||
10 -> {11};
|
10 -> {11};
|
||||||
11 -> {12};
|
11 -> {12};
|
||||||
12 -> {13};
|
12 -> {13};
|
||||||
13 -> {14};
|
13 -> {14};
|
||||||
14 -> {21};
|
14 -> {21};
|
||||||
15 -> {23 16};
|
15 -> {16};
|
||||||
|
15 -> {23} [label=onUncaughtException];
|
||||||
16 -> {17};
|
16 -> {17};
|
||||||
17 -> {18};
|
17 -> {18};
|
||||||
18 -> {19};
|
18 -> {19};
|
||||||
@@ -124,7 +126,8 @@ digraph tryCatch_kt {
|
|||||||
29 -> {30};
|
29 -> {30};
|
||||||
30 -> {31};
|
30 -> {31};
|
||||||
31 -> {37 32};
|
31 -> {37 32};
|
||||||
32 -> {40 33};
|
32 -> {33};
|
||||||
|
32 -> {40} [label=onUncaughtException];
|
||||||
33 -> {34};
|
33 -> {34};
|
||||||
34 -> {35};
|
34 -> {35};
|
||||||
35 -> {36};
|
35 -> {36};
|
||||||
@@ -295,7 +298,8 @@ digraph tryCatch_kt {
|
|||||||
78 -> {79};
|
78 -> {79};
|
||||||
79 -> {80};
|
79 -> {80};
|
||||||
80 -> {97 91 81};
|
80 -> {97 91 81};
|
||||||
81 -> {102 82};
|
81 -> {82};
|
||||||
|
81 -> {102} [label=onUncaughtException];
|
||||||
82 -> {83};
|
82 -> {83};
|
||||||
83 -> {87};
|
83 -> {87};
|
||||||
83 -> {84} [style=dotted];
|
83 -> {84} [style=dotted];
|
||||||
@@ -306,7 +310,8 @@ digraph tryCatch_kt {
|
|||||||
88 -> {89};
|
88 -> {89};
|
||||||
89 -> {90};
|
89 -> {90};
|
||||||
90 -> {102};
|
90 -> {102};
|
||||||
91 -> {102 92};
|
91 -> {92};
|
||||||
|
91 -> {102} [label=onUncaughtException];
|
||||||
92 -> {93};
|
92 -> {93};
|
||||||
93 -> {94} [style=dotted];
|
93 -> {94} [style=dotted];
|
||||||
93 -> {43} [color=green style=dashed];
|
93 -> {43} [color=green style=dashed];
|
||||||
|
|||||||
+13
-3
@@ -541,6 +541,7 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
fun exitJump(jump: FirJump<*>): JumpNode {
|
fun exitJump(jump: FirJump<*>): JumpNode {
|
||||||
val node = createJumpNode(jump)
|
val node = createJumpNode(jump)
|
||||||
|
// TODO: if within `try` with `finally`, don't go to the target directly.
|
||||||
val nextNode = when (jump) {
|
val nextNode = when (jump) {
|
||||||
is FirReturnExpression -> exitTargetsForReturn[jump.target.labeledElement.symbol]
|
is FirReturnExpression -> exitTargetsForReturn[jump.target.labeledElement.symbol]
|
||||||
is FirContinueExpression -> loopEnterNodes[jump.target.labeledElement]
|
is FirContinueExpression -> loopEnterNodes[jump.target.labeledElement]
|
||||||
@@ -793,8 +794,6 @@ class ControlFlowGraphBuilder {
|
|||||||
catchNodeStorage.push(catchNode)
|
catchNodeStorage.push(catchNode)
|
||||||
// a flow where an exception of interest is thrown and caught before executing any of try-main block.
|
// a flow where an exception of interest is thrown and caught before executing any of try-main block.
|
||||||
addEdge(enterTryExpressionNode, catchNode)
|
addEdge(enterTryExpressionNode, catchNode)
|
||||||
// TODO: Should go to the finally block w/ a label, and exit to the exit target w/ the same label.
|
|
||||||
addEdge(catchNode, exitTargetsForTry.top())
|
|
||||||
}
|
}
|
||||||
levelCounter++
|
levelCounter++
|
||||||
|
|
||||||
@@ -816,6 +815,7 @@ class ControlFlowGraphBuilder {
|
|||||||
val finallyEnterNode = finallyEnterNodes.topOrNull()
|
val finallyEnterNode = finallyEnterNodes.topOrNull()
|
||||||
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
||||||
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
||||||
|
// TODO: in case of return/throw in try main block, we need a unique label.
|
||||||
addEdge(node, finallyEnterNode)
|
addEdge(node, finallyEnterNode)
|
||||||
} else {
|
} else {
|
||||||
addEdge(node, tryExitNodes.top())
|
addEdge(node, tryExitNodes.top())
|
||||||
@@ -828,6 +828,14 @@ class ControlFlowGraphBuilder {
|
|||||||
val tryMainExitNode = tryMainExitNodes.top()
|
val tryMainExitNode = tryMainExitNodes.top()
|
||||||
// a flow where an exception of interest is thrown and caught after executing all of try-main block.
|
// a flow where an exception of interest is thrown and caught after executing all of try-main block.
|
||||||
addEdge(tryMainExitNode, it)
|
addEdge(tryMainExitNode, it)
|
||||||
|
val finallyEnterNode = finallyEnterNodes.topOrNull()
|
||||||
|
// a flow where an uncaught exception is thrown before executing any of catch clause.
|
||||||
|
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
||||||
|
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
||||||
|
addEdge(it, finallyEnterNode, label = UncaughtExceptionPath)
|
||||||
|
} else {
|
||||||
|
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
|
||||||
|
}
|
||||||
lastNodes.push(it)
|
lastNodes.push(it)
|
||||||
levelCounter++
|
levelCounter++
|
||||||
}
|
}
|
||||||
@@ -840,6 +848,7 @@ class ControlFlowGraphBuilder {
|
|||||||
val finallyEnterNode = finallyEnterNodes.topOrNull()
|
val finallyEnterNode = finallyEnterNodes.topOrNull()
|
||||||
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
||||||
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
||||||
|
// TODO: in case of return/rethrow in catch clause, we need a unique label.
|
||||||
addEdge(it, finallyEnterNode, propagateDeadness = false)
|
addEdge(it, finallyEnterNode, propagateDeadness = false)
|
||||||
} else {
|
} else {
|
||||||
addEdge(it, tryExitNodes.top(), propagateDeadness = false)
|
addEdge(it, tryExitNodes.top(), propagateDeadness = false)
|
||||||
@@ -861,6 +870,7 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(it, tryExitNode)
|
addEdge(it, tryExitNode)
|
||||||
// a flow that exits to the exit target while there was an uncaught exception.
|
// a flow that exits to the exit target while there was an uncaught exception.
|
||||||
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
|
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
|
||||||
|
// TODO: differentiate flows that return/(re)throw in try main block or catch clauses.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,4 +1265,4 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirDeclaration?.isLocalClassOrAnonymousObject() = ((this as? FirRegularClass)?.isLocal == true) || this is FirAnonymousObject
|
fun FirDeclaration?.isLocalClassOrAnonymousObject() = ((this as? FirRegularClass)?.isLocal == true) || this is FirAnonymousObject
|
||||||
|
|||||||
+3
-3
@@ -62,7 +62,7 @@ fun innerFinallyInitializes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Properly initialized
|
// Properly initialized
|
||||||
<!UNINITIALIZED_VARIABLE!>x<!>.inc()
|
x.inc()
|
||||||
} catch (e: java.lang.Exception) {
|
} catch (e: java.lang.Exception) {
|
||||||
log()
|
log()
|
||||||
}
|
}
|
||||||
@@ -87,12 +87,12 @@ fun innerFinallyInitializesOuterRethrows() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Properly initialized
|
// Properly initialized
|
||||||
<!UNINITIALIZED_VARIABLE!>x<!>.inc()
|
x.inc()
|
||||||
} catch (e: java.lang.Exception) {
|
} catch (e: java.lang.Exception) {
|
||||||
log()
|
log()
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guaranteed to be initialized because all catch-clauses are rethrowing
|
// Guaranteed to be initialized because all catch-clauses are rethrowing
|
||||||
<!UNINITIALIZED_VARIABLE!>x<!>.inc()
|
x.inc()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -43,5 +43,5 @@ fun innerTryCatchInitializes() {
|
|||||||
x = 42
|
x = 42
|
||||||
}
|
}
|
||||||
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
|
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
|
||||||
<!UNINITIALIZED_VARIABLE!>x<!>.inc()
|
x.inc()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -30,5 +30,5 @@ fun innerTryCatchFinally() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<!UNINITIALIZED_VARIABLE!>x<!>.inc()
|
x.inc()
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user