JS: only warn about dead code

This commit is contained in:
Asger F
2018-11-06 11:47:18 +00:00
parent 2d6bf0aff3
commit 5283c6cd48

View File

@@ -11,18 +11,49 @@
import javascript
/**
* Gets the guard node with the opposite outcome of `guard`.
* Holds if there are any contradictory guard nodes in `container`.
*
* We use this to restrict reachability analysis to a small set of containers.
*/
ConditionGuardNode getOppositeGuard(ConditionGuardNode guard) {
result.getTest() = guard.getTest() and
result.getOutcome() = guard.getOutcome().booleanNot()
predicate hasContradictoryGuardNodes(StmtContainer container) {
exists (ConditionGuardNode guard |
RangeAnalysis::isContradictoryGuardNode(guard) and
container = guard.getContainer())
}
/**
* Holds if `block` is reachable and is in a container with contradictory guard nodes.
*/
predicate isReachable(BasicBlock block) {
exists (StmtContainer container |
hasContradictoryGuardNodes(container) and
block = container.getEntryBB())
or
isReachable(block.getAPredecessor()) and
not RangeAnalysis::isContradictoryGuardNode(block.getANode())
}
/**
* Holds if `block` is unreachable, but could be reached if `guard` was not contradictory.
*/
predicate isBlockedByContradictoryGuardNodes(BasicBlock block, ConditionGuardNode guard) {
RangeAnalysis::isContradictoryGuardNode(guard) and
isReachable(block.getAPredecessor()) and // the guard itself is reachable
block = guard.getBasicBlock()
or
isBlockedByContradictoryGuardNodes(block.getAPredecessor(), guard) and
not isReachable(block)
}
/**
* Holds if the given guard node is contradictory and causes an expression or statement to be unreachable.
*/
predicate isGuardNodeWithDeadCode(ConditionGuardNode guard) {
exists (BasicBlock block |
isBlockedByContradictoryGuardNodes(block, guard) and
block.getANode() instanceof ExprOrStmt)
}
from ConditionGuardNode guard
where RangeAnalysis::isContradictoryGuardNode(guard)
// Do not report conditions that themselves are unreachable because of
// a prior contradiction.
and not RangeAnalysis::isContradictoryGuardNode(getOppositeGuard(guard))
where isGuardNodeWithDeadCode(guard)
select guard.getTest(), "The condition '" + guard.getTest() + "' is always " + guard.getOutcome().booleanNot()