1+ /**
2+ * Provides the `CfgImpl` module that is used to construct the basic successor relation on control
3+ * flow elements, and the `CfgInput` module that is used to construct `CgfImpl`.
4+ *
5+ * See `ControlFlowGraphImpl.qll` for the auxiliary classes and predicates that map AST elements to
6+ * control flow elements and sequence their children.
7+ */
8+
19private import swift as S
10+ import codeql.controlflow.Cfg
11+ import codeql.util.Unit
12+ private import Completion as C
213private import ControlFlowGraphImpl as Impl
314import Completion
4- private import codeql.swift.controlflow.ControlFlowGraph as CFG
15+ private import codeql.swift.controlflow.ControlFlowGraph as Cfg
516private import Splitting as Splitting
617private import Scope
718import ControlFlowElements
@@ -10,13 +21,72 @@ import AstControlFlowTrees
1021/** The base class for `ControlFlowTree`. */
1122class ControlFlowTreeBase = ControlFlowElement ;
1223
13- class CfgScope = CFG :: CfgScope ;
24+ class CfgScope = Cfg :: CfgScope ;
1425
1526predicate getCfgScope = Impl:: getCfgScope / 1 ;
1627
1728/** Gets the maximum number of splits allowed for a given node. */
18- int maxSplits ( ) { result = 5 }
19-
2029class Location = S:: Location ;
2130
22- class Node = CFG:: ControlFlowNode ;
31+ class Node = Cfg:: ControlFlowNode ;
32+
33+ module CfgInput implements InputSig< Location > {
34+ class AstNode = ControlFlowElement ;
35+
36+ class Completion = C:: Completion ;
37+
38+ predicate completionIsNormal = C:: completionIsNormal / 1 ;
39+
40+ predicate completionIsSimple = C:: completionIsSimple / 1 ;
41+
42+ predicate completionIsValidFor = C:: completionIsValidFor / 2 ;
43+
44+ /** An AST node with an associated control-flow graph. */
45+ class CfgScope extends S:: Locatable instanceof Impl:: CfgScope:: Range_ { }
46+
47+ CfgScope getCfgScope ( AstNode n ) { result = scopeOfAst ( n .asAstNode ( ) ) }
48+
49+ class SplitKindBase = Splitting:: TSplitKind ;
50+
51+ class Split = Splitting:: Split ;
52+
53+ class SuccessorType = Cfg:: SuccessorType ;
54+
55+ /** Gets a successor type that matches completion `c`. */
56+ SuccessorType getAMatchingSuccessorType ( Completion c ) { result = c .getAMatchingSuccessorType ( ) }
57+
58+ /**
59+ * Hold if `c` represents simple (normal) evaluation of a statement or an
60+ * expression.
61+ */
62+ predicate successorTypeIsSimple ( SuccessorType t ) {
63+ t instanceof Cfg:: SuccessorTypes:: NormalSuccessor
64+ }
65+
66+ /** Holds if `t` is an abnormal exit type out of a CFG scope. */
67+ predicate isAbnormalExitType ( SuccessorType t ) {
68+ t instanceof Cfg:: SuccessorTypes:: ExceptionSuccessor
69+ }
70+
71+ /** Hold if `t` represents a conditional successor type. */
72+ predicate successorTypeIsCondition ( SuccessorType t ) {
73+ t instanceof Cfg:: SuccessorTypes:: BooleanSuccessor or
74+ t instanceof Cfg:: SuccessorTypes:: BreakSuccessor or
75+ t instanceof Cfg:: SuccessorTypes:: ContinueSuccessor or
76+ t instanceof Cfg:: SuccessorTypes:: MatchingSuccessor or
77+ t instanceof Cfg:: SuccessorTypes:: EmptinessSuccessor
78+ }
79+
80+ /** Holds if `first` is first executed when entering `scope`. */
81+ predicate scopeFirst ( CfgScope scope , AstNode first ) {
82+ scope .( Impl:: CfgScope:: Range_ ) .entry ( first )
83+ }
84+
85+ /** Holds if `scope` is exited when `last` finishes with completion `c`. */
86+ predicate scopeLast ( CfgScope scope , AstNode last , Completion c ) {
87+ scope .( Impl:: CfgScope:: Range_ ) .exit ( last , c )
88+ }
89+ }
90+
91+ module CfgImpl = Make< Location , CfgInput > ;
92+
0 commit comments