Skip to content

Commit a917f24

Browse files
committed
QL: QL: Add a query that finds unnecessary 'exists'.
1 parent 690b7ef commit a917f24

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @name Superfluous 'exists' conjunct.
3+
* @description Writing 'exists(x)' when the existence of X is implied by another conjunct is bad practice.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @precision high
7+
* @id ql/superfluous-exists
8+
* @tags maintainability
9+
*/
10+
11+
import ql
12+
import codeql.GlobalValueNumbering
13+
14+
/**
15+
* Gets an operand of this conjunction (we need the restriction
16+
* to `Conjunction` to get the correct transitive closure).
17+
*/
18+
Formula getAConjOperand(Conjunction conj) { result = conj.getAnOperand() }
19+
20+
/** A conjunction that is not a operand of another conjunction. */
21+
class TopLevelConjunction extends Conjunction {
22+
TopLevelConjunction() { not this = getAConjOperand(_) }
23+
24+
/** Gets a formula within this conjunction that is not itself a conjunction. */
25+
Formula getAnAtom() {
26+
not result instanceof Conjunction and
27+
result = getAConjOperand*(this)
28+
}
29+
}
30+
31+
/**
32+
* Holds if the existence of `e` implies the existence of `vn`. For instance, the existence of
33+
* `1 + x` implies the existence of a value number `vn` such that `vn.getAnExpr() = x`.
34+
*/
35+
predicate exprImpliesExists(ValueNumber vn, Expr e) {
36+
vn.getAnExpr() = e
37+
or
38+
exprImpliesExists(vn, e.(BinOpExpr).getAnOperand())
39+
or
40+
exprImpliesExists(vn, e.(InlineCast).getBase())
41+
or
42+
exprImpliesExists(vn, e.(PredicateCall).getAnArgument())
43+
or
44+
exprImpliesExists(vn, [e.(MemberCall).getAnArgument(), e.(MemberCall).getBase()])
45+
or
46+
exprImpliesExists(vn, e.(UnaryExpr).getOperand())
47+
or
48+
exprImpliesExists(vn, e.(ExprAnnotation).getExpression())
49+
or
50+
forex(Formula child | child = e.(Set).getAnElement() | exprImpliesExists(vn, child))
51+
or
52+
exprImpliesExists(vn, e.(AsExpr).getInnerExpr())
53+
or
54+
exprImpliesExists(vn, e.(Range).getAnEndpoint())
55+
or
56+
exists(ExprAggregate agg |
57+
agg = e and
58+
agg.getKind().matches(["strict%", "unique"]) and
59+
exprImpliesExists(vn, agg.getExpr(0))
60+
)
61+
}
62+
63+
/**
64+
* Holds if the satisfiability of `f` implies the existence of `vn`. For instance, if `x.foo()` is
65+
* satisfied, the value number `vn` such that `vn.getAnExpr() = x` exists.
66+
*/
67+
predicate formulaImpliesExists(ValueNumber vn, Formula f) {
68+
forex(Formula child | child = f.(Disjunction).getAnOperand() | formulaImpliesExists(vn, child))
69+
or
70+
formulaImpliesExists(vn, f.(Conjunction).getAnOperand())
71+
or
72+
exprImpliesExists(vn, f.(ComparisonFormula).getAnOperand())
73+
or
74+
exists(IfFormula ifFormula | ifFormula = f |
75+
exprImpliesExists(vn, ifFormula.getCondition())
76+
or
77+
formulaImpliesExists(vn, ifFormula.getThenPart()) and
78+
formulaImpliesExists(vn, ifFormula.getElsePart())
79+
)
80+
or
81+
exprImpliesExists(vn, f.(InstanceOf).getExpr())
82+
or
83+
exprImpliesExists(vn, f.(PredicateCall).getAnArgument())
84+
or
85+
exprImpliesExists(vn, [f.(MemberCall).getAnArgument(), f.(MemberCall).getBase()])
86+
or
87+
exists(InFormula inFormula | inFormula = f |
88+
exprImpliesExists(vn, [inFormula.getExpr(), inFormula.getRange()])
89+
)
90+
}
91+
92+
from TopLevelConjunction toplevel, Exists existsFormula, ValueNumber vn, Formula conjunct
93+
where
94+
existsFormula = toplevel.getAnAtom() and
95+
vn.getAnExpr() = existsFormula.getExpr() and
96+
conjunct = toplevel.getAnAtom() and
97+
formulaImpliesExists(vn, conjunct)
98+
select existsFormula, "This conjunct is superfluous as the existence is implied by $@.", conjunct,
99+
"this conjunct"

0 commit comments

Comments
 (0)