changeset 29054 | 310b8028d7df |
parent 27844 | 8b5d79870a2f |
child 31003 | c4c8cbd9b3b4 |
29053:5c1f1d6b40f6 | 29054:310b8028d7df |
---|---|
1 /* |
1 /* |
2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
351 |
351 |
352 PendingExit(JCTree tree) { |
352 PendingExit(JCTree tree) { |
353 this.tree = tree; |
353 this.tree = tree; |
354 } |
354 } |
355 |
355 |
356 void resolveJump(JCTree tree) { |
356 void resolveJump() { |
357 //do nothing |
357 //do nothing |
358 } |
358 } |
359 } |
359 } |
360 |
360 |
361 abstract void markDead(JCTree tree); |
361 abstract void markDead(); |
362 |
362 |
363 /** Record an outward transfer of control. */ |
363 /** Record an outward transfer of control. */ |
364 void recordExit(JCTree tree, P pe) { |
364 void recordExit(P pe) { |
365 pendingExits.append(pe); |
365 pendingExits.append(pe); |
366 markDead(tree); |
366 markDead(); |
367 } |
367 } |
368 |
368 |
369 /** Resolve all jumps of this statement. */ |
369 /** Resolve all jumps of this statement. */ |
370 private boolean resolveJump(JCTree tree, |
370 private boolean resolveJump(JCTree tree, |
371 ListBuffer<P> oldPendingExits, |
371 ListBuffer<P> oldPendingExits, |
375 pendingExits = oldPendingExits; |
375 pendingExits = oldPendingExits; |
376 for (; exits.nonEmpty(); exits = exits.tail) { |
376 for (; exits.nonEmpty(); exits = exits.tail) { |
377 P exit = exits.head; |
377 P exit = exits.head; |
378 if (exit.tree.hasTag(jk.treeTag) && |
378 if (exit.tree.hasTag(jk.treeTag) && |
379 jk.getTarget(exit.tree) == tree) { |
379 jk.getTarget(exit.tree) == tree) { |
380 exit.resolveJump(tree); |
380 exit.resolveJump(); |
381 resolved = true; |
381 resolved = true; |
382 } else { |
382 } else { |
383 pendingExits.append(exit); |
383 pendingExits.append(exit); |
384 } |
384 } |
385 } |
385 } |
422 * complete normally. |
422 * complete normally. |
423 */ |
423 */ |
424 private boolean alive; |
424 private boolean alive; |
425 |
425 |
426 @Override |
426 @Override |
427 void markDead(JCTree tree) { |
427 void markDead() { |
428 alive = false; |
428 alive = false; |
429 } |
429 } |
430 |
430 |
431 /************************************************************************* |
431 /************************************************************************* |
432 * Visitor methods for statements and definitions |
432 * Visitor methods for statements and definitions |
690 alive = true; |
690 alive = true; |
691 } |
691 } |
692 } |
692 } |
693 |
693 |
694 public void visitBreak(JCBreak tree) { |
694 public void visitBreak(JCBreak tree) { |
695 recordExit(tree, new PendingExit(tree)); |
695 recordExit(new PendingExit(tree)); |
696 } |
696 } |
697 |
697 |
698 public void visitContinue(JCContinue tree) { |
698 public void visitContinue(JCContinue tree) { |
699 recordExit(tree, new PendingExit(tree)); |
699 recordExit(new PendingExit(tree)); |
700 } |
700 } |
701 |
701 |
702 public void visitReturn(JCReturn tree) { |
702 public void visitReturn(JCReturn tree) { |
703 scan(tree.expr); |
703 scan(tree.expr); |
704 recordExit(tree, new PendingExit(tree)); |
704 recordExit(new PendingExit(tree)); |
705 } |
705 } |
706 |
706 |
707 public void visitThrow(JCThrow tree) { |
707 public void visitThrow(JCThrow tree) { |
708 scan(tree.expr); |
708 scan(tree.expr); |
709 markDead(tree); |
709 markDead(); |
710 } |
710 } |
711 |
711 |
712 public void visitApply(JCMethodInvocation tree) { |
712 public void visitApply(JCMethodInvocation tree) { |
713 scan(tree.meth); |
713 scan(tree.meth); |
714 scan(tree.args); |
714 scan(tree.args); |
801 this.thrown = thrown; |
801 this.thrown = thrown; |
802 } |
802 } |
803 } |
803 } |
804 |
804 |
805 @Override |
805 @Override |
806 void markDead(JCTree tree) { |
806 void markDead() { |
807 //do nothing |
807 //do nothing |
808 } |
808 } |
809 |
809 |
810 /*-------------------- Exceptions ----------------------*/ |
810 /*-------------------- Exceptions ----------------------*/ |
811 |
811 |
1199 return exc.tsym == syms.throwableType.tsym || |
1199 return exc.tsym == syms.throwableType.tsym || |
1200 exc.tsym == syms.exceptionType.tsym; |
1200 exc.tsym == syms.exceptionType.tsym; |
1201 } |
1201 } |
1202 |
1202 |
1203 public void visitBreak(JCBreak tree) { |
1203 public void visitBreak(JCBreak tree) { |
1204 recordExit(tree, new FlowPendingExit(tree, null)); |
1204 recordExit(new FlowPendingExit(tree, null)); |
1205 } |
1205 } |
1206 |
1206 |
1207 public void visitContinue(JCContinue tree) { |
1207 public void visitContinue(JCContinue tree) { |
1208 recordExit(tree, new FlowPendingExit(tree, null)); |
1208 recordExit(new FlowPendingExit(tree, null)); |
1209 } |
1209 } |
1210 |
1210 |
1211 public void visitReturn(JCReturn tree) { |
1211 public void visitReturn(JCReturn tree) { |
1212 scan(tree.expr); |
1212 scan(tree.expr); |
1213 recordExit(tree, new FlowPendingExit(tree, null)); |
1213 recordExit(new FlowPendingExit(tree, null)); |
1214 } |
1214 } |
1215 |
1215 |
1216 public void visitThrow(JCThrow tree) { |
1216 public void visitThrow(JCThrow tree) { |
1217 scan(tree.expr); |
1217 scan(tree.expr); |
1218 Symbol sym = TreeInfo.symbol(tree.expr); |
1218 Symbol sym = TreeInfo.symbol(tree.expr); |
1226 } |
1226 } |
1227 } |
1227 } |
1228 else { |
1228 else { |
1229 markThrown(tree, tree.expr.type); |
1229 markThrown(tree, tree.expr.type); |
1230 } |
1230 } |
1231 markDead(tree); |
1231 markDead(); |
1232 } |
1232 } |
1233 |
1233 |
1234 public void visitApply(JCMethodInvocation tree) { |
1234 public void visitApply(JCMethodInvocation tree) { |
1235 scan(tree.meth); |
1235 scan(tree.meth); |
1236 scan(tree.args); |
1236 scan(tree.args); |
1373 * which ensures that no final variable is assigned more than once. This visitor |
1373 * which ensures that no final variable is assigned more than once. This visitor |
1374 * depends on the results of the liveliness analyzer. This pass is also used to mark |
1374 * depends on the results of the liveliness analyzer. This pass is also used to mark |
1375 * effectively-final local variables/parameters. |
1375 * effectively-final local variables/parameters. |
1376 */ |
1376 */ |
1377 |
1377 |
1378 public abstract class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer<P>.AbstractAssignPendingExit> |
1378 public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> { |
1379 extends BaseAnalyzer<P> { |
|
1380 |
1379 |
1381 /** The set of definitely assigned variables. |
1380 /** The set of definitely assigned variables. |
1382 */ |
1381 */ |
1383 protected Bits inits; |
1382 final Bits inits; |
1384 |
1383 |
1385 /** The set of definitely unassigned variables. |
1384 /** The set of definitely unassigned variables. |
1386 */ |
1385 */ |
1387 final Bits uninits; |
1386 final Bits uninits; |
1388 |
1387 |
1426 |
1425 |
1427 /** The list of unreferenced automatic resources. |
1426 /** The list of unreferenced automatic resources. |
1428 */ |
1427 */ |
1429 WriteableScope unrefdResources; |
1428 WriteableScope unrefdResources; |
1430 |
1429 |
1431 /** Set when processing a loop body the second time for DU analysis. */ |
1430 /** Modified when processing a loop body the second time for DU analysis. */ |
1432 FlowKind flowKind = FlowKind.NORMAL; |
1431 FlowKind flowKind = FlowKind.NORMAL; |
1433 |
1432 |
1434 /** The starting position of the analysed tree */ |
1433 /** The starting position of the analyzed tree */ |
1435 int startPos; |
1434 int startPos; |
1436 |
1435 |
1437 public class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { |
1436 public class AssignPendingExit extends BaseAnalyzer.PendingExit { |
1438 |
1437 |
1439 final Bits inits; |
1438 final Bits inits; |
1440 final Bits uninits; |
1439 final Bits uninits; |
1441 final Bits exit_inits = new Bits(true); |
1440 final Bits exit_inits = new Bits(true); |
1442 final Bits exit_uninits = new Bits(true); |
1441 final Bits exit_uninits = new Bits(true); |
1443 |
1442 |
1444 public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { |
1443 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { |
1445 super(tree); |
1444 super(tree); |
1446 this.inits = inits; |
1445 this.inits = inits; |
1447 this.uninits = uninits; |
1446 this.uninits = uninits; |
1448 this.exit_inits.assign(inits); |
1447 this.exit_inits.assign(inits); |
1449 this.exit_uninits.assign(uninits); |
1448 this.exit_uninits.assign(uninits); |
1450 } |
1449 } |
1451 |
1450 |
1452 @Override |
1451 @Override |
1453 public void resolveJump(JCTree tree) { |
1452 public void resolveJump() { |
1454 inits.andSet(exit_inits); |
1453 inits.andSet(exit_inits); |
1455 uninits.andSet(exit_uninits); |
1454 uninits.andSet(exit_uninits); |
1456 } |
1455 } |
1457 } |
1456 } |
1458 |
1457 |
1459 public AbstractAssignAnalyzer() { |
1458 public AssignAnalyzer() { |
1460 this.inits = new Bits(); |
1459 this.inits = new Bits(); |
1461 uninits = new Bits(); |
1460 uninits = new Bits(); |
1462 uninitsTry = new Bits(); |
1461 uninitsTry = new Bits(); |
1463 initsWhenTrue = new Bits(true); |
1462 initsWhenTrue = new Bits(true); |
1464 initsWhenFalse = new Bits(true); |
1463 initsWhenFalse = new Bits(true); |
1467 } |
1466 } |
1468 |
1467 |
1469 private boolean isInitialConstructor = false; |
1468 private boolean isInitialConstructor = false; |
1470 |
1469 |
1471 @Override |
1470 @Override |
1472 protected void markDead(JCTree tree) { |
1471 protected void markDead() { |
1473 if (!isInitialConstructor) { |
1472 if (!isInitialConstructor) { |
1474 inits.inclRange(returnadr, nextadr); |
1473 inits.inclRange(returnadr, nextadr); |
1475 } else { |
1474 } else { |
1476 for (int address = returnadr; address < nextadr; address++) { |
1475 for (int address = returnadr; address < nextadr; address++) { |
1477 if (!(isFinalUninitializedStaticField(vardecls[address].sym))) { |
1476 if (!(isFinalUninitializedStaticField(vardecls[address].sym))) { |
1514 if ((sym.flags() & FINAL) == 0) { |
1513 if ((sym.flags() & FINAL) == 0) { |
1515 sym.flags_field |= EFFECTIVELY_FINAL; |
1514 sym.flags_field |= EFFECTIVELY_FINAL; |
1516 } |
1515 } |
1517 sym.adr = nextadr; |
1516 sym.adr = nextadr; |
1518 vardecls[nextadr] = varDecl; |
1517 vardecls[nextadr] = varDecl; |
1519 exclVarFromInits(varDecl, nextadr); |
1518 inits.excl(nextadr); |
1520 uninits.incl(nextadr); |
1519 uninits.incl(nextadr); |
1521 nextadr++; |
1520 nextadr++; |
1522 } |
1521 } |
1523 |
1522 |
1524 protected void exclVarFromInits(JCTree tree, int adr) { |
|
1525 inits.excl(adr); |
|
1526 } |
|
1527 |
|
1528 protected void assignToInits(JCTree tree, Bits bits) { |
|
1529 inits.assign(bits); |
|
1530 } |
|
1531 |
|
1532 protected void andSetInits(JCTree tree, Bits bits) { |
|
1533 inits.andSet(bits); |
|
1534 } |
|
1535 |
|
1536 protected void orSetInits(JCTree tree, Bits bits) { |
|
1537 inits.orSet(bits); |
|
1538 } |
|
1539 |
|
1540 /** Record an initialization of a trackable variable. |
1523 /** Record an initialization of a trackable variable. |
1541 */ |
1524 */ |
1542 void letInit(DiagnosticPosition pos, VarSymbol sym) { |
1525 void letInit(DiagnosticPosition pos, VarSymbol sym) { |
1543 if (sym.adr >= firstadr && trackable(sym)) { |
1526 if (sym.adr >= firstadr && trackable(sym)) { |
1544 if (uninits.isMember(sym.adr)) { |
1527 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { |
1545 uninit(sym); |
1528 if (!uninits.isMember(sym.adr)) { |
1529 //assignment targeting an effectively final variable |
|
1530 //makes the variable lose its status of effectively final |
|
1531 //if the variable is _not_ definitively unassigned |
|
1532 sym.flags_field &= ~EFFECTIVELY_FINAL; |
|
1533 } else { |
|
1534 uninit(sym); |
|
1535 } |
|
1536 } |
|
1537 else if ((sym.flags() & FINAL) != 0) { |
|
1538 if ((sym.flags() & PARAMETER) != 0) { |
|
1539 if ((sym.flags() & UNION) != 0) { //multi-catch parameter |
|
1540 log.error(pos, "multicatch.parameter.may.not.be.assigned", sym); |
|
1541 } |
|
1542 else { |
|
1543 log.error(pos, "final.parameter.may.not.be.assigned", |
|
1544 sym); |
|
1545 } |
|
1546 } else if (!uninits.isMember(sym.adr)) { |
|
1547 log.error(pos, flowKind.errKey, sym); |
|
1548 } else { |
|
1549 uninit(sym); |
|
1550 } |
|
1546 } |
1551 } |
1547 inits.incl(sym.adr); |
1552 inits.incl(sym.adr); |
1553 } else if ((sym.flags() & FINAL) != 0) { |
|
1554 log.error(pos, "var.might.already.be.assigned", sym); |
|
1548 } |
1555 } |
1549 } |
1556 } |
1550 //where |
1557 //where |
1551 void uninit(VarSymbol sym) { |
1558 void uninit(VarSymbol sym) { |
1552 if (!inits.isMember(sym.adr)) { |
1559 if (!inits.isMember(sym.adr)) { |
1577 */ |
1584 */ |
1578 void checkInit(DiagnosticPosition pos, VarSymbol sym) { |
1585 void checkInit(DiagnosticPosition pos, VarSymbol sym) { |
1579 checkInit(pos, sym, "var.might.not.have.been.initialized"); |
1586 checkInit(pos, sym, "var.might.not.have.been.initialized"); |
1580 } |
1587 } |
1581 |
1588 |
1582 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {} |
1589 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { |
1590 if ((sym.adr >= firstadr || sym.owner.kind != TYP) && |
|
1591 trackable(sym) && |
|
1592 !inits.isMember(sym.adr)) { |
|
1593 log.error(pos, errkey, sym); |
|
1594 inits.incl(sym.adr); |
|
1595 } |
|
1596 } |
|
1583 |
1597 |
1584 /** Utility method to reset several Bits instances. |
1598 /** Utility method to reset several Bits instances. |
1585 */ |
1599 */ |
1586 private void resetBits(Bits... bits) { |
1600 private void resetBits(Bits... bits) { |
1587 for (Bits b : bits) { |
1601 for (Bits b : bits) { |
1601 } |
1615 } |
1602 } |
1616 } |
1603 |
1617 |
1604 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. |
1618 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. |
1605 */ |
1619 */ |
1606 protected void merge(JCTree tree) { |
1620 protected void merge() { |
1607 inits.assign(initsWhenFalse.andSet(initsWhenTrue)); |
1621 inits.assign(initsWhenFalse.andSet(initsWhenTrue)); |
1608 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); |
1622 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); |
1609 } |
1623 } |
1610 |
1624 |
1611 /* ************************************************************************ |
1625 /* ************************************************************************ |
1617 */ |
1631 */ |
1618 void scanExpr(JCTree tree) { |
1632 void scanExpr(JCTree tree) { |
1619 if (tree != null) { |
1633 if (tree != null) { |
1620 scan(tree); |
1634 scan(tree); |
1621 if (inits.isReset()) { |
1635 if (inits.isReset()) { |
1622 merge(tree); |
1636 merge(); |
1623 } |
1637 } |
1624 } |
1638 } |
1625 } |
1639 } |
1626 |
1640 |
1627 /** Analyze a list of expressions. |
1641 /** Analyze a list of expressions. |
1635 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) |
1649 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) |
1636 * rather than (un)inits on exit. |
1650 * rather than (un)inits on exit. |
1637 */ |
1651 */ |
1638 void scanCond(JCTree tree) { |
1652 void scanCond(JCTree tree) { |
1639 if (tree.type.isFalse()) { |
1653 if (tree.type.isFalse()) { |
1640 if (inits.isReset()) merge(tree); |
1654 if (inits.isReset()) merge(); |
1641 initsWhenTrue.assign(inits); |
1655 initsWhenTrue.assign(inits); |
1642 initsWhenTrue.inclRange(firstadr, nextadr); |
1656 initsWhenTrue.inclRange(firstadr, nextadr); |
1643 uninitsWhenTrue.assign(uninits); |
1657 uninitsWhenTrue.assign(uninits); |
1644 uninitsWhenTrue.inclRange(firstadr, nextadr); |
1658 uninitsWhenTrue.inclRange(firstadr, nextadr); |
1645 initsWhenFalse.assign(inits); |
1659 initsWhenFalse.assign(inits); |
1646 uninitsWhenFalse.assign(uninits); |
1660 uninitsWhenFalse.assign(uninits); |
1647 } else if (tree.type.isTrue()) { |
1661 } else if (tree.type.isTrue()) { |
1648 if (inits.isReset()) merge(tree); |
1662 if (inits.isReset()) merge(); |
1649 initsWhenFalse.assign(inits); |
1663 initsWhenFalse.assign(inits); |
1650 initsWhenFalse.inclRange(firstadr, nextadr); |
1664 initsWhenFalse.inclRange(firstadr, nextadr); |
1651 uninitsWhenFalse.assign(uninits); |
1665 uninitsWhenFalse.assign(uninits); |
1652 uninitsWhenFalse.inclRange(firstadr, nextadr); |
1666 uninitsWhenFalse.inclRange(firstadr, nextadr); |
1653 initsWhenTrue.assign(inits); |
1667 initsWhenTrue.assign(inits); |
1662 } |
1676 } |
1663 } |
1677 } |
1664 |
1678 |
1665 /* ------------ Visitor methods for various sorts of trees -------------*/ |
1679 /* ------------ Visitor methods for various sorts of trees -------------*/ |
1666 |
1680 |
1667 @Override |
|
1668 public void visitClassDef(JCClassDecl tree) { |
1681 public void visitClassDef(JCClassDecl tree) { |
1669 if (tree.sym == null) { |
1682 if (tree.sym == null) { |
1670 return; |
1683 return; |
1671 } |
1684 } |
1672 |
1685 |
1673 JCClassDecl classDefPrev = classDef; |
1686 Lint lintPrev = lint; |
1674 int firstadrPrev = firstadr; |
1687 lint = lint.augment(tree.sym); |
1675 int nextadrPrev = nextadr; |
|
1676 ListBuffer<P> pendingExitsPrev = pendingExits; |
|
1677 |
|
1678 pendingExits = new ListBuffer<>(); |
|
1679 if (tree.name != names.empty) { |
|
1680 firstadr = nextadr; |
|
1681 } |
|
1682 classDef = tree; |
|
1683 try { |
1688 try { |
1684 // define all the static fields |
1689 if (tree.sym == null) { |
1685 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1690 return; |
1686 if (l.head.hasTag(VARDEF)) { |
1691 } |
1687 JCVariableDecl def = (JCVariableDecl)l.head; |
1692 |
1688 if ((def.mods.flags & STATIC) != 0) { |
1693 JCClassDecl classDefPrev = classDef; |
1689 VarSymbol sym = def.sym; |
1694 int firstadrPrev = firstadr; |
1690 if (trackable(sym)) { |
1695 int nextadrPrev = nextadr; |
1691 newVar(def); |
1696 ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits; |
1697 |
|
1698 pendingExits = new ListBuffer<>(); |
|
1699 if (tree.name != names.empty) { |
|
1700 firstadr = nextadr; |
|
1701 } |
|
1702 classDef = tree; |
|
1703 try { |
|
1704 // define all the static fields |
|
1705 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
|
1706 if (l.head.hasTag(VARDEF)) { |
|
1707 JCVariableDecl def = (JCVariableDecl)l.head; |
|
1708 if ((def.mods.flags & STATIC) != 0) { |
|
1709 VarSymbol sym = def.sym; |
|
1710 if (trackable(sym)) { |
|
1711 newVar(def); |
|
1712 } |
|
1692 } |
1713 } |
1693 } |
1714 } |
1694 } |
1715 } |
1695 } |
1716 |
1696 |
1717 // process all the static initializers |
1697 // process all the static initializers |
1718 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1698 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1719 if (!l.head.hasTag(METHODDEF) && |
1699 if (!l.head.hasTag(METHODDEF) && |
1720 (TreeInfo.flags(l.head) & STATIC) != 0) { |
1700 (TreeInfo.flags(l.head) & STATIC) != 0) { |
1721 scan(l.head); |
1701 scan(l.head); |
1722 } |
1702 } |
1723 } |
1703 } |
1724 |
1704 |
1725 // define all the instance fields |
1705 // define all the instance fields |
1726 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1706 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1727 if (l.head.hasTag(VARDEF)) { |
1707 if (l.head.hasTag(VARDEF)) { |
1728 JCVariableDecl def = (JCVariableDecl)l.head; |
1708 JCVariableDecl def = (JCVariableDecl)l.head; |
1729 if ((def.mods.flags & STATIC) == 0) { |
1709 if ((def.mods.flags & STATIC) == 0) { |
1730 VarSymbol sym = def.sym; |
1710 VarSymbol sym = def.sym; |
1731 if (trackable(sym)) { |
1711 if (trackable(sym)) { |
1732 newVar(def); |
1712 newVar(def); |
1733 } |
1713 } |
1734 } |
1714 } |
1735 } |
1715 } |
1736 } |
1716 } |
1737 |
1717 |
1738 // process all the instance initializers |
1718 // process all the instance initializers |
1739 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1719 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1740 if (!l.head.hasTag(METHODDEF) && |
1720 if (!l.head.hasTag(METHODDEF) && |
1741 (TreeInfo.flags(l.head) & STATIC) == 0) { |
1721 (TreeInfo.flags(l.head) & STATIC) == 0) { |
1742 scan(l.head); |
1722 scan(l.head); |
1743 } |
1723 } |
1744 } |
1724 } |
1745 |
1725 |
1746 // process all the methods |
1726 // process all the methods |
1747 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1727 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { |
1748 if (l.head.hasTag(METHODDEF)) { |
1728 if (l.head.hasTag(METHODDEF)) { |
1749 scan(l.head); |
1729 scan(l.head); |
1750 } |
1730 } |
1751 } |
1752 } finally { |
|
1753 pendingExits = pendingExitsPrev; |
|
1754 nextadr = nextadrPrev; |
|
1755 firstadr = firstadrPrev; |
|
1756 classDef = classDefPrev; |
|
1731 } |
1757 } |
1732 } finally { |
1758 } finally { |
1733 pendingExits = pendingExitsPrev; |
1759 lint = lintPrev; |
1734 nextadr = nextadrPrev; |
1760 } |
1735 firstadr = firstadrPrev; |
1761 } |
1736 classDef = classDefPrev; |
1762 |
1737 } |
|
1738 } |
|
1739 |
|
1740 @Override |
|
1741 public void visitMethodDef(JCMethodDecl tree) { |
1763 public void visitMethodDef(JCMethodDecl tree) { |
1742 if (tree.body == null) { |
1764 if (tree.body == null) { |
1743 return; |
1765 return; |
1744 } |
1766 } |
1745 /* Ignore synthetic methods, except for translated lambda methods. |
1767 |
1768 /* MemberEnter can generate synthetic methods ignore them |
|
1746 */ |
1769 */ |
1747 if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) { |
1770 if ((tree.sym.flags() & SYNTHETIC) != 0) { |
1748 return; |
1771 return; |
1749 } |
1772 } |
1750 |
1773 |
1751 final Bits initsPrev = new Bits(inits); |
1774 Lint lintPrev = lint; |
1752 final Bits uninitsPrev = new Bits(uninits); |
1775 lint = lint.augment(tree.sym); |
1753 int nextadrPrev = nextadr; |
|
1754 int firstadrPrev = firstadr; |
|
1755 int returnadrPrev = returnadr; |
|
1756 |
|
1757 Assert.check(pendingExits.isEmpty()); |
|
1758 boolean lastInitialConstructor = isInitialConstructor; |
|
1759 try { |
1776 try { |
1760 isInitialConstructor = TreeInfo.isInitialConstructor(tree); |
1777 if (tree.body == null) { |
1761 |
1778 return; |
1762 if (!isInitialConstructor) { |
1779 } |
1763 firstadr = nextadr; |
1780 /* Ignore synthetic methods, except for translated lambda methods. |
1764 } |
1781 */ |
1765 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { |
1782 if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) { |
1766 JCVariableDecl def = l.head; |
1783 return; |
1767 scan(def); |
1784 } |
1768 Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag"); |
1785 |
1769 /* If we are executing the code from Gen, then there can be |
1786 final Bits initsPrev = new Bits(inits); |
1770 * synthetic or mandated variables, ignore them. |
1787 final Bits uninitsPrev = new Bits(uninits); |
1771 */ |
1788 int nextadrPrev = nextadr; |
1772 initParam(def); |
1789 int firstadrPrev = firstadr; |
1773 } |
1790 int returnadrPrev = returnadr; |
1774 // else we are in an instance initializer block; |
1791 |
1775 // leave caught unchanged. |
1792 Assert.check(pendingExits.isEmpty()); |
1776 scan(tree.body); |
1793 boolean lastInitialConstructor = isInitialConstructor; |
1777 |
1794 try { |
1778 if (isInitialConstructor) { |
1795 isInitialConstructor = TreeInfo.isInitialConstructor(tree); |
1779 boolean isSynthesized = (tree.sym.flags() & |
1796 |
1780 GENERATEDCONSTR) != 0; |
1797 if (!isInitialConstructor) { |
1781 for (int i = firstadr; i < nextadr; i++) { |
1798 firstadr = nextadr; |
1782 JCVariableDecl vardecl = vardecls[i]; |
1799 } |
1783 VarSymbol var = vardecl.sym; |
1800 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { |
1784 if (var.owner == classDef.sym) { |
1801 JCVariableDecl def = l.head; |
1785 // choose the diagnostic position based on whether |
1802 scan(def); |
1786 // the ctor is default(synthesized) or not |
1803 Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag"); |
1787 if (isSynthesized) { |
1804 /* If we are executing the code from Gen, then there can be |
1788 checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), |
1805 * synthetic or mandated variables, ignore them. |
1789 var, "var.not.initialized.in.default.constructor"); |
1806 */ |
1790 } else { |
1807 initParam(def); |
1791 checkInit(TreeInfo.diagEndPos(tree.body), var); |
1808 } |
1809 // else we are in an instance initializer block; |
|
1810 // leave caught unchanged. |
|
1811 scan(tree.body); |
|
1812 |
|
1813 if (isInitialConstructor) { |
|
1814 boolean isSynthesized = (tree.sym.flags() & |
|
1815 GENERATEDCONSTR) != 0; |
|
1816 for (int i = firstadr; i < nextadr; i++) { |
|
1817 JCVariableDecl vardecl = vardecls[i]; |
|
1818 VarSymbol var = vardecl.sym; |
|
1819 if (var.owner == classDef.sym) { |
|
1820 // choose the diagnostic position based on whether |
|
1821 // the ctor is default(synthesized) or not |
|
1822 if (isSynthesized) { |
|
1823 checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), |
|
1824 var, "var.not.initialized.in.default.constructor"); |
|
1825 } else { |
|
1826 checkInit(TreeInfo.diagEndPos(tree.body), var); |
|
1827 } |
|
1792 } |
1828 } |
1793 } |
1829 } |
1794 } |
1830 } |
1795 } |
1831 List<AssignPendingExit> exits = pendingExits.toList(); |
1796 List<P> exits = pendingExits.toList(); |
1832 pendingExits = new ListBuffer<>(); |
1797 pendingExits = new ListBuffer<>(); |
1833 while (exits.nonEmpty()) { |
1798 while (exits.nonEmpty()) { |
1834 AssignPendingExit exit = exits.head; |
1799 P exit = exits.head; |
1835 exits = exits.tail; |
1800 exits = exits.tail; |
1836 Assert.check(exit.tree.hasTag(RETURN), exit.tree); |
1801 Assert.check(exit.tree.hasTag(RETURN), exit.tree); |
1837 if (isInitialConstructor) { |
1802 if (isInitialConstructor) { |
1838 inits.assign(exit.exit_inits); |
1803 assignToInits(exit.tree, exit.exit_inits); |
1839 for (int i = firstadr; i < nextadr; i++) { |
1804 for (int i = firstadr; i < nextadr; i++) { |
1840 checkInit(exit.tree.pos(), vardecls[i].sym); |
1805 checkInit(exit.tree.pos(), vardecls[i].sym); |
1841 } |
1806 } |
1842 } |
1807 } |
1843 } |
1844 } finally { |
|
1845 inits.assign(initsPrev); |
|
1846 uninits.assign(uninitsPrev); |
|
1847 nextadr = nextadrPrev; |
|
1848 firstadr = firstadrPrev; |
|
1849 returnadr = returnadrPrev; |
|
1850 isInitialConstructor = lastInitialConstructor; |
|
1808 } |
1851 } |
1809 } finally { |
1852 } finally { |
1810 assignToInits(tree, initsPrev); |
1853 lint = lintPrev; |
1811 uninits.assign(uninitsPrev); |
|
1812 nextadr = nextadrPrev; |
|
1813 firstadr = firstadrPrev; |
|
1814 returnadr = returnadrPrev; |
|
1815 isInitialConstructor = lastInitialConstructor; |
|
1816 } |
1854 } |
1817 } |
1855 } |
1818 |
1856 |
1819 protected void initParam(JCVariableDecl def) { |
1857 protected void initParam(JCVariableDecl def) { |
1820 inits.incl(def.sym.adr); |
1858 inits.incl(def.sym.adr); |
1821 uninits.excl(def.sym.adr); |
1859 uninits.excl(def.sym.adr); |
1822 } |
1860 } |
1823 |
1861 |
1824 public void visitVarDef(JCVariableDecl tree) { |
1862 public void visitVarDef(JCVariableDecl tree) { |
1825 boolean track = trackable(tree.sym); |
1863 Lint lintPrev = lint; |
1826 if (track && tree.sym.owner.kind == MTH) { |
1864 lint = lint.augment(tree.sym); |
1827 newVar(tree); |
1865 try{ |
1828 } |
1866 boolean track = trackable(tree.sym); |
1829 if (tree.init != null) { |
1867 if (track && tree.sym.owner.kind == MTH) { |
1830 scanExpr(tree.init); |
1868 newVar(tree); |
1831 if (track) { |
1869 } |
1832 letInit(tree.pos(), tree.sym); |
1870 if (tree.init != null) { |
1833 } |
1871 scanExpr(tree.init); |
1872 if (track) { |
|
1873 letInit(tree.pos(), tree.sym); |
|
1874 } |
|
1875 } |
|
1876 } finally { |
|
1877 lint = lintPrev; |
|
1834 } |
1878 } |
1835 } |
1879 } |
1836 |
1880 |
1837 public void visitBlock(JCBlock tree) { |
1881 public void visitBlock(JCBlock tree) { |
1838 int nextadrPrev = nextadr; |
1882 int nextadrPrev = nextadr; |
1839 scan(tree.stats); |
1883 scan(tree.stats); |
1840 nextadr = nextadrPrev; |
1884 nextadr = nextadrPrev; |
1841 } |
1885 } |
1842 |
1886 |
1843 int getLogNumberOfErrors() { |
|
1844 return 0; |
|
1845 } |
|
1846 |
|
1847 public void visitDoLoop(JCDoWhileLoop tree) { |
1887 public void visitDoLoop(JCDoWhileLoop tree) { |
1848 ListBuffer<P> prevPendingExits = pendingExits; |
1888 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
1849 FlowKind prevFlowKind = flowKind; |
1889 FlowKind prevFlowKind = flowKind; |
1850 flowKind = FlowKind.NORMAL; |
1890 flowKind = FlowKind.NORMAL; |
1851 final Bits initsSkip = new Bits(true); |
1891 final Bits initsSkip = new Bits(true); |
1852 final Bits uninitsSkip = new Bits(true); |
1892 final Bits uninitsSkip = new Bits(true); |
1853 pendingExits = new ListBuffer<>(); |
1893 pendingExits = new ListBuffer<>(); |
1854 int prevErrors = getLogNumberOfErrors(); |
1894 int prevErrors = log.nerrors; |
1855 do { |
1895 do { |
1856 final Bits uninitsEntry = new Bits(uninits); |
1896 final Bits uninitsEntry = new Bits(uninits); |
1857 uninitsEntry.excludeFrom(nextadr); |
1897 uninitsEntry.excludeFrom(nextadr); |
1858 scan(tree.body); |
1898 scan(tree.body); |
1859 resolveContinues(tree); |
1899 resolveContinues(tree); |
1860 scanCond(tree.cond); |
1900 scanCond(tree.cond); |
1861 if (!flowKind.isFinal()) { |
1901 if (!flowKind.isFinal()) { |
1862 initsSkip.assign(initsWhenFalse); |
1902 initsSkip.assign(initsWhenFalse); |
1863 uninitsSkip.assign(uninitsWhenFalse); |
1903 uninitsSkip.assign(uninitsWhenFalse); |
1864 } |
1904 } |
1865 if (getLogNumberOfErrors() != prevErrors || |
1905 if (log.nerrors != prevErrors || |
1866 flowKind.isFinal() || |
1906 flowKind.isFinal() || |
1867 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) |
1907 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) |
1868 break; |
1908 break; |
1869 assignToInits(tree.cond, initsWhenTrue); |
1909 inits.assign(initsWhenTrue); |
1870 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); |
1910 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); |
1871 flowKind = FlowKind.SPECULATIVE_LOOP; |
1911 flowKind = FlowKind.SPECULATIVE_LOOP; |
1872 } while (true); |
1912 } while (true); |
1873 flowKind = prevFlowKind; |
1913 flowKind = prevFlowKind; |
1874 assignToInits(tree, initsSkip); |
1914 inits.assign(initsSkip); |
1875 uninits.assign(uninitsSkip); |
1915 uninits.assign(uninitsSkip); |
1876 resolveBreaks(tree, prevPendingExits); |
1916 resolveBreaks(tree, prevPendingExits); |
1877 } |
1917 } |
1878 |
1918 |
1879 public void visitWhileLoop(JCWhileLoop tree) { |
1919 public void visitWhileLoop(JCWhileLoop tree) { |
1880 ListBuffer<P> prevPendingExits = pendingExits; |
1920 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
1881 FlowKind prevFlowKind = flowKind; |
1921 FlowKind prevFlowKind = flowKind; |
1882 flowKind = FlowKind.NORMAL; |
1922 flowKind = FlowKind.NORMAL; |
1883 final Bits initsSkip = new Bits(true); |
1923 final Bits initsSkip = new Bits(true); |
1884 final Bits uninitsSkip = new Bits(true); |
1924 final Bits uninitsSkip = new Bits(true); |
1885 pendingExits = new ListBuffer<>(); |
1925 pendingExits = new ListBuffer<>(); |
1886 int prevErrors = getLogNumberOfErrors(); |
1926 int prevErrors = log.nerrors; |
1887 final Bits uninitsEntry = new Bits(uninits); |
1927 final Bits uninitsEntry = new Bits(uninits); |
1888 uninitsEntry.excludeFrom(nextadr); |
1928 uninitsEntry.excludeFrom(nextadr); |
1889 do { |
1929 do { |
1890 scanCond(tree.cond); |
1930 scanCond(tree.cond); |
1891 if (!flowKind.isFinal()) { |
1931 if (!flowKind.isFinal()) { |
1892 initsSkip.assign(initsWhenFalse) ; |
1932 initsSkip.assign(initsWhenFalse) ; |
1893 uninitsSkip.assign(uninitsWhenFalse); |
1933 uninitsSkip.assign(uninitsWhenFalse); |
1894 } |
1934 } |
1895 assignToInits(tree, initsWhenTrue); |
1935 inits.assign(initsWhenTrue); |
1896 uninits.assign(uninitsWhenTrue); |
1936 uninits.assign(uninitsWhenTrue); |
1897 scan(tree.body); |
1937 scan(tree.body); |
1898 resolveContinues(tree); |
1938 resolveContinues(tree); |
1899 if (getLogNumberOfErrors() != prevErrors || |
1939 if (log.nerrors != prevErrors || |
1900 flowKind.isFinal() || |
1940 flowKind.isFinal() || |
1901 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) { |
1941 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) { |
1902 break; |
1942 break; |
1903 } |
1943 } |
1904 uninits.assign(uninitsEntry.andSet(uninits)); |
1944 uninits.assign(uninitsEntry.andSet(uninits)); |
1905 flowKind = FlowKind.SPECULATIVE_LOOP; |
1945 flowKind = FlowKind.SPECULATIVE_LOOP; |
1906 } while (true); |
1946 } while (true); |
1907 flowKind = prevFlowKind; |
1947 flowKind = prevFlowKind; |
1908 //a variable is DA/DU after the while statement, if it's DA/DU assuming the |
1948 //a variable is DA/DU after the while statement, if it's DA/DU assuming the |
1909 //branch is not taken AND if it's DA/DU before any break statement |
1949 //branch is not taken AND if it's DA/DU before any break statement |
1910 assignToInits(tree.body, initsSkip); |
1950 inits.assign(initsSkip); |
1911 uninits.assign(uninitsSkip); |
1951 uninits.assign(uninitsSkip); |
1912 resolveBreaks(tree, prevPendingExits); |
1952 resolveBreaks(tree, prevPendingExits); |
1913 } |
1953 } |
1914 |
1954 |
1915 public void visitForLoop(JCForLoop tree) { |
1955 public void visitForLoop(JCForLoop tree) { |
1916 ListBuffer<P> prevPendingExits = pendingExits; |
1956 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
1917 FlowKind prevFlowKind = flowKind; |
1957 FlowKind prevFlowKind = flowKind; |
1918 flowKind = FlowKind.NORMAL; |
1958 flowKind = FlowKind.NORMAL; |
1919 int nextadrPrev = nextadr; |
1959 int nextadrPrev = nextadr; |
1920 scan(tree.init); |
1960 scan(tree.init); |
1921 final Bits initsSkip = new Bits(true); |
1961 final Bits initsSkip = new Bits(true); |
1922 final Bits uninitsSkip = new Bits(true); |
1962 final Bits uninitsSkip = new Bits(true); |
1923 pendingExits = new ListBuffer<>(); |
1963 pendingExits = new ListBuffer<>(); |
1924 int prevErrors = getLogNumberOfErrors(); |
1964 int prevErrors = log.nerrors; |
1925 do { |
1965 do { |
1926 final Bits uninitsEntry = new Bits(uninits); |
1966 final Bits uninitsEntry = new Bits(uninits); |
1927 uninitsEntry.excludeFrom(nextadr); |
1967 uninitsEntry.excludeFrom(nextadr); |
1928 if (tree.cond != null) { |
1968 if (tree.cond != null) { |
1929 scanCond(tree.cond); |
1969 scanCond(tree.cond); |
1930 if (!flowKind.isFinal()) { |
1970 if (!flowKind.isFinal()) { |
1931 initsSkip.assign(initsWhenFalse); |
1971 initsSkip.assign(initsWhenFalse); |
1932 uninitsSkip.assign(uninitsWhenFalse); |
1972 uninitsSkip.assign(uninitsWhenFalse); |
1933 } |
1973 } |
1934 assignToInits(tree.body, initsWhenTrue); |
1974 inits.assign(initsWhenTrue); |
1935 uninits.assign(uninitsWhenTrue); |
1975 uninits.assign(uninitsWhenTrue); |
1936 } else if (!flowKind.isFinal()) { |
1976 } else if (!flowKind.isFinal()) { |
1937 initsSkip.assign(inits); |
1977 initsSkip.assign(inits); |
1938 initsSkip.inclRange(firstadr, nextadr); |
1978 initsSkip.inclRange(firstadr, nextadr); |
1939 uninitsSkip.assign(uninits); |
1979 uninitsSkip.assign(uninits); |
1940 uninitsSkip.inclRange(firstadr, nextadr); |
1980 uninitsSkip.inclRange(firstadr, nextadr); |
1941 } |
1981 } |
1942 scan(tree.body); |
1982 scan(tree.body); |
1943 resolveContinues(tree); |
1983 resolveContinues(tree); |
1944 scan(tree.step); |
1984 scan(tree.step); |
1945 if (getLogNumberOfErrors() != prevErrors || |
1985 if (log.nerrors != prevErrors || |
1946 flowKind.isFinal() || |
1986 flowKind.isFinal() || |
1947 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) |
1987 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) |
1948 break; |
1988 break; |
1949 uninits.assign(uninitsEntry.andSet(uninits)); |
1989 uninits.assign(uninitsEntry.andSet(uninits)); |
1950 flowKind = FlowKind.SPECULATIVE_LOOP; |
1990 flowKind = FlowKind.SPECULATIVE_LOOP; |
1951 } while (true); |
1991 } while (true); |
1952 flowKind = prevFlowKind; |
1992 flowKind = prevFlowKind; |
1953 //a variable is DA/DU after a for loop, if it's DA/DU assuming the |
1993 //a variable is DA/DU after a for loop, if it's DA/DU assuming the |
1954 //branch is not taken AND if it's DA/DU before any break statement |
1994 //branch is not taken AND if it's DA/DU before any break statement |
1955 assignToInits(tree.body, initsSkip); |
1995 inits.assign(initsSkip); |
1956 uninits.assign(uninitsSkip); |
1996 uninits.assign(uninitsSkip); |
1957 resolveBreaks(tree, prevPendingExits); |
1997 resolveBreaks(tree, prevPendingExits); |
1958 nextadr = nextadrPrev; |
1998 nextadr = nextadrPrev; |
1959 } |
1999 } |
1960 |
2000 |
1961 public void visitForeachLoop(JCEnhancedForLoop tree) { |
2001 public void visitForeachLoop(JCEnhancedForLoop tree) { |
1962 visitVarDef(tree.var); |
2002 visitVarDef(tree.var); |
1963 |
2003 |
1964 ListBuffer<P> prevPendingExits = pendingExits; |
2004 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
1965 FlowKind prevFlowKind = flowKind; |
2005 FlowKind prevFlowKind = flowKind; |
1966 flowKind = FlowKind.NORMAL; |
2006 flowKind = FlowKind.NORMAL; |
1967 int nextadrPrev = nextadr; |
2007 int nextadrPrev = nextadr; |
1968 scan(tree.expr); |
2008 scan(tree.expr); |
1969 final Bits initsStart = new Bits(inits); |
2009 final Bits initsStart = new Bits(inits); |
1970 final Bits uninitsStart = new Bits(uninits); |
2010 final Bits uninitsStart = new Bits(uninits); |
1971 |
2011 |
1972 letInit(tree.pos(), tree.var.sym); |
2012 letInit(tree.pos(), tree.var.sym); |
1973 pendingExits = new ListBuffer<>(); |
2013 pendingExits = new ListBuffer<>(); |
1974 int prevErrors = getLogNumberOfErrors(); |
2014 int prevErrors = log.nerrors; |
1975 do { |
2015 do { |
1976 final Bits uninitsEntry = new Bits(uninits); |
2016 final Bits uninitsEntry = new Bits(uninits); |
1977 uninitsEntry.excludeFrom(nextadr); |
2017 uninitsEntry.excludeFrom(nextadr); |
1978 scan(tree.body); |
2018 scan(tree.body); |
1979 resolveContinues(tree); |
2019 resolveContinues(tree); |
1980 if (getLogNumberOfErrors() != prevErrors || |
2020 if (log.nerrors != prevErrors || |
1981 flowKind.isFinal() || |
2021 flowKind.isFinal() || |
1982 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) |
2022 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) |
1983 break; |
2023 break; |
1984 uninits.assign(uninitsEntry.andSet(uninits)); |
2024 uninits.assign(uninitsEntry.andSet(uninits)); |
1985 flowKind = FlowKind.SPECULATIVE_LOOP; |
2025 flowKind = FlowKind.SPECULATIVE_LOOP; |
1986 } while (true); |
2026 } while (true); |
1987 flowKind = prevFlowKind; |
2027 flowKind = prevFlowKind; |
1988 assignToInits(tree.body, initsStart); |
2028 inits.assign(initsStart); |
1989 uninits.assign(uninitsStart.andSet(uninits)); |
2029 uninits.assign(uninitsStart.andSet(uninits)); |
1990 resolveBreaks(tree, prevPendingExits); |
2030 resolveBreaks(tree, prevPendingExits); |
1991 nextadr = nextadrPrev; |
2031 nextadr = nextadrPrev; |
1992 } |
2032 } |
1993 |
2033 |
1994 public void visitLabelled(JCLabeledStatement tree) { |
2034 public void visitLabelled(JCLabeledStatement tree) { |
1995 ListBuffer<P> prevPendingExits = pendingExits; |
2035 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
1996 pendingExits = new ListBuffer<>(); |
2036 pendingExits = new ListBuffer<>(); |
1997 scan(tree.body); |
2037 scan(tree.body); |
1998 resolveBreaks(tree, prevPendingExits); |
2038 resolveBreaks(tree, prevPendingExits); |
1999 } |
2039 } |
2000 |
2040 |
2001 public void visitSwitch(JCSwitch tree) { |
2041 public void visitSwitch(JCSwitch tree) { |
2002 ListBuffer<P> prevPendingExits = pendingExits; |
2042 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
2003 pendingExits = new ListBuffer<>(); |
2043 pendingExits = new ListBuffer<>(); |
2004 int nextadrPrev = nextadr; |
2044 int nextadrPrev = nextadr; |
2005 scanExpr(tree.selector); |
2045 scanExpr(tree.selector); |
2006 final Bits initsSwitch = new Bits(inits); |
2046 final Bits initsSwitch = new Bits(inits); |
2007 final Bits uninitsSwitch = new Bits(uninits); |
2047 final Bits uninitsSwitch = new Bits(uninits); |
2008 boolean hasDefault = false; |
2048 boolean hasDefault = false; |
2009 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { |
2049 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { |
2010 assignToInits(l.head, initsSwitch); |
2050 inits.assign(initsSwitch); |
2011 uninits.assign(uninits.andSet(uninitsSwitch)); |
2051 uninits.assign(uninits.andSet(uninitsSwitch)); |
2012 JCCase c = l.head; |
2052 JCCase c = l.head; |
2013 if (c.pat == null) { |
2053 if (c.pat == null) { |
2014 hasDefault = true; |
2054 hasDefault = true; |
2015 } else { |
2055 } else { |
2016 scanExpr(c.pat); |
2056 scanExpr(c.pat); |
2017 } |
2057 } |
2018 if (hasDefault) { |
2058 if (hasDefault) { |
2019 assignToInits(null, initsSwitch); |
2059 inits.assign(initsSwitch); |
2020 uninits.assign(uninits.andSet(uninitsSwitch)); |
2060 uninits.assign(uninits.andSet(uninitsSwitch)); |
2021 } |
2061 } |
2022 scan(c.stats); |
2062 scan(c.stats); |
2023 addVars(c.stats, initsSwitch, uninitsSwitch); |
2063 addVars(c.stats, initsSwitch, uninitsSwitch); |
2024 if (!hasDefault) { |
2064 if (!hasDefault) { |
2025 assignToInits(l.head.stats.last(), initsSwitch); |
2065 inits.assign(initsSwitch); |
2026 uninits.assign(uninits.andSet(uninitsSwitch)); |
2066 uninits.assign(uninits.andSet(uninitsSwitch)); |
2027 } |
2067 } |
2028 // Warn about fall-through if lint switch fallthrough enabled. |
2068 // Warn about fall-through if lint switch fallthrough enabled. |
2029 } |
2069 } |
2030 if (!hasDefault) { |
2070 if (!hasDefault) { |
2031 andSetInits(null, initsSwitch); |
2071 inits.andSet(initsSwitch); |
2032 } |
2072 } |
2033 resolveBreaks(tree, prevPendingExits); |
2073 resolveBreaks(tree, prevPendingExits); |
2034 nextadr = nextadrPrev; |
2074 nextadr = nextadrPrev; |
2035 } |
2075 } |
2036 // where |
2076 // where |
2045 uninits.incl(adr); |
2085 uninits.incl(adr); |
2046 } |
2086 } |
2047 } |
2087 } |
2048 } |
2088 } |
2049 |
2089 |
2050 boolean isEnabled(Lint.LintCategory lc) { |
|
2051 return false; |
|
2052 } |
|
2053 |
|
2054 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {} |
|
2055 |
|
2056 public void visitTry(JCTry tree) { |
2090 public void visitTry(JCTry tree) { |
2057 ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>(); |
2091 ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>(); |
2058 final Bits uninitsTryPrev = new Bits(uninitsTry); |
2092 final Bits uninitsTryPrev = new Bits(uninitsTry); |
2059 ListBuffer<P> prevPendingExits = pendingExits; |
2093 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; |
2060 pendingExits = new ListBuffer<>(); |
2094 pendingExits = new ListBuffer<>(); |
2061 final Bits initsTry = new Bits(inits); |
2095 final Bits initsTry = new Bits(inits); |
2062 uninitsTry.assign(uninits); |
2096 uninitsTry.assign(uninits); |
2063 for (JCTree resource : tree.resources) { |
2097 for (JCTree resource : tree.resources) { |
2064 if (resource instanceof JCVariableDecl) { |
2098 if (resource instanceof JCVariableDecl) { |
2077 final Bits initsEnd = new Bits(inits); |
2111 final Bits initsEnd = new Bits(inits); |
2078 final Bits uninitsEnd = new Bits(uninits); |
2112 final Bits uninitsEnd = new Bits(uninits); |
2079 int nextadrCatch = nextadr; |
2113 int nextadrCatch = nextadr; |
2080 |
2114 |
2081 if (!resourceVarDecls.isEmpty() && |
2115 if (!resourceVarDecls.isEmpty() && |
2082 isEnabled(Lint.LintCategory.TRY)) { |
2116 lint.isEnabled(Lint.LintCategory.TRY)) { |
2083 for (JCVariableDecl resVar : resourceVarDecls) { |
2117 for (JCVariableDecl resVar : resourceVarDecls) { |
2084 if (unrefdResources.includes(resVar.sym)) { |
2118 if (unrefdResources.includes(resVar.sym)) { |
2085 reportWarning(Lint.LintCategory.TRY, resVar.pos(), |
2119 log.warning(Lint.LintCategory.TRY, resVar.pos(), |
2086 "try.resource.not.referenced", resVar.sym); |
2120 "try.resource.not.referenced", resVar.sym); |
2087 unrefdResources.remove(resVar.sym); |
2121 unrefdResources.remove(resVar.sym); |
2088 } |
2122 } |
2089 } |
2123 } |
2090 } |
2124 } |
2096 final Bits initsCatchPrev = new Bits(initsTry); |
2130 final Bits initsCatchPrev = new Bits(initsTry); |
2097 final Bits uninitsCatchPrev = new Bits(uninitsTry); |
2131 final Bits uninitsCatchPrev = new Bits(uninitsTry); |
2098 |
2132 |
2099 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { |
2133 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { |
2100 JCVariableDecl param = l.head.param; |
2134 JCVariableDecl param = l.head.param; |
2101 assignToInits(tree.body, initsCatchPrev); |
2135 inits.assign(initsCatchPrev); |
2102 uninits.assign(uninitsCatchPrev); |
2136 uninits.assign(uninitsCatchPrev); |
2103 scan(param); |
2137 scan(param); |
2104 /* If this is a TWR and we are executing the code from Gen, |
2138 /* If this is a TWR and we are executing the code from Gen, |
2105 * then there can be synthetic variables, ignore them. |
2139 * then there can be synthetic variables, ignore them. |
2106 */ |
2140 */ |
2109 initsEnd.andSet(inits); |
2143 initsEnd.andSet(inits); |
2110 uninitsEnd.andSet(uninits); |
2144 uninitsEnd.andSet(uninits); |
2111 nextadr = nextadrCatch; |
2145 nextadr = nextadrCatch; |
2112 } |
2146 } |
2113 if (tree.finalizer != null) { |
2147 if (tree.finalizer != null) { |
2114 assignToInits(tree.finalizer, initsTry); |
2148 inits.assign(initsTry); |
2115 uninits.assign(uninitsTry); |
2149 uninits.assign(uninitsTry); |
2116 ListBuffer<P> exits = pendingExits; |
2150 ListBuffer<AssignPendingExit> exits = pendingExits; |
2117 pendingExits = prevPendingExits; |
2151 pendingExits = prevPendingExits; |
2118 scan(tree.finalizer); |
2152 scan(tree.finalizer); |
2119 if (!tree.finallyCanCompleteNormally) { |
2153 if (!tree.finallyCanCompleteNormally) { |
2120 // discard exits and exceptions from try and finally |
2154 // discard exits and exceptions from try and finally |
2121 } else { |
2155 } else { |
2122 uninits.andSet(uninitsEnd); |
2156 uninits.andSet(uninitsEnd); |
2123 // FIX: this doesn't preserve source order of exits in catch |
2157 // FIX: this doesn't preserve source order of exits in catch |
2124 // versus finally! |
2158 // versus finally! |
2125 while (exits.nonEmpty()) { |
2159 while (exits.nonEmpty()) { |
2126 P exit = exits.next(); |
2160 AssignPendingExit exit = exits.next(); |
2127 if (exit.exit_inits != null) { |
2161 if (exit.exit_inits != null) { |
2128 exit.exit_inits.orSet(inits); |
2162 exit.exit_inits.orSet(inits); |
2129 exit.exit_uninits.andSet(uninits); |
2163 exit.exit_uninits.andSet(uninits); |
2130 } |
2164 } |
2131 pendingExits.append(exit); |
2165 pendingExits.append(exit); |
2132 } |
2166 } |
2133 orSetInits(tree, initsEnd); |
2167 inits.orSet(initsEnd); |
2134 } |
2168 } |
2135 } else { |
2169 } else { |
2136 assignToInits(tree, initsEnd); |
2170 inits.assign(initsEnd); |
2137 uninits.assign(uninitsEnd); |
2171 uninits.assign(uninitsEnd); |
2138 ListBuffer<P> exits = pendingExits; |
2172 ListBuffer<AssignPendingExit> exits = pendingExits; |
2139 pendingExits = prevPendingExits; |
2173 pendingExits = prevPendingExits; |
2140 while (exits.nonEmpty()) pendingExits.append(exits.next()); |
2174 while (exits.nonEmpty()) pendingExits.append(exits.next()); |
2141 } |
2175 } |
2142 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); |
2176 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); |
2143 } |
2177 } |
2144 |
2178 |
2145 public void visitConditional(JCConditional tree) { |
2179 public void visitConditional(JCConditional tree) { |
2146 scanCond(tree.cond); |
2180 scanCond(tree.cond); |
2147 final Bits initsBeforeElse = new Bits(initsWhenFalse); |
2181 final Bits initsBeforeElse = new Bits(initsWhenFalse); |
2148 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); |
2182 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); |
2149 assignToInits(tree.cond, initsWhenTrue); |
2183 inits.assign(initsWhenTrue); |
2150 uninits.assign(uninitsWhenTrue); |
2184 uninits.assign(uninitsWhenTrue); |
2151 if (tree.truepart.type.hasTag(BOOLEAN) && |
2185 if (tree.truepart.type.hasTag(BOOLEAN) && |
2152 tree.falsepart.type.hasTag(BOOLEAN)) { |
2186 tree.falsepart.type.hasTag(BOOLEAN)) { |
2153 // if b and c are boolean valued, then |
2187 // if b and c are boolean valued, then |
2154 // v is (un)assigned after a?b:c when true iff |
2188 // v is (un)assigned after a?b:c when true iff |
2157 scanCond(tree.truepart); |
2191 scanCond(tree.truepart); |
2158 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); |
2192 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); |
2159 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); |
2193 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); |
2160 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); |
2194 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); |
2161 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); |
2195 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); |
2162 assignToInits(tree.truepart, initsBeforeElse); |
2196 inits.assign(initsBeforeElse); |
2163 uninits.assign(uninitsBeforeElse); |
2197 uninits.assign(uninitsBeforeElse); |
2164 scanCond(tree.falsepart); |
2198 scanCond(tree.falsepart); |
2165 initsWhenTrue.andSet(initsAfterThenWhenTrue); |
2199 initsWhenTrue.andSet(initsAfterThenWhenTrue); |
2166 initsWhenFalse.andSet(initsAfterThenWhenFalse); |
2200 initsWhenFalse.andSet(initsAfterThenWhenFalse); |
2167 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); |
2201 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); |
2168 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); |
2202 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); |
2169 } else { |
2203 } else { |
2170 scanExpr(tree.truepart); |
2204 scanExpr(tree.truepart); |
2171 final Bits initsAfterThen = new Bits(inits); |
2205 final Bits initsAfterThen = new Bits(inits); |
2172 final Bits uninitsAfterThen = new Bits(uninits); |
2206 final Bits uninitsAfterThen = new Bits(uninits); |
2173 assignToInits(tree.truepart, initsBeforeElse); |
2207 inits.assign(initsBeforeElse); |
2174 uninits.assign(uninitsBeforeElse); |
2208 uninits.assign(uninitsBeforeElse); |
2175 scanExpr(tree.falsepart); |
2209 scanExpr(tree.falsepart); |
2176 andSetInits(tree.falsepart, initsAfterThen); |
2210 inits.andSet(initsAfterThen); |
2177 uninits.andSet(uninitsAfterThen); |
2211 uninits.andSet(uninitsAfterThen); |
2178 } |
2212 } |
2179 } |
2213 } |
2180 |
2214 |
2181 public void visitIf(JCIf tree) { |
2215 public void visitIf(JCIf tree) { |
2182 scanCond(tree.cond); |
2216 scanCond(tree.cond); |
2183 final Bits initsBeforeElse = new Bits(initsWhenFalse); |
2217 final Bits initsBeforeElse = new Bits(initsWhenFalse); |
2184 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); |
2218 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); |
2185 assignToInits(tree.cond, initsWhenTrue); |
2219 inits.assign(initsWhenTrue); |
2186 uninits.assign(uninitsWhenTrue); |
2220 uninits.assign(uninitsWhenTrue); |
2187 scan(tree.thenpart); |
2221 scan(tree.thenpart); |
2188 if (tree.elsepart != null) { |
2222 if (tree.elsepart != null) { |
2189 final Bits initsAfterThen = new Bits(inits); |
2223 final Bits initsAfterThen = new Bits(inits); |
2190 final Bits uninitsAfterThen = new Bits(uninits); |
2224 final Bits uninitsAfterThen = new Bits(uninits); |
2191 assignToInits(tree.thenpart, initsBeforeElse); |
2225 inits.assign(initsBeforeElse); |
2192 uninits.assign(uninitsBeforeElse); |
2226 uninits.assign(uninitsBeforeElse); |
2193 scan(tree.elsepart); |
2227 scan(tree.elsepart); |
2194 andSetInits(tree.elsepart, initsAfterThen); |
2228 inits.andSet(initsAfterThen); |
2195 uninits.andSet(uninitsAfterThen); |
2229 uninits.andSet(uninitsAfterThen); |
2196 } else { |
2230 } else { |
2197 andSetInits(tree.thenpart, initsBeforeElse); |
2231 inits.andSet(initsBeforeElse); |
2198 uninits.andSet(uninitsBeforeElse); |
2232 uninits.andSet(uninitsBeforeElse); |
2199 } |
2233 } |
2200 } |
|
2201 |
|
2202 protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) { |
|
2203 return null; |
|
2204 } |
2234 } |
2205 |
2235 |
2206 @Override |
2236 @Override |
2207 public void visitBreak(JCBreak tree) { |
2237 public void visitBreak(JCBreak tree) { |
2208 recordExit(tree, createNewPendingExit(tree, inits, uninits)); |
2238 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2209 } |
2239 } |
2210 |
2240 |
2211 @Override |
2241 @Override |
2212 public void visitContinue(JCContinue tree) { |
2242 public void visitContinue(JCContinue tree) { |
2213 recordExit(tree, createNewPendingExit(tree, inits, uninits)); |
2243 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2214 } |
2244 } |
2215 |
2245 |
2216 @Override |
2246 @Override |
2217 public void visitReturn(JCReturn tree) { |
2247 public void visitReturn(JCReturn tree) { |
2218 scanExpr(tree.expr); |
2248 scanExpr(tree.expr); |
2219 recordExit(tree, createNewPendingExit(tree, inits, uninits)); |
2249 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2220 } |
2250 } |
2221 |
2251 |
2222 public void visitThrow(JCThrow tree) { |
2252 public void visitThrow(JCThrow tree) { |
2223 scanExpr(tree.expr); |
2253 scanExpr(tree.expr); |
2224 markDead(tree.expr); |
2254 markDead(); |
2225 } |
2255 } |
2226 |
2256 |
2227 public void visitApply(JCMethodInvocation tree) { |
2257 public void visitApply(JCMethodInvocation tree) { |
2228 scanExpr(tree.meth); |
2258 scanExpr(tree.meth); |
2229 scanExprs(tree.args); |
2259 scanExprs(tree.args); |
2238 @Override |
2268 @Override |
2239 public void visitLambda(JCLambda tree) { |
2269 public void visitLambda(JCLambda tree) { |
2240 final Bits prevUninits = new Bits(uninits); |
2270 final Bits prevUninits = new Bits(uninits); |
2241 final Bits prevInits = new Bits(inits); |
2271 final Bits prevInits = new Bits(inits); |
2242 int returnadrPrev = returnadr; |
2272 int returnadrPrev = returnadr; |
2243 ListBuffer<P> prevPending = pendingExits; |
2273 ListBuffer<AssignPendingExit> prevPending = pendingExits; |
2244 try { |
2274 try { |
2245 returnadr = nextadr; |
2275 returnadr = nextadr; |
2246 pendingExits = new ListBuffer<>(); |
2276 pendingExits = new ListBuffer<>(); |
2247 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { |
2277 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { |
2248 JCVariableDecl def = l.head; |
2278 JCVariableDecl def = l.head; |
2257 } |
2287 } |
2258 } |
2288 } |
2259 finally { |
2289 finally { |
2260 returnadr = returnadrPrev; |
2290 returnadr = returnadrPrev; |
2261 uninits.assign(prevUninits); |
2291 uninits.assign(prevUninits); |
2262 assignToInits(tree, prevInits); |
2292 inits.assign(prevInits); |
2263 pendingExits = prevPending; |
2293 pendingExits = prevPending; |
2264 } |
2294 } |
2265 } |
2295 } |
2266 |
2296 |
2267 public void visitNewArray(JCNewArray tree) { |
2297 public void visitNewArray(JCNewArray tree) { |
2273 final Bits initsExit = new Bits(inits); |
2303 final Bits initsExit = new Bits(inits); |
2274 final Bits uninitsExit = new Bits(uninits); |
2304 final Bits uninitsExit = new Bits(uninits); |
2275 scanCond(tree.cond); |
2305 scanCond(tree.cond); |
2276 uninitsExit.andSet(uninitsWhenTrue); |
2306 uninitsExit.andSet(uninitsWhenTrue); |
2277 if (tree.detail != null) { |
2307 if (tree.detail != null) { |
2278 assignToInits(tree, initsWhenFalse); |
2308 inits.assign(initsWhenFalse); |
2279 uninits.assign(uninitsWhenFalse); |
2309 uninits.assign(uninitsWhenFalse); |
2280 scanExpr(tree.detail); |
2310 scanExpr(tree.detail); |
2281 } |
2311 } |
2282 assignToInits(tree, initsExit); |
2312 inits.assign(initsExit); |
2283 uninits.assign(uninitsExit); |
2313 uninits.assign(uninitsExit); |
2284 } |
2314 } |
2285 |
2315 |
2286 public void visitAssign(JCAssign tree) { |
2316 public void visitAssign(JCAssign tree) { |
2287 JCTree lhs = TreeInfo.skipParens(tree.lhs); |
2317 JCTree lhs = TreeInfo.skipParens(tree.lhs); |
2306 public void visitSelect(JCFieldAccess tree) { |
2336 public void visitSelect(JCFieldAccess tree) { |
2307 super.visitSelect(tree); |
2337 super.visitSelect(tree); |
2308 if (enforceThisDotInit && |
2338 if (enforceThisDotInit && |
2309 tree.selected.hasTag(IDENT) && |
2339 tree.selected.hasTag(IDENT) && |
2310 ((JCIdent)tree.selected).name == names._this && |
2340 ((JCIdent)tree.selected).name == names._this && |
2311 tree.sym.kind == VAR) |
2341 tree.sym.kind == VAR) { |
2312 { |
|
2313 checkInit(tree.pos(), (VarSymbol)tree.sym); |
2342 checkInit(tree.pos(), (VarSymbol)tree.sym); |
2314 } |
2343 } |
2315 } |
2344 } |
2316 |
2345 |
2317 public void visitAssignop(JCAssignOp tree) { |
2346 public void visitAssignop(JCAssignOp tree) { |
2345 switch (tree.getTag()) { |
2374 switch (tree.getTag()) { |
2346 case AND: |
2375 case AND: |
2347 scanCond(tree.lhs); |
2376 scanCond(tree.lhs); |
2348 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); |
2377 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); |
2349 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); |
2378 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); |
2350 assignToInits(tree.lhs, initsWhenTrue); |
2379 inits.assign(initsWhenTrue); |
2351 uninits.assign(uninitsWhenTrue); |
2380 uninits.assign(uninitsWhenTrue); |
2352 scanCond(tree.rhs); |
2381 scanCond(tree.rhs); |
2353 initsWhenFalse.andSet(initsWhenFalseLeft); |
2382 initsWhenFalse.andSet(initsWhenFalseLeft); |
2354 uninitsWhenFalse.andSet(uninitsWhenFalseLeft); |
2383 uninitsWhenFalse.andSet(uninitsWhenFalseLeft); |
2355 break; |
2384 break; |
2356 case OR: |
2385 case OR: |
2357 scanCond(tree.lhs); |
2386 scanCond(tree.lhs); |
2358 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); |
2387 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); |
2359 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); |
2388 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); |
2360 assignToInits(tree.lhs, initsWhenFalse); |
2389 inits.assign(initsWhenFalse); |
2361 uninits.assign(uninitsWhenFalse); |
2390 uninits.assign(uninitsWhenFalse); |
2362 scanCond(tree.rhs); |
2391 scanCond(tree.rhs); |
2363 initsWhenTrue.andSet(initsWhenTrueLeft); |
2392 initsWhenTrue.andSet(initsWhenTrueLeft); |
2364 uninitsWhenTrue.andSet(uninitsWhenTrueLeft); |
2393 uninitsWhenTrue.andSet(uninitsWhenTrueLeft); |
2365 break; |
2394 break; |
2426 unrefdResources = null; |
2455 unrefdResources = null; |
2427 } |
2456 } |
2428 } |
2457 } |
2429 } |
2458 } |
2430 |
2459 |
2431 public class AssignAnalyzer extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> { |
|
2432 |
|
2433 public class AssignPendingExit extends AbstractAssignAnalyzer<AssignPendingExit>.AbstractAssignPendingExit { |
|
2434 |
|
2435 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { |
|
2436 super(tree, inits, uninits); |
|
2437 } |
|
2438 } |
|
2439 |
|
2440 @Override |
|
2441 protected AssignPendingExit createNewPendingExit(JCTree tree, |
|
2442 Bits inits, Bits uninits) { |
|
2443 return new AssignPendingExit(tree, inits, uninits); |
|
2444 } |
|
2445 |
|
2446 /** Record an initialization of a trackable variable. |
|
2447 */ |
|
2448 @Override |
|
2449 void letInit(DiagnosticPosition pos, VarSymbol sym) { |
|
2450 if (sym.adr >= firstadr && trackable(sym)) { |
|
2451 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { |
|
2452 if (!uninits.isMember(sym.adr)) { |
|
2453 //assignment targeting an effectively final variable |
|
2454 //makes the variable lose its status of effectively final |
|
2455 //if the variable is _not_ definitively unassigned |
|
2456 sym.flags_field &= ~EFFECTIVELY_FINAL; |
|
2457 } else { |
|
2458 uninit(sym); |
|
2459 } |
|
2460 } |
|
2461 else if ((sym.flags() & FINAL) != 0) { |
|
2462 if ((sym.flags() & PARAMETER) != 0) { |
|
2463 if ((sym.flags() & UNION) != 0) { //multi-catch parameter |
|
2464 log.error(pos, "multicatch.parameter.may.not.be.assigned", sym); |
|
2465 } |
|
2466 else { |
|
2467 log.error(pos, "final.parameter.may.not.be.assigned", |
|
2468 sym); |
|
2469 } |
|
2470 } else if (!uninits.isMember(sym.adr)) { |
|
2471 log.error(pos, flowKind.errKey, sym); |
|
2472 } else { |
|
2473 uninit(sym); |
|
2474 } |
|
2475 } |
|
2476 inits.incl(sym.adr); |
|
2477 } else if ((sym.flags() & FINAL) != 0) { |
|
2478 log.error(pos, "var.might.already.be.assigned", sym); |
|
2479 } |
|
2480 } |
|
2481 |
|
2482 @Override |
|
2483 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { |
|
2484 if ((sym.adr >= firstadr || sym.owner.kind != TYP) && |
|
2485 trackable(sym) && |
|
2486 !inits.isMember(sym.adr)) { |
|
2487 log.error(pos, errkey, sym); |
|
2488 inits.incl(sym.adr); |
|
2489 } |
|
2490 } |
|
2491 |
|
2492 @Override |
|
2493 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, |
|
2494 String key, Object ... args) { |
|
2495 log.warning(lc, pos, key, args); |
|
2496 } |
|
2497 |
|
2498 @Override |
|
2499 int getLogNumberOfErrors() { |
|
2500 return log.nerrors; |
|
2501 } |
|
2502 |
|
2503 @Override |
|
2504 boolean isEnabled(Lint.LintCategory lc) { |
|
2505 return lint.isEnabled(lc); |
|
2506 } |
|
2507 |
|
2508 @Override |
|
2509 public void visitClassDef(JCClassDecl tree) { |
|
2510 if (tree.sym == null) { |
|
2511 return; |
|
2512 } |
|
2513 |
|
2514 Lint lintPrev = lint; |
|
2515 lint = lint.augment(tree.sym); |
|
2516 try { |
|
2517 super.visitClassDef(tree); |
|
2518 } finally { |
|
2519 lint = lintPrev; |
|
2520 } |
|
2521 } |
|
2522 |
|
2523 @Override |
|
2524 public void visitMethodDef(JCMethodDecl tree) { |
|
2525 if (tree.body == null) { |
|
2526 return; |
|
2527 } |
|
2528 |
|
2529 /* MemberEnter can generate synthetic methods ignore them |
|
2530 */ |
|
2531 if ((tree.sym.flags() & SYNTHETIC) != 0) { |
|
2532 return; |
|
2533 } |
|
2534 |
|
2535 Lint lintPrev = lint; |
|
2536 lint = lint.augment(tree.sym); |
|
2537 try { |
|
2538 super.visitMethodDef(tree); |
|
2539 } finally { |
|
2540 lint = lintPrev; |
|
2541 } |
|
2542 } |
|
2543 |
|
2544 @Override |
|
2545 public void visitVarDef(JCVariableDecl tree) { |
|
2546 if (tree.init == null) { |
|
2547 super.visitVarDef(tree); |
|
2548 } else { |
|
2549 Lint lintPrev = lint; |
|
2550 lint = lint.augment(tree.sym); |
|
2551 try{ |
|
2552 super.visitVarDef(tree); |
|
2553 } finally { |
|
2554 lint = lintPrev; |
|
2555 } |
|
2556 } |
|
2557 } |
|
2558 |
|
2559 } |
|
2560 |
|
2561 /** |
2460 /** |
2562 * This pass implements the last step of the dataflow analysis, namely |
2461 * This pass implements the last step of the dataflow analysis, namely |
2563 * the effectively-final analysis check. This checks that every local variable |
2462 * the effectively-final analysis check. This checks that every local variable |
2564 * reference from a lambda body/local inner class is either final or effectively final. |
2463 * reference from a lambda body/local inner class is either final or effectively final. |
2565 * Additional this also checks that every variable that is used as an operand to |
2464 * Additional this also checks that every variable that is used as an operand to |
2570 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> { |
2469 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> { |
2571 |
2470 |
2572 JCTree currentTree; //local class or lambda |
2471 JCTree currentTree; //local class or lambda |
2573 |
2472 |
2574 @Override |
2473 @Override |
2575 void markDead(JCTree tree) { |
2474 void markDead() { |
2576 //do nothing |
2475 //do nothing |
2577 } |
2476 } |
2578 |
2477 |
2579 @SuppressWarnings("fallthrough") |
2478 @SuppressWarnings("fallthrough") |
2580 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) { |
2479 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) { |