Skip to content

Commit a3e250a

Browse files
committed
Swift: extract iterator variable for for-in loops
1 parent 50d23f1 commit a3e250a

File tree

10 files changed

+6981
-5863
lines changed

10 files changed

+6981
-5863
lines changed

Diff for: swift/extractor/translators/StmtTranslator.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ codeql::ForEachStmt StmtTranslator::translateForEachStmt(const swift::ForEachStm
7373
auto entry = dispatcher.createEntry(stmt);
7474
fillLabeledStmt(stmt, entry);
7575
entry.body = dispatcher.fetchLabel(stmt.getBody());
76-
entry.sequence = dispatcher.fetchLabel(stmt.getTypeCheckedSequence());
76+
// entry.sequence = dispatcher.fetchLabel(stmt.getTypeCheckedSequence());
7777
entry.pattern = dispatcher.fetchLabel(stmt.getPattern());
78+
entry.iteratorVar = dispatcher.fetchLabel(stmt.getIteratorVar());
7879
entry.where = dispatcher.fetchOptionalLabel(stmt.getWhere());
7980
entry.nextCall = dispatcher.fetchOptionalLabel(stmt.getNextCall());
8081
return entry;

Diff for: swift/ql/.generated.list

-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: swift/ql/.gitattributes

-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll

+12-5
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,9 @@ module Stmts {
486486
override ForEachStmt ast;
487487

488488
final override predicate propagatesAbnormal(ControlFlowElement child) {
489-
child.asAstNode() = ast.getSequence().getFullyConverted()
489+
child.asAstNode() = ast.getIteratorVar()
490+
or
491+
child.asAstNode() = ast.getNextCall()
490492
or
491493
child.asAstNode() = ast.getPattern().getFullyUnresolved()
492494
}
@@ -495,7 +497,7 @@ module Stmts {
495497
// Unlike most other statements, `foreach` statements are not modeled in
496498
// pre-order, because we use the `foreach` node itself to represent the
497499
// emptiness test that determines whether to execute the loop body
498-
astFirst(ast.getSequence().getFullyConverted(), first)
500+
astFirst(ast.getIteratorVar(), first)
499501
}
500502

501503
final override predicate last(ControlFlowElement last, Completion c) {
@@ -518,8 +520,13 @@ module Stmts {
518520
}
519521

520522
override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
521-
// Flow from last element of iterator expression to emptiness test
522-
astLast(ast.getSequence().getFullyConverted(), pred, c) and
523+
// Flow from last element of iterator expression to first element of iterator call
524+
astLast(ast.getIteratorVar(), pred, c) and
525+
c instanceof NormalCompletion and
526+
astFirst(ast.getNextCall(), succ)
527+
or
528+
// Flow from iterator call to emptiness test
529+
astLast(ast.getNextCall(), pred, c) and
523530
c instanceof NormalCompletion and
524531
succ.asAstNode() = ast
525532
or
@@ -555,7 +562,7 @@ module Stmts {
555562
// Flow from last element of loop body back to emptiness test.
556563
astLast(ast.getBody(), pred, c) and
557564
c.continuesLoop(ast) and
558-
succ.asAstNode() = ast
565+
astFirst(ast.getNextCall(), succ)
559566
}
560567
}
561568
}

0 commit comments

Comments
 (0)