Make separate classes for control flow node kinds

This puts all the logic of a particular control flow node kind into one
place and makes it easier to add new kinds.
This commit is contained in:
Owen Mansel-Chan
2024-11-15 11:07:01 +00:00
parent f0971684e3
commit 79f4f78fc2

View File

@@ -105,29 +105,19 @@ module ControlFlow {
/** A node in the expression-level control-flow graph. */
class Node extends TNode {
/** Gets the statement containing this node, if any. */
Stmt getEnclosingStmt() {
result = this.asStmt() or
result = this.asExpr().getEnclosingStmt()
}
Stmt getEnclosingStmt() { none() }
/** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() {
this = TExitNode(result) or
result = this.asStmt().getEnclosingCallable() or
result = this.asExpr().getEnclosingCallable()
}
Callable getEnclosingCallable() { none() }
/** Gets the statement this `Node` corresponds to, if any. */
Stmt asStmt() { this = TStmtNode(result) }
Stmt asStmt() { none() }
/** Gets the expression this `Node` corresponds to, if any. */
Expr asExpr() { this = TExprNode(result) }
Expr asExpr() { none() }
/** Gets the call this `Node` corresponds to, if any. */
Call asCall() {
result = this.asExpr() or
result = this.asStmt()
}
Call asCall() { none() }
/** Gets an immediate successor of this node. */
Node getASuccessor() { result = succ(this) }
@@ -148,33 +138,77 @@ module ControlFlow {
BasicBlock getBasicBlock() { result.getANode() = this }
/** Gets a textual representation of this element. */
string toString() {
result = this.asExpr().toString()
or
result = this.asStmt().toString()
or
result = "Exit" and this instanceof ExitNode
}
string toString() { none() }
/** Gets the source location for this element. */
Location getLocation() {
result = this.asExpr().getLocation() or
result = this.asStmt().getLocation() or
result = this.(ExitNode).getEnclosingCallable().getLocation()
}
Location getLocation() { none() }
/**
* Gets the most appropriate AST node for this control flow node, if any.
*/
ExprParent getAstNode() {
result = this.asExpr() or
result = this.asStmt() or
this = TExitNode(result)
}
ExprParent getAstNode() { none() }
}
/** A control-flow node that represents the evaluation of an expression. */
class ExprNode extends Node, TExprNode {
Expr e;
ExprNode() { this = TExprNode(e) }
override Stmt getEnclosingStmt() { result = e.getEnclosingStmt() }
override Callable getEnclosingCallable() { result = e.getEnclosingCallable() }
override Expr asExpr() { result = e }
override Call asCall() { result = e }
override ExprParent getAstNode() { result = e }
/** Gets a textual representation of this element. */
override string toString() { result = e.toString() }
/** Gets the source location for this element. */
override Location getLocation() { result = e.getLocation() }
}
/** A control-flow node that represents a statement. */
class StmtNode extends Node, TStmtNode {
Stmt s;
StmtNode() { this = TStmtNode(s) }
override Stmt getEnclosingStmt() { result = s }
override Callable getEnclosingCallable() { result = s.getEnclosingCallable() }
override Stmt asStmt() { result = s }
override Call asCall() { result = s }
override ExprParent getAstNode() { result = s }
override string toString() { result = s.toString() }
override Location getLocation() { result = s.getLocation() }
}
/** A control flow node indicating the termination of a callable. */
class ExitNode extends Node, TExitNode { }
class ExitNode extends Node, TExitNode {
Callable c;
ExitNode() { this = TExitNode(c) }
override Callable getEnclosingCallable() { result = c }
override ExprParent getAstNode() { result = c }
/** Gets a textual representation of this element. */
override string toString() { result = "Exit" }
/** Gets the source location for this element. */
override Location getLocation() { result = c.getLocation() }
}
}
class ControlFlowNode = ControlFlow::Node;