mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
C++: add edge-based predicates to IRGuards
These predicates currently take a pair of `IRBlock`s - as it stands, at most one edge can exist from one `IRBlock` to a given other `IRBlock`. We may need to revisit that assumption and create an `IREdge` IPA type at some future date
This commit is contained in:
@@ -281,6 +281,16 @@ class IRGuardCondition extends Instruction {
|
||||
ne.controls(controlled, testIsTrue.booleanNot()))
|
||||
}
|
||||
|
||||
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
|
||||
pred.getASuccessor() = succ and
|
||||
controls(pred, testIsTrue)
|
||||
or
|
||||
hasBranchEdge(succ, testIsTrue) and
|
||||
branch.getCondition() = this and
|
||||
branch.getBlock() = pred
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holds if `branch` jumps directly to `succ` when this condition is `testIsTrue`.
|
||||
*
|
||||
@@ -296,7 +306,8 @@ class IRGuardCondition extends Instruction {
|
||||
* return x;
|
||||
* ```
|
||||
*/
|
||||
predicate hasBranchEdge(IRBlock succ, boolean testIsTrue) {
|
||||
private predicate hasBranchEdge(IRBlock succ, boolean testIsTrue) {
|
||||
branch.getCondition() = this and
|
||||
(
|
||||
testIsTrue = true and
|
||||
succ.getFirstInstruction() = branch.getTrueSuccessor()
|
||||
@@ -319,6 +330,14 @@ class IRGuardCondition extends Instruction {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
|
||||
* `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`. */
|
||||
cached predicate ensuresLtEdge(Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean isLessThan) {
|
||||
exists(boolean testIsTrue |
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controlsEdge(pred, succ, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
cached predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue)
|
||||
@@ -331,6 +350,13 @@ class IRGuardCondition extends Instruction {
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
/** Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from
|
||||
* `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`. */
|
||||
cached predicate ensuresEqEdge(Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
|
||||
exists(boolean testIsTrue |
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controlsEdge(pred, succ, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
|
||||
@@ -386,11 +386,7 @@ private predicate boundFlowStepPhi(
|
||||
or
|
||||
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||
(
|
||||
guard.hasBranchEdge(op2.getPredecessorBlock().getLastInstruction(), op2.getUseInstruction().getBlock(), testIsTrue)
|
||||
or
|
||||
guard.controls(op2.getPredecessorBlock(), testIsTrue)
|
||||
) and
|
||||
guard.controlsEdge(op2.getPredecessorBlock(), op2.getUseInstruction().getBlock(), testIsTrue) and
|
||||
reason = TCondReason(guard)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -151,4 +151,3 @@ void test5(int x) {
|
||||
void test6(int x, int y) {
|
||||
return x && y;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user