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

changeset 2820
7f6d6b80a58b
parent 2606
f7f3f96999ba
child 2893
ca5783d9a597
equal deleted inserted replaced
2817:976523f1d562 2820:7f6d6b80a58b
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 }
418 * complete normally. 418 * complete normally.
419 */ 419 */
420 private boolean alive; 420 private boolean alive;
421 421
422 @Override 422 @Override
423 void markDead(JCTree tree) { 423 void markDead() {
424 alive = false; 424 alive = false;
425 } 425 }
426 426
427 /************************************************************************* 427 /*************************************************************************
428 * Visitor methods for statements and definitions 428 * Visitor methods for statements and definitions
462 if (tree.sym == null) return; 462 if (tree.sym == null) return;
463 boolean alivePrev = alive; 463 boolean alivePrev = alive;
464 ListBuffer<PendingExit> pendingExitsPrev = pendingExits; 464 ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
465 Lint lintPrev = lint; 465 Lint lintPrev = lint;
466 466
467 pendingExits = new ListBuffer<PendingExit>(); 467 pendingExits = new ListBuffer<>();
468 lint = lint.augment(tree.sym); 468 lint = lint.augment(tree.sym);
469 469
470 try { 470 try {
471 // process all the static initializers 471 // process all the static initializers
472 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 472 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
511 511
512 if (alive && !tree.sym.type.getReturnType().hasTag(VOID)) 512 if (alive && !tree.sym.type.getReturnType().hasTag(VOID))
513 log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt"); 513 log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
514 514
515 List<PendingExit> exits = pendingExits.toList(); 515 List<PendingExit> exits = pendingExits.toList();
516 pendingExits = new ListBuffer<PendingExit>(); 516 pendingExits = new ListBuffer<>();
517 while (exits.nonEmpty()) { 517 while (exits.nonEmpty()) {
518 PendingExit exit = exits.head; 518 PendingExit exit = exits.head;
519 exits = exits.tail; 519 exits = exits.tail;
520 Assert.check(exit.tree.hasTag(RETURN)); 520 Assert.check(exit.tree.hasTag(RETURN));
521 } 521 }
540 scanStats(tree.stats); 540 scanStats(tree.stats);
541 } 541 }
542 542
543 public void visitDoLoop(JCDoWhileLoop tree) { 543 public void visitDoLoop(JCDoWhileLoop tree) {
544 ListBuffer<PendingExit> prevPendingExits = pendingExits; 544 ListBuffer<PendingExit> prevPendingExits = pendingExits;
545 pendingExits = new ListBuffer<PendingExit>(); 545 pendingExits = new ListBuffer<>();
546 scanStat(tree.body); 546 scanStat(tree.body);
547 alive |= resolveContinues(tree); 547 alive |= resolveContinues(tree);
548 scan(tree.cond); 548 scan(tree.cond);
549 alive = alive && !tree.cond.type.isTrue(); 549 alive = alive && !tree.cond.type.isTrue();
550 alive |= resolveBreaks(tree, prevPendingExits); 550 alive |= resolveBreaks(tree, prevPendingExits);
551 } 551 }
552 552
553 public void visitWhileLoop(JCWhileLoop tree) { 553 public void visitWhileLoop(JCWhileLoop tree) {
554 ListBuffer<PendingExit> prevPendingExits = pendingExits; 554 ListBuffer<PendingExit> prevPendingExits = pendingExits;
555 pendingExits = new ListBuffer<PendingExit>(); 555 pendingExits = new ListBuffer<>();
556 scan(tree.cond); 556 scan(tree.cond);
557 alive = !tree.cond.type.isFalse(); 557 alive = !tree.cond.type.isFalse();
558 scanStat(tree.body); 558 scanStat(tree.body);
559 alive |= resolveContinues(tree); 559 alive |= resolveContinues(tree);
560 alive = resolveBreaks(tree, prevPendingExits) || 560 alive = resolveBreaks(tree, prevPendingExits) ||
562 } 562 }
563 563
564 public void visitForLoop(JCForLoop tree) { 564 public void visitForLoop(JCForLoop tree) {
565 ListBuffer<PendingExit> prevPendingExits = pendingExits; 565 ListBuffer<PendingExit> prevPendingExits = pendingExits;
566 scanStats(tree.init); 566 scanStats(tree.init);
567 pendingExits = new ListBuffer<PendingExit>(); 567 pendingExits = new ListBuffer<>();
568 if (tree.cond != null) { 568 if (tree.cond != null) {
569 scan(tree.cond); 569 scan(tree.cond);
570 alive = !tree.cond.type.isFalse(); 570 alive = !tree.cond.type.isFalse();
571 } else { 571 } else {
572 alive = true; 572 alive = true;
580 580
581 public void visitForeachLoop(JCEnhancedForLoop tree) { 581 public void visitForeachLoop(JCEnhancedForLoop tree) {
582 visitVarDef(tree.var); 582 visitVarDef(tree.var);
583 ListBuffer<PendingExit> prevPendingExits = pendingExits; 583 ListBuffer<PendingExit> prevPendingExits = pendingExits;
584 scan(tree.expr); 584 scan(tree.expr);
585 pendingExits = new ListBuffer<PendingExit>(); 585 pendingExits = new ListBuffer<>();
586 scanStat(tree.body); 586 scanStat(tree.body);
587 alive |= resolveContinues(tree); 587 alive |= resolveContinues(tree);
588 resolveBreaks(tree, prevPendingExits); 588 resolveBreaks(tree, prevPendingExits);
589 alive = true; 589 alive = true;
590 } 590 }
591 591
592 public void visitLabelled(JCLabeledStatement tree) { 592 public void visitLabelled(JCLabeledStatement tree) {
593 ListBuffer<PendingExit> prevPendingExits = pendingExits; 593 ListBuffer<PendingExit> prevPendingExits = pendingExits;
594 pendingExits = new ListBuffer<PendingExit>(); 594 pendingExits = new ListBuffer<>();
595 scanStat(tree.body); 595 scanStat(tree.body);
596 alive |= resolveBreaks(tree, prevPendingExits); 596 alive |= resolveBreaks(tree, prevPendingExits);
597 } 597 }
598 598
599 public void visitSwitch(JCSwitch tree) { 599 public void visitSwitch(JCSwitch tree) {
600 ListBuffer<PendingExit> prevPendingExits = pendingExits; 600 ListBuffer<PendingExit> prevPendingExits = pendingExits;
601 pendingExits = new ListBuffer<PendingExit>(); 601 pendingExits = new ListBuffer<>();
602 scan(tree.selector); 602 scan(tree.selector);
603 boolean hasDefault = false; 603 boolean hasDefault = false;
604 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 604 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
605 alive = true; 605 alive = true;
606 JCCase c = l.head; 606 JCCase c = l.head;
623 alive |= resolveBreaks(tree, prevPendingExits); 623 alive |= resolveBreaks(tree, prevPendingExits);
624 } 624 }
625 625
626 public void visitTry(JCTry tree) { 626 public void visitTry(JCTry tree) {
627 ListBuffer<PendingExit> prevPendingExits = pendingExits; 627 ListBuffer<PendingExit> prevPendingExits = pendingExits;
628 pendingExits = new ListBuffer<PendingExit>(); 628 pendingExits = new ListBuffer<>();
629 for (JCTree resource : tree.resources) { 629 for (JCTree resource : tree.resources) {
630 if (resource instanceof JCVariableDecl) { 630 if (resource instanceof JCVariableDecl) {
631 JCVariableDecl vdecl = (JCVariableDecl) resource; 631 JCVariableDecl vdecl = (JCVariableDecl) resource;
632 visitVarDef(vdecl); 632 visitVarDef(vdecl);
633 } else if (resource instanceof JCExpression) { 633 } else if (resource instanceof JCExpression) {
686 alive = true; 686 alive = true;
687 } 687 }
688 } 688 }
689 689
690 public void visitBreak(JCBreak tree) { 690 public void visitBreak(JCBreak tree) {
691 recordExit(tree, new PendingExit(tree)); 691 recordExit(new PendingExit(tree));
692 } 692 }
693 693
694 public void visitContinue(JCContinue tree) { 694 public void visitContinue(JCContinue tree) {
695 recordExit(tree, new PendingExit(tree)); 695 recordExit(new PendingExit(tree));
696 } 696 }
697 697
698 public void visitReturn(JCReturn tree) { 698 public void visitReturn(JCReturn tree) {
699 scan(tree.expr); 699 scan(tree.expr);
700 recordExit(tree, new PendingExit(tree)); 700 recordExit(new PendingExit(tree));
701 } 701 }
702 702
703 public void visitThrow(JCThrow tree) { 703 public void visitThrow(JCThrow tree) {
704 scan(tree.expr); 704 scan(tree.expr);
705 markDead(tree); 705 markDead();
706 } 706 }
707 707
708 public void visitApply(JCMethodInvocation tree) { 708 public void visitApply(JCMethodInvocation tree) {
709 scan(tree.meth); 709 scan(tree.meth);
710 scan(tree.args); 710 scan(tree.args);
754 } 754 }
755 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) { 755 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
756 try { 756 try {
757 attrEnv = env; 757 attrEnv = env;
758 Flow.this.make = make; 758 Flow.this.make = make;
759 pendingExits = new ListBuffer<PendingExit>(); 759 pendingExits = new ListBuffer<>();
760 alive = true; 760 alive = true;
761 scan(tree); 761 scan(tree);
762 } finally { 762 } finally {
763 pendingExits = null; 763 pendingExits = null;
764 Flow.this.make = null; 764 Flow.this.make = null;
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);
1377 * which ensures that no final variable is assigned more than once. This visitor 1377 * which ensures that no final variable is assigned more than once. This visitor
1378 * depends on the results of the liveliness analyzer. This pass is also used to mark 1378 * depends on the results of the liveliness analyzer. This pass is also used to mark
1379 * effectively-final local variables/parameters. 1379 * effectively-final local variables/parameters.
1380 */ 1380 */
1381 1381
1382 public abstract class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer<P>.AbstractAssignPendingExit> 1382 public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
1383 extends BaseAnalyzer<P> {
1384
1385 /** The set of definitely assigned variables. 1383 /** The set of definitely assigned variables.
1386 */ 1384 */
1387 protected Bits inits; 1385 final Bits inits;
1388 1386
1389 /** The set of definitely unassigned variables. 1387 /** The set of definitely unassigned variables.
1390 */ 1388 */
1391 final Bits uninits; 1389 final Bits uninits;
1392 1390
1430 1428
1431 /** The list of unreferenced automatic resources. 1429 /** The list of unreferenced automatic resources.
1432 */ 1430 */
1433 Scope unrefdResources; 1431 Scope unrefdResources;
1434 1432
1435 /** Set when processing a loop body the second time for DU analysis. */ 1433 /** Modified when processing a loop body the second time for DU analysis. */
1436 FlowKind flowKind = FlowKind.NORMAL; 1434 FlowKind flowKind = FlowKind.NORMAL;
1437 1435
1438 /** The starting position of the analysed tree */ 1436 /** The starting position of the analyzed tree */
1439 int startPos; 1437 int startPos;
1440 1438
1441 public class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { 1439 public class AssignPendingExit extends BaseAnalyzer.PendingExit {
1442 1440
1443 final Bits inits; 1441 final Bits inits;
1444 final Bits uninits; 1442 final Bits uninits;
1445 final Bits exit_inits = new Bits(true); 1443 final Bits exit_inits = new Bits(true);
1446 final Bits exit_uninits = new Bits(true); 1444 final Bits exit_uninits = new Bits(true);
1447 1445
1448 public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 1446 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1449 super(tree); 1447 super(tree);
1450 this.inits = inits; 1448 this.inits = inits;
1451 this.uninits = uninits; 1449 this.uninits = uninits;
1452 this.exit_inits.assign(inits); 1450 this.exit_inits.assign(inits);
1453 this.exit_uninits.assign(uninits); 1451 this.exit_uninits.assign(uninits);
1454 } 1452 }
1455 1453
1456 @Override 1454 @Override
1457 public void resolveJump(JCTree tree) { 1455 void resolveJump() {
1458 inits.andSet(exit_inits); 1456 inits.andSet(exit_inits);
1459 uninits.andSet(exit_uninits); 1457 uninits.andSet(exit_uninits);
1460 } 1458 }
1461 } 1459 }
1462 1460
1463 public AbstractAssignAnalyzer() { 1461 public AssignAnalyzer() {
1464 this.inits = new Bits(); 1462 this.inits = new Bits();
1465 uninits = new Bits(); 1463 uninits = new Bits();
1466 uninitsTry = new Bits(); 1464 uninitsTry = new Bits();
1467 initsWhenTrue = new Bits(true); 1465 initsWhenTrue = new Bits(true);
1468 initsWhenFalse = new Bits(true); 1466 initsWhenFalse = new Bits(true);
1471 } 1469 }
1472 1470
1473 private boolean isInitialConstructor = false; 1471 private boolean isInitialConstructor = false;
1474 1472
1475 @Override 1473 @Override
1476 protected void markDead(JCTree tree) { 1474 void markDead() {
1477 if (!isInitialConstructor) { 1475 if (!isInitialConstructor) {
1478 inits.inclRange(returnadr, nextadr); 1476 inits.inclRange(returnadr, nextadr);
1479 } else { 1477 } else {
1480 for (int address = returnadr; address < nextadr; address++) { 1478 for (int address = returnadr; address < nextadr; address++) {
1481 if (!(isFinalUninitializedStaticField(vardecls[address].sym))) { 1479 if (!(isFinalUninitializedStaticField(vardecls[address].sym))) {
1518 if ((sym.flags() & FINAL) == 0) { 1516 if ((sym.flags() & FINAL) == 0) {
1519 sym.flags_field |= EFFECTIVELY_FINAL; 1517 sym.flags_field |= EFFECTIVELY_FINAL;
1520 } 1518 }
1521 sym.adr = nextadr; 1519 sym.adr = nextadr;
1522 vardecls[nextadr] = varDecl; 1520 vardecls[nextadr] = varDecl;
1523 exclVarFromInits(varDecl, nextadr); 1521 inits.excl(nextadr);
1524 uninits.incl(nextadr); 1522 uninits.incl(nextadr);
1525 nextadr++; 1523 nextadr++;
1526 } 1524 }
1527 1525
1528 protected void exclVarFromInits(JCTree tree, int adr) {
1529 inits.excl(adr);
1530 }
1531
1532 protected void assignToInits(JCTree tree, Bits bits) {
1533 inits.assign(bits);
1534 }
1535
1536 protected void andSetInits(JCTree tree, Bits bits) {
1537 inits.andSet(bits);
1538 }
1539
1540 protected void orSetInits(JCTree tree, Bits bits) {
1541 inits.orSet(bits);
1542 }
1543
1544 /** Record an initialization of a trackable variable. 1526 /** Record an initialization of a trackable variable.
1545 */ 1527 */
1546 void letInit(DiagnosticPosition pos, VarSymbol sym) { 1528 void letInit(DiagnosticPosition pos, VarSymbol sym) {
1547 if (sym.adr >= firstadr && trackable(sym)) { 1529 if (sym.adr >= firstadr && trackable(sym)) {
1548 if (uninits.isMember(sym.adr)) { 1530 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
1549 uninit(sym); 1531 if (!uninits.isMember(sym.adr)) {
1532 //assignment targeting an effectively final variable
1533 //makes the variable lose its status of effectively final
1534 //if the variable is _not_ definitively unassigned
1535 sym.flags_field &= ~EFFECTIVELY_FINAL;
1536 } else {
1537 uninit(sym);
1538 }
1539 } else if ((sym.flags() & FINAL) != 0) {
1540 if ((sym.flags() & PARAMETER) != 0) {
1541 if ((sym.flags() & UNION) != 0) { //multi-catch parameter
1542 log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
1543 } else {
1544 log.error(pos, "final.parameter.may.not.be.assigned",
1545 sym);
1546 }
1547 } else if (!uninits.isMember(sym.adr)) {
1548 log.error(pos, flowKind.errKey, sym);
1549 } else {
1550 uninit(sym);
1551 }
1550 } 1552 }
1551 inits.incl(sym.adr); 1553 inits.incl(sym.adr);
1554 } else if ((sym.flags() & FINAL) != 0) {
1555 log.error(pos, "var.might.already.be.assigned", sym);
1552 } 1556 }
1553 } 1557 }
1554 //where 1558 //where
1555 void uninit(VarSymbol sym) { 1559 void uninit(VarSymbol sym) {
1556 if (!inits.isMember(sym.adr)) { 1560 if (!inits.isMember(sym.adr)) {
1581 */ 1585 */
1582 void checkInit(DiagnosticPosition pos, VarSymbol sym) { 1586 void checkInit(DiagnosticPosition pos, VarSymbol sym) {
1583 checkInit(pos, sym, "var.might.not.have.been.initialized"); 1587 checkInit(pos, sym, "var.might.not.have.been.initialized");
1584 } 1588 }
1585 1589
1586 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {} 1590 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
1591 if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
1592 trackable(sym) &&
1593 !inits.isMember(sym.adr)) {
1594 log.error(pos, errkey, sym);
1595 inits.incl(sym.adr);
1596 }
1597 }
1587 1598
1588 /** Utility method to reset several Bits instances. 1599 /** Utility method to reset several Bits instances.
1589 */ 1600 */
1590 private void resetBits(Bits... bits) { 1601 private void resetBits(Bits... bits) {
1591 for (Bits b : bits) { 1602 for (Bits b : bits) {
1605 } 1616 }
1606 } 1617 }
1607 1618
1608 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. 1619 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1609 */ 1620 */
1610 protected void merge(JCTree tree) { 1621 protected void merge() {
1611 inits.assign(initsWhenFalse.andSet(initsWhenTrue)); 1622 inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1612 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); 1623 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1613 } 1624 }
1614 1625
1615 /* ************************************************************************ 1626 /* ************************************************************************
1621 */ 1632 */
1622 void scanExpr(JCTree tree) { 1633 void scanExpr(JCTree tree) {
1623 if (tree != null) { 1634 if (tree != null) {
1624 scan(tree); 1635 scan(tree);
1625 if (inits.isReset()) { 1636 if (inits.isReset()) {
1626 merge(tree); 1637 merge();
1627 } 1638 }
1628 } 1639 }
1629 } 1640 }
1630 1641
1631 /** Analyze a list of expressions. 1642 /** Analyze a list of expressions.
1639 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) 1650 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1640 * rather than (un)inits on exit. 1651 * rather than (un)inits on exit.
1641 */ 1652 */
1642 void scanCond(JCTree tree) { 1653 void scanCond(JCTree tree) {
1643 if (tree.type.isFalse()) { 1654 if (tree.type.isFalse()) {
1644 if (inits.isReset()) merge(tree); 1655 if (inits.isReset()) merge();
1645 initsWhenTrue.assign(inits); 1656 initsWhenTrue.assign(inits);
1646 initsWhenTrue.inclRange(firstadr, nextadr); 1657 initsWhenTrue.inclRange(firstadr, nextadr);
1647 uninitsWhenTrue.assign(uninits); 1658 uninitsWhenTrue.assign(uninits);
1648 uninitsWhenTrue.inclRange(firstadr, nextadr); 1659 uninitsWhenTrue.inclRange(firstadr, nextadr);
1649 initsWhenFalse.assign(inits); 1660 initsWhenFalse.assign(inits);
1650 uninitsWhenFalse.assign(uninits); 1661 uninitsWhenFalse.assign(uninits);
1651 } else if (tree.type.isTrue()) { 1662 } else if (tree.type.isTrue()) {
1652 if (inits.isReset()) merge(tree); 1663 if (inits.isReset()) merge();
1653 initsWhenFalse.assign(inits); 1664 initsWhenFalse.assign(inits);
1654 initsWhenFalse.inclRange(firstadr, nextadr); 1665 initsWhenFalse.inclRange(firstadr, nextadr);
1655 uninitsWhenFalse.assign(uninits); 1666 uninitsWhenFalse.assign(uninits);
1656 uninitsWhenFalse.inclRange(firstadr, nextadr); 1667 uninitsWhenFalse.inclRange(firstadr, nextadr);
1657 initsWhenTrue.assign(inits); 1668 initsWhenTrue.assign(inits);
1666 } 1677 }
1667 } 1678 }
1668 1679
1669 /* ------------ Visitor methods for various sorts of trees -------------*/ 1680 /* ------------ Visitor methods for various sorts of trees -------------*/
1670 1681
1671 @Override
1672 public void visitClassDef(JCClassDecl tree) { 1682 public void visitClassDef(JCClassDecl tree) {
1673 if (tree.sym == null) { 1683 if (tree.sym == null) {
1674 return; 1684 return;
1675 } 1685 }
1676 1686
1677 JCClassDecl classDefPrev = classDef; 1687 Lint lintPrev = lint;
1678 int firstadrPrev = firstadr; 1688 lint = lint.augment(tree.sym);
1679 int nextadrPrev = nextadr;
1680 ListBuffer<P> pendingExitsPrev = pendingExits;
1681
1682 pendingExits = new ListBuffer<P>();
1683 if (tree.name != names.empty) {
1684 firstadr = nextadr;
1685 }
1686 classDef = tree;
1687 try { 1689 try {
1688 // define all the static fields 1690 if (tree.sym == null) {
1689 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1691 return;
1690 if (l.head.hasTag(VARDEF)) { 1692 }
1691 JCVariableDecl def = (JCVariableDecl)l.head; 1693
1692 if ((def.mods.flags & STATIC) != 0) { 1694 JCClassDecl classDefPrev = classDef;
1693 VarSymbol sym = def.sym; 1695 int firstadrPrev = firstadr;
1694 if (trackable(sym)) { 1696 int nextadrPrev = nextadr;
1695 newVar(def); 1697 ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
1698
1699 pendingExits = new ListBuffer<>();
1700 if (tree.name != names.empty) {
1701 firstadr = nextadr;
1702 }
1703 classDef = tree;
1704 try {
1705 // define all the static fields
1706 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1707 if (l.head.hasTag(VARDEF)) {
1708 JCVariableDecl def = (JCVariableDecl)l.head;
1709 if ((def.mods.flags & STATIC) != 0) {
1710 VarSymbol sym = def.sym;
1711 if (trackable(sym)) {
1712 newVar(def);
1713 }
1696 } 1714 }
1697 } 1715 }
1698 } 1716 }
1699 } 1717
1700 1718 // process all the static initializers
1701 // process all the static initializers 1719 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1702 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1720 if (!l.head.hasTag(METHODDEF) &&
1703 if (!l.head.hasTag(METHODDEF) && 1721 (TreeInfo.flags(l.head) & STATIC) != 0) {
1704 (TreeInfo.flags(l.head) & STATIC) != 0) { 1722 scan(l.head);
1705 scan(l.head); 1723 }
1706 } 1724 }
1707 } 1725
1708 1726 // define all the instance fields
1709 // define all the instance fields 1727 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1710 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1728 if (l.head.hasTag(VARDEF)) {
1711 if (l.head.hasTag(VARDEF)) { 1729 JCVariableDecl def = (JCVariableDecl)l.head;
1712 JCVariableDecl def = (JCVariableDecl)l.head; 1730 if ((def.mods.flags & STATIC) == 0) {
1713 if ((def.mods.flags & STATIC) == 0) { 1731 VarSymbol sym = def.sym;
1714 VarSymbol sym = def.sym; 1732 if (trackable(sym)) {
1715 if (trackable(sym)) { 1733 newVar(def);
1716 newVar(def); 1734 }
1717 } 1735 }
1718 } 1736 }
1719 } 1737 }
1720 } 1738 // process all the instance initializers
1721 1739 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1722 // process all the instance initializers 1740 if (!l.head.hasTag(METHODDEF) &&
1723 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1741 (TreeInfo.flags(l.head) & STATIC) == 0) {
1724 if (!l.head.hasTag(METHODDEF) && 1742 scan(l.head);
1725 (TreeInfo.flags(l.head) & STATIC) == 0) { 1743 }
1726 scan(l.head); 1744 }
1727 } 1745
1728 } 1746 // process all the methods
1729 1747 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1730 // process all the methods 1748 if (l.head.hasTag(METHODDEF)) {
1731 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1749 scan(l.head);
1732 if (l.head.hasTag(METHODDEF)) { 1750 }
1733 scan(l.head); 1751 }
1734 } 1752 } finally {
1753 pendingExits = pendingExitsPrev;
1754 nextadr = nextadrPrev;
1755 firstadr = firstadrPrev;
1756 classDef = classDefPrev;
1735 } 1757 }
1736 } finally { 1758 } finally {
1737 pendingExits = pendingExitsPrev; 1759 lint = lintPrev;
1738 nextadr = nextadrPrev; 1760 }
1739 firstadr = firstadrPrev; 1761 }
1740 classDef = classDefPrev; 1762
1741 }
1742 }
1743
1744 @Override
1745 public void visitMethodDef(JCMethodDecl tree) { 1763 public void visitMethodDef(JCMethodDecl tree) {
1746 if (tree.body == null) { 1764 if (tree.body == null) {
1747 return; 1765 return;
1748 } 1766 }
1749 /* Ignore synthetic methods, except for translated lambda methods. 1767
1768 /* MemberEnter can generate synthetic methods ignore them
1750 */ 1769 */
1751 if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) { 1770 if ((tree.sym.flags() & SYNTHETIC) != 0) {
1752 return; 1771 return;
1753 } 1772 }
1754 1773
1755 final Bits initsPrev = new Bits(inits); 1774 Lint lintPrev = lint;
1756 final Bits uninitsPrev = new Bits(uninits); 1775 lint = lint.augment(tree.sym);
1757 int nextadrPrev = nextadr;
1758 int firstadrPrev = firstadr;
1759 int returnadrPrev = returnadr;
1760
1761 Assert.check(pendingExits.isEmpty());
1762 boolean lastInitialConstructor = isInitialConstructor;
1763 try { 1776 try {
1764 isInitialConstructor = TreeInfo.isInitialConstructor(tree); 1777 if (tree.body == null) {
1765 1778 return;
1766 if (!isInitialConstructor) { 1779 }
1767 firstadr = nextadr; 1780 /* Ignore synthetic methods, except for translated lambda methods.
1768 } 1781 */
1769 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 1782 if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
1770 JCVariableDecl def = l.head; 1783 return;
1771 scan(def); 1784 }
1772 Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag"); 1785
1773 /* If we are executing the code from Gen, then there can be 1786 final Bits initsPrev = new Bits(inits);
1774 * synthetic or mandated variables, ignore them. 1787 final Bits uninitsPrev = new Bits(uninits);
1775 */ 1788 int nextadrPrev = nextadr;
1776 initParam(def); 1789 int firstadrPrev = firstadr;
1777 } 1790 int returnadrPrev = returnadr;
1778 // else we are in an instance initializer block; 1791
1779 // leave caught unchanged. 1792 Assert.check(pendingExits.isEmpty());
1780 scan(tree.body); 1793 boolean lastInitialConstructor = isInitialConstructor;
1781 1794 try {
1782 if (isInitialConstructor) { 1795 isInitialConstructor = TreeInfo.isInitialConstructor(tree);
1783 boolean isSynthesized = (tree.sym.flags() & 1796
1784 GENERATEDCONSTR) != 0; 1797 if (!isInitialConstructor) {
1785 for (int i = firstadr; i < nextadr; i++) { 1798 firstadr = nextadr;
1786 JCVariableDecl vardecl = vardecls[i]; 1799 }
1787 VarSymbol var = vardecl.sym; 1800 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1788 if (var.owner == classDef.sym) { 1801 JCVariableDecl def = l.head;
1789 // choose the diagnostic position based on whether 1802 scan(def);
1790 // the ctor is default(synthesized) or not 1803 Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
1791 if (isSynthesized) { 1804 /* If we are executing the code from Gen, then there can be
1792 checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), 1805 * synthetic or mandated variables, ignore them.
1793 var, "var.not.initialized.in.default.constructor"); 1806 */
1794 } else { 1807 initParam(def);
1795 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 }
1796 } 1828 }
1797 } 1829 }
1798 } 1830 }
1799 } 1831 List<AssignPendingExit> exits = pendingExits.toList();
1800 List<P> exits = pendingExits.toList(); 1832 pendingExits = new ListBuffer<>();
1801 pendingExits = new ListBuffer<>(); 1833 while (exits.nonEmpty()) {
1802 while (exits.nonEmpty()) { 1834 AssignPendingExit exit = exits.head;
1803 P exit = exits.head; 1835 exits = exits.tail;
1804 exits = exits.tail; 1836 Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1805 Assert.check(exit.tree.hasTag(RETURN), exit.tree); 1837 if (isInitialConstructor) {
1806 if (isInitialConstructor) { 1838 inits.assign(exit.exit_inits);
1807 assignToInits(exit.tree, exit.exit_inits); 1839 for (int i = firstadr; i < nextadr; i++) {
1808 for (int i = firstadr; i < nextadr; i++) { 1840 checkInit(exit.tree.pos(), vardecls[i].sym);
1809 checkInit(exit.tree.pos(), vardecls[i].sym); 1841 }
1810 } 1842 }
1811 } 1843 }
1844 } finally {
1845 inits.assign(initsPrev);
1846 uninits.assign(uninitsPrev);
1847 nextadr = nextadrPrev;
1848 firstadr = firstadrPrev;
1849 returnadr = returnadrPrev;
1850 isInitialConstructor = lastInitialConstructor;
1812 } 1851 }
1813 } finally { 1852 } finally {
1814 assignToInits(tree, initsPrev); 1853 lint = lintPrev;
1815 uninits.assign(uninitsPrev);
1816 nextadr = nextadrPrev;
1817 firstadr = firstadrPrev;
1818 returnadr = returnadrPrev;
1819 isInitialConstructor = lastInitialConstructor;
1820 } 1854 }
1821 } 1855 }
1822 1856
1823 protected void initParam(JCVariableDecl def) { 1857 protected void initParam(JCVariableDecl def) {
1824 inits.incl(def.sym.adr); 1858 inits.incl(def.sym.adr);
1825 uninits.excl(def.sym.adr); 1859 uninits.excl(def.sym.adr);
1826 } 1860 }
1827 1861
1828 public void visitVarDef(JCVariableDecl tree) { 1862 public void visitVarDef(JCVariableDecl tree) {
1829 boolean track = trackable(tree.sym); 1863 Lint lintPrev = lint;
1830 if (track && tree.sym.owner.kind == MTH) { 1864 lint = lint.augment(tree.sym);
1831 newVar(tree); 1865 try{
1832 } 1866 boolean track = trackable(tree.sym);
1833 if (tree.init != null) { 1867 if (track && tree.sym.owner.kind == MTH) {
1834 scanExpr(tree.init); 1868 newVar(tree);
1835 if (track) { 1869 }
1836 letInit(tree.pos(), tree.sym); 1870 if (tree.init != null) {
1837 } 1871 scanExpr(tree.init);
1872 if (track) {
1873 letInit(tree.pos(), tree.sym);
1874 }
1875 }
1876 } finally {
1877 lint = lintPrev;
1838 } 1878 }
1839 } 1879 }
1840 1880
1841 public void visitBlock(JCBlock tree) { 1881 public void visitBlock(JCBlock tree) {
1842 int nextadrPrev = nextadr; 1882 int nextadrPrev = nextadr;
1843 scan(tree.stats); 1883 scan(tree.stats);
1844 nextadr = nextadrPrev; 1884 nextadr = nextadrPrev;
1845 } 1885 }
1846 1886
1847 int getLogNumberOfErrors() {
1848 return 0;
1849 }
1850
1851 public void visitDoLoop(JCDoWhileLoop tree) { 1887 public void visitDoLoop(JCDoWhileLoop tree) {
1852 ListBuffer<P> prevPendingExits = pendingExits; 1888 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1853 FlowKind prevFlowKind = flowKind; 1889 FlowKind prevFlowKind = flowKind;
1854 flowKind = FlowKind.NORMAL; 1890 flowKind = FlowKind.NORMAL;
1855 final Bits initsSkip = new Bits(true); 1891 final Bits initsSkip = new Bits(true);
1856 final Bits uninitsSkip = new Bits(true); 1892 final Bits uninitsSkip = new Bits(true);
1857 pendingExits = new ListBuffer<P>(); 1893 pendingExits = new ListBuffer<>();
1858 int prevErrors = getLogNumberOfErrors(); 1894 int prevErrors = log.nerrors;
1859 do { 1895 do {
1860 final Bits uninitsEntry = new Bits(uninits); 1896 final Bits uninitsEntry = new Bits(uninits);
1861 uninitsEntry.excludeFrom(nextadr); 1897 uninitsEntry.excludeFrom(nextadr);
1862 scan(tree.body); 1898 scan(tree.body);
1863 resolveContinues(tree); 1899 resolveContinues(tree);
1864 scanCond(tree.cond); 1900 scanCond(tree.cond);
1865 if (!flowKind.isFinal()) { 1901 if (!flowKind.isFinal()) {
1866 initsSkip.assign(initsWhenFalse); 1902 initsSkip.assign(initsWhenFalse);
1867 uninitsSkip.assign(uninitsWhenFalse); 1903 uninitsSkip.assign(uninitsWhenFalse);
1868 } 1904 }
1869 if (getLogNumberOfErrors() != prevErrors || 1905 if (log.nerrors != prevErrors ||
1870 flowKind.isFinal() || 1906 flowKind.isFinal() ||
1871 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) 1907 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
1872 break; 1908 break;
1873 assignToInits(tree.cond, initsWhenTrue); 1909 inits.assign(initsWhenTrue);
1874 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); 1910 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
1875 flowKind = FlowKind.SPECULATIVE_LOOP; 1911 flowKind = FlowKind.SPECULATIVE_LOOP;
1876 } while (true); 1912 } while (true);
1877 flowKind = prevFlowKind; 1913 flowKind = prevFlowKind;
1878 assignToInits(tree, initsSkip); 1914 inits.assign(initsSkip);
1879 uninits.assign(uninitsSkip); 1915 uninits.assign(uninitsSkip);
1880 resolveBreaks(tree, prevPendingExits); 1916 resolveBreaks(tree, prevPendingExits);
1881 } 1917 }
1882 1918
1883 public void visitWhileLoop(JCWhileLoop tree) { 1919 public void visitWhileLoop(JCWhileLoop tree) {
1884 ListBuffer<P> prevPendingExits = pendingExits; 1920 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1885 FlowKind prevFlowKind = flowKind; 1921 FlowKind prevFlowKind = flowKind;
1886 flowKind = FlowKind.NORMAL; 1922 flowKind = FlowKind.NORMAL;
1887 final Bits initsSkip = new Bits(true); 1923 final Bits initsSkip = new Bits(true);
1888 final Bits uninitsSkip = new Bits(true); 1924 final Bits uninitsSkip = new Bits(true);
1889 pendingExits = new ListBuffer<>(); 1925 pendingExits = new ListBuffer<>();
1890 int prevErrors = getLogNumberOfErrors(); 1926 int prevErrors = log.nerrors;
1891 final Bits uninitsEntry = new Bits(uninits); 1927 final Bits uninitsEntry = new Bits(uninits);
1892 uninitsEntry.excludeFrom(nextadr); 1928 uninitsEntry.excludeFrom(nextadr);
1893 do { 1929 do {
1894 scanCond(tree.cond); 1930 scanCond(tree.cond);
1895 if (!flowKind.isFinal()) { 1931 if (!flowKind.isFinal()) {
1896 initsSkip.assign(initsWhenFalse) ; 1932 initsSkip.assign(initsWhenFalse) ;
1897 uninitsSkip.assign(uninitsWhenFalse); 1933 uninitsSkip.assign(uninitsWhenFalse);
1898 } 1934 }
1899 assignToInits(tree, initsWhenTrue); 1935 inits.assign(initsWhenTrue);
1900 uninits.assign(uninitsWhenTrue); 1936 uninits.assign(uninitsWhenTrue);
1901 scan(tree.body); 1937 scan(tree.body);
1902 resolveContinues(tree); 1938 resolveContinues(tree);
1903 if (getLogNumberOfErrors() != prevErrors || 1939 if (log.nerrors != prevErrors ||
1904 flowKind.isFinal() || 1940 flowKind.isFinal() ||
1905 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) { 1941 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
1906 break; 1942 break;
1907 } 1943 }
1908 uninits.assign(uninitsEntry.andSet(uninits)); 1944 uninits.assign(uninitsEntry.andSet(uninits));
1909 flowKind = FlowKind.SPECULATIVE_LOOP; 1945 flowKind = FlowKind.SPECULATIVE_LOOP;
1910 } while (true); 1946 } while (true);
1911 flowKind = prevFlowKind; 1947 flowKind = prevFlowKind;
1912 //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
1913 //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
1914 assignToInits(tree.body, initsSkip); 1950 inits.assign(initsSkip);
1915 uninits.assign(uninitsSkip); 1951 uninits.assign(uninitsSkip);
1916 resolveBreaks(tree, prevPendingExits); 1952 resolveBreaks(tree, prevPendingExits);
1917 } 1953 }
1918 1954
1919 public void visitForLoop(JCForLoop tree) { 1955 public void visitForLoop(JCForLoop tree) {
1920 ListBuffer<P> prevPendingExits = pendingExits; 1956 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1921 FlowKind prevFlowKind = flowKind; 1957 FlowKind prevFlowKind = flowKind;
1922 flowKind = FlowKind.NORMAL; 1958 flowKind = FlowKind.NORMAL;
1923 int nextadrPrev = nextadr; 1959 int nextadrPrev = nextadr;
1924 scan(tree.init); 1960 scan(tree.init);
1925 final Bits initsSkip = new Bits(true); 1961 final Bits initsSkip = new Bits(true);
1926 final Bits uninitsSkip = new Bits(true); 1962 final Bits uninitsSkip = new Bits(true);
1927 pendingExits = new ListBuffer<P>(); 1963 pendingExits = new ListBuffer<>();
1928 int prevErrors = getLogNumberOfErrors(); 1964 int prevErrors = log.nerrors;
1929 do { 1965 do {
1930 final Bits uninitsEntry = new Bits(uninits); 1966 final Bits uninitsEntry = new Bits(uninits);
1931 uninitsEntry.excludeFrom(nextadr); 1967 uninitsEntry.excludeFrom(nextadr);
1932 if (tree.cond != null) { 1968 if (tree.cond != null) {
1933 scanCond(tree.cond); 1969 scanCond(tree.cond);
1934 if (!flowKind.isFinal()) { 1970 if (!flowKind.isFinal()) {
1935 initsSkip.assign(initsWhenFalse); 1971 initsSkip.assign(initsWhenFalse);
1936 uninitsSkip.assign(uninitsWhenFalse); 1972 uninitsSkip.assign(uninitsWhenFalse);
1937 } 1973 }
1938 assignToInits(tree.body, initsWhenTrue); 1974 inits.assign(initsWhenTrue);
1939 uninits.assign(uninitsWhenTrue); 1975 uninits.assign(uninitsWhenTrue);
1940 } else if (!flowKind.isFinal()) { 1976 } else if (!flowKind.isFinal()) {
1941 initsSkip.assign(inits); 1977 initsSkip.assign(inits);
1942 initsSkip.inclRange(firstadr, nextadr); 1978 initsSkip.inclRange(firstadr, nextadr);
1943 uninitsSkip.assign(uninits); 1979 uninitsSkip.assign(uninits);
1944 uninitsSkip.inclRange(firstadr, nextadr); 1980 uninitsSkip.inclRange(firstadr, nextadr);
1945 } 1981 }
1946 scan(tree.body); 1982 scan(tree.body);
1947 resolveContinues(tree); 1983 resolveContinues(tree);
1948 scan(tree.step); 1984 scan(tree.step);
1949 if (getLogNumberOfErrors() != prevErrors || 1985 if (log.nerrors != prevErrors ||
1950 flowKind.isFinal() || 1986 flowKind.isFinal() ||
1951 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 1987 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1952 break; 1988 break;
1953 uninits.assign(uninitsEntry.andSet(uninits)); 1989 uninits.assign(uninitsEntry.andSet(uninits));
1954 flowKind = FlowKind.SPECULATIVE_LOOP; 1990 flowKind = FlowKind.SPECULATIVE_LOOP;
1955 } while (true); 1991 } while (true);
1956 flowKind = prevFlowKind; 1992 flowKind = prevFlowKind;
1957 //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
1958 //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
1959 assignToInits(tree.body, initsSkip); 1995 inits.assign(initsSkip);
1960 uninits.assign(uninitsSkip); 1996 uninits.assign(uninitsSkip);
1961 resolveBreaks(tree, prevPendingExits); 1997 resolveBreaks(tree, prevPendingExits);
1962 nextadr = nextadrPrev; 1998 nextadr = nextadrPrev;
1963 } 1999 }
1964 2000
1965 public void visitForeachLoop(JCEnhancedForLoop tree) { 2001 public void visitForeachLoop(JCEnhancedForLoop tree) {
1966 visitVarDef(tree.var); 2002 visitVarDef(tree.var);
1967 2003
1968 ListBuffer<P> prevPendingExits = pendingExits; 2004 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1969 FlowKind prevFlowKind = flowKind; 2005 FlowKind prevFlowKind = flowKind;
1970 flowKind = FlowKind.NORMAL; 2006 flowKind = FlowKind.NORMAL;
1971 int nextadrPrev = nextadr; 2007 int nextadrPrev = nextadr;
1972 scan(tree.expr); 2008 scan(tree.expr);
1973 final Bits initsStart = new Bits(inits); 2009 final Bits initsStart = new Bits(inits);
1974 final Bits uninitsStart = new Bits(uninits); 2010 final Bits uninitsStart = new Bits(uninits);
1975 2011
1976 letInit(tree.pos(), tree.var.sym); 2012 letInit(tree.pos(), tree.var.sym);
1977 pendingExits = new ListBuffer<P>(); 2013 pendingExits = new ListBuffer<>();
1978 int prevErrors = getLogNumberOfErrors(); 2014 int prevErrors = log.nerrors;
1979 do { 2015 do {
1980 final Bits uninitsEntry = new Bits(uninits); 2016 final Bits uninitsEntry = new Bits(uninits);
1981 uninitsEntry.excludeFrom(nextadr); 2017 uninitsEntry.excludeFrom(nextadr);
1982 scan(tree.body); 2018 scan(tree.body);
1983 resolveContinues(tree); 2019 resolveContinues(tree);
1984 if (getLogNumberOfErrors() != prevErrors || 2020 if (log.nerrors != prevErrors ||
1985 flowKind.isFinal() || 2021 flowKind.isFinal() ||
1986 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) 2022 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1987 break; 2023 break;
1988 uninits.assign(uninitsEntry.andSet(uninits)); 2024 uninits.assign(uninitsEntry.andSet(uninits));
1989 flowKind = FlowKind.SPECULATIVE_LOOP; 2025 flowKind = FlowKind.SPECULATIVE_LOOP;
1990 } while (true); 2026 } while (true);
1991 flowKind = prevFlowKind; 2027 flowKind = prevFlowKind;
1992 assignToInits(tree.body, initsStart); 2028 inits.assign(initsStart);
1993 uninits.assign(uninitsStart.andSet(uninits)); 2029 uninits.assign(uninitsStart.andSet(uninits));
1994 resolveBreaks(tree, prevPendingExits); 2030 resolveBreaks(tree, prevPendingExits);
1995 nextadr = nextadrPrev; 2031 nextadr = nextadrPrev;
1996 } 2032 }
1997 2033
1998 public void visitLabelled(JCLabeledStatement tree) { 2034 public void visitLabelled(JCLabeledStatement tree) {
1999 ListBuffer<P> prevPendingExits = pendingExits; 2035 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2000 pendingExits = new ListBuffer<P>(); 2036 pendingExits = new ListBuffer<>();
2001 scan(tree.body); 2037 scan(tree.body);
2002 resolveBreaks(tree, prevPendingExits); 2038 resolveBreaks(tree, prevPendingExits);
2003 } 2039 }
2004 2040
2005 public void visitSwitch(JCSwitch tree) { 2041 public void visitSwitch(JCSwitch tree) {
2006 ListBuffer<P> prevPendingExits = pendingExits; 2042 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2007 pendingExits = new ListBuffer<>(); 2043 pendingExits = new ListBuffer<>();
2008 int nextadrPrev = nextadr; 2044 int nextadrPrev = nextadr;
2009 scanExpr(tree.selector); 2045 scanExpr(tree.selector);
2010 final Bits initsSwitch = new Bits(inits); 2046 final Bits initsSwitch = new Bits(inits);
2011 final Bits uninitsSwitch = new Bits(uninits); 2047 final Bits uninitsSwitch = new Bits(uninits);
2012 boolean hasDefault = false; 2048 boolean hasDefault = false;
2013 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 2049 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
2014 assignToInits(l.head, initsSwitch); 2050 inits.assign(initsSwitch);
2015 uninits.assign(uninits.andSet(uninitsSwitch)); 2051 uninits.assign(uninits.andSet(uninitsSwitch));
2016 JCCase c = l.head; 2052 JCCase c = l.head;
2017 if (c.pat == null) { 2053 if (c.pat == null) {
2018 hasDefault = true; 2054 hasDefault = true;
2019 } else { 2055 } else {
2020 scanExpr(c.pat); 2056 scanExpr(c.pat);
2021 } 2057 }
2022 if (hasDefault) { 2058 if (hasDefault) {
2023 assignToInits(null, initsSwitch); 2059 inits.assign(initsSwitch);
2024 uninits.assign(uninits.andSet(uninitsSwitch)); 2060 uninits.assign(uninits.andSet(uninitsSwitch));
2025 } 2061 }
2026 scan(c.stats); 2062 scan(c.stats);
2027 addVars(c.stats, initsSwitch, uninitsSwitch); 2063 addVars(c.stats, initsSwitch, uninitsSwitch);
2028 if (!hasDefault) { 2064 if (!hasDefault) {
2029 assignToInits(l.head.stats.last(), initsSwitch); 2065 inits.assign(initsSwitch);
2030 uninits.assign(uninits.andSet(uninitsSwitch)); 2066 uninits.assign(uninits.andSet(uninitsSwitch));
2031 } 2067 }
2032 // Warn about fall-through if lint switch fallthrough enabled. 2068 // Warn about fall-through if lint switch fallthrough enabled.
2033 } 2069 }
2034 if (!hasDefault) { 2070 if (!hasDefault) {
2035 andSetInits(null, initsSwitch); 2071 inits.andSet(initsSwitch);
2036 } 2072 }
2037 resolveBreaks(tree, prevPendingExits); 2073 resolveBreaks(tree, prevPendingExits);
2038 nextadr = nextadrPrev; 2074 nextadr = nextadrPrev;
2039 } 2075 }
2040 // where 2076 // where
2049 uninits.incl(adr); 2085 uninits.incl(adr);
2050 } 2086 }
2051 } 2087 }
2052 } 2088 }
2053 2089
2054 boolean isEnabled(Lint.LintCategory lc) {
2055 return false;
2056 }
2057
2058 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {}
2059
2060 public void visitTry(JCTry tree) { 2090 public void visitTry(JCTry tree) {
2061 ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>(); 2091 ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2062 final Bits uninitsTryPrev = new Bits(uninitsTry); 2092 final Bits uninitsTryPrev = new Bits(uninitsTry);
2063 ListBuffer<P> prevPendingExits = pendingExits; 2093 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2064 pendingExits = new ListBuffer<>(); 2094 pendingExits = new ListBuffer<>();
2065 final Bits initsTry = new Bits(inits); 2095 final Bits initsTry = new Bits(inits);
2066 uninitsTry.assign(uninits); 2096 uninitsTry.assign(uninits);
2067 for (JCTree resource : tree.resources) { 2097 for (JCTree resource : tree.resources) {
2068 if (resource instanceof JCVariableDecl) { 2098 if (resource instanceof JCVariableDecl) {
2081 final Bits initsEnd = new Bits(inits); 2111 final Bits initsEnd = new Bits(inits);
2082 final Bits uninitsEnd = new Bits(uninits); 2112 final Bits uninitsEnd = new Bits(uninits);
2083 int nextadrCatch = nextadr; 2113 int nextadrCatch = nextadr;
2084 2114
2085 if (!resourceVarDecls.isEmpty() && 2115 if (!resourceVarDecls.isEmpty() &&
2086 isEnabled(Lint.LintCategory.TRY)) { 2116 lint.isEnabled(Lint.LintCategory.TRY)) {
2087 for (JCVariableDecl resVar : resourceVarDecls) { 2117 for (JCVariableDecl resVar : resourceVarDecls) {
2088 if (unrefdResources.includes(resVar.sym)) { 2118 if (unrefdResources.includes(resVar.sym)) {
2089 reportWarning(Lint.LintCategory.TRY, resVar.pos(), 2119 log.warning(Lint.LintCategory.TRY, resVar.pos(),
2090 "try.resource.not.referenced", resVar.sym); 2120 "try.resource.not.referenced", resVar.sym);
2091 unrefdResources.remove(resVar.sym); 2121 unrefdResources.remove(resVar.sym);
2092 } 2122 }
2093 } 2123 }
2094 } 2124 }
2100 final Bits initsCatchPrev = new Bits(initsTry); 2130 final Bits initsCatchPrev = new Bits(initsTry);
2101 final Bits uninitsCatchPrev = new Bits(uninitsTry); 2131 final Bits uninitsCatchPrev = new Bits(uninitsTry);
2102 2132
2103 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 2133 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2104 JCVariableDecl param = l.head.param; 2134 JCVariableDecl param = l.head.param;
2105 assignToInits(tree.body, initsCatchPrev); 2135 inits.assign(initsCatchPrev);
2106 uninits.assign(uninitsCatchPrev); 2136 uninits.assign(uninitsCatchPrev);
2107 scan(param); 2137 scan(param);
2108 /* 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,
2109 * then there can be synthetic variables, ignore them. 2139 * then there can be synthetic variables, ignore them.
2110 */ 2140 */
2113 initsEnd.andSet(inits); 2143 initsEnd.andSet(inits);
2114 uninitsEnd.andSet(uninits); 2144 uninitsEnd.andSet(uninits);
2115 nextadr = nextadrCatch; 2145 nextadr = nextadrCatch;
2116 } 2146 }
2117 if (tree.finalizer != null) { 2147 if (tree.finalizer != null) {
2118 assignToInits(tree.finalizer, initsTry); 2148 inits.assign(initsTry);
2119 uninits.assign(uninitsTry); 2149 uninits.assign(uninitsTry);
2120 ListBuffer<P> exits = pendingExits; 2150 ListBuffer<AssignPendingExit> exits = pendingExits;
2121 pendingExits = prevPendingExits; 2151 pendingExits = prevPendingExits;
2122 scan(tree.finalizer); 2152 scan(tree.finalizer);
2123 if (!tree.finallyCanCompleteNormally) { 2153 if (!tree.finallyCanCompleteNormally) {
2124 // discard exits and exceptions from try and finally 2154 // discard exits and exceptions from try and finally
2125 } else { 2155 } else {
2126 uninits.andSet(uninitsEnd); 2156 uninits.andSet(uninitsEnd);
2127 // FIX: this doesn't preserve source order of exits in catch 2157 // FIX: this doesn't preserve source order of exits in catch
2128 // versus finally! 2158 // versus finally!
2129 while (exits.nonEmpty()) { 2159 while (exits.nonEmpty()) {
2130 P exit = exits.next(); 2160 AssignPendingExit exit = exits.next();
2131 if (exit.exit_inits != null) { 2161 if (exit.exit_inits != null) {
2132 exit.exit_inits.orSet(inits); 2162 exit.exit_inits.orSet(inits);
2133 exit.exit_uninits.andSet(uninits); 2163 exit.exit_uninits.andSet(uninits);
2134 } 2164 }
2135 pendingExits.append(exit); 2165 pendingExits.append(exit);
2136 } 2166 }
2137 orSetInits(tree, initsEnd); 2167 inits.orSet(initsEnd);
2138 } 2168 }
2139 } else { 2169 } else {
2140 assignToInits(tree, initsEnd); 2170 inits.assign(initsEnd);
2141 uninits.assign(uninitsEnd); 2171 uninits.assign(uninitsEnd);
2142 ListBuffer<P> exits = pendingExits; 2172 ListBuffer<AssignPendingExit> exits = pendingExits;
2143 pendingExits = prevPendingExits; 2173 pendingExits = prevPendingExits;
2144 while (exits.nonEmpty()) pendingExits.append(exits.next()); 2174 while (exits.nonEmpty()) pendingExits.append(exits.next());
2145 } 2175 }
2146 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 2176 uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2147 } 2177 }
2148 2178
2149 public void visitConditional(JCConditional tree) { 2179 public void visitConditional(JCConditional tree) {
2150 scanCond(tree.cond); 2180 scanCond(tree.cond);
2151 final Bits initsBeforeElse = new Bits(initsWhenFalse); 2181 final Bits initsBeforeElse = new Bits(initsWhenFalse);
2152 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 2182 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2153 assignToInits(tree.cond, initsWhenTrue); 2183 inits.assign(initsWhenTrue);
2154 uninits.assign(uninitsWhenTrue); 2184 uninits.assign(uninitsWhenTrue);
2155 if (tree.truepart.type.hasTag(BOOLEAN) && 2185 if (tree.truepart.type.hasTag(BOOLEAN) &&
2156 tree.falsepart.type.hasTag(BOOLEAN)) { 2186 tree.falsepart.type.hasTag(BOOLEAN)) {
2157 // if b and c are boolean valued, then 2187 // if b and c are boolean valued, then
2158 // v is (un)assigned after a?b:c when true iff 2188 // v is (un)assigned after a?b:c when true iff
2161 scanCond(tree.truepart); 2191 scanCond(tree.truepart);
2162 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); 2192 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
2163 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); 2193 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
2164 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); 2194 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
2165 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); 2195 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
2166 assignToInits(tree.truepart, initsBeforeElse); 2196 inits.assign(initsBeforeElse);
2167 uninits.assign(uninitsBeforeElse); 2197 uninits.assign(uninitsBeforeElse);
2168 scanCond(tree.falsepart); 2198 scanCond(tree.falsepart);
2169 initsWhenTrue.andSet(initsAfterThenWhenTrue); 2199 initsWhenTrue.andSet(initsAfterThenWhenTrue);
2170 initsWhenFalse.andSet(initsAfterThenWhenFalse); 2200 initsWhenFalse.andSet(initsAfterThenWhenFalse);
2171 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); 2201 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
2172 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); 2202 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
2173 } else { 2203 } else {
2174 scanExpr(tree.truepart); 2204 scanExpr(tree.truepart);
2175 final Bits initsAfterThen = new Bits(inits); 2205 final Bits initsAfterThen = new Bits(inits);
2176 final Bits uninitsAfterThen = new Bits(uninits); 2206 final Bits uninitsAfterThen = new Bits(uninits);
2177 assignToInits(tree.truepart, initsBeforeElse); 2207 inits.assign(initsBeforeElse);
2178 uninits.assign(uninitsBeforeElse); 2208 uninits.assign(uninitsBeforeElse);
2179 scanExpr(tree.falsepart); 2209 scanExpr(tree.falsepart);
2180 andSetInits(tree.falsepart, initsAfterThen); 2210 inits.andSet(initsAfterThen);
2181 uninits.andSet(uninitsAfterThen); 2211 uninits.andSet(uninitsAfterThen);
2182 } 2212 }
2183 } 2213 }
2184 2214
2185 public void visitIf(JCIf tree) { 2215 public void visitIf(JCIf tree) {
2186 scanCond(tree.cond); 2216 scanCond(tree.cond);
2187 final Bits initsBeforeElse = new Bits(initsWhenFalse); 2217 final Bits initsBeforeElse = new Bits(initsWhenFalse);
2188 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); 2218 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2189 assignToInits(tree.cond, initsWhenTrue); 2219 inits.assign(initsWhenTrue);
2190 uninits.assign(uninitsWhenTrue); 2220 uninits.assign(uninitsWhenTrue);
2191 scan(tree.thenpart); 2221 scan(tree.thenpart);
2192 if (tree.elsepart != null) { 2222 if (tree.elsepart != null) {
2193 final Bits initsAfterThen = new Bits(inits); 2223 final Bits initsAfterThen = new Bits(inits);
2194 final Bits uninitsAfterThen = new Bits(uninits); 2224 final Bits uninitsAfterThen = new Bits(uninits);
2195 assignToInits(tree.thenpart, initsBeforeElse); 2225 inits.assign(initsBeforeElse);
2196 uninits.assign(uninitsBeforeElse); 2226 uninits.assign(uninitsBeforeElse);
2197 scan(tree.elsepart); 2227 scan(tree.elsepart);
2198 andSetInits(tree.elsepart, initsAfterThen); 2228 inits.andSet(initsAfterThen);
2199 uninits.andSet(uninitsAfterThen); 2229 uninits.andSet(uninitsAfterThen);
2200 } else { 2230 } else {
2201 andSetInits(tree.thenpart, initsBeforeElse); 2231 inits.andSet(initsBeforeElse);
2202 uninits.andSet(uninitsBeforeElse); 2232 uninits.andSet(uninitsBeforeElse);
2203 } 2233 }
2204 }
2205
2206 protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
2207 return null;
2208 } 2234 }
2209 2235
2210 @Override 2236 @Override
2211 public void visitBreak(JCBreak tree) { 2237 public void visitBreak(JCBreak tree) {
2212 recordExit(tree, createNewPendingExit(tree, inits, uninits)); 2238 recordExit(new AssignPendingExit(tree, inits, uninits));
2213 } 2239 }
2214 2240
2215 @Override 2241 @Override
2216 public void visitContinue(JCContinue tree) { 2242 public void visitContinue(JCContinue tree) {
2217 recordExit(tree, createNewPendingExit(tree, inits, uninits)); 2243 recordExit(new AssignPendingExit(tree, inits, uninits));
2218 } 2244 }
2219 2245
2220 @Override 2246 @Override
2221 public void visitReturn(JCReturn tree) { 2247 public void visitReturn(JCReturn tree) {
2222 scanExpr(tree.expr); 2248 scanExpr(tree.expr);
2223 recordExit(tree, createNewPendingExit(tree, inits, uninits)); 2249 recordExit(new AssignPendingExit(tree, inits, uninits));
2224 } 2250 }
2225 2251
2226 public void visitThrow(JCThrow tree) { 2252 public void visitThrow(JCThrow tree) {
2227 scanExpr(tree.expr); 2253 scanExpr(tree.expr);
2228 markDead(tree.expr); 2254 markDead();
2229 } 2255 }
2230 2256
2231 public void visitApply(JCMethodInvocation tree) { 2257 public void visitApply(JCMethodInvocation tree) {
2232 scanExpr(tree.meth); 2258 scanExpr(tree.meth);
2233 scanExprs(tree.args); 2259 scanExprs(tree.args);
2242 @Override 2268 @Override
2243 public void visitLambda(JCLambda tree) { 2269 public void visitLambda(JCLambda tree) {
2244 final Bits prevUninits = new Bits(uninits); 2270 final Bits prevUninits = new Bits(uninits);
2245 final Bits prevInits = new Bits(inits); 2271 final Bits prevInits = new Bits(inits);
2246 int returnadrPrev = returnadr; 2272 int returnadrPrev = returnadr;
2247 ListBuffer<P> prevPending = pendingExits; 2273 ListBuffer<AssignPendingExit> prevPending = pendingExits;
2248 try { 2274 try {
2249 returnadr = nextadr; 2275 returnadr = nextadr;
2250 pendingExits = new ListBuffer<P>(); 2276 pendingExits = new ListBuffer<>();
2251 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 2277 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2252 JCVariableDecl def = l.head; 2278 JCVariableDecl def = l.head;
2253 scan(def); 2279 scan(def);
2254 inits.incl(def.sym.adr); 2280 inits.incl(def.sym.adr);
2255 uninits.excl(def.sym.adr); 2281 uninits.excl(def.sym.adr);
2261 } 2287 }
2262 } 2288 }
2263 finally { 2289 finally {
2264 returnadr = returnadrPrev; 2290 returnadr = returnadrPrev;
2265 uninits.assign(prevUninits); 2291 uninits.assign(prevUninits);
2266 assignToInits(tree, prevInits); 2292 inits.assign(prevInits);
2267 pendingExits = prevPending; 2293 pendingExits = prevPending;
2268 } 2294 }
2269 } 2295 }
2270 2296
2271 public void visitNewArray(JCNewArray tree) { 2297 public void visitNewArray(JCNewArray tree) {
2277 final Bits initsExit = new Bits(inits); 2303 final Bits initsExit = new Bits(inits);
2278 final Bits uninitsExit = new Bits(uninits); 2304 final Bits uninitsExit = new Bits(uninits);
2279 scanCond(tree.cond); 2305 scanCond(tree.cond);
2280 uninitsExit.andSet(uninitsWhenTrue); 2306 uninitsExit.andSet(uninitsWhenTrue);
2281 if (tree.detail != null) { 2307 if (tree.detail != null) {
2282 assignToInits(tree, initsWhenFalse); 2308 inits.assign(initsWhenFalse);
2283 uninits.assign(uninitsWhenFalse); 2309 uninits.assign(uninitsWhenFalse);
2284 scanExpr(tree.detail); 2310 scanExpr(tree.detail);
2285 } 2311 }
2286 assignToInits(tree, initsExit); 2312 inits.assign(initsExit);
2287 uninits.assign(uninitsExit); 2313 uninits.assign(uninitsExit);
2288 } 2314 }
2289 2315
2290 public void visitAssign(JCAssign tree) { 2316 public void visitAssign(JCAssign tree) {
2291 JCTree lhs = TreeInfo.skipParens(tree.lhs); 2317 JCTree lhs = TreeInfo.skipParens(tree.lhs);
2349 switch (tree.getTag()) { 2375 switch (tree.getTag()) {
2350 case AND: 2376 case AND:
2351 scanCond(tree.lhs); 2377 scanCond(tree.lhs);
2352 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); 2378 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2353 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); 2379 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2354 assignToInits(tree.lhs, initsWhenTrue); 2380 inits.assign(initsWhenTrue);
2355 uninits.assign(uninitsWhenTrue); 2381 uninits.assign(uninitsWhenTrue);
2356 scanCond(tree.rhs); 2382 scanCond(tree.rhs);
2357 initsWhenFalse.andSet(initsWhenFalseLeft); 2383 initsWhenFalse.andSet(initsWhenFalseLeft);
2358 uninitsWhenFalse.andSet(uninitsWhenFalseLeft); 2384 uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2359 break; 2385 break;
2360 case OR: 2386 case OR:
2361 scanCond(tree.lhs); 2387 scanCond(tree.lhs);
2362 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); 2388 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2363 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); 2389 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2364 assignToInits(tree.lhs, initsWhenFalse); 2390 inits.assign(initsWhenFalse);
2365 uninits.assign(uninitsWhenFalse); 2391 uninits.assign(uninitsWhenFalse);
2366 scanCond(tree.rhs); 2392 scanCond(tree.rhs);
2367 initsWhenTrue.andSet(initsWhenTrueLeft); 2393 initsWhenTrue.andSet(initsWhenTrueLeft);
2368 uninitsWhenTrue.andSet(uninitsWhenTrueLeft); 2394 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2369 break; 2395 break;
2434 unrefdResources = null; 2460 unrefdResources = null;
2435 } 2461 }
2436 } 2462 }
2437 } 2463 }
2438 2464
2439 public class AssignAnalyzer extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> {
2440
2441 public class AssignPendingExit extends AbstractAssignAnalyzer<AssignPendingExit>.AbstractAssignPendingExit {
2442
2443 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
2444 super(tree, inits, uninits);
2445 }
2446 }
2447
2448 @Override
2449 protected AssignPendingExit createNewPendingExit(JCTree tree,
2450 Bits inits, Bits uninits) {
2451 return new AssignPendingExit(tree, inits, uninits);
2452 }
2453
2454 /** Record an initialization of a trackable variable.
2455 */
2456 @Override
2457 void letInit(DiagnosticPosition pos, VarSymbol sym) {
2458 if (sym.adr >= firstadr && trackable(sym)) {
2459 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
2460 if (!uninits.isMember(sym.adr)) {
2461 //assignment targeting an effectively final variable
2462 //makes the variable lose its status of effectively final
2463 //if the variable is _not_ definitively unassigned
2464 sym.flags_field &= ~EFFECTIVELY_FINAL;
2465 } else {
2466 uninit(sym);
2467 }
2468 }
2469 else if ((sym.flags() & FINAL) != 0) {
2470 if ((sym.flags() & PARAMETER) != 0) {
2471 if ((sym.flags() & UNION) != 0) { //multi-catch parameter
2472 log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
2473 }
2474 else {
2475 log.error(pos, "final.parameter.may.not.be.assigned",
2476 sym);
2477 }
2478 } else if (!uninits.isMember(sym.adr)) {
2479 log.error(pos, flowKind.errKey, sym);
2480 } else {
2481 uninit(sym);
2482 }
2483 }
2484 inits.incl(sym.adr);
2485 } else if ((sym.flags() & FINAL) != 0) {
2486 log.error(pos, "var.might.already.be.assigned", sym);
2487 }
2488 }
2489
2490 @Override
2491 void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
2492 if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
2493 trackable(sym) &&
2494 !inits.isMember(sym.adr)) {
2495 log.error(pos, errkey, sym);
2496 inits.incl(sym.adr);
2497 }
2498 }
2499
2500 @Override
2501 void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos,
2502 String key, Object ... args) {
2503 log.warning(lc, pos, key, args);
2504 }
2505
2506 @Override
2507 int getLogNumberOfErrors() {
2508 return log.nerrors;
2509 }
2510
2511 @Override
2512 boolean isEnabled(Lint.LintCategory lc) {
2513 return lint.isEnabled(lc);
2514 }
2515
2516 @Override
2517 public void visitClassDef(JCClassDecl tree) {
2518 if (tree.sym == null) {
2519 return;
2520 }
2521
2522 Lint lintPrev = lint;
2523 lint = lint.augment(tree.sym);
2524 try {
2525 super.visitClassDef(tree);
2526 } finally {
2527 lint = lintPrev;
2528 }
2529 }
2530
2531 @Override
2532 public void visitMethodDef(JCMethodDecl tree) {
2533 if (tree.body == null) {
2534 return;
2535 }
2536
2537 /* MemberEnter can generate synthetic methods ignore them
2538 */
2539 if ((tree.sym.flags() & SYNTHETIC) != 0) {
2540 return;
2541 }
2542
2543 Lint lintPrev = lint;
2544 lint = lint.augment(tree.sym);
2545 try {
2546 super.visitMethodDef(tree);
2547 } finally {
2548 lint = lintPrev;
2549 }
2550 }
2551
2552 @Override
2553 public void visitVarDef(JCVariableDecl tree) {
2554 if (tree.init == null) {
2555 super.visitVarDef(tree);
2556 } else {
2557 Lint lintPrev = lint;
2558 lint = lint.augment(tree.sym);
2559 try{
2560 super.visitVarDef(tree);
2561 } finally {
2562 lint = lintPrev;
2563 }
2564 }
2565 }
2566
2567 }
2568
2569 /** 2465 /**
2570 * This pass implements the last step of the dataflow analysis, namely 2466 * This pass implements the last step of the dataflow analysis, namely
2571 * the effectively-final analysis check. This checks that every local variable 2467 * the effectively-final analysis check. This checks that every local variable
2572 * reference from a lambda body/local inner class is either final or effectively final. 2468 * reference from a lambda body/local inner class is either final or effectively final.
2573 * As effectively final variables are marked as such during DA/DU, this pass must run after 2469 * As effectively final variables are marked as such during DA/DU, this pass must run after
2576 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> { 2472 class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
2577 2473
2578 JCTree currentTree; //local class or lambda 2474 JCTree currentTree; //local class or lambda
2579 2475
2580 @Override 2476 @Override
2581 void markDead(JCTree tree) { 2477 void markDead() {
2582 //do nothing 2478 //do nothing
2583 } 2479 }
2584 2480
2585 @SuppressWarnings("fallthrough") 2481 @SuppressWarnings("fallthrough")
2586 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) { 2482 void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2713 } 2609 }
2714 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) { 2610 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
2715 try { 2611 try {
2716 attrEnv = env; 2612 attrEnv = env;
2717 Flow.this.make = make; 2613 Flow.this.make = make;
2718 pendingExits = new ListBuffer<PendingExit>(); 2614 pendingExits = new ListBuffer<>();
2719 scan(tree); 2615 scan(tree);
2720 } finally { 2616 } finally {
2721 pendingExits = null; 2617 pendingExits = null;
2722 Flow.this.make = null; 2618 Flow.this.make = null;
2723 } 2619 }

mercurial