1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Sat Sep 14 15:23:21 2013 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Sat Sep 14 19:04:47 2013 +0100 1.3 @@ -207,7 +207,7 @@ 1.4 1.5 public void analyzeTree(Env<AttrContext> env, TreeMaker make) { 1.6 new AliveAnalyzer().analyzeTree(env, make); 1.7 - new AssignAnalyzer().analyzeTree(env, make); 1.8 + new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); 1.9 new FlowAnalyzer().analyzeTree(env, make); 1.10 new CaptureAnalyzer().analyzeTree(env, make); 1.11 } 1.12 @@ -239,7 +239,7 @@ 1.13 //related errors, which will allow for more errors to be detected 1.14 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 1.15 try { 1.16 - new AssignAnalyzer().analyzeTree(env, that, make); 1.17 + new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); 1.18 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); 1.19 flowAnalyzer.analyzeTree(env, that, make); 1.20 return flowAnalyzer.inferredThrownTypes; 1.21 @@ -292,15 +292,6 @@ 1.22 } 1.23 1.24 /** 1.25 - * Utility method to reset several Bits instances. 1.26 - */ 1.27 - private void resetBits(Bits... bits) { 1.28 - for (Bits b : bits) { 1.29 - b.reset(); 1.30 - } 1.31 - } 1.32 - 1.33 - /** 1.34 * Base visitor class for all visitors implementing dataflow analysis logic. 1.35 * This class define the shared logic for handling jumps (break/continue statements). 1.36 */ 1.37 @@ -347,17 +338,17 @@ 1.38 this.tree = tree; 1.39 } 1.40 1.41 - void resolveJump() { 1.42 + void resolveJump(JCTree tree) { 1.43 //do nothing 1.44 } 1.45 } 1.46 1.47 - abstract void markDead(); 1.48 + abstract void markDead(JCTree tree); 1.49 1.50 /** Record an outward transfer of control. */ 1.51 void recordExit(JCTree tree, P pe) { 1.52 pendingExits.append(pe); 1.53 - markDead(); 1.54 + markDead(tree); 1.55 } 1.56 1.57 /** Resolve all jumps of this statement. */ 1.58 @@ -371,7 +362,7 @@ 1.59 P exit = exits.head; 1.60 if (exit.tree.hasTag(jk.treeTag) && 1.61 jk.getTarget(exit.tree) == tree) { 1.62 - exit.resolveJump(); 1.63 + exit.resolveJump(tree); 1.64 resolved = true; 1.65 } else { 1.66 pendingExits.append(exit); 1.67 @@ -380,12 +371,12 @@ 1.68 return resolved; 1.69 } 1.70 1.71 - /** Resolve all breaks of this statement. */ 1.72 + /** Resolve all continues of this statement. */ 1.73 boolean resolveContinues(JCTree tree) { 1.74 return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE); 1.75 } 1.76 1.77 - /** Resolve all continues of this statement. */ 1.78 + /** Resolve all breaks of this statement. */ 1.79 boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) { 1.80 return resolveJump(tree, oldPendingExits, JumpKind.BREAK); 1.81 } 1.82 @@ -414,7 +405,7 @@ 1.83 private boolean alive; 1.84 1.85 @Override 1.86 - void markDead() { 1.87 + void markDead(JCTree tree) { 1.88 alive = false; 1.89 } 1.90 1.91 @@ -696,7 +687,7 @@ 1.92 1.93 public void visitThrow(JCThrow tree) { 1.94 scan(tree.expr); 1.95 - markDead(); 1.96 + markDead(tree); 1.97 } 1.98 1.99 public void visitApply(JCMethodInvocation tree) { 1.100 @@ -797,7 +788,7 @@ 1.101 } 1.102 1.103 @Override 1.104 - void markDead() { 1.105 + void markDead(JCTree tree) { 1.106 //do nothing 1.107 } 1.108 1.109 @@ -1222,7 +1213,7 @@ 1.110 else { 1.111 markThrown(tree, tree.expr.type); 1.112 } 1.113 - markDead(); 1.114 + markDead(tree); 1.115 } 1.116 1.117 public void visitApply(JCMethodInvocation tree) { 1.118 @@ -1372,11 +1363,13 @@ 1.119 * depends on the results of the liveliness analyzer. This pass is also used to mark 1.120 * effectively-final local variables/parameters. 1.121 */ 1.122 - class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> { 1.123 + 1.124 + public abstract static class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer.AbstractAssignPendingExit> 1.125 + extends BaseAnalyzer<P> { 1.126 1.127 /** The set of definitely assigned variables. 1.128 */ 1.129 - final Bits inits; 1.130 + protected final Bits inits; 1.131 1.132 /** The set of definitely unassigned variables. 1.133 */ 1.134 @@ -1402,7 +1395,7 @@ 1.135 1.136 /** A mapping from addresses to variable symbols. 1.137 */ 1.138 - JCVariableDecl[] vardecls; 1.139 + protected JCVariableDecl[] vardecls; 1.140 1.141 /** The current class being defined. 1.142 */ 1.143 @@ -1414,11 +1407,11 @@ 1.144 1.145 /** The next available variable sequence number. 1.146 */ 1.147 - int nextadr; 1.148 + protected int nextadr; 1.149 1.150 /** The first variable sequence number in a block that can return. 1.151 */ 1.152 - int returnadr; 1.153 + protected int returnadr; 1.154 1.155 /** The list of unreferenced automatic resources. 1.156 */ 1.157 @@ -1430,35 +1423,46 @@ 1.158 /** The starting position of the analysed tree */ 1.159 int startPos; 1.160 1.161 - AssignAnalyzer() { 1.162 - inits = new Bits(); 1.163 + final Symtab syms; 1.164 + 1.165 + protected Names names; 1.166 + 1.167 + public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { 1.168 + 1.169 + final Bits inits; 1.170 + final Bits uninits; 1.171 + final Bits exit_inits = new Bits(true); 1.172 + final Bits exit_uninits = new Bits(true); 1.173 + 1.174 + public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 1.175 + super(tree); 1.176 + this.inits = inits; 1.177 + this.uninits = uninits; 1.178 + this.exit_inits.assign(inits); 1.179 + this.exit_uninits.assign(uninits); 1.180 + } 1.181 + 1.182 + @Override 1.183 + public void resolveJump(JCTree tree) { 1.184 + inits.andSet(exit_inits); 1.185 + uninits.andSet(exit_uninits); 1.186 + } 1.187 + } 1.188 + 1.189 + public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) { 1.190 + this.inits = inits; 1.191 uninits = new Bits(); 1.192 uninitsTry = new Bits(); 1.193 initsWhenTrue = new Bits(true); 1.194 initsWhenFalse = new Bits(true); 1.195 uninitsWhenTrue = new Bits(true); 1.196 uninitsWhenFalse = new Bits(true); 1.197 - } 1.198 - 1.199 - class AssignPendingExit extends BaseAnalyzer.PendingExit { 1.200 - 1.201 - final Bits exit_inits = new Bits(true); 1.202 - final Bits exit_uninits = new Bits(true); 1.203 - 1.204 - AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 1.205 - super(tree); 1.206 - this.exit_inits.assign(inits); 1.207 - this.exit_uninits.assign(uninits); 1.208 - } 1.209 - 1.210 - void resolveJump() { 1.211 - inits.andSet(exit_inits); 1.212 - uninits.andSet(exit_uninits); 1.213 - } 1.214 + this.syms = syms; 1.215 + this.names = names; 1.216 } 1.217 1.218 @Override 1.219 - void markDead() { 1.220 + protected void markDead(JCTree tree) { 1.221 inits.inclRange(returnadr, nextadr); 1.222 uninits.inclRange(returnadr, nextadr); 1.223 } 1.224 @@ -1468,7 +1472,7 @@ 1.225 /** Do we need to track init/uninit state of this symbol? 1.226 * I.e. is symbol either a local or a blank final variable? 1.227 */ 1.228 - boolean trackable(VarSymbol sym) { 1.229 + protected boolean trackable(VarSymbol sym) { 1.230 return 1.231 sym.pos >= startPos && 1.232 ((sym.owner.kind == MTH || 1.233 @@ -1488,44 +1492,35 @@ 1.234 } 1.235 sym.adr = nextadr; 1.236 vardecls[nextadr] = varDecl; 1.237 - inits.excl(nextadr); 1.238 + exclVarFromInits(varDecl, nextadr); 1.239 uninits.incl(nextadr); 1.240 nextadr++; 1.241 } 1.242 1.243 + protected void exclVarFromInits(JCTree tree, int adr) { 1.244 + inits.excl(adr); 1.245 + } 1.246 + 1.247 + protected void assignToInits(JCTree tree, Bits bits) { 1.248 + inits.assign(bits); 1.249 + } 1.250 + 1.251 + protected void andSetInits(JCTree tree, Bits bits) { 1.252 + inits.andSet(bits); 1.253 + } 1.254 + 1.255 + protected void orSetInits(JCTree tree, Bits bits) { 1.256 + inits.orSet(bits); 1.257 + } 1.258 + 1.259 /** Record an initialization of a trackable variable. 1.260 */ 1.261 void letInit(DiagnosticPosition pos, VarSymbol sym) { 1.262 if (sym.adr >= firstadr && trackable(sym)) { 1.263 - if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { 1.264 - if (!uninits.isMember(sym.adr)) { 1.265 - //assignment targeting an effectively final variable 1.266 - //makes the variable lose its status of effectively final 1.267 - //if the variable is _not_ definitively unassigned 1.268 - sym.flags_field &= ~EFFECTIVELY_FINAL; 1.269 - } else { 1.270 - uninit(sym); 1.271 - } 1.272 - } 1.273 - else if ((sym.flags() & FINAL) != 0) { 1.274 - if ((sym.flags() & PARAMETER) != 0) { 1.275 - if ((sym.flags() & UNION) != 0) { //multi-catch parameter 1.276 - log.error(pos, "multicatch.parameter.may.not.be.assigned", 1.277 - sym); 1.278 - } 1.279 - else { 1.280 - log.error(pos, "final.parameter.may.not.be.assigned", 1.281 - sym); 1.282 - } 1.283 - } else if (!uninits.isMember(sym.adr)) { 1.284 - log.error(pos, flowKind.errKey, sym); 1.285 - } else { 1.286 - uninit(sym); 1.287 - } 1.288 + if (uninits.isMember(sym.adr)) { 1.289 + uninit(sym); 1.290 } 1.291 inits.incl(sym.adr); 1.292 - } else if ((sym.flags() & FINAL) != 0) { 1.293 - log.error(pos, "var.might.already.be.assigned", sym); 1.294 } 1.295 } 1.296 //where 1.297 @@ -1559,12 +1554,14 @@ 1.298 void checkInit(DiagnosticPosition pos, VarSymbol sym) { 1.299 checkInit(pos, sym, "var.might.not.have.been.initialized"); 1.300 } 1.301 - void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { 1.302 - if ((sym.adr >= firstadr || sym.owner.kind != TYP) && 1.303 - trackable(sym) && 1.304 - !inits.isMember(sym.adr)) { 1.305 - log.error(pos, errkey, sym); 1.306 - inits.incl(sym.adr); 1.307 + 1.308 + void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {} 1.309 + 1.310 + /** Utility method to reset several Bits instances. 1.311 + */ 1.312 + private void resetBits(Bits... bits) { 1.313 + for (Bits b : bits) { 1.314 + b.reset(); 1.315 } 1.316 } 1.317 1.318 @@ -1582,7 +1579,7 @@ 1.319 1.320 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. 1.321 */ 1.322 - void merge() { 1.323 + protected void merge(JCTree tree) { 1.324 inits.assign(initsWhenFalse.andSet(initsWhenTrue)); 1.325 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); 1.326 } 1.327 @@ -1597,7 +1594,9 @@ 1.328 void scanExpr(JCTree tree) { 1.329 if (tree != null) { 1.330 scan(tree); 1.331 - if (inits.isReset()) merge(); 1.332 + if (inits.isReset()) { 1.333 + merge(tree); 1.334 + } 1.335 } 1.336 } 1.337 1.338 @@ -1614,7 +1613,7 @@ 1.339 */ 1.340 void scanCond(JCTree tree) { 1.341 if (tree.type.isFalse()) { 1.342 - if (inits.isReset()) merge(); 1.343 + if (inits.isReset()) merge(tree); 1.344 initsWhenTrue.assign(inits); 1.345 initsWhenTrue.inclRange(firstadr, nextadr); 1.346 uninitsWhenTrue.assign(uninits); 1.347 @@ -1622,7 +1621,7 @@ 1.348 initsWhenFalse.assign(inits); 1.349 uninitsWhenFalse.assign(uninits); 1.350 } else if (tree.type.isTrue()) { 1.351 - if (inits.isReset()) merge(); 1.352 + if (inits.isReset()) merge(tree); 1.353 initsWhenFalse.assign(inits); 1.354 initsWhenFalse.inclRange(firstadr, nextadr); 1.355 uninitsWhenFalse.assign(uninits); 1.356 @@ -1641,22 +1640,22 @@ 1.357 1.358 /* ------------ Visitor methods for various sorts of trees -------------*/ 1.359 1.360 + @Override 1.361 public void visitClassDef(JCClassDecl tree) { 1.362 - if (tree.sym == null) return; 1.363 + if (tree.sym == null) { 1.364 + return; 1.365 + } 1.366 1.367 JCClassDecl classDefPrev = classDef; 1.368 int firstadrPrev = firstadr; 1.369 int nextadrPrev = nextadr; 1.370 - ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits; 1.371 - Lint lintPrev = lint; 1.372 + ListBuffer<P> pendingExitsPrev = pendingExits; 1.373 1.374 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.375 + pendingExits = new ListBuffer<P>(); 1.376 if (tree.name != names.empty) { 1.377 firstadr = nextadr; 1.378 } 1.379 classDef = tree; 1.380 - lint = lint.augment(tree.sym); 1.381 - 1.382 try { 1.383 // define all the static fields 1.384 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1.385 @@ -1664,8 +1663,9 @@ 1.386 JCVariableDecl def = (JCVariableDecl)l.head; 1.387 if ((def.mods.flags & STATIC) != 0) { 1.388 VarSymbol sym = def.sym; 1.389 - if (trackable(sym)) 1.390 + if (trackable(sym)) { 1.391 newVar(def); 1.392 + } 1.393 } 1.394 } 1.395 } 1.396 @@ -1684,8 +1684,9 @@ 1.397 JCVariableDecl def = (JCVariableDecl)l.head; 1.398 if ((def.mods.flags & STATIC) == 0) { 1.399 VarSymbol sym = def.sym; 1.400 - if (trackable(sym)) 1.401 + if (trackable(sym)) { 1.402 newVar(def); 1.403 + } 1.404 } 1.405 } 1.406 } 1.407 @@ -1709,21 +1710,25 @@ 1.408 nextadr = nextadrPrev; 1.409 firstadr = firstadrPrev; 1.410 classDef = classDefPrev; 1.411 - lint = lintPrev; 1.412 } 1.413 } 1.414 1.415 + @Override 1.416 public void visitMethodDef(JCMethodDecl tree) { 1.417 - if (tree.body == null) return; 1.418 + if (tree.body == null) { 1.419 + return; 1.420 + } 1.421 + /* MemberEnter can generate synthetic methods, ignore them 1.422 + */ 1.423 + if ((tree.sym.flags() & SYNTHETIC) != 0) { 1.424 + return; 1.425 + } 1.426 1.427 final Bits initsPrev = new Bits(inits); 1.428 final Bits uninitsPrev = new Bits(uninits); 1.429 int nextadrPrev = nextadr; 1.430 int firstadrPrev = firstadr; 1.431 int returnadrPrev = returnadr; 1.432 - Lint lintPrev = lint; 1.433 - 1.434 - lint = lint.augment(tree.sym); 1.435 1.436 Assert.check(pendingExits.isEmpty()); 1.437 1.438 @@ -1731,13 +1736,17 @@ 1.439 boolean isInitialConstructor = 1.440 TreeInfo.isInitialConstructor(tree); 1.441 1.442 - if (!isInitialConstructor) 1.443 + if (!isInitialConstructor) { 1.444 firstadr = nextadr; 1.445 + } 1.446 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 1.447 JCVariableDecl def = l.head; 1.448 scan(def); 1.449 - inits.incl(def.sym.adr); 1.450 - uninits.excl(def.sym.adr); 1.451 + Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag"); 1.452 + /* If we are executing the code from Gen, then there can be 1.453 + * synthetic or mandated variables, ignore them. 1.454 + */ 1.455 + initParam(def); 1.456 } 1.457 // else we are in an instance initializer block; 1.458 // leave caught unchanged. 1.459 @@ -1761,39 +1770,42 @@ 1.460 } 1.461 } 1.462 } 1.463 - List<AssignPendingExit> exits = pendingExits.toList(); 1.464 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.465 + List<P> exits = pendingExits.toList(); 1.466 + pendingExits = new ListBuffer<>(); 1.467 while (exits.nonEmpty()) { 1.468 - AssignPendingExit exit = exits.head; 1.469 + P exit = exits.head; 1.470 exits = exits.tail; 1.471 Assert.check(exit.tree.hasTag(RETURN), exit.tree); 1.472 if (isInitialConstructor) { 1.473 - inits.assign(exit.exit_inits); 1.474 - for (int i = firstadr; i < nextadr; i++) 1.475 + assignToInits(exit.tree, exit.exit_inits); 1.476 + for (int i = firstadr; i < nextadr; i++) { 1.477 checkInit(exit.tree.pos(), vardecls[i].sym); 1.478 + } 1.479 } 1.480 } 1.481 } finally { 1.482 - inits.assign(initsPrev); 1.483 + assignToInits(tree, initsPrev); 1.484 uninits.assign(uninitsPrev); 1.485 nextadr = nextadrPrev; 1.486 firstadr = firstadrPrev; 1.487 returnadr = returnadrPrev; 1.488 - lint = lintPrev; 1.489 } 1.490 } 1.491 1.492 + protected void initParam(JCVariableDecl def) { 1.493 + inits.incl(def.sym.adr); 1.494 + uninits.excl(def.sym.adr); 1.495 + } 1.496 + 1.497 public void visitVarDef(JCVariableDecl tree) { 1.498 boolean track = trackable(tree.sym); 1.499 - if (track && tree.sym.owner.kind == MTH) newVar(tree); 1.500 + if (track && tree.sym.owner.kind == MTH) { 1.501 + newVar(tree); 1.502 + } 1.503 if (tree.init != null) { 1.504 - Lint lintPrev = lint; 1.505 - lint = lint.augment(tree.sym); 1.506 - try{ 1.507 - scanExpr(tree.init); 1.508 - if (track) letInit(tree.pos(), tree.sym); 1.509 - } finally { 1.510 - lint = lintPrev; 1.511 + scanExpr(tree.init); 1.512 + if (track) { 1.513 + letInit(tree.pos(), tree.sym); 1.514 } 1.515 } 1.516 } 1.517 @@ -1804,14 +1816,18 @@ 1.518 nextadr = nextadrPrev; 1.519 } 1.520 1.521 + int getLogNumberOfErrors() { 1.522 + return 0; 1.523 + } 1.524 + 1.525 public void visitDoLoop(JCDoWhileLoop tree) { 1.526 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.527 + ListBuffer<P> prevPendingExits = pendingExits; 1.528 FlowKind prevFlowKind = flowKind; 1.529 flowKind = FlowKind.NORMAL; 1.530 final Bits initsSkip = new Bits(true); 1.531 final Bits uninitsSkip = new Bits(true); 1.532 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.533 - int prevErrors = log.nerrors; 1.534 + pendingExits = new ListBuffer<P>(); 1.535 + int prevErrors = getLogNumberOfErrors(); 1.536 do { 1.537 final Bits uninitsEntry = new Bits(uninits); 1.538 uninitsEntry.excludeFrom(nextadr); 1.539 @@ -1822,28 +1838,28 @@ 1.540 initsSkip.assign(initsWhenFalse); 1.541 uninitsSkip.assign(uninitsWhenFalse); 1.542 } 1.543 - if (log.nerrors != prevErrors || 1.544 + if (getLogNumberOfErrors() != prevErrors || 1.545 flowKind.isFinal() || 1.546 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) 1.547 break; 1.548 - inits.assign(initsWhenTrue); 1.549 + assignToInits(tree.cond, initsWhenTrue); 1.550 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); 1.551 flowKind = FlowKind.SPECULATIVE_LOOP; 1.552 } while (true); 1.553 flowKind = prevFlowKind; 1.554 - inits.assign(initsSkip); 1.555 + assignToInits(tree, initsSkip); 1.556 uninits.assign(uninitsSkip); 1.557 resolveBreaks(tree, prevPendingExits); 1.558 } 1.559 1.560 public void visitWhileLoop(JCWhileLoop tree) { 1.561 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.562 + ListBuffer<P> prevPendingExits = pendingExits; 1.563 FlowKind prevFlowKind = flowKind; 1.564 flowKind = FlowKind.NORMAL; 1.565 final Bits initsSkip = new Bits(true); 1.566 final Bits uninitsSkip = new Bits(true); 1.567 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.568 - int prevErrors = log.nerrors; 1.569 + pendingExits = new ListBuffer<>(); 1.570 + int prevErrors = getLogNumberOfErrors(); 1.571 final Bits uninitsEntry = new Bits(uninits); 1.572 uninitsEntry.excludeFrom(nextadr); 1.573 do { 1.574 @@ -1852,35 +1868,36 @@ 1.575 initsSkip.assign(initsWhenFalse) ; 1.576 uninitsSkip.assign(uninitsWhenFalse); 1.577 } 1.578 - inits.assign(initsWhenTrue); 1.579 + assignToInits(tree, initsWhenTrue); 1.580 uninits.assign(uninitsWhenTrue); 1.581 scan(tree.body); 1.582 resolveContinues(tree); 1.583 - if (log.nerrors != prevErrors || 1.584 + if (getLogNumberOfErrors() != prevErrors || 1.585 flowKind.isFinal() || 1.586 - new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1.587 + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) { 1.588 break; 1.589 + } 1.590 uninits.assign(uninitsEntry.andSet(uninits)); 1.591 flowKind = FlowKind.SPECULATIVE_LOOP; 1.592 } while (true); 1.593 flowKind = prevFlowKind; 1.594 //a variable is DA/DU after the while statement, if it's DA/DU assuming the 1.595 //branch is not taken AND if it's DA/DU before any break statement 1.596 - inits.assign(initsSkip); 1.597 + assignToInits(tree.body, initsSkip); 1.598 uninits.assign(uninitsSkip); 1.599 resolveBreaks(tree, prevPendingExits); 1.600 } 1.601 1.602 public void visitForLoop(JCForLoop tree) { 1.603 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.604 + ListBuffer<P> prevPendingExits = pendingExits; 1.605 FlowKind prevFlowKind = flowKind; 1.606 flowKind = FlowKind.NORMAL; 1.607 int nextadrPrev = nextadr; 1.608 scan(tree.init); 1.609 final Bits initsSkip = new Bits(true); 1.610 final Bits uninitsSkip = new Bits(true); 1.611 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.612 - int prevErrors = log.nerrors; 1.613 + pendingExits = new ListBuffer<P>(); 1.614 + int prevErrors = getLogNumberOfErrors(); 1.615 do { 1.616 final Bits uninitsEntry = new Bits(uninits); 1.617 uninitsEntry.excludeFrom(nextadr); 1.618 @@ -1890,7 +1907,7 @@ 1.619 initsSkip.assign(initsWhenFalse); 1.620 uninitsSkip.assign(uninitsWhenFalse); 1.621 } 1.622 - inits.assign(initsWhenTrue); 1.623 + assignToInits(tree.body, initsWhenTrue); 1.624 uninits.assign(uninitsWhenTrue); 1.625 } else if (!flowKind.isFinal()) { 1.626 initsSkip.assign(inits); 1.627 @@ -1901,7 +1918,7 @@ 1.628 scan(tree.body); 1.629 resolveContinues(tree); 1.630 scan(tree.step); 1.631 - if (log.nerrors != prevErrors || 1.632 + if (getLogNumberOfErrors() != prevErrors || 1.633 flowKind.isFinal() || 1.634 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1.635 break; 1.636 @@ -1911,7 +1928,7 @@ 1.637 flowKind = prevFlowKind; 1.638 //a variable is DA/DU after a for loop, if it's DA/DU assuming the 1.639 //branch is not taken AND if it's DA/DU before any break statement 1.640 - inits.assign(initsSkip); 1.641 + assignToInits(tree.body, initsSkip); 1.642 uninits.assign(uninitsSkip); 1.643 resolveBreaks(tree, prevPendingExits); 1.644 nextadr = nextadrPrev; 1.645 @@ -1920,7 +1937,7 @@ 1.646 public void visitForeachLoop(JCEnhancedForLoop tree) { 1.647 visitVarDef(tree.var); 1.648 1.649 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.650 + ListBuffer<P> prevPendingExits = pendingExits; 1.651 FlowKind prevFlowKind = flowKind; 1.652 flowKind = FlowKind.NORMAL; 1.653 int nextadrPrev = nextadr; 1.654 @@ -1929,14 +1946,14 @@ 1.655 final Bits uninitsStart = new Bits(uninits); 1.656 1.657 letInit(tree.pos(), tree.var.sym); 1.658 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.659 - int prevErrors = log.nerrors; 1.660 + pendingExits = new ListBuffer<P>(); 1.661 + int prevErrors = getLogNumberOfErrors(); 1.662 do { 1.663 final Bits uninitsEntry = new Bits(uninits); 1.664 uninitsEntry.excludeFrom(nextadr); 1.665 scan(tree.body); 1.666 resolveContinues(tree); 1.667 - if (log.nerrors != prevErrors || 1.668 + if (getLogNumberOfErrors() != prevErrors || 1.669 flowKind.isFinal() || 1.670 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1.671 break; 1.672 @@ -1944,41 +1961,50 @@ 1.673 flowKind = FlowKind.SPECULATIVE_LOOP; 1.674 } while (true); 1.675 flowKind = prevFlowKind; 1.676 - inits.assign(initsStart); 1.677 + assignToInits(tree.body, initsStart); 1.678 uninits.assign(uninitsStart.andSet(uninits)); 1.679 resolveBreaks(tree, prevPendingExits); 1.680 nextadr = nextadrPrev; 1.681 } 1.682 1.683 public void visitLabelled(JCLabeledStatement tree) { 1.684 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.685 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.686 + ListBuffer<P> prevPendingExits = pendingExits; 1.687 + pendingExits = new ListBuffer<P>(); 1.688 scan(tree.body); 1.689 resolveBreaks(tree, prevPendingExits); 1.690 } 1.691 1.692 public void visitSwitch(JCSwitch tree) { 1.693 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.694 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.695 + ListBuffer<P> prevPendingExits = pendingExits; 1.696 + pendingExits = new ListBuffer<>(); 1.697 int nextadrPrev = nextadr; 1.698 scanExpr(tree.selector); 1.699 final Bits initsSwitch = new Bits(inits); 1.700 final Bits uninitsSwitch = new Bits(uninits); 1.701 boolean hasDefault = false; 1.702 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1.703 - inits.assign(initsSwitch); 1.704 + assignToInits(l.head, initsSwitch); 1.705 uninits.assign(uninits.andSet(uninitsSwitch)); 1.706 JCCase c = l.head; 1.707 - if (c.pat == null) 1.708 + if (c.pat == null) { 1.709 hasDefault = true; 1.710 - else 1.711 + } else { 1.712 scanExpr(c.pat); 1.713 + } 1.714 + if (hasDefault) { 1.715 + assignToInits(null, initsSwitch); 1.716 + uninits.assign(uninits.andSet(uninitsSwitch)); 1.717 + } 1.718 scan(c.stats); 1.719 addVars(c.stats, initsSwitch, uninitsSwitch); 1.720 + if (!hasDefault) { 1.721 + assignToInits(l.head.stats.last(), initsSwitch); 1.722 + uninits.assign(uninits.andSet(uninitsSwitch)); 1.723 + } 1.724 // Warn about fall-through if lint switch fallthrough enabled. 1.725 } 1.726 if (!hasDefault) { 1.727 - inits.andSet(initsSwitch); 1.728 + andSetInits(null, initsSwitch); 1.729 } 1.730 resolveBreaks(tree, prevPendingExits); 1.731 nextadr = nextadrPrev; 1.732 @@ -1997,11 +2023,17 @@ 1.733 } 1.734 } 1.735 1.736 + boolean isEnabled(Lint.LintCategory lc) { 1.737 + return false; 1.738 + } 1.739 + 1.740 + void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {} 1.741 + 1.742 public void visitTry(JCTry tree) { 1.743 ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb(); 1.744 final Bits uninitsTryPrev = new Bits(uninitsTry); 1.745 - ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1.746 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.747 + ListBuffer<P> prevPendingExits = pendingExits; 1.748 + pendingExits = new ListBuffer<>(); 1.749 final Bits initsTry = new Bits(inits); 1.750 uninitsTry.assign(uninits); 1.751 for (JCTree resource : tree.resources) { 1.752 @@ -2023,10 +2055,10 @@ 1.753 int nextadrCatch = nextadr; 1.754 1.755 if (!resourceVarDecls.isEmpty() && 1.756 - lint.isEnabled(Lint.LintCategory.TRY)) { 1.757 + isEnabled(Lint.LintCategory.TRY)) { 1.758 for (JCVariableDecl resVar : resourceVarDecls) { 1.759 if (unrefdResources.includes(resVar.sym)) { 1.760 - log.warning(Lint.LintCategory.TRY, resVar.pos(), 1.761 + reportWarning(Lint.LintCategory.TRY, resVar.pos(), 1.762 "try.resource.not.referenced", resVar.sym); 1.763 unrefdResources.remove(resVar.sym); 1.764 } 1.765 @@ -2042,20 +2074,22 @@ 1.766 1.767 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1.768 JCVariableDecl param = l.head.param; 1.769 - inits.assign(initsCatchPrev); 1.770 + assignToInits(tree.body, initsCatchPrev); 1.771 uninits.assign(uninitsCatchPrev); 1.772 scan(param); 1.773 - inits.incl(param.sym.adr); 1.774 - uninits.excl(param.sym.adr); 1.775 + /* If this is a TWR and we are executing the code from Gen, 1.776 + * then there can be synthetic variables, ignore them. 1.777 + */ 1.778 + initParam(param); 1.779 scan(l.head.body); 1.780 initsEnd.andSet(inits); 1.781 uninitsEnd.andSet(uninits); 1.782 nextadr = nextadrCatch; 1.783 } 1.784 if (tree.finalizer != null) { 1.785 - inits.assign(initsTry); 1.786 + assignToInits(tree.finalizer, initsTry); 1.787 uninits.assign(uninitsTry); 1.788 - ListBuffer<AssignPendingExit> exits = pendingExits; 1.789 + ListBuffer<P> exits = pendingExits; 1.790 pendingExits = prevPendingExits; 1.791 scan(tree.finalizer); 1.792 if (!tree.finallyCanCompleteNormally) { 1.793 @@ -2065,19 +2099,19 @@ 1.794 // FIX: this doesn't preserve source order of exits in catch 1.795 // versus finally! 1.796 while (exits.nonEmpty()) { 1.797 - AssignPendingExit exit = exits.next(); 1.798 + P exit = exits.next(); 1.799 if (exit.exit_inits != null) { 1.800 exit.exit_inits.orSet(inits); 1.801 exit.exit_uninits.andSet(uninits); 1.802 } 1.803 pendingExits.append(exit); 1.804 } 1.805 - inits.orSet(initsEnd); 1.806 + orSetInits(tree, initsEnd); 1.807 } 1.808 } else { 1.809 - inits.assign(initsEnd); 1.810 + assignToInits(tree, initsEnd); 1.811 uninits.assign(uninitsEnd); 1.812 - ListBuffer<AssignPendingExit> exits = pendingExits; 1.813 + ListBuffer<P> exits = pendingExits; 1.814 pendingExits = prevPendingExits; 1.815 while (exits.nonEmpty()) pendingExits.append(exits.next()); 1.816 } 1.817 @@ -2088,7 +2122,7 @@ 1.818 scanCond(tree.cond); 1.819 final Bits initsBeforeElse = new Bits(initsWhenFalse); 1.820 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 1.821 - inits.assign(initsWhenTrue); 1.822 + assignToInits(tree.cond, initsWhenTrue); 1.823 uninits.assign(uninitsWhenTrue); 1.824 if (tree.truepart.type.hasTag(BOOLEAN) && 1.825 tree.falsepart.type.hasTag(BOOLEAN)) { 1.826 @@ -2101,7 +2135,7 @@ 1.827 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); 1.828 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); 1.829 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); 1.830 - inits.assign(initsBeforeElse); 1.831 + assignToInits(tree.truepart, initsBeforeElse); 1.832 uninits.assign(uninitsBeforeElse); 1.833 scanCond(tree.falsepart); 1.834 initsWhenTrue.andSet(initsAfterThenWhenTrue); 1.835 @@ -2112,10 +2146,10 @@ 1.836 scanExpr(tree.truepart); 1.837 final Bits initsAfterThen = new Bits(inits); 1.838 final Bits uninitsAfterThen = new Bits(uninits); 1.839 - inits.assign(initsBeforeElse); 1.840 + assignToInits(tree.truepart, initsBeforeElse); 1.841 uninits.assign(uninitsBeforeElse); 1.842 scanExpr(tree.falsepart); 1.843 - inits.andSet(initsAfterThen); 1.844 + andSetInits(tree.falsepart, initsAfterThen); 1.845 uninits.andSet(uninitsAfterThen); 1.846 } 1.847 } 1.848 @@ -2124,39 +2158,46 @@ 1.849 scanCond(tree.cond); 1.850 final Bits initsBeforeElse = new Bits(initsWhenFalse); 1.851 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 1.852 - inits.assign(initsWhenTrue); 1.853 + assignToInits(tree.cond, initsWhenTrue); 1.854 uninits.assign(uninitsWhenTrue); 1.855 scan(tree.thenpart); 1.856 if (tree.elsepart != null) { 1.857 final Bits initsAfterThen = new Bits(inits); 1.858 final Bits uninitsAfterThen = new Bits(uninits); 1.859 - inits.assign(initsBeforeElse); 1.860 + assignToInits(tree.thenpart, initsBeforeElse); 1.861 uninits.assign(uninitsBeforeElse); 1.862 scan(tree.elsepart); 1.863 - inits.andSet(initsAfterThen); 1.864 + andSetInits(tree.elsepart, initsAfterThen); 1.865 uninits.andSet(uninitsAfterThen); 1.866 } else { 1.867 - inits.andSet(initsBeforeElse); 1.868 + andSetInits(tree.thenpart, initsBeforeElse); 1.869 uninits.andSet(uninitsBeforeElse); 1.870 } 1.871 } 1.872 1.873 - public void visitBreak(JCBreak tree) { 1.874 - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 1.875 + protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) { 1.876 + return null; 1.877 } 1.878 1.879 - public void visitContinue(JCContinue tree) { 1.880 - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 1.881 + @Override 1.882 + public void visitBreak(JCBreak tree) { 1.883 + recordExit(tree, createNewPendingExit(tree, inits, uninits)); 1.884 } 1.885 1.886 + @Override 1.887 + public void visitContinue(JCContinue tree) { 1.888 + recordExit(tree, createNewPendingExit(tree, inits, uninits)); 1.889 + } 1.890 + 1.891 + @Override 1.892 public void visitReturn(JCReturn tree) { 1.893 scanExpr(tree.expr); 1.894 - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 1.895 + recordExit(tree, createNewPendingExit(tree, inits, uninits)); 1.896 } 1.897 1.898 public void visitThrow(JCThrow tree) { 1.899 scanExpr(tree.expr); 1.900 - markDead(); 1.901 + markDead(tree.expr); 1.902 } 1.903 1.904 public void visitApply(JCMethodInvocation tree) { 1.905 @@ -2175,10 +2216,10 @@ 1.906 final Bits prevUninits = new Bits(uninits); 1.907 final Bits prevInits = new Bits(inits); 1.908 int returnadrPrev = returnadr; 1.909 - ListBuffer<AssignPendingExit> prevPending = pendingExits; 1.910 + ListBuffer<P> prevPending = pendingExits; 1.911 try { 1.912 returnadr = nextadr; 1.913 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.914 + pendingExits = new ListBuffer<P>(); 1.915 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 1.916 JCVariableDecl def = l.head; 1.917 scan(def); 1.918 @@ -2194,7 +2235,7 @@ 1.919 finally { 1.920 returnadr = returnadrPrev; 1.921 uninits.assign(prevUninits); 1.922 - inits.assign(prevInits); 1.923 + assignToInits(tree, prevInits); 1.924 pendingExits = prevPending; 1.925 } 1.926 } 1.927 @@ -2210,11 +2251,11 @@ 1.928 scanCond(tree.cond); 1.929 uninitsExit.andSet(uninitsWhenTrue); 1.930 if (tree.detail != null) { 1.931 - inits.assign(initsWhenFalse); 1.932 + assignToInits(tree, initsWhenFalse); 1.933 uninits.assign(uninitsWhenFalse); 1.934 scanExpr(tree.detail); 1.935 } 1.936 - inits.assign(initsExit); 1.937 + assignToInits(tree, initsExit); 1.938 uninits.assign(uninitsExit); 1.939 } 1.940 1.941 @@ -2260,7 +2301,7 @@ 1.942 scanCond(tree.lhs); 1.943 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); 1.944 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); 1.945 - inits.assign(initsWhenTrue); 1.946 + assignToInits(tree.lhs, initsWhenTrue); 1.947 uninits.assign(uninitsWhenTrue); 1.948 scanCond(tree.rhs); 1.949 initsWhenFalse.andSet(initsWhenFalseLeft); 1.950 @@ -2270,7 +2311,7 @@ 1.951 scanCond(tree.lhs); 1.952 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); 1.953 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); 1.954 - inits.assign(initsWhenFalse); 1.955 + assignToInits(tree.lhs, initsWhenFalse); 1.956 uninits.assign(uninitsWhenFalse); 1.957 scanCond(tree.rhs); 1.958 initsWhenTrue.andSet(initsWhenTrueLeft); 1.959 @@ -2308,14 +2349,12 @@ 1.960 1.961 /** Perform definite assignment/unassignment analysis on a tree. 1.962 */ 1.963 - public void analyzeTree(Env<AttrContext> env, TreeMaker make) { 1.964 - analyzeTree(env, env.tree, make); 1.965 - } 1.966 + public void analyzeTree(Env<?> env) { 1.967 + analyzeTree(env, env.tree); 1.968 + } 1.969 1.970 - public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) { 1.971 + public void analyzeTree(Env<?> env, JCTree tree) { 1.972 try { 1.973 - attrEnv = env; 1.974 - Flow.this.make = make; 1.975 startPos = tree.pos().getStartPosition(); 1.976 1.977 if (vardecls == null) 1.978 @@ -2325,7 +2364,7 @@ 1.979 vardecls[i] = null; 1.980 firstadr = 0; 1.981 nextadr = 0; 1.982 - pendingExits = new ListBuffer<AssignPendingExit>(); 1.983 + pendingExits = new ListBuffer<>(); 1.984 this.classDef = null; 1.985 unrefdResources = new Scope(env.enclClass.sym); 1.986 scan(tree); 1.987 @@ -2334,18 +2373,160 @@ 1.988 startPos = -1; 1.989 resetBits(inits, uninits, uninitsTry, initsWhenTrue, 1.990 initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); 1.991 - if (vardecls != null) for (int i=0; i<vardecls.length; i++) 1.992 - vardecls[i] = null; 1.993 + if (vardecls != null) { 1.994 + for (int i=0; i<vardecls.length; i++) 1.995 + vardecls[i] = null; 1.996 + } 1.997 firstadr = 0; 1.998 nextadr = 0; 1.999 pendingExits = null; 1.1000 - Flow.this.make = null; 1.1001 this.classDef = null; 1.1002 unrefdResources = null; 1.1003 } 1.1004 } 1.1005 } 1.1006 1.1007 + public static class AssignAnalyzer 1.1008 + extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> { 1.1009 + 1.1010 + Log log; 1.1011 + Lint lint; 1.1012 + 1.1013 + public static class AssignPendingExit 1.1014 + extends AbstractAssignAnalyzer.AbstractAssignPendingExit { 1.1015 + 1.1016 + public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 1.1017 + super(tree, inits, uninits); 1.1018 + } 1.1019 + } 1.1020 + 1.1021 + public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) { 1.1022 + super(new Bits(), syms, names); 1.1023 + this.log = log; 1.1024 + this.lint = lint; 1.1025 + } 1.1026 + 1.1027 + @Override 1.1028 + protected AssignPendingExit createNewPendingExit(JCTree tree, 1.1029 + Bits inits, Bits uninits) { 1.1030 + return new AssignPendingExit(tree, inits, uninits); 1.1031 + } 1.1032 + 1.1033 + /** Record an initialization of a trackable variable. 1.1034 + */ 1.1035 + @Override 1.1036 + void letInit(DiagnosticPosition pos, VarSymbol sym) { 1.1037 + if (sym.adr >= firstadr && trackable(sym)) { 1.1038 + if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { 1.1039 + if (!uninits.isMember(sym.adr)) { 1.1040 + //assignment targeting an effectively final variable 1.1041 + //makes the variable lose its status of effectively final 1.1042 + //if the variable is _not_ definitively unassigned 1.1043 + sym.flags_field &= ~EFFECTIVELY_FINAL; 1.1044 + } else { 1.1045 + uninit(sym); 1.1046 + } 1.1047 + } 1.1048 + else if ((sym.flags() & FINAL) != 0) { 1.1049 + if ((sym.flags() & PARAMETER) != 0) { 1.1050 + if ((sym.flags() & UNION) != 0) { //multi-catch parameter 1.1051 + log.error(pos, "multicatch.parameter.may.not.be.assigned", sym); 1.1052 + } 1.1053 + else { 1.1054 + log.error(pos, "final.parameter.may.not.be.assigned", 1.1055 + sym); 1.1056 + } 1.1057 + } else if (!uninits.isMember(sym.adr)) { 1.1058 + log.error(pos, flowKind.errKey, sym); 1.1059 + } else { 1.1060 + uninit(sym); 1.1061 + } 1.1062 + } 1.1063 + inits.incl(sym.adr); 1.1064 + } else if ((sym.flags() & FINAL) != 0) { 1.1065 + log.error(pos, "var.might.already.be.assigned", sym); 1.1066 + } 1.1067 + } 1.1068 + 1.1069 + @Override 1.1070 + void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { 1.1071 + if ((sym.adr >= firstadr || sym.owner.kind != TYP) && 1.1072 + trackable(sym) && 1.1073 + !inits.isMember(sym.adr)) { 1.1074 + log.error(pos, errkey, sym); 1.1075 + inits.incl(sym.adr); 1.1076 + } 1.1077 + } 1.1078 + 1.1079 + @Override 1.1080 + void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, 1.1081 + String key, Object ... args) { 1.1082 + log.warning(lc, pos, key, args); 1.1083 + } 1.1084 + 1.1085 + @Override 1.1086 + int getLogNumberOfErrors() { 1.1087 + return log.nerrors; 1.1088 + } 1.1089 + 1.1090 + @Override 1.1091 + boolean isEnabled(Lint.LintCategory lc) { 1.1092 + return lint.isEnabled(lc); 1.1093 + } 1.1094 + 1.1095 + @Override 1.1096 + public void visitClassDef(JCClassDecl tree) { 1.1097 + if (tree.sym == null) { 1.1098 + return; 1.1099 + } 1.1100 + 1.1101 + Lint lintPrev = lint; 1.1102 + lint = lint.augment(tree.sym); 1.1103 + try { 1.1104 + super.visitClassDef(tree); 1.1105 + } finally { 1.1106 + lint = lintPrev; 1.1107 + } 1.1108 + } 1.1109 + 1.1110 + @Override 1.1111 + public void visitMethodDef(JCMethodDecl tree) { 1.1112 + if (tree.body == null) { 1.1113 + return; 1.1114 + } 1.1115 + 1.1116 + /* MemberEnter can generate synthetic methods ignore them 1.1117 + */ 1.1118 + if ((tree.sym.flags() & SYNTHETIC) != 0) { 1.1119 + return; 1.1120 + } 1.1121 + 1.1122 + Lint lintPrev = lint; 1.1123 + lint = lint.augment(tree.sym); 1.1124 + try { 1.1125 + super.visitMethodDef(tree); 1.1126 + } finally { 1.1127 + lint = lintPrev; 1.1128 + } 1.1129 + } 1.1130 + 1.1131 + @Override 1.1132 + public void visitVarDef(JCVariableDecl tree) { 1.1133 + if (tree.init == null) { 1.1134 + super.visitVarDef(tree); 1.1135 + } else { 1.1136 + Lint lintPrev = lint; 1.1137 + lint = lint.augment(tree.sym); 1.1138 + try{ 1.1139 + super.visitVarDef(tree); 1.1140 + } finally { 1.1141 + lint = lintPrev; 1.1142 + } 1.1143 + } 1.1144 + } 1.1145 + 1.1146 + } 1.1147 + 1.1148 /** 1.1149 * This pass implements the last step of the dataflow analysis, namely 1.1150 * the effectively-final analysis check. This checks that every local variable 1.1151 @@ -2358,7 +2539,7 @@ 1.1152 JCTree currentTree; //local class or lambda 1.1153 1.1154 @Override 1.1155 - void markDead() { 1.1156 + void markDead(JCTree tree) { 1.1157 //do nothing 1.1158 } 1.1159