📄 flow.java
字号:
alive = resolveBreaks(tree, prevPendingExits) || tree.cond != null && !tree.cond.type.isTrue(); nextadr = nextadrPrev; } public void visitForeachLoop(JCEnhancedForLoop tree) { visitVarDef(tree.var); ListBuffer<PendingExit> prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; int nextadrPrev = nextadr; scan(tree.expr); Bits initsStart = inits.dup(); Bits uninitsStart = uninits.dup(); letInit(tree.pos(), tree.var.sym); pendingExits = new ListBuffer<PendingExit>(); do { Bits uninitsEntry = uninits.dup(); 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 = initsStart; uninits = uninitsStart.andSet(uninits); resolveBreaks(tree, prevPendingExits); alive = true; nextadr = nextadrPrev; } public void visitLabelled(JCLabeledStatement tree) { ListBuffer<PendingExit> prevPendingExits = pendingExits; pendingExits = new ListBuffer<PendingExit>(); scanStat(tree.body); alive |= resolveBreaks(tree, prevPendingExits); } public void visitSwitch(JCSwitch tree) { ListBuffer<PendingExit> prevPendingExits = pendingExits; pendingExits = new ListBuffer<PendingExit>(); int nextadrPrev = nextadr; scanExpr(tree.selector); Bits initsSwitch = inits; Bits uninitsSwitch = uninits.dup(); boolean hasDefault = false; for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { alive = true; inits = initsSwitch.dup(); uninits = uninits.andSet(uninitsSwitch); JCCase c = l.head; if (c.pat == null) hasDefault = true; else scanExpr(c.pat); scanStats(c.stats); addVars(c.stats, initsSwitch, uninitsSwitch); // Warn about fall-through if lint switch fallthrough enabled. if (!loopPassTwo && alive && lint.isEnabled(Lint.LintCategory.FALLTHROUGH) && c.stats.nonEmpty() && l.tail.nonEmpty()) log.warning(l.tail.head.pos(), "possible.fall-through.into.case"); } if (!hasDefault) { inits.andSet(initsSwitch); alive = true; } alive |= resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } // where /** Add any variables defined in stats to inits and uninits. */ private static void addVars(List<JCStatement> stats, Bits inits, Bits uninits) { for (;stats.nonEmpty(); stats = stats.tail) { JCTree stat = stats.head; if (stat.getTag() == JCTree.VARDEF) { int adr = ((JCVariableDecl) stat).sym.adr; inits.excl(adr); uninits.incl(adr); } } } public void visitTry(JCTry tree) { List<Type> caughtPrev = caught; List<Type> thrownPrev = thrown; thrown = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) caught = chk.incl(l.head.param.type, caught); Bits uninitsTryPrev = uninitsTry; ListBuffer<PendingExit> prevPendingExits = pendingExits; pendingExits = new ListBuffer<PendingExit>(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); scanStat(tree.body); List<Type> thrownInTry = thrown; thrown = thrownPrev; caught = caughtPrev; boolean aliveEnd = alive; uninitsTry.andSet(uninits); Bits initsEnd = inits; Bits uninitsEnd = uninits; int nextadrCatch = nextadr; List<Type> caughtInTry = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; JCVariableDecl param = l.head.param; Type exc = param.type; if (chk.subset(exc, caughtInTry)) { log.error(l.head.pos(), "except.already.caught", exc); } else if (!chk.isUnchecked(l.head.pos(), exc) && exc.tsym != syms.throwableType.tsym && exc.tsym != syms.exceptionType.tsym && !chk.intersects(exc, thrownInTry)) { log.error(l.head.pos(), "except.never.thrown.in.try", exc); } caughtInTry = chk.incl(exc, caughtInTry); inits = initsTry.dup(); uninits = uninitsTry.dup(); scan(param); inits.incl(param.sym.adr); uninits.excl(param.sym.adr); scanStat(l.head.body); initsEnd.andSet(inits); uninitsEnd.andSet(uninits); nextadr = nextadrCatch; aliveEnd |= alive; } if (tree.finalizer != null) { List<Type> savedThrown = thrown; thrown = List.nil(); inits = initsTry.dup(); uninits = uninitsTry.dup(); ListBuffer<PendingExit> exits = pendingExits; pendingExits = prevPendingExits; alive = true; scanStat(tree.finalizer); if (!alive) { // discard exits and exceptions from try and finally thrown = chk.union(thrown, thrownPrev); if (!loopPassTwo && lint.isEnabled(Lint.LintCategory.FINALLY)) { log.warning(TreeInfo.diagEndPos(tree.finalizer), "finally.cannot.complete"); } } else { thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); thrown = chk.union(thrown, savedThrown); uninits.andSet(uninitsEnd); // FIX: this doesn't preserve source order of exits in catch // versus finally! while (exits.nonEmpty()) { PendingExit exit = 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<PendingExit> exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); } public void visitConditional(JCConditional 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) { // if b and c are boolean valued, then // v is (un)assigned after a?b:c when true iff // v is (un)assigned after b when true and // v is (un)assigned after c when true 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(JCIf 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(JCBreak tree) { recordExit(tree); } public void visitContinue(JCContinue tree) { recordExit(tree); } public void visitReturn(JCReturn tree) { scanExpr(tree.expr); // if not initial constructor, should markDead instead of recordExit recordExit(tree); } public void visitThrow(JCThrow tree) { scanExpr(tree.expr); markThrown(tree, tree.expr.type); markDead(); } public void visitApply(JCMethodInvocation tree) { scanExpr(tree.meth); scanExprs(tree.args); for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail) markThrown(tree, l.head); } public void visitNewClass(JCNewClass tree) { scanExpr(tree.encl); scanExprs(tree.args); // scan(tree.def); for (List<Type> l = tree.constructor.type.getThrownTypes(); l.nonEmpty(); l = l.tail) markThrown(tree, l.head); scan(tree.def); } public void visitNewArray(JCNewArray tree) { scanExprs(tree.dims); scanExprs(tree.elems); } public void visitAssert(JCAssert 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(JCAssign tree) { JCTree lhs = TreeInfo.skipParens(tree.lhs); if (!(lhs instanceof JCIdent)) scanExpr(lhs); scanExpr(tree.rhs); letInit(lhs); } public void visitAssignop(JCAssignOp tree) { scanExpr(tree.lhs); scanExpr(tree.rhs); letInit(tree.lhs); } public void visitUnary(JCUnary tree) { switch (tree.getTag()) { case JCTree.NOT: scanCond(tree.arg); Bits t = initsWhenFalse; initsWhenFalse = initsWhenTrue; initsWhenTrue = t; t = uninitsWhenFalse; uninitsWhenFalse = uninitsWhenTrue; uninitsWhenTrue = t; break; case JCTree.PREINC: case JCTree.POSTINC: case JCTree.PREDEC: case JCTree.POSTDEC: scanExpr(tree.arg); letInit(tree.arg); break; default: scanExpr(tree.arg); } } public void visitBinary(JCBinary tree) { switch (tree.getTag()) { case JCTree.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 JCTree.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(JCIdent tree) { if (tree.sym.kind == VAR) checkInit(tree.pos(), (VarSymbol)tree.sym); } public void visitTypeCast(JCTypeCast tree) { super.visitTypeCast(tree); if (!tree.type.isErroneous() && lint.isEnabled(Lint.LintCategory.CAST) && types.isSameType(tree.expr.type, tree.clazz.type)) { log.warning(tree.pos(), "redundant.cast", tree.expr.type); } } public void visitTopLevel(JCCompilationUnit tree) { // Do nothing for TopLevel since each class is visited individually }/************************************************************************** * main method *************************************************************************/ /** Perform definite assignment/unassignment analysis on a tree. */ public void analyzeTree(JCTree 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<PendingExit>(); alive = true; this.thrown = this.caught = null; this.classDef = null; scan(tree); } finally { // note that recursive invocations of this method fail hard 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 + -