📄 flow.java
字号:
} 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.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 != null && !tree.cond.type.isTrue(); nextadr = nextadrPrev; } public void visitLabelled(Labelled tree) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer(); scanStat(tree.body); alive |= resolveBreaks(tree, prevPendingExits); } public void visitSwitch(Switch tree) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer(); int nextadrPrev = nextadr; scanExpr(tree.selector); Bits initsSwitch = inits; Bits uninitsSwitch = uninits.dup(); boolean hasDefault = false; for (List l = tree.cases; l.nonEmpty(); l = l.tail) { alive = true; inits = initsSwitch.dup(); uninits = uninits.andSet(uninitsSwitch); Case c = (Tree.Case) l.head; if (c.pat == null) hasDefault = true; else scanExpr(c.pat); scanStats(c.stats); addVars(c.stats, initsSwitch, uninitsSwitch); if (!loopPassTwo && switchCheck && alive && c.stats.nonEmpty() && l.tail.nonEmpty()) log.warning(((Tree.Case) l.tail.head).pos, "possible.fall-through.into.case"); } if (!hasDefault) { inits.andSet(initsSwitch); alive = true; } alive |= resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } /** * Add any variables defined in stats to inits and uninits. */ private static void addVars(List stats, Bits inits, Bits uninits) { for (; stats.nonEmpty(); stats = stats.tail) { Tree stat = (Tree) stats.head; if (stat.tag == Tree.VARDEF) { int adr = ((VarDef) stat).sym.adr; inits.excl(adr); uninits.incl(adr); } } } public void visitTry(Try tree) { List caughtPrev = caught; List thrownPrev = thrown; thrown = Type.emptyList; for (List l = tree.catchers; l.nonEmpty(); l = l.tail) caught = chk.incl(((Tree.Catch) l.head).param.type, caught); Bits uninitsTryPrev = uninitsTry; ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); scanStat(tree.body); List thrownInTry = thrown; thrown = thrownPrev; caught = caughtPrev; boolean aliveEnd = alive; uninitsTry.andSet(uninits); Bits initsEnd = inits; Bits uninitsEnd = uninits; int nextadrCatch = nextadr; List caughtInTry = Type.emptyList; for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; VarDef param = ((Tree.Catch) l.head).param; Type exc = param.type; if (chk.subset(exc, caughtInTry)) { log.error(((Tree.Catch) l.head).pos, "except.already.caught", exc.toJava()); } else if (!chk.isUnchecked(((Tree.Catch) l.head).pos, exc) && exc != syms.throwableType && exc != syms.exceptionType && !chk.intersects(exc, thrownInTry)) { log.error(((Tree.Catch) l.head).pos, "except.never.thrown.in.try", exc.toJava()); } caughtInTry = chk.incl(exc, caughtInTry); inits = initsTry.dup(); uninits = uninitsTry.dup(); scan(param); inits.incl(param.sym.adr); uninits.excl(param.sym.adr); scanStat(((Tree.Catch) l.head).body); initsEnd.andSet(inits); uninitsEnd.andSet(uninits); nextadr = nextadrCatch; aliveEnd |= alive; } if (tree.finalizer != null) { List savedThrown = thrown; thrown = Type.emptyList; inits = initsTry.dup(); uninits = uninitsTry.dup(); ListBuffer exits = pendingExits; pendingExits = prevPendingExits; alive = true; scanStat(tree.finalizer); if (!alive) { thrown = chk.union(thrown, thrownPrev); if (!loopPassTwo) log.warning(TreeInfo.endPos(tree.finalizer), "finally.cannot.complete"); } else { thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); thrown = chk.union(thrown, savedThrown); uninits.andSet(uninitsEnd); while (exits.nonEmpty()) { PendingExit exit = (Flow.PendingExit) exits.next(); if (exit.inits != null) { exit.inits.orSet(inits); exit.uninits.andSet(uninits); } pendingExits.append(exit); } inits.orSet(initsEnd); alive = aliveEnd; } } else { thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); inits = initsEnd; uninits = uninitsEnd; alive = aliveEnd; ListBuffer exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); } public void visitConditional(Conditional tree) { scanCond(tree.cond); Bits initsBeforeElse = initsWhenFalse; Bits uninitsBeforeElse = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; if (tree.truepart.type.tag == BOOLEAN && tree.falsepart.type.tag == BOOLEAN) { scanCond(tree.truepart); Bits initsAfterThenWhenTrue = initsWhenTrue.dup(); Bits initsAfterThenWhenFalse = initsWhenFalse.dup(); Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup(); Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup(); inits = initsBeforeElse; uninits = uninitsBeforeElse; scanCond(tree.falsepart); initsWhenTrue.andSet(initsAfterThenWhenTrue); initsWhenFalse.andSet(initsAfterThenWhenFalse); uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); } else { scanExpr(tree.truepart); Bits initsAfterThen = inits.dup(); Bits uninitsAfterThen = uninits.dup(); inits = initsBeforeElse; uninits = uninitsBeforeElse; scanExpr(tree.falsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); } } public void visitIf(If tree) { scanCond(tree.cond); Bits initsBeforeElse = initsWhenFalse; Bits uninitsBeforeElse = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; scanStat(tree.thenpart); if (tree.elsepart != null) { boolean aliveAfterThen = alive; alive = true; Bits initsAfterThen = inits.dup(); Bits uninitsAfterThen = uninits.dup(); inits = initsBeforeElse; uninits = uninitsBeforeElse; scanStat(tree.elsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); alive = alive | aliveAfterThen; } else { inits.andSet(initsBeforeElse); uninits.andSet(uninitsBeforeElse); alive = true; } } public void visitBreak(Break tree) { recordExit(tree); } public void visitContinue(Continue tree) { recordExit(tree); } public void visitReturn(Return tree) { scanExpr(tree.expr); recordExit(tree); } public void visitThrow(Throw tree) { scanExpr(tree.expr); markThrown(tree, tree.expr.type); markDead(); } public void visitApply(Apply tree) { scanExpr(tree.meth); scanExprs(tree.args); for (List l = tree.meth.type.thrown(); l.nonEmpty(); l = l.tail) markThrown(tree, (Type) l.head); } public void visitNewClass(NewClass tree) { scanExpr(tree.encl); scanExprs(tree.args); for (List l = tree.constructor.type.thrown(); l.nonEmpty(); l = l.tail) markThrown(tree, (Type) l.head); scan(tree.def); } public void visitNewArray(NewArray tree) { scanExprs(tree.dims); scanExprs(tree.elems); } public void visitAssert(Assert tree) { Bits initsExit = inits.dup(); Bits uninitsExit = uninits.dup(); scanCond(tree.cond); uninitsExit.andSet(uninitsWhenTrue); if (tree.detail != null) { inits = initsWhenFalse; uninits = uninitsWhenFalse; scanExpr(tree.detail); } inits = initsExit; uninits = uninitsExit; } public void visitAssign(Assign tree) { Tree lhs = TreeInfo.skipParens(tree.lhs); if (!(lhs instanceof Ident)) scanExpr(lhs); scanExpr(tree.rhs); letInit(lhs); } public void visitAssignop(Assignop tree) { scanExpr(tree.lhs); scanExpr(tree.rhs); letInit(tree.lhs); } public void visitUnary(Unary tree) { switch (tree.tag) { case Tree.NOT: scanCond(tree.arg); Bits t = initsWhenFalse; initsWhenFalse = initsWhenTrue; initsWhenTrue = t; t = uninitsWhenFalse; uninitsWhenFalse = uninitsWhenTrue; uninitsWhenTrue = t; break; case Tree.PREINC: case Tree.POSTINC: case Tree.PREDEC: case Tree.POSTDEC: scanExpr(tree.arg); letInit(tree.arg); break; default: scanExpr(tree.arg); } } public void visitBinary(Binary tree) { switch (tree.tag) { case Tree.AND: scanCond(tree.lhs); Bits initsWhenFalseLeft = initsWhenFalse; Bits uninitsWhenFalseLeft = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; scanCond(tree.rhs); initsWhenFalse.andSet(initsWhenFalseLeft); uninitsWhenFalse.andSet(uninitsWhenFalseLeft); break; case Tree.OR: scanCond(tree.lhs); Bits initsWhenTrueLeft = initsWhenTrue; Bits uninitsWhenTrueLeft = uninitsWhenTrue; inits = initsWhenFalse; uninits = uninitsWhenFalse; scanCond(tree.rhs); initsWhenTrue.andSet(initsWhenTrueLeft); uninitsWhenTrue.andSet(uninitsWhenTrueLeft); break; default: scanExpr(tree.lhs); scanExpr(tree.rhs); } } public void visitIdent(Ident tree) { if (tree.sym.kind == VAR) checkInit(tree.pos, (VarSymbol) tree.sym); } /** * Perform definite assignment/unassignment analysis on a tree. */ public void analyzeTree(Tree tree, TreeMaker make) { try { this.make = make; inits = new Bits(); uninits = new Bits(); uninitsTry = new Bits(); initsWhenTrue = initsWhenFalse = uninitsWhenTrue = uninitsWhenFalse = null; if (vars == null) vars = new VarSymbol[32]; else for (int i = 0; i < vars.length; i++) vars[i] = null; firstadr = 0; nextadr = 0; pendingExits = new ListBuffer(); alive = true; this.thrown = this.caught = null; this.classDef = null; scan(tree); } finally { inits = uninits = uninitsTry = null; initsWhenTrue = initsWhenFalse = uninitsWhenTrue = uninitsWhenFalse = null; if (vars != null) for (int i = 0; i < vars.length; i++) vars[i] = null; firstadr = 0; nextadr = 0; pendingExits = null; this.make = null; this.thrown = this.caught = null; this.classDef = null; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -