src/share/classes/com/sun/tools/javac/comp/Flow.java

changeset 2027
4932bb04c4b8
parent 2019
77d395862700
child 2047
5f915a0c9615
equal deleted inserted replaced
2026:03c26c60499c 2027:4932bb04c4b8
205 return instance; 205 return instance;
206 } 206 }
207 207
208 public void analyzeTree(Env<AttrContext> env, TreeMaker make) { 208 public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
209 new AliveAnalyzer().analyzeTree(env, make); 209 new AliveAnalyzer().analyzeTree(env, make);
210 new AssignAnalyzer().analyzeTree(env, make); 210 new AssignAnalyzer(log, syms, lint, names).analyzeTree(env);
211 new FlowAnalyzer().analyzeTree(env, make); 211 new FlowAnalyzer().analyzeTree(env, make);
212 new CaptureAnalyzer().analyzeTree(env, make); 212 new CaptureAnalyzer().analyzeTree(env, make);
213 } 213 }
214 214
215 public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) { 215 public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
237 //message will be reported and will cause compilation to skip the flow analyis 237 //message will be reported and will cause compilation to skip the flow analyis
238 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis 238 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
239 //related errors, which will allow for more errors to be detected 239 //related errors, which will allow for more errors to be detected
240 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 240 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
241 try { 241 try {
242 new AssignAnalyzer().analyzeTree(env, that, make); 242 new AssignAnalyzer(log, syms, lint, names).analyzeTree(env);
243 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); 243 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
244 flowAnalyzer.analyzeTree(env, that, make); 244 flowAnalyzer.analyzeTree(env, that, make);
245 return flowAnalyzer.inferredThrownTypes; 245 return flowAnalyzer.inferredThrownTypes;
246 } finally { 246 } finally {
247 log.popDiagnosticHandler(diagHandler); 247 log.popDiagnosticHandler(diagHandler);
290 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); 290 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
291 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); 291 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
292 } 292 }
293 293
294 /** 294 /**
295 * Utility method to reset several Bits instances.
296 */
297 private void resetBits(Bits... bits) {
298 for (Bits b : bits) {
299 b.reset();
300 }
301 }
302
303 /**
304 * Base visitor class for all visitors implementing dataflow analysis logic. 295 * Base visitor class for all visitors implementing dataflow analysis logic.
305 * This class define the shared logic for handling jumps (break/continue statements). 296 * This class define the shared logic for handling jumps (break/continue statements).
306 */ 297 */
307 static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner { 298 static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
308 299
345 336
346 PendingExit(JCTree tree) { 337 PendingExit(JCTree tree) {
347 this.tree = tree; 338 this.tree = tree;
348 } 339 }
349 340
350 void resolveJump() { 341 void resolveJump(JCTree tree) {
351 //do nothing 342 //do nothing
352 } 343 }
353 } 344 }
354 345
355 abstract void markDead(); 346 abstract void markDead(JCTree tree);
356 347
357 /** Record an outward transfer of control. */ 348 /** Record an outward transfer of control. */
358 void recordExit(JCTree tree, P pe) { 349 void recordExit(JCTree tree, P pe) {
359 pendingExits.append(pe); 350 pendingExits.append(pe);
360 markDead(); 351 markDead(tree);
361 } 352 }
362 353
363 /** Resolve all jumps of this statement. */ 354 /** Resolve all jumps of this statement. */
364 private boolean resolveJump(JCTree tree, 355 private boolean resolveJump(JCTree tree,
365 ListBuffer<P> oldPendingExits, 356 ListBuffer<P> oldPendingExits,
369 pendingExits = oldPendingExits; 360 pendingExits = oldPendingExits;
370 for (; exits.nonEmpty(); exits = exits.tail) { 361 for (; exits.nonEmpty(); exits = exits.tail) {
371 P exit = exits.head; 362 P exit = exits.head;
372 if (exit.tree.hasTag(jk.treeTag) && 363 if (exit.tree.hasTag(jk.treeTag) &&
373 jk.getTarget(exit.tree) == tree) { 364 jk.getTarget(exit.tree) == tree) {
374 exit.resolveJump(); 365 exit.resolveJump(tree);
375 resolved = true; 366 resolved = true;
376 } else { 367 } else {
377 pendingExits.append(exit); 368 pendingExits.append(exit);
378 } 369 }
379 } 370 }
380 return resolved; 371 return resolved;
381 } 372 }
382 373
383 /** Resolve all breaks of this statement. */ 374 /** Resolve all continues of this statement. */
384 boolean resolveContinues(JCTree tree) { 375 boolean resolveContinues(JCTree tree) {
385 return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE); 376 return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
386 } 377 }
387 378
388 /** Resolve all continues of this statement. */ 379 /** Resolve all breaks of this statement. */
389 boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) { 380 boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
390 return resolveJump(tree, oldPendingExits, JumpKind.BREAK); 381 return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
391 } 382 }
392 383
393 @Override 384 @Override
412 * complete normally. 403 * complete normally.
413 */ 404 */
414 private boolean alive; 405 private boolean alive;
415 406
416 @Override 407 @Override
417 void markDead() { 408 void markDead(JCTree tree) {
418 alive = false; 409 alive = false;
419 } 410 }
420 411
421 /************************************************************************* 412 /*************************************************************************
422 * Visitor methods for statements and definitions 413 * Visitor methods for statements and definitions
694 recordExit(tree, new PendingExit(tree)); 685 recordExit(tree, new PendingExit(tree));
695 } 686 }
696 687
697 public void visitThrow(JCThrow tree) { 688 public void visitThrow(JCThrow tree) {
698 scan(tree.expr); 689 scan(tree.expr);
699 markDead(); 690 markDead(tree);
700 } 691 }
701 692
702 public void visitApply(JCMethodInvocation tree) { 693 public void visitApply(JCMethodInvocation tree) {
703 scan(tree.meth); 694 scan(tree.meth);
704 scan(tree.args); 695 scan(tree.args);
795 this.thrown = thrown; 786 this.thrown = thrown;
796 } 787 }
797 } 788 }
798 789
799 @Override 790 @Override
800 void markDead() { 791 void markDead(JCTree tree) {
801 //do nothing 792 //do nothing
802 } 793 }
803 794
804 /*-------------------- Exceptions ----------------------*/ 795 /*-------------------- Exceptions ----------------------*/
805 796
1220 } 1211 }
1221 } 1212 }
1222 else { 1213 else {
1223 markThrown(tree, tree.expr.type); 1214 markThrown(tree, tree.expr.type);
1224 } 1215 }
1225 markDead(); 1216 markDead(tree);
1226 } 1217 }
1227 1218
1228 public void visitApply(JCMethodInvocation tree) { 1219 public void visitApply(JCMethodInvocation tree) {
1229 scan(tree.meth); 1220 scan(tree.meth);
1230 scan(tree.args); 1221 scan(tree.args);
1370 * each variable is assigned when used and (ii) definite unassignment analysis, 1361 * each variable is assigned when used and (ii) definite unassignment analysis,
1371 * which ensures that no final variable is assigned more than once. This visitor 1362 * which ensures that no final variable is assigned more than once. This visitor
1372 * depends on the results of the liveliness analyzer. This pass is also used to mark 1363 * depends on the results of the liveliness analyzer. This pass is also used to mark
1373 * effectively-final local variables/parameters. 1364 * effectively-final local variables/parameters.
1374 */ 1365 */
1375 class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> { 1366
1367 public abstract static class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer.AbstractAssignPendingExit>
1368 extends BaseAnalyzer<P> {
1376 1369
1377 /** The set of definitely assigned variables. 1370 /** The set of definitely assigned variables.
1378 */ 1371 */
1379 final Bits inits; 1372 protected final Bits inits;
1380 1373
1381 /** The set of definitely unassigned variables. 1374 /** The set of definitely unassigned variables.
1382 */ 1375 */
1383 final Bits uninits; 1376 final Bits uninits;
1384 1377
1400 final Bits uninitsWhenTrue; 1393 final Bits uninitsWhenTrue;
1401 final Bits uninitsWhenFalse; 1394 final Bits uninitsWhenFalse;
1402 1395
1403 /** A mapping from addresses to variable symbols. 1396 /** A mapping from addresses to variable symbols.
1404 */ 1397 */
1405 JCVariableDecl[] vardecls; 1398 protected JCVariableDecl[] vardecls;
1406 1399
1407 /** The current class being defined. 1400 /** The current class being defined.
1408 */ 1401 */
1409 JCClassDecl classDef; 1402 JCClassDecl classDef;
1410 1403
1412 */ 1405 */
1413 int firstadr; 1406 int firstadr;
1414 1407
1415 /** The next available variable sequence number. 1408 /** The next available variable sequence number.
1416 */ 1409 */
1417 int nextadr; 1410 protected int nextadr;
1418 1411
1419 /** The first variable sequence number in a block that can return. 1412 /** The first variable sequence number in a block that can return.
1420 */ 1413 */
1421 int returnadr; 1414 protected int returnadr;
1422 1415
1423 /** The list of unreferenced automatic resources. 1416 /** The list of unreferenced automatic resources.
1424 */ 1417 */
1425 Scope unrefdResources; 1418 Scope unrefdResources;
1426 1419
1428 FlowKind flowKind = FlowKind.NORMAL; 1421 FlowKind flowKind = FlowKind.NORMAL;
1429 1422
1430 /** The starting position of the analysed tree */ 1423 /** The starting position of the analysed tree */
1431 int startPos; 1424 int startPos;
1432 1425
1433 AssignAnalyzer() { 1426 final Symtab syms;
1434 inits = new Bits(); 1427
1428 protected Names names;
1429
1430 public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit {
1431
1432 final Bits inits;
1433 final Bits uninits;
1434 final Bits exit_inits = new Bits(true);
1435 final Bits exit_uninits = new Bits(true);
1436
1437 public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1438 super(tree);
1439 this.inits = inits;
1440 this.uninits = uninits;
1441 this.exit_inits.assign(inits);
1442 this.exit_uninits.assign(uninits);
1443 }
1444
1445 @Override
1446 public void resolveJump(JCTree tree) {
1447 inits.andSet(exit_inits);
1448 uninits.andSet(exit_uninits);
1449 }
1450 }
1451
1452 public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) {
1453 this.inits = inits;
1435 uninits = new Bits(); 1454 uninits = new Bits();
1436 uninitsTry = new Bits(); 1455 uninitsTry = new Bits();
1437 initsWhenTrue = new Bits(true); 1456 initsWhenTrue = new Bits(true);
1438 initsWhenFalse = new Bits(true); 1457 initsWhenFalse = new Bits(true);
1439 uninitsWhenTrue = new Bits(true); 1458 uninitsWhenTrue = new Bits(true);
1440 uninitsWhenFalse = new Bits(true); 1459 uninitsWhenFalse = new Bits(true);
1441 } 1460 this.syms = syms;
1442 1461 this.names = names;
1443 class AssignPendingExit extends BaseAnalyzer.PendingExit { 1462 }
1444 1463
1445 final Bits exit_inits = new Bits(true); 1464 @Override
1446 final Bits exit_uninits = new Bits(true); 1465 protected void markDead(JCTree tree) {
1447
1448 AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1449 super(tree);
1450 this.exit_inits.assign(inits);
1451 this.exit_uninits.assign(uninits);
1452 }
1453
1454 void resolveJump() {
1455 inits.andSet(exit_inits);
1456 uninits.andSet(exit_uninits);
1457 }
1458 }
1459
1460 @Override
1461 void markDead() {
1462 inits.inclRange(returnadr, nextadr); 1466 inits.inclRange(returnadr, nextadr);
1463 uninits.inclRange(returnadr, nextadr); 1467 uninits.inclRange(returnadr, nextadr);
1464 } 1468 }
1465 1469
1466 /*-------------- Processing variables ----------------------*/ 1470 /*-------------- Processing variables ----------------------*/
1467 1471
1468 /** Do we need to track init/uninit state of this symbol? 1472 /** Do we need to track init/uninit state of this symbol?
1469 * I.e. is symbol either a local or a blank final variable? 1473 * I.e. is symbol either a local or a blank final variable?
1470 */ 1474 */
1471 boolean trackable(VarSymbol sym) { 1475 protected boolean trackable(VarSymbol sym) {
1472 return 1476 return
1473 sym.pos >= startPos && 1477 sym.pos >= startPos &&
1474 ((sym.owner.kind == MTH || 1478 ((sym.owner.kind == MTH ||
1475 ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL && 1479 ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
1476 classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)))); 1480 classDef.sym.isEnclosedBy((ClassSymbol)sym.owner))));
1486 if ((sym.flags() & FINAL) == 0) { 1490 if ((sym.flags() & FINAL) == 0) {
1487 sym.flags_field |= EFFECTIVELY_FINAL; 1491 sym.flags_field |= EFFECTIVELY_FINAL;
1488 } 1492 }
1489 sym.adr = nextadr; 1493 sym.adr = nextadr;
1490 vardecls[nextadr] = varDecl; 1494 vardecls[nextadr] = varDecl;
1491 inits.excl(nextadr); 1495 exclVarFromInits(varDecl, nextadr);
1492 uninits.incl(nextadr); 1496 uninits.incl(nextadr);
1493 nextadr++; 1497 nextadr++;
1494 } 1498 }
1495 1499
1500 protected void exclVarFromInits(JCTree tree, int adr) {
1501 inits.excl(adr);
1502 }
1503
1504 protected void assignToInits(JCTree tree, Bits bits) {
1505 inits.assign(bits);
1506 }
1507
1508 protected void andSetInits(JCTree tree, Bits bits) {
1509 inits.andSet(bits);
1510 }
1511
1512 protected void orSetInits(JCTree tree, Bits bits) {
1513 inits.orSet(bits);
1514 }
1515
1496 /** Record an initialization of a trackable variable. 1516 /** Record an initialization of a trackable variable.
1497 */ 1517 */
1498 void letInit(DiagnosticPosition pos, VarSymbol sym) { 1518 void letInit(DiagnosticPosition pos, VarSymbol sym) {
1499 if (sym.adr >= firstadr && trackable(sym)) { 1519 if (sym.adr >= firstadr && trackable(sym)) {
1500 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { 1520 if (uninits.isMember(sym.adr)) {
1501 if (!uninits.isMember(sym.adr)) { 1521 uninit(sym);
1502 //assignment targeting an effectively final variable
1503 //makes the variable lose its status of effectively final
1504 //if the variable is _not_ definitively unassigned
1505 sym.flags_field &= ~EFFECTIVELY_FINAL;
1506 } else {
1507 uninit(sym);
1508 }
1509 }
1510 else if ((sym.flags() & FINAL) != 0) {
1511 if ((sym.flags() & PARAMETER) != 0) {
1512 if ((sym.flags() & UNION) != 0) { //multi-catch parameter
1513 log.error(pos, "multicatch.parameter.may.not.be.assigned",
1514 sym);
1515 }
1516 else {
1517 log.error(pos, "final.parameter.may.not.be.assigned",
1518 sym);
1519 }
1520 } else if (!uninits.isMember(sym.adr)) {
1521 log.error(pos, flowKind.errKey, sym);
1522 } else {
1523 uninit(sym);
1524 }
1525 } 1522 }
1526 inits.incl(sym.adr); 1523 inits.incl(sym.adr);
1527 } else if ((sym.flags() & FINAL) != 0) {
1528 log.error(pos, "var.might.already.be.assigned", sym);
1529 } 1524 }
1530 } 1525 }
1531 //where 1526 //where
1532 void uninit(VarSymbol sym) { 1527 void uninit(VarSymbol sym) {
1533 if (!inits.isMember(sym.adr)) { 1528 if (!inits.isMember(sym.adr)) {
1557 /** Check that trackable variable is initialized. 1552 /** Check that trackable variable is initialized.
1558 */ 1553 */
1559 void checkInit(DiagnosticPosition pos, VarSymbol sym) { 1554 void checkInit(DiagnosticPosition pos, VarSymbol sym) {
1560 checkInit(pos, sym, "var.might.not.have.been.initialized"); 1555 checkInit(pos, sym, "var.might.not.have.been.initialized");
1561 } 1556 }
1562 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { 1557
1563 if ((sym.adr >= firstadr || sym.owner.kind != TYP) && 1558 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {}
1564 trackable(sym) && 1559
1565 !inits.isMember(sym.adr)) { 1560 /** Utility method to reset several Bits instances.
1566 log.error(pos, errkey, sym); 1561 */
1567 inits.incl(sym.adr); 1562 private void resetBits(Bits... bits) {
1563 for (Bits b : bits) {
1564 b.reset();
1568 } 1565 }
1569 } 1566 }
1570 1567
1571 /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets 1568 /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
1572 */ 1569 */
1580 } 1577 }
1581 } 1578 }
1582 1579
1583 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. 1580 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1584 */ 1581 */
1585 void merge() { 1582 protected void merge(JCTree tree) {
1586 inits.assign(initsWhenFalse.andSet(initsWhenTrue)); 1583 inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1587 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); 1584 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1588 } 1585 }
1589 1586
1590 /* ************************************************************************ 1587 /* ************************************************************************
1595 * (un)initsWhenTrue(WhenFalse) on exit. 1592 * (un)initsWhenTrue(WhenFalse) on exit.
1596 */ 1593 */
1597 void scanExpr(JCTree tree) { 1594 void scanExpr(JCTree tree) {
1598 if (tree != null) { 1595 if (tree != null) {
1599 scan(tree); 1596 scan(tree);
1600 if (inits.isReset()) merge(); 1597 if (inits.isReset()) {
1598 merge(tree);
1599 }
1601 } 1600 }
1602 } 1601 }
1603 1602
1604 /** Analyze a list of expressions. 1603 /** Analyze a list of expressions.
1605 */ 1604 */
1612 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) 1611 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1613 * rather than (un)inits on exit. 1612 * rather than (un)inits on exit.
1614 */ 1613 */
1615 void scanCond(JCTree tree) { 1614 void scanCond(JCTree tree) {
1616 if (tree.type.isFalse()) { 1615 if (tree.type.isFalse()) {
1617 if (inits.isReset()) merge(); 1616 if (inits.isReset()) merge(tree);
1618 initsWhenTrue.assign(inits); 1617 initsWhenTrue.assign(inits);
1619 initsWhenTrue.inclRange(firstadr, nextadr); 1618 initsWhenTrue.inclRange(firstadr, nextadr);
1620 uninitsWhenTrue.assign(uninits); 1619 uninitsWhenTrue.assign(uninits);
1621 uninitsWhenTrue.inclRange(firstadr, nextadr); 1620 uninitsWhenTrue.inclRange(firstadr, nextadr);
1622 initsWhenFalse.assign(inits); 1621 initsWhenFalse.assign(inits);
1623 uninitsWhenFalse.assign(uninits); 1622 uninitsWhenFalse.assign(uninits);
1624 } else if (tree.type.isTrue()) { 1623 } else if (tree.type.isTrue()) {
1625 if (inits.isReset()) merge(); 1624 if (inits.isReset()) merge(tree);
1626 initsWhenFalse.assign(inits); 1625 initsWhenFalse.assign(inits);
1627 initsWhenFalse.inclRange(firstadr, nextadr); 1626 initsWhenFalse.inclRange(firstadr, nextadr);
1628 uninitsWhenFalse.assign(uninits); 1627 uninitsWhenFalse.assign(uninits);
1629 uninitsWhenFalse.inclRange(firstadr, nextadr); 1628 uninitsWhenFalse.inclRange(firstadr, nextadr);
1630 initsWhenTrue.assign(inits); 1629 initsWhenTrue.assign(inits);
1639 } 1638 }
1640 } 1639 }
1641 1640
1642 /* ------------ Visitor methods for various sorts of trees -------------*/ 1641 /* ------------ Visitor methods for various sorts of trees -------------*/
1643 1642
1643 @Override
1644 public void visitClassDef(JCClassDecl tree) { 1644 public void visitClassDef(JCClassDecl tree) {
1645 if (tree.sym == null) return; 1645 if (tree.sym == null) {
1646 return;
1647 }
1646 1648
1647 JCClassDecl classDefPrev = classDef; 1649 JCClassDecl classDefPrev = classDef;
1648 int firstadrPrev = firstadr; 1650 int firstadrPrev = firstadr;
1649 int nextadrPrev = nextadr; 1651 int nextadrPrev = nextadr;
1650 ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits; 1652 ListBuffer<P> pendingExitsPrev = pendingExits;
1651 Lint lintPrev = lint; 1653
1652 1654 pendingExits = new ListBuffer<P>();
1653 pendingExits = new ListBuffer<AssignPendingExit>();
1654 if (tree.name != names.empty) { 1655 if (tree.name != names.empty) {
1655 firstadr = nextadr; 1656 firstadr = nextadr;
1656 } 1657 }
1657 classDef = tree; 1658 classDef = tree;
1658 lint = lint.augment(tree.sym);
1659
1660 try { 1659 try {
1661 // define all the static fields 1660 // define all the static fields
1662 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1661 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1663 if (l.head.hasTag(VARDEF)) { 1662 if (l.head.hasTag(VARDEF)) {
1664 JCVariableDecl def = (JCVariableDecl)l.head; 1663 JCVariableDecl def = (JCVariableDecl)l.head;
1665 if ((def.mods.flags & STATIC) != 0) { 1664 if ((def.mods.flags & STATIC) != 0) {
1666 VarSymbol sym = def.sym; 1665 VarSymbol sym = def.sym;
1667 if (trackable(sym)) 1666 if (trackable(sym)) {
1668 newVar(def); 1667 newVar(def);
1668 }
1669 } 1669 }
1670 } 1670 }
1671 } 1671 }
1672 1672
1673 // process all the static initializers 1673 // process all the static initializers
1682 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1682 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1683 if (l.head.hasTag(VARDEF)) { 1683 if (l.head.hasTag(VARDEF)) {
1684 JCVariableDecl def = (JCVariableDecl)l.head; 1684 JCVariableDecl def = (JCVariableDecl)l.head;
1685 if ((def.mods.flags & STATIC) == 0) { 1685 if ((def.mods.flags & STATIC) == 0) {
1686 VarSymbol sym = def.sym; 1686 VarSymbol sym = def.sym;
1687 if (trackable(sym)) 1687 if (trackable(sym)) {
1688 newVar(def); 1688 newVar(def);
1689 }
1689 } 1690 }
1690 } 1691 }
1691 } 1692 }
1692 1693
1693 // process all the instance initializers 1694 // process all the instance initializers
1707 } finally { 1708 } finally {
1708 pendingExits = pendingExitsPrev; 1709 pendingExits = pendingExitsPrev;
1709 nextadr = nextadrPrev; 1710 nextadr = nextadrPrev;
1710 firstadr = firstadrPrev; 1711 firstadr = firstadrPrev;
1711 classDef = classDefPrev; 1712 classDef = classDefPrev;
1712 lint = lintPrev; 1713 }
1713 } 1714 }
1714 } 1715
1715 1716 @Override
1716 public void visitMethodDef(JCMethodDecl tree) { 1717 public void visitMethodDef(JCMethodDecl tree) {
1717 if (tree.body == null) return; 1718 if (tree.body == null) {
1719 return;
1720 }
1721 /* MemberEnter can generate synthetic methods, ignore them
1722 */
1723 if ((tree.sym.flags() & SYNTHETIC) != 0) {
1724 return;
1725 }
1718 1726
1719 final Bits initsPrev = new Bits(inits); 1727 final Bits initsPrev = new Bits(inits);
1720 final Bits uninitsPrev = new Bits(uninits); 1728 final Bits uninitsPrev = new Bits(uninits);
1721 int nextadrPrev = nextadr; 1729 int nextadrPrev = nextadr;
1722 int firstadrPrev = firstadr; 1730 int firstadrPrev = firstadr;
1723 int returnadrPrev = returnadr; 1731 int returnadrPrev = returnadr;
1724 Lint lintPrev = lint;
1725
1726 lint = lint.augment(tree.sym);
1727 1732
1728 Assert.check(pendingExits.isEmpty()); 1733 Assert.check(pendingExits.isEmpty());
1729 1734
1730 try { 1735 try {
1731 boolean isInitialConstructor = 1736 boolean isInitialConstructor =
1732 TreeInfo.isInitialConstructor(tree); 1737 TreeInfo.isInitialConstructor(tree);
1733 1738
1734 if (!isInitialConstructor) 1739 if (!isInitialConstructor) {
1735 firstadr = nextadr; 1740 firstadr = nextadr;
1741 }
1736 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 1742 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1737 JCVariableDecl def = l.head; 1743 JCVariableDecl def = l.head;
1738 scan(def); 1744 scan(def);
1739 inits.incl(def.sym.adr); 1745 Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
1740 uninits.excl(def.sym.adr); 1746 /* If we are executing the code from Gen, then there can be
1747 * synthetic or mandated variables, ignore them.
1748 */
1749 initParam(def);
1741 } 1750 }
1742 // else we are in an instance initializer block; 1751 // else we are in an instance initializer block;
1743 // leave caught unchanged. 1752 // leave caught unchanged.
1744 scan(tree.body); 1753 scan(tree.body);
1745 1754
1759 checkInit(TreeInfo.diagEndPos(tree.body), var); 1768 checkInit(TreeInfo.diagEndPos(tree.body), var);
1760 } 1769 }
1761 } 1770 }
1762 } 1771 }
1763 } 1772 }
1764 List<AssignPendingExit> exits = pendingExits.toList(); 1773 List<P> exits = pendingExits.toList();
1765 pendingExits = new ListBuffer<AssignPendingExit>(); 1774 pendingExits = new ListBuffer<>();
1766 while (exits.nonEmpty()) { 1775 while (exits.nonEmpty()) {
1767 AssignPendingExit exit = exits.head; 1776 P exit = exits.head;
1768 exits = exits.tail; 1777 exits = exits.tail;
1769 Assert.check(exit.tree.hasTag(RETURN), exit.tree); 1778 Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1770 if (isInitialConstructor) { 1779 if (isInitialConstructor) {
1771 inits.assign(exit.exit_inits); 1780 assignToInits(exit.tree, exit.exit_inits);
1772 for (int i = firstadr; i < nextadr; i++) 1781 for (int i = firstadr; i < nextadr; i++) {
1773 checkInit(exit.tree.pos(), vardecls[i].sym); 1782 checkInit(exit.tree.pos(), vardecls[i].sym);
1783 }
1774 } 1784 }
1775 } 1785 }
1776 } finally { 1786 } finally {
1777 inits.assign(initsPrev); 1787 assignToInits(tree, initsPrev);
1778 uninits.assign(uninitsPrev); 1788 uninits.assign(uninitsPrev);
1779 nextadr = nextadrPrev; 1789 nextadr = nextadrPrev;
1780 firstadr = firstadrPrev; 1790 firstadr = firstadrPrev;
1781 returnadr = returnadrPrev; 1791 returnadr = returnadrPrev;
1782 lint = lintPrev; 1792 }
1783 } 1793 }
1794
1795 protected void initParam(JCVariableDecl def) {
1796 inits.incl(def.sym.adr);
1797 uninits.excl(def.sym.adr);
1784 } 1798 }
1785 1799
1786 public void visitVarDef(JCVariableDecl tree) { 1800 public void visitVarDef(JCVariableDecl tree) {
1787 boolean track = trackable(tree.sym); 1801 boolean track = trackable(tree.sym);
1788 if (track && tree.sym.owner.kind == MTH) newVar(tree); 1802 if (track && tree.sym.owner.kind == MTH) {
1803 newVar(tree);
1804 }
1789 if (tree.init != null) { 1805 if (tree.init != null) {
1790 Lint lintPrev = lint; 1806 scanExpr(tree.init);
1791 lint = lint.augment(tree.sym); 1807 if (track) {
1792 try{ 1808 letInit(tree.pos(), tree.sym);
1793 scanExpr(tree.init);
1794 if (track) letInit(tree.pos(), tree.sym);
1795 } finally {
1796 lint = lintPrev;
1797 } 1809 }
1798 } 1810 }
1799 } 1811 }
1800 1812
1801 public void visitBlock(JCBlock tree) { 1813 public void visitBlock(JCBlock tree) {
1802 int nextadrPrev = nextadr; 1814 int nextadrPrev = nextadr;
1803 scan(tree.stats); 1815 scan(tree.stats);
1804 nextadr = nextadrPrev; 1816 nextadr = nextadrPrev;
1805 } 1817 }
1806 1818
1819 int getLogNumberOfErrors() {
1820 return 0;
1821 }
1822
1807 public void visitDoLoop(JCDoWhileLoop tree) { 1823 public void visitDoLoop(JCDoWhileLoop tree) {
1808 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1824 ListBuffer<P> prevPendingExits = pendingExits;
1809 FlowKind prevFlowKind = flowKind; 1825 FlowKind prevFlowKind = flowKind;
1810 flowKind = FlowKind.NORMAL; 1826 flowKind = FlowKind.NORMAL;
1811 final Bits initsSkip = new Bits(true); 1827 final Bits initsSkip = new Bits(true);
1812 final Bits uninitsSkip = new Bits(true); 1828 final Bits uninitsSkip = new Bits(true);
1813 pendingExits = new ListBuffer<AssignPendingExit>(); 1829 pendingExits = new ListBuffer<P>();
1814 int prevErrors = log.nerrors; 1830 int prevErrors = getLogNumberOfErrors();
1815 do { 1831 do {
1816 final Bits uninitsEntry = new Bits(uninits); 1832 final Bits uninitsEntry = new Bits(uninits);
1817 uninitsEntry.excludeFrom(nextadr); 1833 uninitsEntry.excludeFrom(nextadr);
1818 scan(tree.body); 1834 scan(tree.body);
1819 resolveContinues(tree); 1835 resolveContinues(tree);
1820 scanCond(tree.cond); 1836 scanCond(tree.cond);
1821 if (!flowKind.isFinal()) { 1837 if (!flowKind.isFinal()) {
1822 initsSkip.assign(initsWhenFalse); 1838 initsSkip.assign(initsWhenFalse);
1823 uninitsSkip.assign(uninitsWhenFalse); 1839 uninitsSkip.assign(uninitsWhenFalse);
1824 } 1840 }
1825 if (log.nerrors != prevErrors || 1841 if (getLogNumberOfErrors() != prevErrors ||
1826 flowKind.isFinal() || 1842 flowKind.isFinal() ||
1827 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) 1843 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
1828 break; 1844 break;
1829 inits.assign(initsWhenTrue); 1845 assignToInits(tree.cond, initsWhenTrue);
1830 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); 1846 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
1831 flowKind = FlowKind.SPECULATIVE_LOOP; 1847 flowKind = FlowKind.SPECULATIVE_LOOP;
1832 } while (true); 1848 } while (true);
1833 flowKind = prevFlowKind; 1849 flowKind = prevFlowKind;
1834 inits.assign(initsSkip); 1850 assignToInits(tree, initsSkip);
1835 uninits.assign(uninitsSkip); 1851 uninits.assign(uninitsSkip);
1836 resolveBreaks(tree, prevPendingExits); 1852 resolveBreaks(tree, prevPendingExits);
1837 } 1853 }
1838 1854
1839 public void visitWhileLoop(JCWhileLoop tree) { 1855 public void visitWhileLoop(JCWhileLoop tree) {
1840 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1856 ListBuffer<P> prevPendingExits = pendingExits;
1841 FlowKind prevFlowKind = flowKind; 1857 FlowKind prevFlowKind = flowKind;
1842 flowKind = FlowKind.NORMAL; 1858 flowKind = FlowKind.NORMAL;
1843 final Bits initsSkip = new Bits(true); 1859 final Bits initsSkip = new Bits(true);
1844 final Bits uninitsSkip = new Bits(true); 1860 final Bits uninitsSkip = new Bits(true);
1845 pendingExits = new ListBuffer<AssignPendingExit>(); 1861 pendingExits = new ListBuffer<>();
1846 int prevErrors = log.nerrors; 1862 int prevErrors = getLogNumberOfErrors();
1847 final Bits uninitsEntry = new Bits(uninits); 1863 final Bits uninitsEntry = new Bits(uninits);
1848 uninitsEntry.excludeFrom(nextadr); 1864 uninitsEntry.excludeFrom(nextadr);
1849 do { 1865 do {
1850 scanCond(tree.cond); 1866 scanCond(tree.cond);
1851 if (!flowKind.isFinal()) { 1867 if (!flowKind.isFinal()) {
1852 initsSkip.assign(initsWhenFalse) ; 1868 initsSkip.assign(initsWhenFalse) ;
1853 uninitsSkip.assign(uninitsWhenFalse); 1869 uninitsSkip.assign(uninitsWhenFalse);
1854 } 1870 }
1855 inits.assign(initsWhenTrue); 1871 assignToInits(tree, initsWhenTrue);
1856 uninits.assign(uninitsWhenTrue); 1872 uninits.assign(uninitsWhenTrue);
1857 scan(tree.body); 1873 scan(tree.body);
1858 resolveContinues(tree); 1874 resolveContinues(tree);
1859 if (log.nerrors != prevErrors || 1875 if (getLogNumberOfErrors() != prevErrors ||
1860 flowKind.isFinal() || 1876 flowKind.isFinal() ||
1861 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1877 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
1862 break; 1878 break;
1879 }
1863 uninits.assign(uninitsEntry.andSet(uninits)); 1880 uninits.assign(uninitsEntry.andSet(uninits));
1864 flowKind = FlowKind.SPECULATIVE_LOOP; 1881 flowKind = FlowKind.SPECULATIVE_LOOP;
1865 } while (true); 1882 } while (true);
1866 flowKind = prevFlowKind; 1883 flowKind = prevFlowKind;
1867 //a variable is DA/DU after the while statement, if it's DA/DU assuming the 1884 //a variable is DA/DU after the while statement, if it's DA/DU assuming the
1868 //branch is not taken AND if it's DA/DU before any break statement 1885 //branch is not taken AND if it's DA/DU before any break statement
1869 inits.assign(initsSkip); 1886 assignToInits(tree.body, initsSkip);
1870 uninits.assign(uninitsSkip); 1887 uninits.assign(uninitsSkip);
1871 resolveBreaks(tree, prevPendingExits); 1888 resolveBreaks(tree, prevPendingExits);
1872 } 1889 }
1873 1890
1874 public void visitForLoop(JCForLoop tree) { 1891 public void visitForLoop(JCForLoop tree) {
1875 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1892 ListBuffer<P> prevPendingExits = pendingExits;
1876 FlowKind prevFlowKind = flowKind; 1893 FlowKind prevFlowKind = flowKind;
1877 flowKind = FlowKind.NORMAL; 1894 flowKind = FlowKind.NORMAL;
1878 int nextadrPrev = nextadr; 1895 int nextadrPrev = nextadr;
1879 scan(tree.init); 1896 scan(tree.init);
1880 final Bits initsSkip = new Bits(true); 1897 final Bits initsSkip = new Bits(true);
1881 final Bits uninitsSkip = new Bits(true); 1898 final Bits uninitsSkip = new Bits(true);
1882 pendingExits = new ListBuffer<AssignPendingExit>(); 1899 pendingExits = new ListBuffer<P>();
1883 int prevErrors = log.nerrors; 1900 int prevErrors = getLogNumberOfErrors();
1884 do { 1901 do {
1885 final Bits uninitsEntry = new Bits(uninits); 1902 final Bits uninitsEntry = new Bits(uninits);
1886 uninitsEntry.excludeFrom(nextadr); 1903 uninitsEntry.excludeFrom(nextadr);
1887 if (tree.cond != null) { 1904 if (tree.cond != null) {
1888 scanCond(tree.cond); 1905 scanCond(tree.cond);
1889 if (!flowKind.isFinal()) { 1906 if (!flowKind.isFinal()) {
1890 initsSkip.assign(initsWhenFalse); 1907 initsSkip.assign(initsWhenFalse);
1891 uninitsSkip.assign(uninitsWhenFalse); 1908 uninitsSkip.assign(uninitsWhenFalse);
1892 } 1909 }
1893 inits.assign(initsWhenTrue); 1910 assignToInits(tree.body, initsWhenTrue);
1894 uninits.assign(uninitsWhenTrue); 1911 uninits.assign(uninitsWhenTrue);
1895 } else if (!flowKind.isFinal()) { 1912 } else if (!flowKind.isFinal()) {
1896 initsSkip.assign(inits); 1913 initsSkip.assign(inits);
1897 initsSkip.inclRange(firstadr, nextadr); 1914 initsSkip.inclRange(firstadr, nextadr);
1898 uninitsSkip.assign(uninits); 1915 uninitsSkip.assign(uninits);
1899 uninitsSkip.inclRange(firstadr, nextadr); 1916 uninitsSkip.inclRange(firstadr, nextadr);
1900 } 1917 }
1901 scan(tree.body); 1918 scan(tree.body);
1902 resolveContinues(tree); 1919 resolveContinues(tree);
1903 scan(tree.step); 1920 scan(tree.step);
1904 if (log.nerrors != prevErrors || 1921 if (getLogNumberOfErrors() != prevErrors ||
1905 flowKind.isFinal() || 1922 flowKind.isFinal() ||
1906 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1923 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1907 break; 1924 break;
1908 uninits.assign(uninitsEntry.andSet(uninits)); 1925 uninits.assign(uninitsEntry.andSet(uninits));
1909 flowKind = FlowKind.SPECULATIVE_LOOP; 1926 flowKind = FlowKind.SPECULATIVE_LOOP;
1910 } while (true); 1927 } while (true);
1911 flowKind = prevFlowKind; 1928 flowKind = prevFlowKind;
1912 //a variable is DA/DU after a for loop, if it's DA/DU assuming the 1929 //a variable is DA/DU after a for loop, if it's DA/DU assuming the
1913 //branch is not taken AND if it's DA/DU before any break statement 1930 //branch is not taken AND if it's DA/DU before any break statement
1914 inits.assign(initsSkip); 1931 assignToInits(tree.body, initsSkip);
1915 uninits.assign(uninitsSkip); 1932 uninits.assign(uninitsSkip);
1916 resolveBreaks(tree, prevPendingExits); 1933 resolveBreaks(tree, prevPendingExits);
1917 nextadr = nextadrPrev; 1934 nextadr = nextadrPrev;
1918 } 1935 }
1919 1936
1920 public void visitForeachLoop(JCEnhancedForLoop tree) { 1937 public void visitForeachLoop(JCEnhancedForLoop tree) {
1921 visitVarDef(tree.var); 1938 visitVarDef(tree.var);
1922 1939
1923 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1940 ListBuffer<P> prevPendingExits = pendingExits;
1924 FlowKind prevFlowKind = flowKind; 1941 FlowKind prevFlowKind = flowKind;
1925 flowKind = FlowKind.NORMAL; 1942 flowKind = FlowKind.NORMAL;
1926 int nextadrPrev = nextadr; 1943 int nextadrPrev = nextadr;
1927 scan(tree.expr); 1944 scan(tree.expr);
1928 final Bits initsStart = new Bits(inits); 1945 final Bits initsStart = new Bits(inits);
1929 final Bits uninitsStart = new Bits(uninits); 1946 final Bits uninitsStart = new Bits(uninits);
1930 1947
1931 letInit(tree.pos(), tree.var.sym); 1948 letInit(tree.pos(), tree.var.sym);
1932 pendingExits = new ListBuffer<AssignPendingExit>(); 1949 pendingExits = new ListBuffer<P>();
1933 int prevErrors = log.nerrors; 1950 int prevErrors = getLogNumberOfErrors();
1934 do { 1951 do {
1935 final Bits uninitsEntry = new Bits(uninits); 1952 final Bits uninitsEntry = new Bits(uninits);
1936 uninitsEntry.excludeFrom(nextadr); 1953 uninitsEntry.excludeFrom(nextadr);
1937 scan(tree.body); 1954 scan(tree.body);
1938 resolveContinues(tree); 1955 resolveContinues(tree);
1939 if (log.nerrors != prevErrors || 1956 if (getLogNumberOfErrors() != prevErrors ||
1940 flowKind.isFinal() || 1957 flowKind.isFinal() ||
1941 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1958 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1942 break; 1959 break;
1943 uninits.assign(uninitsEntry.andSet(uninits)); 1960 uninits.assign(uninitsEntry.andSet(uninits));
1944 flowKind = FlowKind.SPECULATIVE_LOOP; 1961 flowKind = FlowKind.SPECULATIVE_LOOP;
1945 } while (true); 1962 } while (true);
1946 flowKind = prevFlowKind; 1963 flowKind = prevFlowKind;
1947 inits.assign(initsStart); 1964 assignToInits(tree.body, initsStart);
1948 uninits.assign(uninitsStart.andSet(uninits)); 1965 uninits.assign(uninitsStart.andSet(uninits));
1949 resolveBreaks(tree, prevPendingExits); 1966 resolveBreaks(tree, prevPendingExits);
1950 nextadr = nextadrPrev; 1967 nextadr = nextadrPrev;
1951 } 1968 }
1952 1969
1953 public void visitLabelled(JCLabeledStatement tree) { 1970 public void visitLabelled(JCLabeledStatement tree) {
1954 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1971 ListBuffer<P> prevPendingExits = pendingExits;
1955 pendingExits = new ListBuffer<AssignPendingExit>(); 1972 pendingExits = new ListBuffer<P>();
1956 scan(tree.body); 1973 scan(tree.body);
1957 resolveBreaks(tree, prevPendingExits); 1974 resolveBreaks(tree, prevPendingExits);
1958 } 1975 }
1959 1976
1960 public void visitSwitch(JCSwitch tree) { 1977 public void visitSwitch(JCSwitch tree) {
1961 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1978 ListBuffer<P> prevPendingExits = pendingExits;
1962 pendingExits = new ListBuffer<AssignPendingExit>(); 1979 pendingExits = new ListBuffer<>();
1963 int nextadrPrev = nextadr; 1980 int nextadrPrev = nextadr;
1964 scanExpr(tree.selector); 1981 scanExpr(tree.selector);
1965 final Bits initsSwitch = new Bits(inits); 1982 final Bits initsSwitch = new Bits(inits);
1966 final Bits uninitsSwitch = new Bits(uninits); 1983 final Bits uninitsSwitch = new Bits(uninits);
1967 boolean hasDefault = false; 1984 boolean hasDefault = false;
1968 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1985 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
1969 inits.assign(initsSwitch); 1986 assignToInits(l.head, initsSwitch);
1970 uninits.assign(uninits.andSet(uninitsSwitch)); 1987 uninits.assign(uninits.andSet(uninitsSwitch));
1971 JCCase c = l.head; 1988 JCCase c = l.head;
1972 if (c.pat == null) 1989 if (c.pat == null) {
1973 hasDefault = true; 1990 hasDefault = true;
1974 else 1991 } else {
1975 scanExpr(c.pat); 1992 scanExpr(c.pat);
1993 }
1994 if (hasDefault) {
1995 assignToInits(null, initsSwitch);
1996 uninits.assign(uninits.andSet(uninitsSwitch));
1997 }
1976 scan(c.stats); 1998 scan(c.stats);
1977 addVars(c.stats, initsSwitch, uninitsSwitch); 1999 addVars(c.stats, initsSwitch, uninitsSwitch);
2000 if (!hasDefault) {
2001 assignToInits(l.head.stats.last(), initsSwitch);
2002 uninits.assign(uninits.andSet(uninitsSwitch));
2003 }
1978 // Warn about fall-through if lint switch fallthrough enabled. 2004 // Warn about fall-through if lint switch fallthrough enabled.
1979 } 2005 }
1980 if (!hasDefault) { 2006 if (!hasDefault) {
1981 inits.andSet(initsSwitch); 2007 andSetInits(null, initsSwitch);
1982 } 2008 }
1983 resolveBreaks(tree, prevPendingExits); 2009 resolveBreaks(tree, prevPendingExits);
1984 nextadr = nextadrPrev; 2010 nextadr = nextadrPrev;
1985 } 2011 }
1986 // where 2012 // where
1995 uninits.incl(adr); 2021 uninits.incl(adr);
1996 } 2022 }
1997 } 2023 }
1998 } 2024 }
1999 2025
2026 boolean isEnabled(Lint.LintCategory lc) {
2027 return false;
2028 }
2029
2030 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {}
2031
2000 public void visitTry(JCTry tree) { 2032 public void visitTry(JCTry tree) {
2001 ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb(); 2033 ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
2002 final Bits uninitsTryPrev = new Bits(uninitsTry); 2034 final Bits uninitsTryPrev = new Bits(uninitsTry);
2003 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 2035 ListBuffer<P> prevPendingExits = pendingExits;
2004 pendingExits = new ListBuffer<AssignPendingExit>(); 2036 pendingExits = new ListBuffer<>();
2005 final Bits initsTry = new Bits(inits); 2037 final Bits initsTry = new Bits(inits);
2006 uninitsTry.assign(uninits); 2038 uninitsTry.assign(uninits);
2007 for (JCTree resource : tree.resources) { 2039 for (JCTree resource : tree.resources) {
2008 if (resource instanceof JCVariableDecl) { 2040 if (resource instanceof JCVariableDecl) {
2009 JCVariableDecl vdecl = (JCVariableDecl) resource; 2041 JCVariableDecl vdecl = (JCVariableDecl) resource;
2021 final Bits initsEnd = new Bits(inits); 2053 final Bits initsEnd = new Bits(inits);
2022 final Bits uninitsEnd = new Bits(uninits); 2054 final Bits uninitsEnd = new Bits(uninits);
2023 int nextadrCatch = nextadr; 2055 int nextadrCatch = nextadr;
2024 2056
2025 if (!resourceVarDecls.isEmpty() && 2057 if (!resourceVarDecls.isEmpty() &&
2026 lint.isEnabled(Lint.LintCategory.TRY)) { 2058 isEnabled(Lint.LintCategory.TRY)) {
2027 for (JCVariableDecl resVar : resourceVarDecls) { 2059 for (JCVariableDecl resVar : resourceVarDecls) {
2028 if (unrefdResources.includes(resVar.sym)) { 2060 if (unrefdResources.includes(resVar.sym)) {
2029 log.warning(Lint.LintCategory.TRY, resVar.pos(), 2061 reportWarning(Lint.LintCategory.TRY, resVar.pos(),
2030 "try.resource.not.referenced", resVar.sym); 2062 "try.resource.not.referenced", resVar.sym);
2031 unrefdResources.remove(resVar.sym); 2063 unrefdResources.remove(resVar.sym);
2032 } 2064 }
2033 } 2065 }
2034 } 2066 }
2040 final Bits initsCatchPrev = new Bits(initsTry); 2072 final Bits initsCatchPrev = new Bits(initsTry);
2041 final Bits uninitsCatchPrev = new Bits(uninitsTry); 2073 final Bits uninitsCatchPrev = new Bits(uninitsTry);
2042 2074
2043 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 2075 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2044 JCVariableDecl param = l.head.param; 2076 JCVariableDecl param = l.head.param;
2045 inits.assign(initsCatchPrev); 2077 assignToInits(tree.body, initsCatchPrev);
2046 uninits.assign(uninitsCatchPrev); 2078 uninits.assign(uninitsCatchPrev);
2047 scan(param); 2079 scan(param);
2048 inits.incl(param.sym.adr); 2080 /* If this is a TWR and we are executing the code from Gen,
2049 uninits.excl(param.sym.adr); 2081 * then there can be synthetic variables, ignore them.
2082 */
2083 initParam(param);
2050 scan(l.head.body); 2084 scan(l.head.body);
2051 initsEnd.andSet(inits); 2085 initsEnd.andSet(inits);
2052 uninitsEnd.andSet(uninits); 2086 uninitsEnd.andSet(uninits);
2053 nextadr = nextadrCatch; 2087 nextadr = nextadrCatch;
2054 } 2088 }
2055 if (tree.finalizer != null) { 2089 if (tree.finalizer != null) {
2056 inits.assign(initsTry); 2090 assignToInits(tree.finalizer, initsTry);
2057 uninits.assign(uninitsTry); 2091 uninits.assign(uninitsTry);
2058 ListBuffer<AssignPendingExit> exits = pendingExits; 2092 ListBuffer<P> exits = pendingExits;
2059 pendingExits = prevPendingExits; 2093 pendingExits = prevPendingExits;
2060 scan(tree.finalizer); 2094 scan(tree.finalizer);
2061 if (!tree.finallyCanCompleteNormally) { 2095 if (!tree.finallyCanCompleteNormally) {
2062 // discard exits and exceptions from try and finally 2096 // discard exits and exceptions from try and finally
2063 } else { 2097 } else {
2064 uninits.andSet(uninitsEnd); 2098 uninits.andSet(uninitsEnd);
2065 // FIX: this doesn't preserve source order of exits in catch 2099 // FIX: this doesn't preserve source order of exits in catch
2066 // versus finally! 2100 // versus finally!
2067 while (exits.nonEmpty()) { 2101 while (exits.nonEmpty()) {
2068 AssignPendingExit exit = exits.next(); 2102 P exit = exits.next();
2069 if (exit.exit_inits != null) { 2103 if (exit.exit_inits != null) {
2070 exit.exit_inits.orSet(inits); 2104 exit.exit_inits.orSet(inits);
2071 exit.exit_uninits.andSet(uninits); 2105 exit.exit_uninits.andSet(uninits);
2072 } 2106 }
2073 pendingExits.append(exit); 2107 pendingExits.append(exit);
2074 } 2108 }
2075 inits.orSet(initsEnd); 2109 orSetInits(tree, initsEnd);
2076 } 2110 }
2077 } else { 2111 } else {
2078 inits.assign(initsEnd); 2112 assignToInits(tree, initsEnd);
2079 uninits.assign(uninitsEnd); 2113 uninits.assign(uninitsEnd);
2080 ListBuffer<AssignPendingExit> exits = pendingExits; 2114 ListBuffer<P> exits = pendingExits;
2081 pendingExits = prevPendingExits; 2115 pendingExits = prevPendingExits;
2082 while (exits.nonEmpty()) pendingExits.append(exits.next()); 2116 while (exits.nonEmpty()) pendingExits.append(exits.next());
2083 } 2117 }
2084 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 2118 uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2085 } 2119 }
2086 2120
2087 public void visitConditional(JCConditional tree) { 2121 public void visitConditional(JCConditional tree) {
2088 scanCond(tree.cond); 2122 scanCond(tree.cond);
2089 final Bits initsBeforeElse = new Bits(initsWhenFalse); 2123 final Bits initsBeforeElse = new Bits(initsWhenFalse);
2090 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 2124 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2091 inits.assign(initsWhenTrue); 2125 assignToInits(tree.cond, initsWhenTrue);
2092 uninits.assign(uninitsWhenTrue); 2126 uninits.assign(uninitsWhenTrue);
2093 if (tree.truepart.type.hasTag(BOOLEAN) && 2127 if (tree.truepart.type.hasTag(BOOLEAN) &&
2094 tree.falsepart.type.hasTag(BOOLEAN)) { 2128 tree.falsepart.type.hasTag(BOOLEAN)) {
2095 // if b and c are boolean valued, then 2129 // if b and c are boolean valued, then
2096 // v is (un)assigned after a?b:c when true iff 2130 // v is (un)assigned after a?b:c when true iff
2099 scanCond(tree.truepart); 2133 scanCond(tree.truepart);
2100 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); 2134 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
2101 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); 2135 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
2102 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); 2136 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
2103 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); 2137 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
2104 inits.assign(initsBeforeElse); 2138 assignToInits(tree.truepart, initsBeforeElse);
2105 uninits.assign(uninitsBeforeElse); 2139 uninits.assign(uninitsBeforeElse);
2106 scanCond(tree.falsepart); 2140 scanCond(tree.falsepart);
2107 initsWhenTrue.andSet(initsAfterThenWhenTrue); 2141 initsWhenTrue.andSet(initsAfterThenWhenTrue);
2108 initsWhenFalse.andSet(initsAfterThenWhenFalse); 2142 initsWhenFalse.andSet(initsAfterThenWhenFalse);
2109 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); 2143 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
2110 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); 2144 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
2111 } else { 2145 } else {
2112 scanExpr(tree.truepart); 2146 scanExpr(tree.truepart);
2113 final Bits initsAfterThen = new Bits(inits); 2147 final Bits initsAfterThen = new Bits(inits);
2114 final Bits uninitsAfterThen = new Bits(uninits); 2148 final Bits uninitsAfterThen = new Bits(uninits);
2115 inits.assign(initsBeforeElse); 2149 assignToInits(tree.truepart, initsBeforeElse);
2116 uninits.assign(uninitsBeforeElse); 2150 uninits.assign(uninitsBeforeElse);
2117 scanExpr(tree.falsepart); 2151 scanExpr(tree.falsepart);
2118 inits.andSet(initsAfterThen); 2152 andSetInits(tree.falsepart, initsAfterThen);
2119 uninits.andSet(uninitsAfterThen); 2153 uninits.andSet(uninitsAfterThen);
2120 } 2154 }
2121 } 2155 }
2122 2156
2123 public void visitIf(JCIf tree) { 2157 public void visitIf(JCIf tree) {
2124 scanCond(tree.cond); 2158 scanCond(tree.cond);
2125 final Bits initsBeforeElse = new Bits(initsWhenFalse); 2159 final Bits initsBeforeElse = new Bits(initsWhenFalse);
2126 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 2160 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2127 inits.assign(initsWhenTrue); 2161 assignToInits(tree.cond, initsWhenTrue);
2128 uninits.assign(uninitsWhenTrue); 2162 uninits.assign(uninitsWhenTrue);
2129 scan(tree.thenpart); 2163 scan(tree.thenpart);
2130 if (tree.elsepart != null) { 2164 if (tree.elsepart != null) {
2131 final Bits initsAfterThen = new Bits(inits); 2165 final Bits initsAfterThen = new Bits(inits);
2132 final Bits uninitsAfterThen = new Bits(uninits); 2166 final Bits uninitsAfterThen = new Bits(uninits);
2133 inits.assign(initsBeforeElse); 2167 assignToInits(tree.thenpart, initsBeforeElse);
2134 uninits.assign(uninitsBeforeElse); 2168 uninits.assign(uninitsBeforeElse);
2135 scan(tree.elsepart); 2169 scan(tree.elsepart);
2136 inits.andSet(initsAfterThen); 2170 andSetInits(tree.elsepart, initsAfterThen);
2137 uninits.andSet(uninitsAfterThen); 2171 uninits.andSet(uninitsAfterThen);
2138 } else { 2172 } else {
2139 inits.andSet(initsBeforeElse); 2173 andSetInits(tree.thenpart, initsBeforeElse);
2140 uninits.andSet(uninitsBeforeElse); 2174 uninits.andSet(uninitsBeforeElse);
2141 } 2175 }
2142 } 2176 }
2143 2177
2178 protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
2179 return null;
2180 }
2181
2182 @Override
2144 public void visitBreak(JCBreak tree) { 2183 public void visitBreak(JCBreak tree) {
2145 recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 2184 recordExit(tree, createNewPendingExit(tree, inits, uninits));
2146 } 2185 }
2147 2186
2187 @Override
2148 public void visitContinue(JCContinue tree) { 2188 public void visitContinue(JCContinue tree) {
2149 recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 2189 recordExit(tree, createNewPendingExit(tree, inits, uninits));
2150 } 2190 }
2151 2191
2192 @Override
2152 public void visitReturn(JCReturn tree) { 2193 public void visitReturn(JCReturn tree) {
2153 scanExpr(tree.expr); 2194 scanExpr(tree.expr);
2154 recordExit(tree, new AssignPendingExit(tree, inits, uninits)); 2195 recordExit(tree, createNewPendingExit(tree, inits, uninits));
2155 } 2196 }
2156 2197
2157 public void visitThrow(JCThrow tree) { 2198 public void visitThrow(JCThrow tree) {
2158 scanExpr(tree.expr); 2199 scanExpr(tree.expr);
2159 markDead(); 2200 markDead(tree.expr);
2160 } 2201 }
2161 2202
2162 public void visitApply(JCMethodInvocation tree) { 2203 public void visitApply(JCMethodInvocation tree) {
2163 scanExpr(tree.meth); 2204 scanExpr(tree.meth);
2164 scanExprs(tree.args); 2205 scanExprs(tree.args);
2173 @Override 2214 @Override
2174 public void visitLambda(JCLambda tree) { 2215 public void visitLambda(JCLambda tree) {
2175 final Bits prevUninits = new Bits(uninits); 2216 final Bits prevUninits = new Bits(uninits);
2176 final Bits prevInits = new Bits(inits); 2217 final Bits prevInits = new Bits(inits);
2177 int returnadrPrev = returnadr; 2218 int returnadrPrev = returnadr;
2178 ListBuffer<AssignPendingExit> prevPending = pendingExits; 2219 ListBuffer<P> prevPending = pendingExits;
2179 try { 2220 try {
2180 returnadr = nextadr; 2221 returnadr = nextadr;
2181 pendingExits = new ListBuffer<AssignPendingExit>(); 2222 pendingExits = new ListBuffer<P>();
2182 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 2223 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2183 JCVariableDecl def = l.head; 2224 JCVariableDecl def = l.head;
2184 scan(def); 2225 scan(def);
2185 inits.incl(def.sym.adr); 2226 inits.incl(def.sym.adr);
2186 uninits.excl(def.sym.adr); 2227 uninits.excl(def.sym.adr);
2192 } 2233 }
2193 } 2234 }
2194 finally { 2235 finally {
2195 returnadr = returnadrPrev; 2236 returnadr = returnadrPrev;
2196 uninits.assign(prevUninits); 2237 uninits.assign(prevUninits);
2197 inits.assign(prevInits); 2238 assignToInits(tree, prevInits);
2198 pendingExits = prevPending; 2239 pendingExits = prevPending;
2199 } 2240 }
2200 } 2241 }
2201 2242
2202 public void visitNewArray(JCNewArray tree) { 2243 public void visitNewArray(JCNewArray tree) {
2208 final Bits initsExit = new Bits(inits); 2249 final Bits initsExit = new Bits(inits);
2209 final Bits uninitsExit = new Bits(uninits); 2250 final Bits uninitsExit = new Bits(uninits);
2210 scanCond(tree.cond); 2251 scanCond(tree.cond);
2211 uninitsExit.andSet(uninitsWhenTrue); 2252 uninitsExit.andSet(uninitsWhenTrue);
2212 if (tree.detail != null) { 2253 if (tree.detail != null) {
2213 inits.assign(initsWhenFalse); 2254 assignToInits(tree, initsWhenFalse);
2214 uninits.assign(uninitsWhenFalse); 2255 uninits.assign(uninitsWhenFalse);
2215 scanExpr(tree.detail); 2256 scanExpr(tree.detail);
2216 } 2257 }
2217 inits.assign(initsExit); 2258 assignToInits(tree, initsExit);
2218 uninits.assign(uninitsExit); 2259 uninits.assign(uninitsExit);
2219 } 2260 }
2220 2261
2221 public void visitAssign(JCAssign tree) { 2262 public void visitAssign(JCAssign tree) {
2222 JCTree lhs = TreeInfo.skipParens(tree.lhs); 2263 JCTree lhs = TreeInfo.skipParens(tree.lhs);
2258 switch (tree.getTag()) { 2299 switch (tree.getTag()) {
2259 case AND: 2300 case AND:
2260 scanCond(tree.lhs); 2301 scanCond(tree.lhs);
2261 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); 2302 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2262 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); 2303 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2263 inits.assign(initsWhenTrue); 2304 assignToInits(tree.lhs, initsWhenTrue);
2264 uninits.assign(uninitsWhenTrue); 2305 uninits.assign(uninitsWhenTrue);
2265 scanCond(tree.rhs); 2306 scanCond(tree.rhs);
2266 initsWhenFalse.andSet(initsWhenFalseLeft); 2307 initsWhenFalse.andSet(initsWhenFalseLeft);
2267 uninitsWhenFalse.andSet(uninitsWhenFalseLeft); 2308 uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2268 break; 2309 break;
2269 case OR: 2310 case OR:
2270 scanCond(tree.lhs); 2311 scanCond(tree.lhs);
2271 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); 2312 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2272 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); 2313 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2273 inits.assign(initsWhenFalse); 2314 assignToInits(tree.lhs, initsWhenFalse);
2274 uninits.assign(uninitsWhenFalse); 2315 uninits.assign(uninitsWhenFalse);
2275 scanCond(tree.rhs); 2316 scanCond(tree.rhs);
2276 initsWhenTrue.andSet(initsWhenTrueLeft); 2317 initsWhenTrue.andSet(initsWhenTrueLeft);
2277 uninitsWhenTrue.andSet(uninitsWhenTrueLeft); 2318 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2278 break; 2319 break;
2306 * main method 2347 * main method
2307 *************************************************************************/ 2348 *************************************************************************/
2308 2349
2309 /** Perform definite assignment/unassignment analysis on a tree. 2350 /** Perform definite assignment/unassignment analysis on a tree.
2310 */ 2351 */
2311 public void analyzeTree(Env<AttrContext> env, TreeMaker make) { 2352 public void analyzeTree(Env<?> env) {
2312 analyzeTree(env, env.tree, make); 2353 analyzeTree(env, env.tree);
2313 } 2354 }
2314 2355
2315 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) { 2356 public void analyzeTree(Env<?> env, JCTree tree) {
2316 try { 2357 try {
2317 attrEnv = env;
2318 Flow.this.make = make;
2319 startPos = tree.pos().getStartPosition(); 2358 startPos = tree.pos().getStartPosition();
2320 2359
2321 if (vardecls == null) 2360 if (vardecls == null)
2322 vardecls = new JCVariableDecl[32]; 2361 vardecls = new JCVariableDecl[32];
2323 else 2362 else
2324 for (int i=0; i<vardecls.length; i++) 2363 for (int i=0; i<vardecls.length; i++)
2325 vardecls[i] = null; 2364 vardecls[i] = null;
2326 firstadr = 0; 2365 firstadr = 0;
2327 nextadr = 0; 2366 nextadr = 0;
2328 pendingExits = new ListBuffer<AssignPendingExit>(); 2367 pendingExits = new ListBuffer<>();
2329 this.classDef = null; 2368 this.classDef = null;
2330 unrefdResources = new Scope(env.enclClass.sym); 2369 unrefdResources = new Scope(env.enclClass.sym);
2331 scan(tree); 2370 scan(tree);
2332 } finally { 2371 } finally {
2333 // note that recursive invocations of this method fail hard 2372 // note that recursive invocations of this method fail hard
2334 startPos = -1; 2373 startPos = -1;
2335 resetBits(inits, uninits, uninitsTry, initsWhenTrue, 2374 resetBits(inits, uninits, uninitsTry, initsWhenTrue,
2336 initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); 2375 initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
2337 if (vardecls != null) for (int i=0; i<vardecls.length; i++) 2376 if (vardecls != null) {
2338 vardecls[i] = null; 2377 for (int i=0; i<vardecls.length; i++)
2378 vardecls[i] = null;
2379 }
2339 firstadr = 0; 2380 firstadr = 0;
2340 nextadr = 0; 2381 nextadr = 0;
2341 pendingExits = null; 2382 pendingExits = null;
2342 Flow.this.make = null;
2343 this.classDef = null; 2383 this.classDef = null;
2344 unrefdResources = null; 2384 unrefdResources = null;
2345 } 2385 }
2346 } 2386 }
2387 }
2388
2389 public static class AssignAnalyzer
2390 extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> {
2391
2392 Log log;
2393 Lint lint;
2394
2395 public static class AssignPendingExit
2396 extends AbstractAssignAnalyzer.AbstractAssignPendingExit {
2397
2398 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
2399 super(tree, inits, uninits);
2400 }
2401 }
2402
2403 public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) {
2404 super(new Bits(), syms, names);
2405 this.log = log;
2406 this.lint = lint;
2407 }
2408
2409 @Override
2410 protected AssignPendingExit createNewPendingExit(JCTree tree,
2411 Bits inits, Bits uninits) {
2412 return new AssignPendingExit(tree, inits, uninits);
2413 }
2414
2415 /** Record an initialization of a trackable variable.
2416 */
2417 @Override
2418 void letInit(DiagnosticPosition pos, VarSymbol sym) {
2419 if (sym.adr >= firstadr && trackable(sym)) {
2420 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
2421 if (!uninits.isMember(sym.adr)) {
2422 //assignment targeting an effectively final variable
2423 //makes the variable lose its status of effectively final
2424 //if the variable is _not_ definitively unassigned
2425 sym.flags_field &= ~EFFECTIVELY_FINAL;
2426 } else {
2427 uninit(sym);
2428 }
2429 }
2430 else if ((sym.flags() & FINAL) != 0) {
2431 if ((sym.flags() & PARAMETER) != 0) {
2432 if ((sym.flags() & UNION) != 0) { //multi-catch parameter
2433 log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
2434 }
2435 else {
2436 log.error(pos, "final.parameter.may.not.be.assigned",
2437 sym);
2438 }
2439 } else if (!uninits.isMember(sym.adr)) {
2440 log.error(pos, flowKind.errKey, sym);
2441 } else {
2442 uninit(sym);
2443 }
2444 }
2445 inits.incl(sym.adr);
2446 } else if ((sym.flags() & FINAL) != 0) {
2447 log.error(pos, "var.might.already.be.assigned", sym);
2448 }
2449 }
2450
2451 @Override
2452 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
2453 if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
2454 trackable(sym) &&
2455 !inits.isMember(sym.adr)) {
2456 log.error(pos, errkey, sym);
2457 inits.incl(sym.adr);
2458 }
2459 }
2460
2461 @Override
2462 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos,
2463 String key, Object ... args) {
2464 log.warning(lc, pos, key, args);
2465 }
2466
2467 @Override
2468 int getLogNumberOfErrors() {
2469 return log.nerrors;
2470 }
2471
2472 @Override
2473 boolean isEnabled(Lint.LintCategory lc) {
2474 return lint.isEnabled(lc);
2475 }
2476
2477 @Override
2478 public void visitClassDef(JCClassDecl tree) {
2479 if (tree.sym == null) {
2480 return;
2481 }
2482
2483 Lint lintPrev = lint;
2484 lint = lint.augment(tree.sym);
2485 try {
2486 super.visitClassDef(tree);
2487 } finally {
2488 lint = lintPrev;
2489 }
2490 }
2491
2492 @Override
2493 public void visitMethodDef(JCMethodDecl tree) {
2494 if (tree.body == null) {
2495 return;
2496 }
2497
2498 /* MemberEnter can generate synthetic methods ignore them
2499 */
2500 if ((tree.sym.flags() & SYNTHETIC) != 0) {
2501 return;
2502 }
2503
2504 Lint lintPrev = lint;
2505 lint = lint.augment(tree.sym);
2506 try {
2507 super.visitMethodDef(tree);
2508 } finally {
2509 lint = lintPrev;
2510 }
2511 }
2512
2513 @Override
2514 public void visitVarDef(JCVariableDecl tree) {
2515 if (tree.init == null) {
2516 super.visitVarDef(tree);
2517 } else {
2518 Lint lintPrev = lint;
2519 lint = lint.augment(tree.sym);
2520 try{
2521 super.visitVarDef(tree);
2522 } finally {
2523 lint = lintPrev;
2524 }
2525 }
2526 }
2527
2347 } 2528 }
2348 2529
2349 /** 2530 /**
2350 * This pass implements the last step of the dataflow analysis, namely 2531 * This pass implements the last step of the dataflow analysis, namely
2351 * the effectively-final analysis check. This checks that every local variable 2532 * the effectively-final analysis check. This checks that every local variable
2356 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> { 2537 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
2357 2538
2358 JCTree currentTree; //local class or lambda 2539 JCTree currentTree; //local class or lambda
2359 2540
2360 @Override 2541 @Override
2361 void markDead() { 2542 void markDead(JCTree tree) {
2362 //do nothing 2543 //do nothing
2363 } 2544 }
2364 2545
2365 @SuppressWarnings("fallthrough") 2546 @SuppressWarnings("fallthrough")
2366 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) { 2547 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {

mercurial