Skip to content

Commit a59335d

Browse files
authored
Merge pull request #9557 from MathiasVP/closure-expr-as-cfg-callable
Swift: Mark closures as callables in the CFG library
2 parents 9dbb451 + 2fdb3d6 commit a59335d

File tree

4 files changed

+123
-1
lines changed

4 files changed

+123
-1
lines changed

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ cached
44
newtype TControlFlowElement =
55
TAstElement(AstNode n) or
66
TFuncDeclElement(AbstractFunctionDecl func) { func.hasBody() } or
7+
TClosureElement(ClosureExpr clos) or
78
TPropertyGetterElement(Decl accessor, Expr ref) { isPropertyGetterElement(accessor, ref) } or
89
TPropertySetterElement(AccessorDecl accessor, AssignExpr assign) {
910
isPropertySetterElement(accessor, assign)
@@ -187,3 +188,15 @@ class KeyPathElement extends ControlFlowElement, TKeyPathElement {
187188

188189
override string toString() { result = expr.toString() }
189190
}
191+
192+
class ClosureElement extends ControlFlowElement, TClosureElement {
193+
ClosureExpr expr;
194+
195+
ClosureElement() { this = TClosureElement(expr) }
196+
197+
override Location getLocation() { result = expr.getLocation() }
198+
199+
ClosureExpr getAst() { result = expr }
200+
201+
override string toString() { result = expr.toString() }
202+
}

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ module CfgScope {
6565

6666
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
6767
}
68+
69+
private class ClosureExprScope extends Range_ instanceof ClosureExpr {
70+
Exprs::ClosureExprTree tree;
71+
72+
ClosureExprScope() { tree.getAst() = this }
73+
74+
final override predicate entry(ControlFlowElement first) { first(tree, first) }
75+
76+
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
77+
}
6878
}
6979

7080
/** Holds if `first` is first executed when entering `scope`. */
@@ -1046,6 +1056,21 @@ module Exprs {
10461056
}
10471057
}
10481058

1059+
class ClosureExprTree extends StandardPreOrderTree, TClosureElement {
1060+
ClosureExpr expr;
1061+
1062+
ClosureExprTree() { this = TClosureElement(expr) }
1063+
1064+
ClosureExpr getAst() { result = expr }
1065+
1066+
final override ControlFlowElement getChildElement(int i) {
1067+
result.asAstNode() = expr.getParam(i)
1068+
or
1069+
result.asAstNode() = expr.getBody() and
1070+
i = expr.getNumberOfParams()
1071+
}
1072+
}
1073+
10491074
private class BindOptionalTree extends AstStandardPostOrderTree {
10501075
override BindOptionalExpr ast;
10511076

swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ private import swift
22
private import codeql.swift.generated.GetImmediateParent
33

44
module CallableBase {
5-
class TypeRange = @abstract_function_decl or @key_path_expr;
5+
class TypeRange = @abstract_function_decl or @key_path_expr or @closure_expr;
66

77
class Range extends Scope::Range, TypeRange { }
88
}

swift/ql/test/library-tests/controlflow/graph/Cfg.expected

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,41 @@ cfg.swift:
373373
# 46| return ...
374374
#-----| return -> exit createClosure1 (normal)
375375

376+
# 46| enter { ... }
377+
#-----| -> { ... }
378+
379+
# 46| exit { ... }
380+
381+
# 46| exit { ... } (normal)
382+
#-----| -> exit { ... }
383+
376384
# 46| { ... }
377385
#-----| -> return ...
378386

387+
# 46| { ... }
388+
#-----| -> +
389+
390+
# 47| return ...
391+
#-----| return -> exit { ... } (normal)
392+
393+
# 47| s
394+
#-----| ->
395+
396+
# 47| ... call to + ...
397+
#-----| -> return ...
398+
399+
# 47| +
400+
#-----| -> String.Type
401+
402+
# 47| String.Type
403+
#-----| -> call to +
404+
405+
# 47| call to +
406+
#-----| -> s
407+
408+
# 47|
409+
#-----| -> ... call to + ...
410+
379411
# 51| createClosure2
380412
#-----| -> x
381413

@@ -436,9 +468,44 @@ cfg.swift:
436468
# 59| return ...
437469
#-----| return -> exit createClosure3 (normal)
438470

471+
# 59| enter { ... }
472+
#-----| -> { ... }
473+
474+
# 59| exit { ... }
475+
476+
# 59| exit { ... } (normal)
477+
#-----| -> exit { ... }
478+
439479
# 59| { ... }
440480
#-----| -> return ...
441481

482+
# 59| { ... }
483+
#-----| -> y
484+
485+
# 60| y
486+
#-----| -> +
487+
488+
# 60| x
489+
#-----| -> y
490+
491+
# 60| ... call to + ...
492+
#-----| -> return ...
493+
494+
# 60| return ...
495+
#-----| return -> exit { ... } (normal)
496+
497+
# 60| +
498+
#-----| -> Int.Type
499+
500+
# 60| Int.Type
501+
#-----| -> call to +
502+
503+
# 60| call to +
504+
#-----| -> x
505+
506+
# 60| y
507+
#-----| -> ... call to + ...
508+
442509
# 64| callClosures
443510
#-----| -> x1
444511

@@ -4633,12 +4700,23 @@ cfg.swift:
46334700
# 368| return ...
46344701
#-----| return -> exit testCapture (normal)
46354702

4703+
# 368| enter { ... }
4704+
#-----| -> { ... }
4705+
4706+
# 368| exit { ... }
4707+
4708+
# 368| exit { ... } (normal)
4709+
#-----| -> exit { ... }
4710+
46364711
# 368| { ... }
46374712
#-----| -> return ...
46384713

46394714
# 368| { ... }
46404715
#-----| -> { ... }
46414716

4717+
# 368| { ... }
4718+
#-----| -> z
4719+
46424720
# 368| z
46434721
#-----| match -> +
46444722

@@ -4672,6 +4750,12 @@ cfg.swift:
46724750
# 368| literal
46734751
#-----| -> var ... = ...
46744752

4753+
# 369| return ...
4754+
#-----| return -> exit { ... } (normal)
4755+
4756+
# 369| z
4757+
#-----| -> return ...
4758+
46754759
# 373| enter testTupleElement
46764760
#-----| -> testTupleElement
46774761

0 commit comments

Comments
 (0)