diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index e6ba8485eee..6473d4572a5 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -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;