Skip to content

Commit 00c7bc1

Browse files
authored
Merge pull request #19505 from aschackmull/java/basicblock
Java: Use the shared BasicBlocks library.
2 parents 2952c0d + 10efea1 commit 00c7bc1

File tree

39 files changed

+331
-233
lines changed

39 files changed

+331
-233
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private import SemanticExprSpecific::SemanticExprConfig as Specific
1010
*/
1111
class SemBasicBlock extends Specific::BasicBlock {
1212
/** Holds if this block (transitively) dominates `otherblock`. */
13-
final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
13+
final predicate dominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
1414

1515
/** Gets an expression that is evaluated in this basic block. */
1616
final SemExpr getAnExpr() { result.getBasicBlock() = this }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* Java now uses the shared `BasicBlock` library. This means that the names of several member predicates have been changed to align with the names used in other languages. The old predicates have been deprecated. The `BasicBlock` class itself no longer extends `ControlFlowNode` - the predicate `getFirstNode` can be used to fix any QL code that somehow relied on this.

java/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: java
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/controlflow: ${workspace}
910
codeql/dataflow: ${workspace}
1011
codeql/mad: ${workspace}
1112
codeql/quantum: ${workspace}

java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll

Lines changed: 107 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -4,91 +4,128 @@
44

55
import java
66
import Dominance
7+
private import codeql.controlflow.BasicBlock as BB
78

8-
cached
9-
private module BasicBlockStage {
10-
cached
11-
predicate ref() { any() }
9+
private module Input implements BB::InputSig<Location> {
10+
import SuccessorType
1211

13-
cached
14-
predicate backref() {
15-
(exists(any(BasicBlock bb).getABBSuccessor()) implies any()) and
16-
(exists(any(BasicBlock bb).getNode(_)) implies any()) and
17-
(exists(any(BasicBlock bb).length()) implies any())
18-
}
19-
}
20-
21-
/**
22-
* A control-flow node that represents the start of a basic block.
23-
*
24-
* A basic block is a series of nodes with no control-flow branching, which can
25-
* often be treated as a unit in analyses.
26-
*/
27-
class BasicBlock extends ControlFlowNode {
28-
cached
29-
BasicBlock() {
30-
BasicBlockStage::ref() and
31-
not exists(this.getAPredecessor()) and
32-
exists(this.getASuccessor())
33-
or
34-
strictcount(this.getAPredecessor()) > 1
35-
or
36-
exists(ControlFlowNode pred | pred = this.getAPredecessor() |
37-
strictcount(pred.getASuccessor()) > 1
38-
)
39-
}
12+
/** Hold if `t` represents a conditional successor type. */
13+
predicate successorTypeIsCondition(SuccessorType t) { none() }
4014

41-
/** Gets an immediate successor of this basic block. */
42-
cached
43-
BasicBlock getABBSuccessor() {
44-
BasicBlockStage::ref() and
45-
result = this.getLastNode().getASuccessor()
46-
}
15+
/** A delineated part of the AST with its own CFG. */
16+
class CfgScope = Callable;
4717

48-
/** Gets an immediate predecessor of this basic block. */
49-
BasicBlock getABBPredecessor() { result.getABBSuccessor() = this }
18+
/** The class of control flow nodes. */
19+
class Node = ControlFlowNode;
5020

51-
/** Gets a control-flow node contained in this basic block. */
52-
ControlFlowNode getANode() { result = this.getNode(_) }
21+
/** Gets the CFG scope in which this node occurs. */
22+
CfgScope nodeGetCfgScope(Node node) { node.getEnclosingCallable() = result }
5323

54-
/** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */
55-
cached
56-
ControlFlowNode getNode(int pos) {
57-
BasicBlockStage::ref() and
58-
result = this and
59-
pos = 0
24+
private Node getASpecificSuccessor(Node node, SuccessorType t) {
25+
node.(ConditionNode).getABranchSuccessor(t.(BooleanSuccessor).getValue()) = result
6026
or
61-
exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 |
62-
this.getNode(mid_pos) = mid and
63-
mid.getASuccessor() = result and
64-
not result instanceof BasicBlock
65-
)
27+
node.getAnExceptionSuccessor() = result and t instanceof ExceptionSuccessor
6628
}
6729

68-
/** Gets the first control-flow node in this basic block. */
69-
ControlFlowNode getFirstNode() { result = this }
70-
71-
/** Gets the last control-flow node in this basic block. */
72-
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
30+
/** Gets an immediate successor of this node. */
31+
Node nodeGetASuccessor(Node node, SuccessorType t) {
32+
result = getASpecificSuccessor(node, t)
33+
or
34+
node.getASuccessor() = result and
35+
t instanceof NormalSuccessor and
36+
not result = getASpecificSuccessor(node, _)
37+
}
7338

74-
/** Gets the number of control-flow nodes contained in this basic block. */
75-
cached
76-
int length() {
77-
BasicBlockStage::ref() and
78-
result = strictcount(this.getANode())
39+
/**
40+
* Holds if `node` represents an entry node to be used when calculating
41+
* dominance.
42+
*/
43+
predicate nodeIsDominanceEntry(Node node) {
44+
exists(Stmt entrystmt | entrystmt = node.asStmt() |
45+
exists(Callable c | entrystmt = c.getBody())
46+
or
47+
// This disjunct is technically superfluous, but safeguards against extractor problems.
48+
entrystmt instanceof BlockStmt and
49+
not exists(entrystmt.getEnclosingCallable()) and
50+
not entrystmt.getParent() instanceof Stmt
51+
)
7952
}
8053

81-
/** Holds if this basic block strictly dominates `node`. */
82-
predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) }
54+
/**
55+
* Holds if `node` represents an exit node to be used when calculating
56+
* post dominance.
57+
*/
58+
predicate nodeIsPostDominanceExit(Node node) { node instanceof ControlFlow::ExitNode }
59+
}
60+
61+
private module BbImpl = BB::Make<Location, Input>;
8362

84-
/** Holds if this basic block dominates `node`. (This is reflexive.) */
85-
predicate bbDominates(BasicBlock node) { bbDominates(this, node) }
63+
import BbImpl
8664

87-
/** Holds if this basic block strictly post-dominates `node`. */
88-
predicate bbStrictlyPostDominates(BasicBlock node) { bbStrictlyPostDominates(this, node) }
65+
/** Holds if the dominance relation is calculated for `bb`. */
66+
predicate hasDominanceInformation(BasicBlock bb) {
67+
exists(BasicBlock entry |
68+
Input::nodeIsDominanceEntry(entry.getFirstNode()) and entry.getASuccessor*() = bb
69+
)
70+
}
8971

90-
/** Holds if this basic block post-dominates `node`. (This is reflexive.) */
91-
predicate bbPostDominates(BasicBlock node) { bbPostDominates(this, node) }
72+
/**
73+
* A basic block, that is, a maximal straight-line sequence of control flow nodes
74+
* without branches or joins.
75+
*/
76+
class BasicBlock extends BbImpl::BasicBlock {
77+
/** Gets the immediately enclosing callable whose body contains this node. */
78+
Callable getEnclosingCallable() { result = this.getScope() }
79+
80+
/**
81+
* Holds if this basic block dominates basic block `bb`.
82+
*
83+
* That is, all paths reaching `bb` from the entry point basic block must
84+
* go through this basic block.
85+
*/
86+
predicate dominates(BasicBlock bb) { super.dominates(bb) }
87+
88+
/**
89+
* DEPRECATED: Use `getASuccessor` instead.
90+
*
91+
* Gets an immediate successor of this basic block.
92+
*/
93+
deprecated BasicBlock getABBSuccessor() { result = this.getASuccessor() }
94+
95+
/**
96+
* DEPRECATED: Use `getAPredecessor` instead.
97+
*
98+
* Gets an immediate predecessor of this basic block.
99+
*/
100+
deprecated BasicBlock getABBPredecessor() { result.getASuccessor() = this }
101+
102+
/**
103+
* DEPRECATED: Use `strictlyDominates` instead.
104+
*
105+
* Holds if this basic block strictly dominates `node`.
106+
*/
107+
deprecated predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) }
108+
109+
/**
110+
* DEPRECATED: Use `dominates` instead.
111+
*
112+
* Holds if this basic block dominates `node`. (This is reflexive.)
113+
*/
114+
deprecated predicate bbDominates(BasicBlock node) { this.dominates(node) }
115+
116+
/**
117+
* DEPRECATED: Use `strictlyPostDominates` instead.
118+
*
119+
* Holds if this basic block strictly post-dominates `node`.
120+
*/
121+
deprecated predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) }
122+
123+
/**
124+
* DEPRECATED: Use `postDominates` instead.
125+
*
126+
* Holds if this basic block post-dominates `node`. (This is reflexive.)
127+
*/
128+
deprecated predicate bbPostDominates(BasicBlock node) { this.postDominates(node) }
92129
}
93130

94131
/** A basic block that ends in an exit node. */

java/ql/lib/semmle/code/java/controlflow/Dominance.qll

Lines changed: 45 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,91 +8,75 @@ import java
88
* Predicates for basic-block-level dominance.
99
*/
1010

11-
/** Entry points for control-flow. */
12-
private predicate flowEntry(BasicBlock entry) {
13-
exists(Stmt entrystmt | entrystmt = entry.getFirstNode().asStmt() |
14-
exists(Callable c | entrystmt = c.getBody())
15-
or
16-
// This disjunct is technically superfluous, but safeguards against extractor problems.
17-
entrystmt instanceof BlockStmt and
18-
not exists(entry.getEnclosingCallable()) and
19-
not entrystmt.getParent() instanceof Stmt
20-
)
21-
}
22-
23-
/** The successor relation for basic blocks. */
24-
private predicate bbSucc(BasicBlock pre, BasicBlock post) { post = pre.getABBSuccessor() }
25-
26-
/** The immediate dominance relation for basic blocks. */
27-
cached
28-
predicate bbIDominates(BasicBlock dom, BasicBlock node) =
29-
idominance(flowEntry/1, bbSucc/2)(_, dom, node)
30-
31-
/** Holds if the dominance relation is calculated for `bb`. */
32-
predicate hasDominanceInformation(BasicBlock bb) {
33-
exists(BasicBlock entry | flowEntry(entry) and bbSucc*(entry, bb))
11+
/**
12+
* DEPRECATED: Use `BasicBlock::immediatelyDominates` instead.
13+
*
14+
* The immediate dominance relation for basic blocks.
15+
*/
16+
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock node) {
17+
dom.immediatelyDominates(node)
3418
}
3519

3620
/** Exit points for basic-block control-flow. */
3721
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
3822

3923
/** Reversed `bbSucc`. */
40-
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }
24+
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() }
4125

4226
/** The immediate post-dominance relation on basic blocks. */
43-
cached
44-
predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
27+
deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
4528
idominance(bbSink/1, bbPred/2)(_, dominator, node)
4629

47-
/** Holds if `dom` strictly dominates `node`. */
48-
predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) { bbIDominates+(dom, node) }
49-
50-
/** Holds if `dom` dominates `node`. (This is reflexive.) */
51-
predicate bbDominates(BasicBlock dom, BasicBlock node) {
52-
bbStrictlyDominates(dom, node) or dom = node
30+
/**
31+
* DEPRECATED: Use `BasicBlock::strictlyDominates` instead.
32+
*
33+
* Holds if `dom` strictly dominates `node`.
34+
*/
35+
deprecated predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) {
36+
dom.strictlyDominates(node)
5337
}
5438

55-
/** Holds if `dom` strictly post-dominates `node`. */
56-
predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) { bbIPostDominates+(dom, node) }
39+
/**
40+
* DEPRECATED: Use `BasicBlock::dominates` instead.
41+
*
42+
* Holds if `dom` dominates `node`. (This is reflexive.)
43+
*/
44+
deprecated predicate bbDominates(BasicBlock dom, BasicBlock node) { dom.dominates(node) }
5745

58-
/** Holds if `dom` post-dominates `node`. (This is reflexive.) */
59-
predicate bbPostDominates(BasicBlock dom, BasicBlock node) {
60-
bbStrictlyPostDominates(dom, node) or dom = node
46+
/**
47+
* DEPRECATED: Use `BasicBlock::strictlyPostDominates` instead.
48+
*
49+
* Holds if `dom` strictly post-dominates `node`.
50+
*/
51+
deprecated predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) {
52+
dom.strictlyPostDominates(node)
6153
}
6254

55+
/**
56+
* DEPRECATED: Use `BasicBlock::postDominates` instead.
57+
*
58+
* Holds if `dom` post-dominates `node`. (This is reflexive.)
59+
*/
60+
deprecated predicate bbPostDominates(BasicBlock dom, BasicBlock node) { dom.postDominates(node) }
61+
6362
/**
6463
* The dominance frontier relation for basic blocks.
6564
*
6665
* This is equivalent to:
6766
*
6867
* ```
69-
* bbDominates(x, w.getABBPredecessor()) and not bbStrictlyDominates(x, w)
68+
* x.dominates(w.getAPredecessor()) and not x.strictlyDominates(w)
7069
* ```
7170
*/
7271
predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
73-
x = w.getABBPredecessor() and not bbIDominates(x, w)
72+
x = w.getAPredecessor() and not x.immediatelyDominates(w)
7473
or
7574
exists(BasicBlock prev | dominanceFrontier(prev, w) |
76-
bbIDominates(x, prev) and
77-
not bbIDominates(x, w)
75+
x.immediatelyDominates(prev) and
76+
not x.immediatelyDominates(w)
7877
)
7978
}
8079

81-
/**
82-
* Holds if `(bb1, bb2)` is an edge that dominates `bb2`, that is, all other
83-
* predecessors of `bb2` are dominated by `bb2`. This implies that `bb1` is the
84-
* immediate dominator of `bb2`.
85-
*
86-
* This is a necessary and sufficient condition for an edge to dominate anything,
87-
* and in particular `dominatingEdge(bb1, bb2) and bb2.bbDominates(bb3)` means
88-
* that the edge `(bb1, bb2)` dominates `bb3`.
89-
*/
90-
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
91-
bbIDominates(bb1, bb2) and
92-
bb1.getABBSuccessor() = bb2 and
93-
forall(BasicBlock pred | pred = bb2.getABBPredecessor() and pred != bb1 | bbDominates(bb2, pred))
94-
}
95-
9680
/*
9781
* Predicates for expression-level dominance.
9882
*/
@@ -102,7 +86,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
10286
exists(BasicBlock bb, int i | dominator = bb.getNode(i) and node = bb.getNode(i + 1))
10387
or
10488
exists(BasicBlock dom, BasicBlock bb |
105-
bbIDominates(dom, bb) and
89+
dom.immediatelyDominates(bb) and
10690
dominator = dom.getLastNode() and
10791
node = bb.getFirstNode()
10892
)
@@ -112,7 +96,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
11296
pragma[inline]
11397
predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
11498
// This predicate is gigantic, so it must be inlined.
115-
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
99+
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
116100
or
117101
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i < j)
118102
}
@@ -121,7 +105,7 @@ predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
121105
pragma[inline]
122106
predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
123107
// This predicate is gigantic, so it must be inlined.
124-
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
108+
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
125109
or
126110
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i <= j)
127111
}
@@ -130,7 +114,7 @@ predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
130114
pragma[inline]
131115
predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
132116
// This predicate is gigantic, so it must be inlined.
133-
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
117+
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
134118
or
135119
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i > j)
136120
}
@@ -139,7 +123,7 @@ predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
139123
pragma[inline]
140124
predicate postDominates(ControlFlowNode dom, ControlFlowNode node) {
141125
// This predicate is gigantic, so it must be inlined.
142-
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
126+
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
143127
or
144128
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i >= j)
145129
}

0 commit comments

Comments
 (0)