Skip to content

Commit 37a1b0b

Browse files
committed
Java: some mechanical transformations
Only one in Dominance required thinking.
1 parent df8ce5d commit 37a1b0b

File tree

7 files changed

+50
-42
lines changed

7 files changed

+50
-42
lines changed

java/ql/lib/semmle/code/java/Expr.qll

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ class Expr extends ExprParent, @expr {
6161
Expr getAChildExpr() { exprs(result, _, _, this, _) }
6262

6363
/** Gets the basic block in which this expression occurs, if any. */
64-
BasicBlock getBasicBlock() { result.getANode() = this }
64+
BasicBlock getBasicBlock() { result.getANode().asExpr() = this }
6565

6666
/** Gets the `ControlFlowNode` corresponding to this expression. */
67-
ControlFlowNode getControlFlowNode() { result = this }
67+
ControlFlowNode getControlFlowNode() { result.asExpr() = this }
6868

6969
/** This statement's Halstead ID (used to compute Halstead metrics). */
7070
string getHalsteadID() { result = this.toString() }

java/ql/lib/semmle/code/java/Statement.qll

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ class Stmt extends StmtParent, ExprParent, @stmt {
4545
Stmt getAChild() { result.getParent() = this }
4646

4747
/** Gets the basic block in which this statement occurs. */
48-
BasicBlock getBasicBlock() { result.getANode() = this }
48+
BasicBlock getBasicBlock() { result.getANode().asStmt() = this }
4949

5050
/** Gets the `ControlFlowNode` corresponding to this statement. */
51-
ControlFlowNode getControlFlowNode() { result = this }
51+
ControlFlowNode getControlFlowNode() { result.asStmt() = this }
5252

5353
/** Cast this statement to a class that provides access to metrics information. */
5454
MetricStmt getMetrics() { result = this }

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

+10-11
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import java
99
*/
1010

1111
/** Entry points for control-flow. */
12-
private predicate flowEntry(Stmt entry) {
13-
exists(Callable c | entry = c.getBody())
14-
or
15-
// This disjunct is technically superfluous, but safeguards against extractor problems.
16-
entry instanceof BlockStmt and
17-
not exists(entry.getEnclosingCallable()) and
18-
not entry.getParent() instanceof Stmt
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+
)
1921
}
2022

2123
/** The successor relation for basic blocks. */
@@ -31,11 +33,8 @@ predicate hasDominanceInformation(BasicBlock bb) {
3133
exists(BasicBlock entry | flowEntry(entry) and bbSucc*(entry, bb))
3234
}
3335

34-
/** Exit points for control-flow. */
35-
private predicate flowExit(Callable exit) { exists(ControlFlowNode s | s.getASuccessor() = exit) }
36-
3736
/** Exit points for basic-block control-flow. */
38-
private predicate bbSink(BasicBlock exit) { flowExit(exit.getLastNode()) }
37+
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
3938

4039
/** Reversed `bbSucc`. */
4140
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private PatternCase getClosestPrecedingPatternCase(SwitchCase case) {
113113
private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pred) {
114114
pred = sc.getControlFlowNode().getAPredecessor() and
115115
(
116-
pred.(Expr).getParent*() = sc.getSelectorExpr()
116+
pred.asExpr().getParent*() = sc.getSelectorExpr()
117117
or
118118
// Ambiguous: in the case of `case String _ when x: case "SomeConstant":`, the guard `x`
119119
// passing edge will fall through into the constant case, and the guard failing edge
@@ -122,7 +122,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
122122
exists(PatternCase previousPatternCase |
123123
previousPatternCase = getClosestPrecedingPatternCase(sc)
124124
|
125-
pred.(Expr).getParent*() = previousPatternCase.getGuard() and
125+
pred.asExpr().getParent*() = previousPatternCase.getGuard() and
126126
// Check there is any statement in between the previous pattern case and this one,
127127
// or the case is a rule, so there is no chance of a fall-through.
128128
(
@@ -133,7 +133,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
133133
or
134134
// Unambigious: on the test-passing edge there must be at least one intervening
135135
// declaration node, including anonymous `_` declarations.
136-
pred = getClosestPrecedingPatternCase(sc)
136+
pred.asStmt() = getClosestPrecedingPatternCase(sc)
137137
)
138138
}
139139

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

+11-7
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ abstract class ActionConfiguration extends string {
3232
private BasicBlock actionBlock(ActionConfiguration conf) {
3333
exists(ControlFlowNode node | result = node.getBasicBlock() |
3434
conf.isAction(node) or
35-
callAlwaysPerformsAction(node, conf)
35+
callAlwaysPerformsAction(node.asCall(), conf)
3636
)
3737
}
3838

@@ -43,19 +43,23 @@ private predicate callAlwaysPerformsAction(Call call, ActionConfiguration conf)
4343
)
4444
}
4545

46+
private class ExitBlock extends BasicBlock {
47+
ExitBlock() { this.getLastNode() instanceof ControlFlow::ExitNode }
48+
}
49+
4650
/** Holds if an action dominates the exit of the callable. */
4751
private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) {
48-
exists(BasicBlock exit |
49-
exit.getLastNode() = callable and
52+
exists(ExitBlock exit |
53+
exit.getEnclosingCallable() = callable and
5054
actionBlock(conf).bbDominates(exit)
5155
)
5256
}
5357

5458
/** Gets a `BasicBlock` that contains an action that does not dominate the exit. */
5559
private BasicBlock nonDominatingActionBlock(ActionConfiguration conf) {
56-
exists(BasicBlock exit |
60+
exists(ExitBlock exit |
5761
result = actionBlock(conf) and
58-
exit.getLastNode() = result.getEnclosingCallable() and
62+
exit.getEnclosingCallable() = result.getEnclosingCallable() and
5963
not result.bbDominates(exit)
6064
)
6165
}
@@ -80,8 +84,8 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
8084
private predicate callableAlwaysPerformsAction(Callable callable, ActionConfiguration conf) {
8185
actionDominatesExit(callable, conf)
8286
or
83-
exists(BasicBlock exit |
84-
exit.getLastNode() = callable and
87+
exists(ExitBlock exit |
88+
exit.getEnclosingCallable() = callable and
8589
postActionBlock(exit, conf)
8690
)
8791
}

java/ql/lib/semmle/code/java/dataflow/SSA.qll

+20-15
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ private module SsaImpl {
228228
/** Holds if `n` must update the locally tracked variable `v`. */
229229
cached
230230
predicate certainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
231-
exists(VariableUpdate a | a = n | getDestVar(a) = v) and
231+
exists(VariableUpdate a | a.getControlFlowNode() = n | getDestVar(a) = v) and
232232
b.getNode(i) = n and
233233
hasDominanceInformation(b)
234234
or
@@ -237,8 +237,8 @@ private module SsaImpl {
237237

238238
/** Gets the definition point of a nested class in the parent scope. */
239239
private ControlFlowNode parentDef(NestedClass nc) {
240-
nc.(AnonymousClass).getClassInstanceExpr() = result or
241-
nc.(LocalClass).getLocalTypeDeclStmt() = result
240+
nc.(AnonymousClass).getClassInstanceExpr().getControlFlowNode() = result or
241+
nc.(LocalClass).getLocalTypeDeclStmt().getControlFlowNode() = result
242242
}
243243

244244
/**
@@ -276,7 +276,7 @@ private module SsaImpl {
276276

277277
/** Holds if `VarAccess` `use` of `v` occurs in `b` at index `i`. */
278278
private predicate variableUse(TrackedVar v, VarRead use, BasicBlock b, int i) {
279-
v.getAnAccess() = use and b.getNode(i) = use
279+
v.getAnAccess() = use and b.getNode(i) = use.getControlFlowNode()
280280
}
281281

282282
/** Holds if the value of `v` is captured in `b` at index `i`. */
@@ -423,7 +423,7 @@ private module SsaImpl {
423423
* `f` has an update somewhere.
424424
*/
425425
private predicate updateCandidate(TrackedField f, Call call, BasicBlock b, int i) {
426-
b.getNode(i) = call and
426+
b.getNode(i).asCall() = call and
427427
call.getEnclosingCallable() = f.getEnclosingCallable() and
428428
relevantFieldUpdate(_, f.getField(), _)
429429
}
@@ -550,7 +550,7 @@ private module SsaImpl {
550550
/** Holds if `n` might update the locally tracked variable `v`. */
551551
cached
552552
predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
553-
exists(Call c | c = n | updatesNamedField(c, v, _)) and
553+
exists(Call c | c = n.asCall() | updatesNamedField(c, v, _)) and
554554
b.getNode(i) = n and
555555
hasDominanceInformation(b)
556556
or
@@ -574,12 +574,16 @@ private module SsaImpl {
574574
/** Holds if `v` has an implicit definition at the entry, `b`, of the callable. */
575575
cached
576576
predicate hasEntryDef(TrackedVar v, BasicBlock b) {
577-
exists(LocalScopeVariable l, Callable c | v = TLocalVar(c, l) and c.getBody() = b |
577+
exists(LocalScopeVariable l, Callable c |
578+
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
579+
|
578580
l instanceof Parameter or
579581
l.getCallable() != c
580582
)
581583
or
582-
v instanceof SsaSourceField and v.getEnclosingCallable().getBody() = b and liveAtEntry(v, b)
584+
v instanceof SsaSourceField and
585+
v.getEnclosingCallable().getBody().getControlFlowNode() = b and
586+
liveAtEntry(v, b)
583587
}
584588

585589
/**
@@ -882,7 +886,7 @@ private newtype TSsaVariable =
882886
} or
883887
TSsaEntryDef(TrackedVar v, BasicBlock b) { hasEntryDef(v, b) } or
884888
TSsaUntracked(SsaSourceField nf, ControlFlowNode n) {
885-
n = nf.getAnAccess().(FieldRead) and not trackField(nf)
889+
n = nf.getAnAccess().(FieldRead).getControlFlowNode() and not trackField(nf)
886890
}
887891

888892
/**
@@ -940,7 +944,7 @@ class SsaVariable extends TSsaVariable {
940944
/** Gets an access of this SSA variable. */
941945
VarRead getAUse() {
942946
ssaDefReachesUse(_, this, result) or
943-
this = TSsaUntracked(_, result)
947+
this = TSsaUntracked(_, result.getControlFlowNode())
944948
}
945949

946950
/**
@@ -954,7 +958,7 @@ class SsaVariable extends TSsaVariable {
954958
*/
955959
VarRead getAFirstUse() {
956960
firstUse(this, result) or
957-
this = TSsaUntracked(_, result)
961+
this = TSsaUntracked(_, result.getControlFlowNode())
958962
}
959963

960964
/** Holds if this SSA variable is live at the end of `b`. */
@@ -990,15 +994,16 @@ class SsaUpdate extends SsaVariable {
990994
class SsaExplicitUpdate extends SsaUpdate, TSsaCertainUpdate {
991995
SsaExplicitUpdate() {
992996
exists(VariableUpdate upd |
993-
upd = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
997+
upd.getControlFlowNode() = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
994998
)
995999
}
9961000

9971001
override string toString() { result = "SSA def(" + this.getSourceVariable() + ")" }
9981002

9991003
/** Gets the `VariableUpdate` defining the SSA variable. */
10001004
VariableUpdate getDefiningExpr() {
1001-
result = this.getCfgNode() and getDestVar(result) = this.getSourceVariable()
1005+
result.getControlFlowNode() = this.getCfgNode() and
1006+
getDestVar(result) = this.getSourceVariable()
10021007
}
10031008
}
10041009

@@ -1038,7 +1043,7 @@ class SsaImplicitUpdate extends SsaUpdate {
10381043
exists(SsaSourceField f, Callable setter |
10391044
f = this.getSourceVariable() and
10401045
relevantFieldUpdate(setter, f.getField(), result) and
1041-
updatesNamedField(this.getCfgNode(), f, setter)
1046+
updatesNamedField(this.getCfgNode().asCall(), f, setter)
10421047
)
10431048
}
10441049

@@ -1086,7 +1091,7 @@ class SsaImplicitInit extends SsaVariable, TSsaEntryDef {
10861091
*/
10871092
predicate isParameterDefinition(Parameter p) {
10881093
this.getSourceVariable() = TLocalVar(p.getCallable(), p) and
1089-
p.getCallable().getBody() = this.getCfgNode()
1094+
p.getCallable().getBody().getControlFlowNode() = this.getCfgNode()
10901095
}
10911096
}
10921097

java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ private module Input implements TypeFlowInput<Location> {
235235
downcastSuccessorAux(pragma[only_bind_into](cast), v, t, t1, t2) and
236236
t1.getASourceSupertype+() = t2 and
237237
va = v.getAUse() and
238-
dominates(cast, va) and
239-
dominates(cast.(ControlFlowNode).getANormalSuccessor(), va)
238+
dominates(cast.getControlFlowNode(), va.getControlFlowNode()) and
239+
dominates(cast.getControlFlowNode().getANormalSuccessor(), va.getControlFlowNode())
240240
)
241241
}
242242

0 commit comments

Comments
 (0)