Skip to content

Commit 1fba345

Browse files
authored
Merge pull request #15219 from rdmarsh2/rdmarsh2/swift/parameterized-cfg-library
Swift: switch to shared, parameterized CFG library
2 parents e50a0ee + c38ae93 commit 1fba345

File tree

13 files changed

+459
-1217
lines changed

13 files changed

+459
-1217
lines changed
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import codeql.swift.controlflow.internal.ControlFlowGraphImplShared::Consistency
1+
import codeql.swift.controlflow.internal.ControlFlowGraphImplSpecific::CfgImpl::Consistency
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The control flow graph library (`codeql.swift.controlflow`) has been transitioned to use the shared implementation from the `codeql/controlflow` qlpack. No result changes are expected due to this change.

swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
private import swift
44
private import ControlFlowGraph
5-
private import internal.ControlFlowGraphImpl
5+
private import internal.ControlFlowGraphImpl as Impl
66
private import internal.ControlFlowElements
77
private import CfgNodes
88
private import SuccessorTypes
@@ -133,7 +133,9 @@ private module Cached {
133133
private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
134134

135135
/** Holds if `bb` is an exit basic block that represents normal exit. */
136-
private predicate normalExitBB(BasicBlock bb) { bb.getANode().(AnnotatedExitNode).isNormal() }
136+
private predicate normalExitBB(BasicBlock bb) {
137+
bb.getANode().(Impl::AnnotatedExitNode).isNormal()
138+
}
137139

138140
/** Holds if `dom` is an immediate post-dominator of `bb`. */
139141
cached
@@ -167,7 +169,9 @@ private predicate entryBB(BasicBlock bb) { bb.getFirstNode() instanceof EntryNod
167169
class EntryBasicBlock extends BasicBlock {
168170
EntryBasicBlock() { entryBB(this) }
169171

170-
override CfgScope getScope() { this.getFirstNode() = TEntryNode(result) }
172+
override CfgScope getScope() {
173+
this.getFirstNode() = any(EntryNode node | node.getScope() = result)
174+
}
171175
}
172176

173177
/**
@@ -178,7 +182,7 @@ class AnnotatedExitBasicBlock extends BasicBlock {
178182
private boolean normal;
179183

180184
AnnotatedExitBasicBlock() {
181-
exists(AnnotatedExitNode n |
185+
exists(Impl::AnnotatedExitNode n |
182186
n = this.getANode() and
183187
if n.isNormal() then normal = true else normal = false
184188
)

swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll

+27-84
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,39 @@
33
private import swift
44
private import BasicBlocks
55
private import ControlFlowGraph
6-
private import internal.ControlFlowGraphImpl
6+
private import internal.ControlFlowGraphImpl as Impl
77
private import internal.ControlFlowElements
88
private import internal.Splitting
99

10-
/** An entry node for a given scope. */
11-
class EntryNode extends ControlFlowNode, TEntryNode {
12-
private CfgScope scope;
13-
14-
EntryNode() { this = TEntryNode(scope) }
15-
16-
final override EntryBasicBlock getBasicBlock() { result = ControlFlowNode.super.getBasicBlock() }
17-
18-
final override Location getLocation() { result = scope.getLocation() }
19-
20-
final override string toString() { result = "enter " + scope }
21-
}
22-
23-
/** An exit node for a given scope, annotated with the type of exit. */
24-
class AnnotatedExitNode extends ControlFlowNode, TAnnotatedExitNode {
25-
private CfgScope scope;
26-
private boolean normal;
27-
28-
AnnotatedExitNode() { this = TAnnotatedExitNode(scope, normal) }
29-
30-
/** Holds if this node represent a normal exit. */
31-
final predicate isNormal() { normal = true }
32-
33-
final override AnnotatedExitBasicBlock getBasicBlock() {
34-
result = ControlFlowNode.super.getBasicBlock()
35-
}
36-
37-
final override Location getLocation() { result = scope.getLocation() }
38-
39-
final override string toString() {
40-
exists(string s |
41-
normal = true and s = "normal"
42-
or
43-
normal = false and s = "abnormal"
44-
|
45-
result = "exit " + scope + " (" + s + ")"
46-
)
47-
}
48-
}
49-
50-
/** An exit node for a given scope. */
51-
class ExitNode extends ControlFlowNode, TExitNode {
52-
private CfgScope scope;
53-
54-
ExitNode() { this = TExitNode(scope) }
55-
56-
final override Location getLocation() { result = scope.getLocation() }
57-
58-
final override string toString() { result = "exit " + scope }
59-
}
60-
6110
/**
6211
* A node for an AST node.
6312
*
6413
* Each AST node maps to zero or more `CfgNode`s: zero when the node is unreachable
6514
* (dead) code or not important for control flow, and multiple when there are different
6615
* splits for the AST node.
6716
*/
68-
class CfgNode extends ControlFlowNode, TElementNode {
69-
private Splits splits;
70-
ControlFlowElement n;
71-
72-
CfgNode() { this = TElementNode(_, n, splits) }
73-
74-
final override ControlFlowElement getNode() { result = n }
17+
class CfgNode extends ControlFlowNode instanceof Impl::AstCfgNode {
18+
final override ControlFlowElement getNode() { result = this.getAstNode() }
7519

76-
override Location getLocation() { result = n.getLocation() }
77-
78-
final override string toString() {
79-
exists(string s | s = n.toString() |
80-
result = "[" + this.getSplitsString() + "] " + s
81-
or
82-
not exists(this.getSplitsString()) and result = s
83-
)
84-
}
20+
/** Gets a split for this control flow node, if any. */
21+
final Split getASplit() { result = super.getASplit() }
8522

8623
/** Gets a comma-separated list of strings for each split in this node, if any. */
87-
final string getSplitsString() {
88-
result = splits.toString() and
89-
result != ""
90-
}
91-
92-
/** Gets a split for this control flow node, if any. */
93-
final Split getASplit() { result = splits.getASplit() }
24+
final string getSplitsString() { result = super.getSplitsString() }
9425

9526
/** Gets the AST representation of this control flow node, if any. */
9627
Expr getAst() {
97-
result = n.asAstNode()
28+
result = this.getNode().asAstNode()
9829
or
99-
result = n.(PropertyGetterElement).getRef()
30+
result = this.getNode().(PropertyGetterElement).getRef()
10031
or
101-
result = n.(PropertySetterElement).getAssignExpr()
32+
result = this.getNode().(PropertySetterElement).getAssignExpr()
10233
or
103-
result = n.(PropertyObserverElement).getAssignExpr()
34+
result = this.getNode().(PropertyObserverElement).getAssignExpr()
10435
or
105-
result = n.(ClosureElement).getAst()
36+
result = this.getNode().(ClosureElement).getAst()
10637
or
107-
result = n.(KeyPathElement).getAst()
38+
result = this.getNode().(KeyPathElement).getAst()
10839
}
10940
}
11041

@@ -130,7 +61,9 @@ class PatternCfgNode extends CfgNode {
13061

13162
/** A control-flow node that wraps a property getter. */
13263
class PropertyGetterCfgNode extends CfgNode {
133-
override PropertyGetterElement n;
64+
PropertyGetterElement n;
65+
66+
PropertyGetterCfgNode() { n = this.getAstNode() }
13467

13568
Expr getRef() { result = n.getRef() }
13669

@@ -141,7 +74,9 @@ class PropertyGetterCfgNode extends CfgNode {
14174

14275
/** A control-flow node that wraps a property setter. */
14376
class PropertySetterCfgNode extends CfgNode {
144-
override PropertySetterElement n;
77+
PropertySetterElement n;
78+
79+
PropertySetterCfgNode() { n = this.getAstNode() }
14580

14681
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
14782

@@ -153,7 +88,9 @@ class PropertySetterCfgNode extends CfgNode {
15388
}
15489

15590
class PropertyObserverCfgNode extends CfgNode {
156-
override PropertyObserverElement n;
91+
PropertyObserverElement n;
92+
93+
PropertyObserverCfgNode() { n = this.getAstNode() }
15794

15895
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
15996

@@ -201,3 +138,9 @@ class KeyPathApplicationExprCfgNode extends ExprCfgNode {
201138
class KeyPathExprCfgNode extends ExprCfgNode {
202139
override KeyPathExpr e;
203140
}
141+
142+
class EntryNode = Impl::EntryNode;
143+
144+
class ExitNode = Impl::ExitNode;
145+
146+
class AnnotatedExitNode = Impl::AnnotatedExitNode;

swift/ql/lib/codeql/swift/controlflow/ControlFlowGraph.qll

+2-8
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,10 @@ class CfgScope extends Scope instanceof CfgScope::Range_ {
2727
*
2828
* Only nodes that can be reached from an entry point are included in the CFG.
2929
*/
30-
class ControlFlowNode extends TCfgNode {
31-
/** Gets a textual representation of this control flow node. */
32-
string toString() { none() }
33-
30+
class ControlFlowNode extends Node {
3431
/** Gets the AST node that this node corresponds to, if any. */
3532
ControlFlowElement getNode() { none() }
3633

37-
/** Gets the location of this control flow node. */
38-
Location getLocation() { none() }
39-
4034
/** Gets the file of this control flow node. */
4135
final File getFile() { result = this.getLocation().getFile() }
4236

@@ -50,7 +44,7 @@ class ControlFlowNode extends TCfgNode {
5044
BasicBlock getBasicBlock() { result.getANode() = this }
5145

5246
/** Gets a successor node of a given type, if any. */
53-
final ControlFlowNode getASuccessor(SuccessorType t) { result = getASuccessor(this, t) }
47+
final ControlFlowNode getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
5448

5549
/** Gets an immediate successor, if any. */
5650
final ControlFlowNode getASuccessor() { result = this.getASuccessor(_) }

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
private import swift
22
private import Completion
3-
private import ControlFlowGraphImplShared
3+
private import ControlFlowGraphImplSpecific::CfgImpl
44
private import ControlFlowElements
55

66
abstract class AstControlFlowTree extends ControlFlowTree {

0 commit comments

Comments
 (0)