📄 flow.java
字号:
return result; } /** Resolve all continues of this statement. */ boolean resolveContinues(JCTree tree) { boolean result = false; List<PendingExit> exits = pendingExits.toList(); pendingExits = new ListBuffer<PendingExit>(); for (; exits.nonEmpty(); exits = exits.tail) { PendingExit exit = exits.head; if (exit.tree.getTag() == JCTree.CONTINUE && ((JCContinue) exit.tree).target == tree) { inits.andSet(exit.inits); uninits.andSet(exit.uninits); result = true; } else { pendingExits.append(exit); } } return result; } /** Record that statement is unreachable. */ void markDead() { inits.inclRange(firstadr, nextadr); uninits.inclRange(firstadr, nextadr); alive = false; } /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets */ void split() { initsWhenFalse = inits.dup(); uninitsWhenFalse = uninits.dup(); initsWhenTrue = inits; uninitsWhenTrue = uninits; inits = uninits = null; } /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. */ void merge() { inits = initsWhenFalse.andSet(initsWhenTrue); uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); }/* ************************************************************************ * Visitor methods for statements and definitions *************************************************************************/ /** Analyze a definition. */ void scanDef(JCTree tree) { scanStat(tree); if (tree != null && tree.getTag() == JCTree.BLOCK && !alive) { log.error(tree.pos(), "initializer.must.be.able.to.complete.normally"); } } /** Analyze a statement. Check that statement is reachable. */ void scanStat(JCTree tree) { if (!alive && tree != null) { log.error(tree.pos(), "unreachable.stmt"); if (tree.getTag() != JCTree.SKIP) alive = true; } scan(tree); } /** Analyze list of statements. */ void scanStats(List<? extends JCStatement> trees) { if (trees != null) for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail) scanStat(l.head); } /** Analyze an expression. Make sure to set (un)inits rather than * (un)initsWhenTrue(WhenFalse) on exit. */ void scanExpr(JCTree tree) { if (tree != null) { scan(tree); if (inits == null) merge(); } } /** Analyze a list of expressions. */ void scanExprs(List<? extends JCExpression> trees) { if (trees != null) for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail) scanExpr(l.head); } /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) * rather than (un)inits on exit. */ void scanCond(JCTree tree) { if (tree.type.isFalse()) { if (inits == null) merge(); initsWhenTrue = inits.dup(); initsWhenTrue.inclRange(firstadr, nextadr); uninitsWhenTrue = uninits.dup(); uninitsWhenTrue.inclRange(firstadr, nextadr); initsWhenFalse = inits; uninitsWhenFalse = uninits; } else if (tree.type.isTrue()) { if (inits == null) merge(); initsWhenFalse = inits.dup(); initsWhenFalse.inclRange(firstadr, nextadr); uninitsWhenFalse = uninits.dup(); uninitsWhenFalse.inclRange(firstadr, nextadr); initsWhenTrue = inits; uninitsWhenTrue = uninits; } else { scan(tree); if (inits != null) split(); } inits = uninits = null; } /* ------------ Visitor methods for various sorts of trees -------------*/ public void visitClassDef(JCClassDecl tree) { if (tree.sym == null) return; JCClassDecl classDefPrev = classDef; List<Type> thrownPrev = thrown; List<Type> caughtPrev = caught; boolean alivePrev = alive; int firstadrPrev = firstadr; int nextadrPrev = nextadr; ListBuffer<PendingExit> pendingExitsPrev = pendingExits; Lint lintPrev = lint; pendingExits = new ListBuffer<PendingExit>(); if (tree.name != names.empty) { caught = List.nil(); firstadr = nextadr; } classDef = tree; thrown = List.nil(); lint = lint.augment(tree.sym.attributes_field); try { // define all the static fields for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (l.head.getTag() == JCTree.VARDEF) { JCVariableDecl def = (JCVariableDecl)l.head; if ((def.mods.flags & STATIC) != 0) { VarSymbol sym = def.sym; if (trackable(sym)) newVar(sym); } } } // process all the static initializers for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (l.head.getTag() != JCTree.METHODDEF && (TreeInfo.flags(l.head) & STATIC) != 0) { scanDef(l.head); errorUncaught(); } } // add intersection of all thrown clauses of initial constructors // to set of caught exceptions, unless class is anonymous. if (tree.name != names.empty) { boolean firstConstructor = true; for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (TreeInfo.isInitialConstructor(l.head)) { List<Type> mthrown = ((JCMethodDecl) l.head).sym.type.getThrownTypes(); if (firstConstructor) { caught = mthrown; firstConstructor = false; } else { caught = chk.intersect(mthrown, caught); } } } } // define all the instance fields for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (l.head.getTag() == JCTree.VARDEF) { JCVariableDecl def = (JCVariableDecl)l.head; if ((def.mods.flags & STATIC) == 0) { VarSymbol sym = def.sym; if (trackable(sym)) newVar(sym); } } } // process all the instance initializers for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (l.head.getTag() != JCTree.METHODDEF && (TreeInfo.flags(l.head) & STATIC) == 0) { scanDef(l.head); errorUncaught(); } } // in an anonymous class, add the set of thrown exceptions to // the throws clause of the synthetic constructor and propagate // outwards. if (tree.name == names.empty) { for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (TreeInfo.isInitialConstructor(l.head)) { JCMethodDecl mdef = (JCMethodDecl)l.head; mdef.thrown = make.Types(thrown); mdef.sym.type.setThrown(thrown); } } thrownPrev = chk.union(thrown, thrownPrev); } // process all the methods for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { if (l.head.getTag() == JCTree.METHODDEF) { scan(l.head); errorUncaught(); } } thrown = thrownPrev; } finally { pendingExits = pendingExitsPrev; alive = alivePrev; nextadr = nextadrPrev; firstadr = firstadrPrev; caught = caughtPrev; classDef = classDefPrev; lint = lintPrev; } } public void visitMethodDef(JCMethodDecl tree) { if (tree.body == null) return; List<Type> caughtPrev = caught; List<Type> mthrown = tree.sym.type.getThrownTypes(); Bits initsPrev = inits.dup(); Bits uninitsPrev = uninits.dup(); int nextadrPrev = nextadr; int firstadrPrev = firstadr; Lint lintPrev = lint; lint = lint.augment(tree.sym.attributes_field); assert pendingExits.isEmpty(); try { boolean isInitialConstructor = TreeInfo.isInitialConstructor(tree); if (!isInitialConstructor) firstadr = nextadr; for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { JCVariableDecl def = l.head; scan(def); inits.incl(def.sym.adr); uninits.excl(def.sym.adr); } if (isInitialConstructor) caught = chk.union(caught, mthrown); else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK) caught = mthrown; // else we are in an instance initializer block; // leave caught unchanged. alive = true; scanStat(tree.body); if (alive && tree.sym.type.getReturnType().tag != VOID) log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt"); if (isInitialConstructor) { for (int i = firstadr; i < nextadr; i++) if (vars[i].owner == classDef.sym) checkInit(TreeInfo.diagEndPos(tree.body), vars[i]); } List<PendingExit> exits = pendingExits.toList(); pendingExits = new ListBuffer<PendingExit>(); while (exits.nonEmpty()) { PendingExit exit = exits.head; exits = exits.tail; if (exit.thrown == null) { assert exit.tree.getTag() == JCTree.RETURN; if (isInitialConstructor) { inits = exit.inits; for (int i = firstadr; i < nextadr; i++) checkInit(exit.tree.pos(), vars[i]); } } else { // uncaught throws will be reported later pendingExits.append(exit); } } } finally { inits = initsPrev; uninits = uninitsPrev; nextadr = nextadrPrev; firstadr = firstadrPrev; caught = caughtPrev; lint = lintPrev; } } public void visitVarDef(JCVariableDecl tree) { boolean track = trackable(tree.sym); if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); if (tree.init != null) { Lint lintPrev = lint; lint = lint.augment(tree.sym.attributes_field); try{ scanExpr(tree.init); if (track) letInit(tree.pos(), tree.sym); } finally { lint = lintPrev; } } } public void visitBlock(JCBlock tree) { int nextadrPrev = nextadr; scanStats(tree.stats); nextadr = nextadrPrev; } public void visitDoLoop(JCDoWhileLoop tree) { ListBuffer<PendingExit> prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; pendingExits = new ListBuffer<PendingExit>(); do { Bits uninitsEntry = uninits.dup(); scanStat(tree.body); alive |= resolveContinues(tree); scanCond(tree.cond); if (log.nerrors != 0 || loopPassTwo || uninitsEntry.diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) break; inits = initsWhenTrue; uninits = uninitsEntry.andSet(uninitsWhenTrue); loopPassTwo = true; alive = true; } while (true); loopPassTwo = prevLoopPassTwo; inits = initsWhenFalse; uninits = uninitsWhenFalse; alive = alive && !tree.cond.type.isTrue(); alive |= resolveBreaks(tree, prevPendingExits); } public void visitWhileLoop(JCWhileLoop tree) { ListBuffer<PendingExit> prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; Bits initsCond; Bits uninitsCond; pendingExits = new ListBuffer<PendingExit>(); do { Bits uninitsEntry = uninits.dup(); scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; alive = !tree.cond.type.isFalse(); scanStat(tree.body); alive |= resolveContinues(tree); if (log.nerrors != 0 || loopPassTwo || uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1) break; uninits = uninitsEntry.andSet(uninits); loopPassTwo = true; alive = true; } while (true); loopPassTwo = prevLoopPassTwo; inits = initsCond; uninits = uninitsCond; alive = resolveBreaks(tree, prevPendingExits) || !tree.cond.type.isTrue(); } public void visitForLoop(JCForLoop tree) { ListBuffer<PendingExit> prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; int nextadrPrev = nextadr; scanStats(tree.init); Bits initsCond; Bits uninitsCond; pendingExits = new ListBuffer<PendingExit>(); do { Bits uninitsEntry = uninits.dup(); if (tree.cond != null) { scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; alive = !tree.cond.type.isFalse(); } else { initsCond = inits.dup(); initsCond.inclRange(firstadr, nextadr); uninitsCond = uninits.dup(); uninitsCond.inclRange(firstadr, nextadr); alive = true; } scanStat(tree.body); alive |= resolveContinues(tree); scan(tree.step); if (log.nerrors != 0 || loopPassTwo || uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) break; uninits = uninitsEntry.andSet(uninits); loopPassTwo = true; alive = true; } while (true); loopPassTwo = prevLoopPassTwo; inits = initsCond; uninits = uninitsCond;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -