@@ -5,70 +5,59 @@ overlay[local]
55module ;
66
77import go
8- private import ControlFlowGraphImpl
98private import ControlFlowGraphShared
109
11- /** Provides helper predicates for mapping btween CFG nodes and the AST. */
10+ /** Provides helper predicates for mapping between CFG nodes and the AST. */
1211module ControlFlow {
13- /** A file or function with which a CFG is associated. */
12+ /** A function with which a CFG is associated. */
1413 class Root extends AstNode {
15- Root ( ) { exists ( this .( File ) . getADecl ( ) ) or exists ( this . ( FuncDef ) .getBody ( ) ) }
14+ Root ( ) { exists ( this .( FuncDef ) .getBody ( ) ) }
1615
17- /** Holds if `nd` belongs to this file or function. */
18- predicate isRootOf ( AstNode nd ) {
19- this = nd .getEnclosingFunction ( )
20- or
21- not exists ( nd .getEnclosingFunction ( ) ) and
22- this = nd .getFile ( )
23- }
16+ /** Holds if `nd` belongs to this function. */
17+ predicate isRootOf ( AstNode nd ) { this = nd .getEnclosingFunction ( ) }
2418
25- /** Gets the synthetic entry node of the CFG for this file or function. */
19+ /** Gets the synthetic entry node of the CFG for this function. */
2620 EntryNode getEntryNode ( ) { result = ControlFlow:: entryNode ( this ) }
2721
28- /** Gets the synthetic exit node of the CFG for this file or function. */
22+ /** Gets the synthetic exit node of the CFG for this function. */
2923 ExitNode getExitNode ( ) { result = ControlFlow:: exitNode ( this ) }
3024 }
3125
3226 /**
33- * A node in the intra-procedural control-flow graph of a Go function or file .
27+ * A node in the intra-procedural control-flow graph of a Go function.
3428 *
3529 * Nodes correspond to expressions and statements that compute a value or perform
3630 * an operation (as opposed to providing syntactic structure or type information).
3731 *
38- * There are also synthetic entry and exit nodes for each Go function and file
32+ * There are also synthetic entry and exit nodes for each Go function
3933 * that mark the beginning and the end, respectively, of the execution of the
40- * function and the loading of the file .
34+ * function.
4135 */
42- class Node extends TControlFlowNode {
43- /** Gets a node that directly follows this one in the control-flow graph. */
44- Node getASuccessor ( ) { result = CFG:: succ ( this ) }
45-
46- /** Gets a node that directly precedes this one in the control-flow graph. */
47- Node getAPredecessor ( ) { this = result .getASuccessor ( ) }
48-
36+ class Node extends GoCfg:: ControlFlowNode {
4937 /** Holds if this is a node with more than one successor. */
5038 predicate isBranch ( ) { strictcount ( this .getASuccessor ( ) ) > 1 }
5139
5240 /** Holds if this is a node with more than one predecessor. */
5341 predicate isJoin ( ) { strictcount ( this .getAPredecessor ( ) ) > 1 }
5442
5543 /** Holds if this is the first control-flow node in `subtree`. */
56- predicate isFirstNodeOf ( AstNode subtree ) { CFG:: firstNode ( subtree , this ) }
57-
58- /** Holds if this node is the (unique) entry node of a function or file. */
59- predicate isEntryNode ( ) { this instanceof MkEntryNode }
44+ predicate isFirstNodeOf ( AstNode subtree ) {
45+ this .isBefore ( subtree )
46+ or
47+ this .injects ( subtree )
48+ }
6049
61- /** Holds if this node is the (unique) exit node of a function or file . */
62- predicate isExitNode ( ) { this instanceof MkExitNode }
50+ /** Holds if this node is the (unique) entry node of a function. */
51+ predicate isEntryNode ( ) { this instanceof GoCfg :: ControlFlow :: EntryNode }
6352
64- /** Gets the basic block to which this node belongs . */
65- BasicBlock getBasicBlock ( ) { result . getANode ( ) = this }
53+ /** Holds if this node is the (unique) exit node of a function . */
54+ predicate isExitNode ( ) { this instanceof GoCfg :: ControlFlow :: ExitNode }
6655
6756 /** Holds if this node dominates `dominee` in the control-flow graph. */
6857 overlay [ caller?]
6958 pragma [ inline]
7059 predicate dominatesNode ( ControlFlow:: Node dominee ) {
71- exists ( ReachableBasicBlock thisbb , ReachableBasicBlock dbb , int i , int j |
60+ exists ( GoCfg :: Cfg :: BasicBlock thisbb , GoCfg :: Cfg :: BasicBlock dbb , int i , int j |
7261 this = thisbb .getNode ( i ) and dominee = dbb .getNode ( j )
7362 |
7463 thisbb .strictlyDominates ( dbb )
@@ -77,20 +66,12 @@ module ControlFlow {
7766 )
7867 }
7968
80- /** Gets the innermost function or file to which this node belongs. */
81- Root getRoot ( ) { none ( ) }
69+ /** Gets the innermost function to which this node belongs. */
70+ Root getRoot ( ) { result = this . getEnclosingCallable ( ) }
8271
8372 /** Gets the file to which this node belongs. */
8473 File getFile ( ) { result = this .getLocation ( ) .getFile ( ) }
8574
86- /**
87- * Gets a textual representation of this control flow node.
88- */
89- string toString ( ) { result = "control-flow node" }
90-
91- /** Gets the source location for this element. */
92- Location getLocation ( ) { none ( ) }
93-
9475 /**
9576 * DEPRECATED: Use `getLocation()` instead.
9677 *
@@ -114,6 +95,12 @@ module ControlFlow {
11495 }
11596 }
11697
98+ /** A synthetic entry node for a function. */
99+ class EntryNode extends Node instanceof GoCfg:: ControlFlow:: EntryNode { }
100+
101+ /** A synthetic exit node for a function. */
102+ class ExitNode extends Node instanceof GoCfg:: ControlFlow:: ExitNode { }
103+
117104 /**
118105 * A control-flow node that initializes or updates the value of a constant, a variable,
119106 * a field, or an (array, slice, or map) element.
@@ -173,7 +160,7 @@ module ControlFlow {
173160 exists ( IR:: FieldTarget trg | trg = super .getLhs ( ) |
174161 (
175162 trg .getBase ( ) = base or
176- trg .getBase ( ) = MkImplicitDeref ( base .( IR:: EvalInstruction ) .getExpr ( ) )
163+ trg .getBase ( ) = IR :: implicitDerefInstruction ( base .( IR:: EvalInstruction ) .getExpr ( ) )
177164 ) and
178165 trg .getField ( ) = f and
179166 super .getRhs ( ) = rhs
@@ -221,7 +208,7 @@ module ControlFlow {
221208 exists ( IR:: ElementTarget trg | trg = super .getLhs ( ) |
222209 (
223210 trg .getBase ( ) = base or
224- trg .getBase ( ) = MkImplicitDeref ( base .( IR:: EvalInstruction ) .getExpr ( ) )
211+ trg .getBase ( ) = IR :: implicitDerefInstruction ( base .( IR:: EvalInstruction ) .getExpr ( ) )
225212 ) and
226213 trg .getIndex ( ) = index and
227214 super .getRhs ( ) = rhs
@@ -251,11 +238,15 @@ module ControlFlow {
251238 * A control-flow node recording the fact that a certain expression has a known
252239 * Boolean value at this point in the program.
253240 */
254- class ConditionGuardNode extends IR :: Instruction , MkConditionGuardNode {
241+ class ConditionGuardNode extends Node {
255242 Expr cond ;
256243 boolean outcome ;
257244
258- ConditionGuardNode ( ) { this = MkConditionGuardNode ( cond , outcome ) }
245+ ConditionGuardNode ( ) {
246+ this .isAfterTrue ( cond ) and outcome = true
247+ or
248+ this .isAfterFalse ( cond ) and outcome = false
249+ }
259250
260251 private predicate ensuresAux ( Expr expr , boolean b ) {
261252 expr = cond and b = outcome
@@ -321,29 +312,27 @@ module ControlFlow {
321312 boolean getOutcome ( ) { result = outcome }
322313
323314 override Root getRoot ( ) { result .isRootOf ( cond ) }
324-
325- override string toString ( ) { result = cond + " is " + outcome }
326-
327- override Location getLocation ( ) { result = cond .getLocation ( ) }
328315 }
329316
330317 /**
331- * Gets the entry node of function or file `root`.
318+ * Gets the entry node of function `root`.
332319 */
333- Node entryNode ( Root root ) { result = MkEntryNode ( root ) }
320+ EntryNode entryNode ( Root root ) { result . getEnclosingCallable ( ) = root }
334321
335322 /**
336- * Gets the exit node of function or file `root`.
323+ * Gets the exit node of function `root`.
337324 */
338- Node exitNode ( Root root ) { result = MkExitNode ( root ) }
325+ ExitNode exitNode ( Root root ) { result . getEnclosingCallable ( ) = root }
339326
340327 /**
341328 * Holds if the function `f` may return without panicking, exiting the process, or looping forever.
342329 *
343330 * This is defined conservatively, and so may also hold of a function that in fact
344331 * cannot return normally, but never fails to hold of a function that can return normally.
345332 */
346- predicate mayReturnNormally ( FuncDecl f ) { CFG:: mayReturnNormally ( f .getBody ( ) ) }
333+ predicate mayReturnNormally ( FuncDecl f ) {
334+ exists ( GoCfg:: ControlFlow:: NormalExitNode exit | exit .getEnclosingCallable ( ) = f )
335+ }
347336
348337 /**
349338 * Holds if `pred` is the node for the case `testExpr` in an expression
@@ -353,20 +342,16 @@ module ControlFlow {
353342 predicate isSwitchCaseTestPassingEdge (
354343 ControlFlow:: Node pred , ControlFlow:: Node succ , Expr switchExpr , Expr testExpr
355344 ) {
356- CFG:: isSwitchCaseTestPassingEdge ( pred , succ , switchExpr , testExpr )
345+ exists ( ExpressionSwitchStmt ess , CaseClause cc , int i |
346+ ess .getExpr ( ) = switchExpr and
347+ cc = ess .getACase ( ) and
348+ testExpr = cc .getExpr ( i ) and
349+ pred .isAfter ( testExpr ) and
350+ succ .isFirstNodeOf ( cc .getStmt ( 0 ) )
351+ )
357352 }
358353}
359354
360355class ControlFlowNode = ControlFlow:: Node ;
361356
362357class Write = ControlFlow:: WriteNode ;
363-
364- /**
365- * Provides the shared CFG library types for Go.
366- *
367- * These types are generated by the shared `codeql.controlflow.ControlFlowGraph`
368- * library and coexist with the existing Go CFG types during the transition.
369- * Use `SharedCfg::ControlFlowNode` to access the shared library's node type,
370- * `SharedCfg::ControlFlow::EntryNode` for entry nodes, etc.
371- */
372- module SharedCfg = GoCfg;
0 commit comments