📄 flow.java
字号:
/**
* Resolve all breaks of this statement.
*/
boolean resolveBreaks(Tree tree, ListBuffer oldPendingExits) {
boolean result = false;
List exits = pendingExits.toList();
pendingExits = oldPendingExits;
for (; exits.nonEmpty(); exits = exits.tail) {
PendingExit exit = (Flow.PendingExit) exits.head;
if (exit.tree.tag == Tree.BREAK && ((Break) exit.tree).target == tree) {
inits.andSet(exit.inits);
uninits.andSet(exit.uninits);
result = true;
} else {
pendingExits.append(exit);
}
}
return result;
}
/**
* Resolve all continues of this statement.
*/
boolean resolveContinues(Tree tree) {
boolean result = false;
List exits = pendingExits.toList();
pendingExits = new ListBuffer();
for (; exits.nonEmpty(); exits = exits.tail) {
PendingExit exit = (Flow.PendingExit) exits.head;
if (exit.tree.tag == Tree.CONTINUE &&
((Continue) 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);
}
/**
* Analyze a definition.
*/
void scanDef(Tree tree) {
scanStat(tree);
if (tree != null && tree.tag == Tree.BLOCK && !alive) {
log.error(tree.pos, "initializer.must.be.able.to.complete.normally");
}
}
/**
* Analyze a statement. Check that statement is reachable.
*/
void scanStat(Tree tree) {
if (!alive && tree != null) {
log.error(tree.pos, "unreachable.stmt");
if (tree.tag != Tree.SKIP)
alive = true;
}
scan(tree);
}
/**
* Analyze list of statements.
*/
void scanStats(List trees) {
if (trees != null)
for (List l = trees; l.nonEmpty(); l = l.tail)
scanStat((Tree) l.head);
}
/**
* Analyze an expression. Make sure to set (un)inits rather than
* (un)initsWhenTrue(WhenFalse) on exit.
*/
void scanExpr(Tree tree) {
if (tree != null) {
scan(tree);
if (inits == null)
merge();
}
}
/**
* Analyze a list of expressions.
*/
void scanExprs(List trees) {
if (trees != null)
for (List l = trees; l.nonEmpty(); l = l.tail)
scanExpr((Tree) l.head);
}
/**
* Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
* rather than (un)inits on exit.
*/
void scanCond(Tree 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;
}
public void visitClassDef(ClassDef tree) {
if (tree.sym == null)
return;
ClassDef classDefPrev = classDef;
List thrownPrev = thrown;
List caughtPrev = caught;
boolean alivePrev = alive;
int firstadrPrev = firstadr;
int nextadrPrev = nextadr;
ListBuffer pendingExitsPrev = pendingExits;
pendingExits = new ListBuffer();
if (tree.name != names.empty) {
caught = Type.emptyList;
firstadr = nextadr;
}
classDef = tree;
thrown = Type.emptyList;
try {
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (((Tree) l.head).tag == Tree.VARDEF) {
VarDef def = (VarDef) l.head;
if ((def.flags & STATIC) != 0) {
VarSymbol sym = def.sym;
if (trackable(sym))
newVar(sym);
}
}
}
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (((Tree) l.head).tag != Tree.METHODDEF &&
(TreeInfo.flags((Tree) l.head) & STATIC) != 0) {
scanDef((Tree) l.head);
errorUncaught();
}
}
if (tree.name != names.empty) {
boolean firstConstructor = true;
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (TreeInfo.isInitialConstructor((Tree) l.head)) {
List mthrown = ((MethodDef) l.head).sym.type.thrown();
if (firstConstructor) {
caught = mthrown;
firstConstructor = false;
} else {
caught = chk.intersect(mthrown, caught);
}
}
}
}
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (((Tree) l.head).tag == Tree.VARDEF) {
VarDef def = (VarDef) l.head;
if ((def.flags & STATIC) == 0) {
VarSymbol sym = def.sym;
if (trackable(sym))
newVar(sym);
}
}
}
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (((Tree) l.head).tag != Tree.METHODDEF &&
(TreeInfo.flags((Tree) l.head) & STATIC) == 0) {
scanDef((Tree) l.head);
errorUncaught();
}
}
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (((Tree) l.head).tag == Tree.METHODDEF) {
scan((Tree) l.head);
errorUncaught();
}
}
if (tree.name == names.empty) {
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
if (TreeInfo.isInitialConstructor((Tree) l.head)) {
MethodDef mdef = (MethodDef) l.head;
mdef.thrown = make.Types(thrown);
((MethodType) mdef.sym.type).thrown = thrown;
}
}
thrown = chk.union(thrown, thrownPrev);
} else {
thrown = thrownPrev;
}
}
finally { pendingExits = pendingExitsPrev;
alive = alivePrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
caught = caughtPrev;
classDef = classDefPrev;
} }
public void visitMethodDef(MethodDef tree) {
if (tree.body == null)
return;
List caughtPrev = caught;
List mthrown = tree.sym.type.thrown();
Bits initsPrev = inits.dup();
Bits uninitsPrev = uninits.dup();
int nextadrPrev = nextadr;
int firstadrPrev = firstadr;
assert pendingExits.isEmpty();
try {
boolean isInitialConstructor = TreeInfo.isInitialConstructor(tree);
if (!isInitialConstructor)
firstadr = nextadr;
for (List l = tree.params; l.nonEmpty(); l = l.tail) {
VarDef def = (Tree.VarDef) 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;
alive = true;
scanStat(tree.body);
int endPos = TreeInfo.endPos(tree.body);
if (alive && tree.sym.type.restype().tag != VOID)
log.error(endPos, "missing.ret.stmt");
if (isInitialConstructor) {
for (int i = firstadr; i < nextadr; i++)
if (vars[i].owner == classDef.sym)
checkInit(endPos, vars[i]);
}
List exits = pendingExits.toList();
pendingExits = new ListBuffer();
while (exits.nonEmpty()) {
PendingExit exit = (Flow.PendingExit) exits.head;
exits = exits.tail;
if (exit.thrown == null) {
assert exit.tree.tag == Tree.RETURN;
if (isInitialConstructor) {
inits = exit.inits;
for (int i = firstadr; i < nextadr; i++)
checkInit(exit.tree.pos, vars[i]);
}
} else {
pendingExits.append(exit);
}
}
}
finally { inits = initsPrev;
uninits = uninitsPrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
caught = caughtPrev;
} }
public void visitVarDef(VarDef tree) {
boolean track = trackable(tree.sym);
if (track && tree.sym.owner.kind == MTH)
newVar(tree.sym);
if (tree.init != null) {
scanExpr(tree.init);
if (track)
letInit(tree.pos, tree.sym);
}
}
public void visitBlock(Block tree) {
int nextadrPrev = nextadr;
scanStats(tree.stats);
nextadr = nextadrPrev;
}
public void visitDoLoop(DoLoop tree) {
ListBuffer prevPendingExits = pendingExits;
boolean prevLoopPassTwo = loopPassTwo;
do {
pendingExits = new ListBuffer();
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(WhileLoop tree) {
ListBuffer prevPendingExits = pendingExits;
boolean prevLoopPassTwo = loopPassTwo;
Bits initsCond;
Bits uninitsCond;
do {
pendingExits = new ListBuffer();
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(ForLoop tree) {
ListBuffer prevPendingExits = pendingExits;
boolean prevLoopPassTwo = loopPassTwo;
int nextadrPrev = nextadr;
scanStats(tree.init);
Bits initsCond;
Bits uninitsCond;
do {
pendingExits = new ListBuffer();
Bits uninitsEntry = uninits.dup();
if (tree.cond != null) {
scanCond(tree.cond);
initsCond = initsWhenFalse;
uninitsCond = uninitsWhenFalse;
inits = initsWhenTrue;
uninits = uninitsWhenTrue;
alive = !tree.cond.type.isFalse();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -