Skip to content

Commit b101aee

Browse files
committed
Unified: Support loop guards.
1 parent ef0de81 commit b101aee

5 files changed

Lines changed: 23 additions & 4 deletions

File tree

‎shared/controlflow/codeql/controlflow/ControlFlowGraph.qll‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ signature module AstSig<LocationSig Location> {
161161
Expr getCollection();
162162
}
163163

164+
/** Gets the loop guard of the given `loop`, if any. */
165+
default AstNode getLoopGuard(ForEachStmt loop) { none() }
166+
164167
/**
165168
* A `break` statement.
166169
*
@@ -656,6 +659,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
656659
any(DoStmt dostmt).getCondition() = n or
657660
any(UntilStmt untilstmt).getCondition() = n or
658661
any(ForStmt forstmt).getCondition() = n or
662+
getLoopGuard(_) = n or
659663
any(ConditionalExpr condexpr).getCondition() = n or
660664
any(CatchClause catch).getCondition() = n or
661665
any(Case case).getGuard() = n
@@ -1701,8 +1705,19 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
17011705
n2.isBefore(foreachstmt.getVariable())
17021706
or
17031707
n1.isAfter(foreachstmt.getVariable()) and
1708+
(
1709+
n2.isBefore(getLoopGuard(foreachstmt))
1710+
or
1711+
not exists(getLoopGuard(foreachstmt)) and
1712+
n2.isBefore(foreachstmt.getBody())
1713+
)
1714+
or
1715+
n1.isAfterTrue(getLoopGuard(foreachstmt)) and
17041716
n2.isBefore(foreachstmt.getBody())
17051717
or
1718+
n1.isAfterFalse(getLoopGuard(foreachstmt)) and
1719+
n2.isAdditional(foreachstmt, loopHeaderTag())
1720+
or
17061721
n1.isAfter(foreachstmt.getBody()) and
17071722
n2.isAdditional(foreachstmt, loopHeaderTag())
17081723
or

‎unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,13 @@ module Ast implements AstSig<Location> {
125125
class ForEachStmt extends LoopStmt instanceof U::ForEachStmt {
126126
override Stmt getBody() { result = U::ForEachStmt.super.getBody() }
127127

128-
// TODO support foreach guard
129-
//
130128
Expr getVariable() { result = super.getPattern() }
131129

132130
Expr getCollection() { result = super.getIterable() }
133131
}
134132

133+
AstNode getLoopGuard(ForEachStmt foreachstmt) { result = foreachstmt.(U::ForEachStmt).getGuard() }
134+
135135
class BreakStmt = U::BreakExpr;
136136

137137
class ContinueStmt = U::ContinueExpr;

‎unified/ql/test/library-tests/controlflow/basicblock-slices.expected‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@
118118
| 140 | cfg.swift:140:7:140:7 | _ | '_' |
119119
| 141 | cfg.swift:141:9:141:12 | Block | 'Block' |
120120
| 143 | cfg.swift:143:3:145:3 | ForEachStmt | 'ForEachStmt -V 0 -> 10 -^ ... ... ...' |
121-
| 143 | cfg.swift:143:7:143:7 | y | 'y -> Block' |
121+
| 143 | cfg.swift:143:7:143:7 | y | 'y -> y -> 5 -^ ... != ...' |
122+
| 143 | cfg.swift:143:32:145:3 | Block | 'Block' |
122123
| 144 | cfg.swift:144:5:144:9 | print | 'print -> Argument -V y -^ print(...)' |
123124
| 147 | cfg.swift:147:3:160:3 | SwitchExpr | 'SwitchExpr -V x' |
124125
| 148 | cfg.swift:148:5:150:17 | SwitchCase | 'SwitchCase -V 0 -> 1 -^ OrPattern' |

‎unified/ql/test/library-tests/controlflow/cfg.expected‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ bbStep
2020
| cfg.swift:141:9:141:12 | Block | 'Block : successor -> _(-1)' |
2121
| cfg.swift:143:12:143:17 | ... ... ... | '... ... ... : empty -> SwitchExpr(+4)' |
2222
| cfg.swift:143:12:143:17 | ... ... ... | '... ... ... : non-empty -> y(+0)' |
23+
| cfg.swift:143:25:143:30 | ... != ... | '... != ... : false -> SwitchExpr(+4)' |
24+
| cfg.swift:143:25:143:30 | ... != ... | '... != ... : false -> y(+0)' |
25+
| cfg.swift:143:25:143:30 | ... != ... | '... != ... : true -> Block(+0)' |
2326
| cfg.swift:144:5:144:12 | print(...) | 'print(...) : successor -> SwitchExpr(+3)' |
2427
| cfg.swift:144:5:144:12 | print(...) | 'print(...) : successor -> y(-1)' |
2528
| cfg.swift:148:10:148:13 | OrPattern | 'OrPattern : match -> Block(+1)' |

‎unified/ql/test/library-tests/controlflow/cfg.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func patterns(x : Int) -> Bool {
140140
for _ in 0...10 // $ bbStep='... ... ... : empty -> ForEachStmt(+3)' bbStep='... ... ... : non-empty -> _(+0)'
141141
{ } // $ bbStep='Block : successor -> _(-1)' bbStep='Block : successor -> ForEachStmt(+2)'
142142

143-
for y in 0...10 where y != 5 { // $ bbStep='... ... ... : empty -> SwitchExpr(+4)' bbStep='... ... ... : non-empty -> y(+0)'
143+
for y in 0...10 where y != 5 { // $ bbStep='... ... ... : empty -> SwitchExpr(+4)' bbStep='... ... ... : non-empty -> y(+0)' bbStep='... != ... : false -> SwitchExpr(+4)' bbStep='... != ... : false -> y(+0)' bbStep='... != ... : true -> Block(+0)'
144144
print(y) // $ bbStep='print(...) : successor -> SwitchExpr(+3)' bbStep='print(...) : successor -> y(-1)'
145145
}
146146

0 commit comments

Comments
 (0)