boolean (@NotNull ControlFlow flow, final int startOffset, final int endOffset) { final class MyVisitor extends InstructionClientVisitor<Boolean> { // false if control flow at this offset terminates either by return called or exception thrown private final boolean[] isNormalCompletion = new boolean[flow.getSize() + 1]; private MyVisitor() { int i; final int length = flow.getSize(); for (i = 0; i < startOffset; i++) { isNormalCompletion[i] = true; } for (i = endOffset; i <= length; i++) { isNormalCompletion[i] = true; } } @Override public void visitConditionalThrowToInstruction(ConditionalThrowToInstruction instruction, int offset, int nextOffset) { if (nextOffset > flow.getSize()) nextOffset = flow.getSize(); if (offset > endOffset) return; int throwToOffset = instruction.offset; boolean isNormal; if (throwToOffset == nextOffset) { if (throwToOffset <= endOffset) { isNormal = !isLeaf(nextOffset) && isNormalCompletion[nextOffset]; } else { return; } } else { isNormal = isLeaf(nextOffset) || isNormalCompletion[nextOffset]; } isNormalCompletion[offset] |= isNormal; } @Override public void visitThrowToInstruction(ThrowToInstruction instruction, int offset, int nextOffset) { if (nextOffset > flow.getSize()) nextOffset = flow.getSize(); if (offset > endOffset) return; if (nextOffset <= endOffset) { boolean isNormal = !isLeaf(nextOffset) && isNormalCompletion[nextOffset]; isNormalCompletion[offset] |= isNormal; } } @Override public void visitCallInstruction(CallInstruction instruction, int offset, int nextOffset) { if (nextOffset > flow.getSize()) nextOffset = flow.getSize(); if (offset > endOffset) return; if (nextOffset > endOffset && nextOffset != offset + 1) { return; } boolean isNormal = isNormalCompletion[nextOffset]; isNormalCompletion[offset] |= isNormal; } @Override public void visitGoToInstruction(GoToInstruction instruction, int offset, int nextOffset) { if (nextOffset > flow.getSize()) nextOffset = flow.getSize(); if (offset > endOffset) return; boolean isRethrowFromFinally = instruction instanceof ReturnInstruction && ((ReturnInstruction)instruction).isRethrowFromFinally(); boolean isNormal = !instruction.isReturn && isNormalCompletion[nextOffset] && !isRethrowFromFinally; isNormalCompletion[offset] |= isNormal; } @Override public void visitInstruction(Instruction instruction, int offset, int nextOffset) { if (nextOffset > flow.getSize()) nextOffset = flow.getSize(); if (offset > endOffset) return; final boolean isNormal = isLeaf(nextOffset) || isNormalCompletion[nextOffset]; isNormalCompletion[offset] |= isNormal; } @Override @NotNull public Boolean getResult() { return !isNormalCompletion[startOffset]; } } final MyVisitor visitor = new MyVisitor(); depthFirstSearch(flow, visitor, startOffset, endOffset); return visitor.getResult().booleanValue(); }