private void analyzeCFG(Map<CFG.Block, Set<Symbol>> in, Map<CFG.Block, Set<Symbol>> kill, Map<CFG.Block, Set<Symbol>> gen) { Deque<CFG.Block> workList = new LinkedList<>(); workList.addAll(cfg.reversedBlocks()); while (!workList.isEmpty()) { CFG.Block block = workList.removeFirst(); Set<Symbol> blockOut = out.computeIfAbsent(block, k -> new HashSet<>()); block.successors().stream().map(in::get).filter(Objects::nonNull).forEach(blockOut::addAll); block.exceptions().stream().map(in::get).filter(Objects::nonNull).forEach(blockOut::addAll); // in = gen and (out - kill) Set<Symbol> newIn = new HashSet<>(gen.get(block)); newIn.addAll(Sets.difference(blockOut, kill.get(block))); if (newIn.equals(in.get(block))) { continue; } in.put(block, newIn); block.predecessors().forEach(workList::addLast); } }
private void analyzeCFG(Map<CFG.Block, Set<Symbol>> in, Map<CFG.Block, Set<Symbol>> kill, Map<CFG.Block, Set<Symbol>> gen) { Deque<CFG.Block> workList = new LinkedList<>(); workList.addAll(cfg.reversedBlocks()); while (!workList.isEmpty()) { CFG.Block block = workList.removeFirst(); Set<Symbol> blockOut = out.computeIfAbsent(block, k -> new HashSet<>()); block.successors().stream().map(in::get).filter(Objects::nonNull).forEach(blockOut::addAll); block.exceptions().stream().map(in::get).filter(Objects::nonNull).forEach(blockOut::addAll); // in = gen and (out - kill) Set<Symbol> newIn = new HashSet<>(gen.get(block)); newIn.addAll(Sets.difference(blockOut, kill.get(block))); if (newIn.equals(in.get(block))) { continue; } in.put(block, newIn); block.predecessors().forEach(workList::addLast); } }
private void analyzeCFG(Map<CFG.Block, Set<Symbol>> in, Map<CFG.Block, Set<Symbol>> kill, Map<CFG.Block, Set<Symbol>> gen) { Deque<CFG.Block> workList = new LinkedList<>(); workList.addAll(cfg.reversedBlocks()); while (!workList.isEmpty()) { CFG.Block block = workList.removeFirst(); Set<Symbol> blockOut = out.get(block); if (blockOut == null) { blockOut = new HashSet<>(); out.put(block, blockOut); } for (CFG.Block successor : block.successors()) { Set<Symbol> inOfSuccessor = in.get(successor); if (inOfSuccessor != null) { blockOut.addAll(inOfSuccessor); } } // in = gen and (out - kill) Set<Symbol> newIn = new HashSet<>(gen.get(block)); newIn.addAll(Sets.difference(blockOut, kill.get(block))); if (newIn.equals(in.get(block))) { continue; } in.put(block, newIn); for (CFG.Block predecessor : block.predecessors()) { workList.addLast(predecessor); } } }
programPosition = node.programPoint; programState = node.programState; if (programPosition.block.successors().isEmpty()) { checkerDispatcher.executeCheckEndOfExecutionPath(constraintManager); LOG.debug("End of potential path reached!");
@CheckForNull private static Set<Block> localSuccessors(CFG.Block block, Map<Tree, CFGLoop> container) { if (isStarting(block)) { CFGLoop loop = container.get(block.terminator()); if (loop == null) { loop = create(block, container); } Set<Block> loopSuccessors = new HashSet<>(loop.successors); if (block.trueBlock() == null) { // Special case where no condition is given in FOR loop: only one successor specified return null; } else { loopSuccessors.add(block.falseBlock()); } return loopSuccessors; } return block.successors(); }
private void checkBlock(Block block) { Block successorWithoutJump = block.successorWithoutJump(); Tree terminator = block.terminator(); if (terminator != null && successorWithoutJump != null && terminator.is(Tree.Kind.CONTINUE_STATEMENT, Tree.Kind.RETURN_STATEMENT) && !isReturnWithExpression(terminator) && !isSwitchCaseChild(terminator)) { successorWithoutJump = nonEmptySuccessor(successorWithoutJump); Block successor = nonEmptySuccessor(block.successors().iterator().next()); if (successorWithoutJump.equals(successor)) { reportIssue(terminator, "Remove this redundant jump."); } } }
@CheckForNull private static Set<Block> localSuccessors(CFG.Block block, Map<Tree, CFGLoop> container) { if (isStarting(block)) { CFGLoop loop = container.get(block.terminator()); if (loop == null) { loop = create(block, container); } Set<Block> loopSuccessors = new HashSet<>(loop.successors); if (block.trueBlock() == null) { // Special case where no condition is given in FOR loop: only one successor specified return null; } else { loopSuccessors.add(block.falseBlock()); } return loopSuccessors; } return block.successors(); }
@Override public void visitNode(Tree tree) { SwitchStatementTree switchStatementTree = (SwitchStatementTree) tree; List<CaseGroupTree> caseGroupTrees = switchStatementTree.cases(); CFG cfg = CFG.buildCFG(Collections.singletonList(tree), true); Set<CFG.Block> switchSuccessors = cfg.entryBlock().successors(); Map<CFG.Block, CaseGroupTree> cfgBlockToCaseGroupMap = createMapping(switchSuccessors, caseGroupTrees); switchSuccessors.stream() .filter(cfgBlockToCaseGroupMap.keySet()::contains) .flatMap(cfgBlock -> getForbiddenCaseGroupPredecessors(cfgBlock, cfgBlockToCaseGroupMap)) .map(CaseGroupTree::labels) .map(caseGroupLabels -> caseGroupLabels.get(caseGroupLabels.size() - 1)) .forEach(label -> reportIssue(label, "End this switch case with an unconditional break, return or throw statement.")); }
private static boolean isDirectFlowSuccessorOf(CFG.Block successor, CFG.Block block) { return successor != block.exitBlock() || (block.successors().size() == 1 && successor.isMethodExitBlock()); }
@Override public void visitNode(Tree tree) { SwitchStatementTree switchStatementTree = (SwitchStatementTree) tree; List<CaseGroupTree> caseGroupTrees = switchStatementTree.cases(); CFG cfg = CFG.buildCFG(Collections.singletonList(tree), true); Set<CFG.Block> switchSuccessors = cfg.entryBlock().successors(); Map<CFG.Block, CaseGroupTree> cfgBlockToCaseGroupMap = createMapping(switchSuccessors, caseGroupTrees); switchSuccessors.stream() .filter(cfgBlockToCaseGroupMap.keySet()::contains) .flatMap(cfgBlock -> getForbiddenCaseGroupPredecessors(cfgBlock, cfgBlockToCaseGroupMap)) .map(CaseGroupTree::labels) .map(caseGroupLabels -> caseGroupLabels.get(caseGroupLabels.size() - 1)) .forEach(label -> reportIssue(label, "End this switch case with an unconditional break, return or throw statement.")); }
public boolean isMethodExitBlock() { return successors().isEmpty(); }
private static boolean isDirectFlowSuccessorOf(CFG.Block successor, CFG.Block block) { return successor != block.exitBlock() || (block.successors().size() == 1 && successor.isMethodExitBlock()); }
public boolean isMethodExitBlock() { return successors().isEmpty(); }
private void checkBlock(Block block) { Block successorWithoutJump = block.successorWithoutJump(); Tree terminator = block.terminator(); if (terminator != null && successorWithoutJump != null && terminator.is(Tree.Kind.CONTINUE_STATEMENT, Tree.Kind.RETURN_STATEMENT) && !isReturnWithExpression(terminator) && !isSwitchCaseChild(terminator)) { successorWithoutJump = nonEmptySuccessor(successorWithoutJump); Block successor = nonEmptySuccessor(block.successors().iterator().next()); if (successorWithoutJump.equals(successor)) { reportIssue(terminator, "Remove this redundant jump."); } } }
private static Block nonEmptySuccessor(Block initialBlock) { Block result = initialBlock; while (result.elements().isEmpty() && result.successors().size() == 1) { result = result.successors().iterator().next(); } return result; } }
private void collectWaysOut(Map<Tree, CFGLoop> container) { for (CFG.Block block : blocks) { if (isStarting(block)) { CFGLoop innerLoop = container.get(block.terminator()); successors.addAll(innerLoop.successors()); } else { successors.addAll(block.successors()); } } successors.removeAll(blocks); successors.remove(startingBlock); }
private void collectWaysOut(Map<Tree, CFGLoop> container) { for (CFG.Block block : blocks) { if (isStarting(block)) { CFGLoop innerLoop = container.get(block.terminator()); successors.addAll(innerLoop.successors()); } else { successors.addAll(block.successors()); } } successors.removeAll(blocks); successors.remove(startingBlock); }
private void initialize(CFG.Block block, Map<Tree, CFGLoop> container) { Block loopFirstBlock = block.trueBlock(); if (loopFirstBlock == null) { // Special case where no condition is given in FOR loop: only one successor specified loopFirstBlock = block.successors().iterator().next(); } collectBlocks(loopFirstBlock, container); successors.addAll(block.successors()); successors.remove(block.falseBlock()); collectWaysOut(container); }
private static Block nonEmptySuccessor(Block initialBlock) { Block result = initialBlock; while (result.elements().isEmpty() && result.successors().size() == 1) { result = result.successors().iterator().next(); } return result; } }
private void initialize(CFG.Block block, Map<Tree, CFGLoop> container) { Block loopFirstBlock = block.trueBlock(); if (loopFirstBlock == null) { // Special case where no condition is given in FOR loop: only one successor specified loopFirstBlock = block.successors().iterator().next(); } collectBlocks(loopFirstBlock, container); successors.addAll(block.successors()); successors.remove(block.falseBlock()); collectWaysOut(container); }