From 4a97a449fc215717e58183c3af0ee0214cfc5cfd Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 6 Feb 2026 16:37:43 +0100 Subject: [PATCH] Java: Replace ControlFlowNode.asCall with Call.getControlFlowNode. --- java/ql/lib/semmle/code/java/ControlFlowGraph.qll | 6 ------ java/ql/lib/semmle/code/java/Expr.qll | 9 +++++++++ java/ql/lib/semmle/code/java/Statement.qll | 6 ++++++ java/ql/lib/semmle/code/java/controlflow/Paths.qll | 2 +- java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll | 2 +- .../lib/semmle/code/java/dataflow/internal/SsaImpl.qll | 9 ++++++--- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 64449b6f93d..de1a239faea 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -162,12 +162,6 @@ module ControlFlow { /** Gets the expression this `Node` corresponds to, if any. */ Expr asExpr() { this = TExprNode(result) } - /** Gets the call this `Node` corresponds to, if any. */ - Call asCall() { - result = this.asExpr() or - result = this.asStmt() - } - /** Gets a textual representation of this element. */ string toString() { none() } diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index c609c35cd71..068ba100be9 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1245,6 +1245,9 @@ class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr { /** Gets the immediately enclosing statement of this class instance creation expression. */ override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() } + /** Gets a printable representation of this expression. */ override string toString() { result = "new " + this.getConstructor().getName() + "(...)" @@ -2113,6 +2116,9 @@ class MethodCall extends Expr, Call, @methodaccess { /** Gets the immediately enclosing statement that contains this method access. */ override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() } + /** Gets a printable representation of this expression. */ override string toString() { if exists(this.getMethod()) @@ -2305,6 +2311,9 @@ class Call extends ExprParent, @caller { /** Gets the enclosing statement of this call. */ /*abstract*/ Stmt getEnclosingStmt() { none() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + /*abstract*/ ControlFlowNode getControlFlowNode() { none() } + /** Gets the number of arguments provided in this call. */ int getNumArgument() { count(this.getAnArgument()) = result } diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index d7c091862db..e2c7779b43c 100644 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -960,6 +960,9 @@ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructori /** Gets the immediately enclosing statement of this constructor invocation. */ override Stmt getEnclosingStmt() { result = this } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() } + override string pp() { result = "this(...)" } override string toString() { result = "this(...)" } @@ -1001,6 +1004,9 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr /** Gets the immediately enclosing statement of this constructor invocation. */ override Stmt getEnclosingStmt() { result = this } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() } + override string pp() { result = "super(...)" } override string toString() { result = "super(...)" } diff --git a/java/ql/lib/semmle/code/java/controlflow/Paths.qll b/java/ql/lib/semmle/code/java/controlflow/Paths.qll index abc56e32b5c..23f0786966d 100644 --- a/java/ql/lib/semmle/code/java/controlflow/Paths.qll +++ b/java/ql/lib/semmle/code/java/controlflow/Paths.qll @@ -34,7 +34,7 @@ abstract class ActionConfiguration extends string { private BasicBlock actionBlock(ActionConfiguration conf) { exists(ControlFlowNode node | result = node.getBasicBlock() | conf.isAction(node) or - callAlwaysPerformsAction(node.asCall(), conf) + callAlwaysPerformsAction(any(Call call | call.getControlFlowNode() = node), conf) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll b/java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll index feeb0d100c6..60ed5591a95 100644 --- a/java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll +++ b/java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll @@ -229,7 +229,7 @@ class InstanceAccessExt extends TInstanceAccessExt { /** Gets the control flow node associated with this instance access. */ ControlFlowNode getCfgNode() { exists(ExprParent e | e = this.getAssociatedExprOrStmt() | - result.asCall() = e + result = e.(Call).getControlFlowNode() or e.(InstanceAccess).getControlFlowNode() = result or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll index 4610f576168..160cf030392 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll @@ -153,7 +153,7 @@ private predicate hasEntryDef(TrackedVar v, BasicBlock b) { overlay[global] pragma[nomagic] private predicate uncertainVariableUpdateImpl(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) { - exists(Call c | c = n.asCall() | updatesNamedField(c, v, _)) and + exists(Call c | c.getControlFlowNode() = n | updatesNamedField(c, v, _)) and b.getNode(i) = n and hasDominanceInformation(b) or @@ -525,8 +525,11 @@ private module Cached { overlay[global] cached predicate defUpdatesNamedField(SsaImplicitWrite calldef, TrackedField f, Callable setter) { - f = calldef.getSourceVariable() and - updatesNamedField0(calldef.getControlFlowNode().asCall(), f, setter) + exists(Call call | + f = calldef.getSourceVariable() and + call.getControlFlowNode() = calldef.getControlFlowNode() and + updatesNamedField0(call, f, setter) + ) } /** Holds if `init` is a closure variable that captures the value of `capturedvar`. */