Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 715a92c

Browse files
committed
Kotlin: Add CFG for when expressions
1 parent 070c0a0 commit 715a92c

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ private module ControlFlowGraphImpl {
303303
)
304304
or
305305
exists(ConditionalStmt condstmt | condstmt.getCondition() = b)
306+
or
307+
exists(WhenBranch whenbranch |
308+
whenbranch.getCondition() = b)
309+
or
310+
exists(WhenExpr whenexpr |
311+
inBooleanContext(whenexpr) and
312+
whenexpr.getBranch(_).getResult() = b)
306313
}
307314

308315
/**
@@ -386,7 +393,7 @@ private module ControlFlowGraphImpl {
386393
private Stmt nonReturningStmt() {
387394
result instanceof ThrowStmt
388395
or
389-
result.(ExprStmt).getExpr() = nonReturningMethodAccess()
396+
result.(ExprStmt).getExpr() = nonReturningExpr()
390397
or
391398
result.(BlockStmt).getLastStmt() = nonReturningStmt()
392399
or
@@ -401,6 +408,20 @@ private module ControlFlowGraphImpl {
401408
)
402409
}
403410

411+
/**
412+
* Gets an expression that always throws an exception or calls `exit`.
413+
*/
414+
private Expr nonReturningExpr() {
415+
result = nonReturningMethodAccess()
416+
or
417+
exists(WhenExpr whenexpr | whenexpr = result |
418+
whenexpr.getBranch(_).isElseBranch() and
419+
forex(WhenBranch whenbranch | whenbranch = whenexpr.getBranch(_) |
420+
whenbranch.getResult() = nonReturningExpr()
421+
or
422+
whenbranch.getResult() = nonReturningStmt()))
423+
}
424+
404425
/**
405426
* Expressions and statements with CFG edges in post-order AST traversal.
406427
*
@@ -459,6 +480,8 @@ private module ControlFlowGraphImpl {
459480
this instanceof LocalTypeDeclStmt
460481
or
461482
this instanceof AssertStmt
483+
or
484+
this instanceof WhenBranch
462485
}
463486

464487
/** Gets child nodes in their order of execution. Indexing starts at either -1 or 0. */
@@ -570,6 +593,8 @@ private module ControlFlowGraphImpl {
570593
or
571594
result = n and n instanceof ConditionalExpr
572595
or
596+
result = n and n instanceof WhenExpr
597+
or
573598
result = n and n.(PostOrderNode).isLeafNode()
574599
or
575600
result = first(n.(PostOrderNode).firstChild())
@@ -880,6 +905,23 @@ private module ControlFlowGraphImpl {
880905
last(s.getVariable(count(s.getAVariable())), last, completion) and
881906
completion = NormalCompletion()
882907
)
908+
or
909+
// The last node in a `when` expression is the last node in any of its branches or
910+
// the last node of the condition in the absence of an else-branch.
911+
exists(WhenExpr whenexpr | whenexpr = n |
912+
last = n and
913+
completion = NormalCompletion() and
914+
not whenexpr.getBranch(_).isElseBranch()
915+
or
916+
last(whenexpr.getBranch(_).getResult(), last, completion)
917+
)
918+
or
919+
exists(WhenBranch whenbranch | whenbranch = n |
920+
last(whenbranch.getCondition(), last, BooleanCompletion(false, _)) and
921+
completion = NormalCompletion()
922+
or
923+
last(whenbranch.getResult(), last, completion)
924+
)
883925
}
884926

885927
/**
@@ -1142,6 +1184,27 @@ private module ControlFlowGraphImpl {
11421184
or
11431185
exists(int i | last(s.getVariable(i), n, completion) and result = first(s.getVariable(i + 1)))
11441186
)
1187+
or
1188+
// When expressions:
1189+
exists(WhenExpr whenexpr | n = whenexpr |
1190+
n = whenexpr and result = first(whenexpr.getBranch(0)) and
1191+
completion = NormalCompletion()
1192+
or
1193+
exists(int i |
1194+
last(whenexpr.getBranch(i).getCondition(), n, completion) and
1195+
completion = BooleanCompletion(false, _) and
1196+
result = first(whenexpr.getBranch(i + 1)))
1197+
)
1198+
or
1199+
// When branches:
1200+
exists(WhenBranch whenbranch | n = whenbranch |
1201+
completion = NormalCompletion() and
1202+
result = first(whenbranch.getCondition())
1203+
or
1204+
last(whenbranch.getCondition(), n, completion) and
1205+
completion = BooleanCompletion(true, _) and
1206+
result = first(whenbranch.getResult())
1207+
)
11451208
}
11461209

11471210
/*

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,9 @@ class WhenExpr extends Expr, @whenexpr {
21472147

21482148
/** Gets the `i`th branch. */
21492149
WhenBranch getBranch(int i) { when_branch(result, this, i) }
2150+
2151+
/** Holds if this was written as an `if` expression. */
2152+
predicate isIf() { when_if(this) }
21502153
}
21512154

21522155
/** A Kotlin `when` branch. */
@@ -2160,6 +2163,11 @@ class WhenBranch extends Top, @whenbranch {
21602163
result.(Stmt).isNthChildOf(this, 1)
21612164
}
21622165

2166+
/** Holds if this is an `else` branch. */
2167+
predicate isElseBranch() {
2168+
when_branch_else(this)
2169+
}
2170+
21632171
override string toString() { result = "... -> ..." }
21642172

21652173
override string getAPrimaryQlClass() { result = "WhenBranch" }

0 commit comments

Comments
 (0)