/** * Returns in the then and else blocks must be consistent with each other. If there is no else * block, then the return statement can fall through. * * @return logical OR of END_* flags */ private int endCheckIf() { Node th, el; int rv = END_UNREACHED; th = next; el = ((Jump) this).target; rv = th.endCheck(); if (el != null) rv |= el.endCheck(); else rv |= END_DROPS_OFF; return rv; }
/** * A general block of code is examined statement by statement. If any statement (even compound * ones) returns in all branches, then subsequent statements are not examined. * * @return logical OR of END_* flags */ private int endCheckBlock() { Node n; int rv = END_DROPS_OFF; // check each statment and if the statement can continue onto the next // one, then check the next statement for (n = first; ((rv & END_DROPS_OFF) != 0) && n != null; n = n.next) { rv &= ~END_DROPS_OFF; rv |= n.endCheck(); } return rv; }
/** * Consistency of return statements is checked between the case statements. If there is no * default, then the switch can fall through. If there is a default,we check to see if all code * paths in the default return or if there is a code path that can fall through. * * @return logical OR of END_* flags */ private int endCheckSwitch() { Node n; int rv = END_UNREACHED; // examine the cases for (n = first.next; n != null; n = n.next) { if (n.type == Token.CASE) { rv |= ((Jump) n).target.endCheck(); } else break; } // we don't care how the cases drop into each other rv &= ~END_DROPS_OFF; // examine the default n = ((Jump) this).getDefault(); if (n != null) rv |= n.endCheck(); else rv |= END_DROPS_OFF; // remove the switch block rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); return rv; }