📄 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 + -