< prev index next >

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

Print this page
rev 52724 : imported patch 8214031
rev 52725 : [mq]: 8214031-review1


 283     }
 284 
 285     protected Flow(Context context) {
 286         context.put(flowKey, this);
 287         names = Names.instance(context);
 288         log = Log.instance(context);
 289         syms = Symtab.instance(context);
 290         types = Types.instance(context);
 291         chk = Check.instance(context);
 292         lint = Lint.instance(context);
 293         rs = Resolve.instance(context);
 294         diags = JCDiagnostic.Factory.instance(context);
 295         Source source = Source.instance(context);
 296         allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source);
 297     }
 298 
 299     /**
 300      * Base visitor class for all visitors implementing dataflow analysis logic.
 301      * This class define the shared logic for handling jumps (break/continue statements).
 302      */
 303     static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
 304 
 305         enum JumpKind {
 306             BREAK(JCTree.Tag.BREAK) {
 307                 @Override
 308                 JCTree getTarget(JCTree tree) {
 309                     return ((JCBreak)tree).target;
 310                 }
 311             },
 312             CONTINUE(JCTree.Tag.CONTINUE) {
 313                 @Override
 314                 JCTree getTarget(JCTree tree) {
 315                     return ((JCContinue)tree).target;
 316                 }
 317             };
 318 
 319             final JCTree.Tag treeTag;
 320 
 321             private JumpKind(Tag treeTag) {
 322                 this.treeTag = treeTag;
 323             }
 324 
 325             abstract JCTree getTarget(JCTree tree);
 326         }
 327 
 328         /** The currently pending exits that go from current inner blocks
 329          *  to an enclosing block, in source order.
 330          */
 331         ListBuffer<P> pendingExits;
 332 
 333         /** A pending exit.  These are the statements return, break, and
 334          *  continue.  In addition, exception-throwing expressions or
 335          *  statements are put here when not known to be caught.  This
 336          *  will typically result in an error unless it is within a
 337          *  try-finally whose finally block cannot complete normally.
 338          */
 339         static class PendingExit {
 340             JCTree tree;
 341 
 342             PendingExit(JCTree tree) {
 343                 this.tree = tree;
 344             }
 345 
 346             void resolveJump() {
 347                 //do nothing
 348             }
 349         }
 350 
 351         abstract void markDead();
 352 
 353         /** Record an outward transfer of control. */
 354         void recordExit(P pe) {
 355             pendingExits.append(pe);
 356             markDead();
 357         }
 358 
 359         /** Resolve all jumps of this statement. */
 360         private Liveness resolveJump(JCTree tree,
 361                          ListBuffer<P> oldPendingExits,
 362                          JumpKind jk) {
 363             boolean resolved = false;
 364             List<P> exits = pendingExits.toList();
 365             pendingExits = oldPendingExits;
 366             for (; exits.nonEmpty(); exits = exits.tail) {
 367                 P exit = exits.head;
 368                 if (exit.tree.hasTag(jk.treeTag) &&
 369                         jk.getTarget(exit.tree) == tree) {
 370                     exit.resolveJump();
 371                     resolved = true;
 372                 } else {
 373                     pendingExits.append(exit);
 374                 }
 375             }
 376             return Liveness.from(resolved);
 377         }
 378 
 379         /** Resolve all continues of this statement. */
 380         Liveness resolveContinues(JCTree tree) {
 381             return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
 382         }
 383 
 384         /** Resolve all breaks of this statement. */
 385         Liveness resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
 386             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
 387         }
 388 
 389         @Override
 390         public void scan(JCTree tree) {
 391             if (tree != null && (
 392                     tree.type == null ||
 393                     tree.type != Type.stuckType)) {
 394                 super.scan(tree);
 395             }
 396         }
 397 
 398         public void visitPackageDef(JCPackageDecl tree) {
 399             // Do nothing for PackageDecl
 400         }
 401 
 402         protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
 403             JCBreak brk = make.at(Position.NOPOS).Break(null);
 404             brk.target = swtch;
 405             scan(brk);
 406         }
 407     }
 408 
 409     /**
 410      * This pass implements the first step of the dataflow analysis, namely
 411      * the liveness analysis check. This checks that every statement is reachable.
 412      * The output of this analysis pass are used by other analyzers. This analyzer
 413      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
 414      */
 415     class AliveAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
 416 
 417         /** A flag that indicates whether the last statement could
 418          *  complete normally.
 419          */
 420         private Liveness alive;
 421 
 422         @Override
 423         void markDead() {
 424             alive = Liveness.DEAD;
 425         }
 426 
 427     /*************************************************************************
 428      * Visitor methods for statements and definitions
 429      *************************************************************************/
 430 
 431         /** Analyze a definition.
 432          */
 433         void scanDef(JCTree tree) {
 434             scanStat(tree);
 435             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && alive == Liveness.DEAD) {


 814         public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
 815             try {
 816                 attrEnv = env;
 817                 Flow.this.make = make;
 818                 pendingExits = new ListBuffer<>();
 819                 alive = Liveness.ALIVE;
 820                 scan(tree);
 821             } finally {
 822                 pendingExits = null;
 823                 Flow.this.make = null;
 824             }
 825         }
 826     }
 827 
 828     /**
 829      * This pass implements the second step of the dataflow analysis, namely
 830      * the exception analysis. This is to ensure that every checked exception that is
 831      * thrown is declared or caught. The analyzer uses some info that has been set by
 832      * the liveliness analyzer.
 833      */
 834     class FlowAnalyzer extends BaseAnalyzer<FlowAnalyzer.FlowPendingExit> {
 835 
 836         /** A flag that indicates whether the last statement could
 837          *  complete normally.
 838          */
 839         HashMap<Symbol, List<Type>> preciseRethrowTypes;
 840 
 841         /** The current class being defined.
 842          */
 843         JCClassDecl classDef;
 844 
 845         /** The list of possibly thrown declarable exceptions.
 846          */
 847         List<Type> thrown;
 848 
 849         /** The list of exceptions that are either caught or declared to be
 850          *  thrown.
 851          */
 852         List<Type> caught;
 853 
 854         class FlowPendingExit extends BaseAnalyzer.PendingExit {
 855 
 856             Type thrown;
 857 
 858             FlowPendingExit(JCTree tree, Type thrown) {
 859                 super(tree);
 860                 this.thrown = thrown;
 861             }
 862         }
 863 
 864         @Override
 865         void markDead() {
 866             //do nothing
 867         }
 868 
 869         /*-------------------- Exceptions ----------------------*/
 870 
 871         /** Complain that pending exceptions are not caught.
 872          */
 873         void errorUncaught() {
 874             for (FlowPendingExit exit = pendingExits.next();
 875                  exit != null;
 876                  exit = pendingExits.next()) {


 877                 if (classDef != null &&
 878                     classDef.pos == exit.tree.pos) {
 879                     log.error(exit.tree.pos(),
 880                               Errors.UnreportedExceptionDefaultConstructor(exit.thrown));
 881                 } else if (exit.tree.hasTag(VARDEF) &&
 882                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
 883                     log.error(exit.tree.pos(),
 884                               Errors.UnreportedExceptionImplicitClose(exit.thrown,
 885                                                                       ((JCVariableDecl)exit.tree).sym.name));
 886                 } else {
 887                     log.error(exit.tree.pos(),
 888                               Errors.UnreportedExceptionNeedToCatchOrThrow(exit.thrown));
 889                 }
 890             }
 891         }
 892 
 893         /** Record that exception is potentially thrown and check that it
 894          *  is caught.
 895          */
 896         void markThrown(JCTree tree, Type exc) {
 897             if (!chk.isUnchecked(tree.pos(), exc)) {
 898                 if (!chk.isHandled(exc, caught)) {
 899                     pendingExits.append(new FlowPendingExit(tree, exc));
 900                 }
 901                 thrown = chk.incl(exc, thrown);
 902             }
 903         }
 904 
 905     /*************************************************************************
 906      * Visitor methods for statements and definitions
 907      *************************************************************************/
 908 
 909         /* ------------ Visitor methods for various sorts of trees -------------*/
 910 
 911         public void visitClassDef(JCClassDecl tree) {
 912             if (tree.sym == null) return;
 913 
 914             JCClassDecl classDefPrev = classDef;
 915             List<Type> thrownPrev = thrown;
 916             List<Type> caughtPrev = caught;
 917             ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
 918             Lint lintPrev = lint;
 919             boolean anonymousClass = tree.name == names.empty;
 920             pendingExits = new ListBuffer<>();
 921             if (!anonymousClass) {
 922                 caught = List.nil();
 923             }
 924             classDef = tree;
 925             thrown = List.nil();
 926             lint = lint.augment(tree.sym);
 927 
 928             try {
 929                 // process all the static initializers
 930                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 931                     if (!l.head.hasTag(METHODDEF) &&
 932                         (TreeInfo.flags(l.head) & STATIC) != 0) {
 933                         scan(l.head);
 934                         errorUncaught();
 935                     }
 936                 }
 937 


1007             Lint lintPrev = lint;
1008 
1009             lint = lint.augment(tree.sym);
1010 
1011             Assert.check(pendingExits.isEmpty());
1012 
1013             try {
1014                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1015                     JCVariableDecl def = l.head;
1016                     scan(def);
1017                 }
1018                 if (TreeInfo.isInitialConstructor(tree))
1019                     caught = chk.union(caught, mthrown);
1020                 else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
1021                     caught = mthrown;
1022                 // else we are in an instance initializer block;
1023                 // leave caught unchanged.
1024 
1025                 scan(tree.body);
1026 
1027                 List<FlowPendingExit> exits = pendingExits.toList();
1028                 pendingExits = new ListBuffer<>();
1029                 while (exits.nonEmpty()) {
1030                     FlowPendingExit exit = exits.head;
1031                     exits = exits.tail;
1032                     if (exit.thrown == null) {
1033                         Assert.check(exit.tree.hasTag(RETURN));
1034                     } else {
1035                         // uncaught throws will be reported later
1036                         pendingExits.append(exit);
1037                     }
1038                 }
1039             } finally {
1040                 caught = caughtPrev;
1041                 lint = lintPrev;
1042             }
1043         }
1044 
1045         public void visitVarDef(JCVariableDecl tree) {
1046             if (tree.init != null) {
1047                 Lint lintPrev = lint;
1048                 lint = lint.augment(tree.sym);
1049                 try{
1050                     scan(tree.init);
1051                 } finally {
1052                     lint = lintPrev;
1053                 }
1054             }
1055         }
1056 
1057         public void visitBlock(JCBlock tree) {
1058             scan(tree.stats);
1059         }
1060 
1061         public void visitDoLoop(JCDoWhileLoop tree) {
1062             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1063             pendingExits = new ListBuffer<>();
1064             scan(tree.body);
1065             resolveContinues(tree);
1066             scan(tree.cond);
1067             resolveBreaks(tree, prevPendingExits);
1068         }
1069 
1070         public void visitWhileLoop(JCWhileLoop tree) {
1071             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1072             pendingExits = new ListBuffer<>();
1073             scan(tree.cond);
1074             scan(tree.body);
1075             resolveContinues(tree);
1076             resolveBreaks(tree, prevPendingExits);
1077         }
1078 
1079         public void visitForLoop(JCForLoop tree) {
1080             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1081             scan(tree.init);
1082             pendingExits = new ListBuffer<>();
1083             if (tree.cond != null) {
1084                 scan(tree.cond);
1085             }
1086             scan(tree.body);
1087             resolveContinues(tree);
1088             scan(tree.step);
1089             resolveBreaks(tree, prevPendingExits);
1090         }
1091 
1092         public void visitForeachLoop(JCEnhancedForLoop tree) {
1093             visitVarDef(tree.var);
1094             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1095             scan(tree.expr);
1096             pendingExits = new ListBuffer<>();
1097             scan(tree.body);
1098             resolveContinues(tree);
1099             resolveBreaks(tree, prevPendingExits);
1100         }
1101 
1102         public void visitLabelled(JCLabeledStatement tree) {
1103             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1104             pendingExits = new ListBuffer<>();
1105             scan(tree.body);
1106             resolveBreaks(tree, prevPendingExits);
1107         }
1108 
1109         public void visitSwitch(JCSwitch tree) {
1110             handleSwitch(tree, tree.selector, tree.cases);
1111         }
1112 
1113         @Override
1114         public void visitSwitchExpression(JCSwitchExpression tree) {
1115             handleSwitch(tree, tree.selector, tree.cases);
1116         }
1117 
1118         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
1119             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1120             pendingExits = new ListBuffer<>();
1121             scan(selector);
1122             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
1123                 JCCase c = l.head;
1124                 scan(c.pats);
1125                 scan(c.stats);
1126             }
1127             resolveBreaks(tree, prevPendingExits);
1128         }
1129 
1130         public void visitTry(JCTry tree) {
1131             List<Type> caughtPrev = caught;
1132             List<Type> thrownPrev = thrown;
1133             thrown = List.nil();
1134             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1135                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1136                         ((JCTypeUnion)l.head.param.vartype).alternatives :
1137                         List.of(l.head.param.vartype);
1138                 for (JCExpression ct : subClauses) {
1139                     caught = chk.incl(ct.type, caught);
1140                 }
1141             }
1142 
1143             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1144             pendingExits = new ListBuffer<>();
1145             for (JCTree resource : tree.resources) {
1146                 if (resource instanceof JCVariableDecl) {
1147                     JCVariableDecl vdecl = (JCVariableDecl) resource;
1148                     visitVarDef(vdecl);
1149                 } else if (resource instanceof JCExpression) {
1150                     scan((JCExpression) resource);
1151                 } else {
1152                     throw new AssertionError(tree);  // parser error
1153                 }
1154             }
1155             for (JCTree resource : tree.resources) {
1156                 List<Type> closeableSupertypes = resource.type.isCompound() ?
1157                     types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1158                     List.of(resource.type);
1159                 for (Type sup : closeableSupertypes) {
1160                     if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1161                         Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1162                                 attrEnv,
1163                                 types.skipTypeVars(sup, false),


1187                 List<Type> ctypes = List.nil();
1188                 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1189                 for (JCExpression ct : subClauses) {
1190                     Type exc = ct.type;
1191                     if (exc != syms.unknownType) {
1192                         ctypes = ctypes.append(exc);
1193                         if (types.isSameType(exc, syms.objectType))
1194                             continue;
1195                         checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1196                         caughtInTry = chk.incl(exc, caughtInTry);
1197                     }
1198                 }
1199                 scan(param);
1200                 preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1201                 scan(l.head.body);
1202                 preciseRethrowTypes.remove(param.sym);
1203             }
1204             if (tree.finalizer != null) {
1205                 List<Type> savedThrown = thrown;
1206                 thrown = List.nil();
1207                 ListBuffer<FlowPendingExit> exits = pendingExits;
1208                 pendingExits = prevPendingExits;
1209                 scan(tree.finalizer);
1210                 if (!tree.finallyCanCompleteNormally) {
1211                     // discard exits and exceptions from try and finally
1212                     thrown = chk.union(thrown, thrownPrev);
1213                 } else {
1214                     thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1215                     thrown = chk.union(thrown, savedThrown);
1216                     // FIX: this doesn't preserve source order of exits in catch
1217                     // versus finally!
1218                     while (exits.nonEmpty()) {
1219                         pendingExits.append(exits.next());
1220                     }
1221                 }
1222             } else {
1223                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1224                 ListBuffer<FlowPendingExit> exits = pendingExits;
1225                 pendingExits = prevPendingExits;
1226                 while (exits.nonEmpty()) pendingExits.append(exits.next());
1227             }
1228         }
1229 
1230         @Override
1231         public void visitIf(JCIf tree) {
1232             scan(tree.cond);
1233             scan(tree.thenpart);
1234             if (tree.elsepart != null) {
1235                 scan(tree.elsepart);
1236             }
1237         }
1238 
1239         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1240             if (chk.subset(exc, caughtInTry)) {
1241                 log.error(pos, Errors.ExceptAlreadyCaught(exc));
1242             } else if (!chk.isUnchecked(pos, exc) &&
1243                     !isExceptionOrThrowable(exc) &&
1244                     !chk.intersects(exc, thrownInTry)) {


1250                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1251                 // exception, that would have been covered in the branch above
1252                 if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1253                         !isExceptionOrThrowable(exc)) {
1254                     Warning key = catchableThrownTypes.length() == 1 ?
1255                             Warnings.UnreachableCatch(catchableThrownTypes) :
1256                             Warnings.UnreachableCatch1(catchableThrownTypes);
1257                     log.warning(pos, key);
1258                 }
1259             }
1260         }
1261         //where
1262             private boolean isExceptionOrThrowable(Type exc) {
1263                 return exc.tsym == syms.throwableType.tsym ||
1264                     exc.tsym == syms.exceptionType.tsym;
1265             }
1266 
1267         public void visitBreak(JCBreak tree) {
1268             if (tree.isValueBreak())
1269                 scan(tree.value);
1270             recordExit(new FlowPendingExit(tree, null));
1271         }
1272 
1273         public void visitContinue(JCContinue tree) {
1274             recordExit(new FlowPendingExit(tree, null));
1275         }
1276 
1277         public void visitReturn(JCReturn tree) {
1278             scan(tree.expr);
1279             recordExit(new FlowPendingExit(tree, null));
1280         }
1281 
1282         public void visitThrow(JCThrow tree) {
1283             scan(tree.expr);
1284             Symbol sym = TreeInfo.symbol(tree.expr);
1285             if (sym != null &&
1286                 sym.kind == VAR &&
1287                 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1288                 preciseRethrowTypes.get(sym) != null) {
1289                 for (Type t : preciseRethrowTypes.get(sym)) {
1290                     markThrown(tree, t);
1291                 }
1292             }
1293             else {
1294                 markThrown(tree, tree.expr.type);
1295             }
1296             markDead();
1297         }
1298 
1299         public void visitApply(JCMethodInvocation tree) {


1326                     for (List<Type> l = tree.constructor.type.getThrownTypes();
1327                          l.nonEmpty();
1328                          l = l.tail) {
1329                         caught = chk.incl(l.head, caught);
1330                     }
1331                 scan(tree.def);
1332             }
1333             finally {
1334                 caught = caughtPrev;
1335             }
1336         }
1337 
1338         @Override
1339         public void visitLambda(JCLambda tree) {
1340             if (tree.type != null &&
1341                     tree.type.isErroneous()) {
1342                 return;
1343             }
1344             List<Type> prevCaught = caught;
1345             List<Type> prevThrown = thrown;
1346             ListBuffer<FlowPendingExit> prevPending = pendingExits;
1347             try {
1348                 pendingExits = new ListBuffer<>();
1349                 caught = tree.getDescriptorType(types).getThrownTypes();
1350                 thrown = List.nil();
1351                 scan(tree.body);
1352                 List<FlowPendingExit> exits = pendingExits.toList();
1353                 pendingExits = new ListBuffer<>();
1354                 while (exits.nonEmpty()) {
1355                     FlowPendingExit exit = exits.head;
1356                     exits = exits.tail;
1357                     if (exit.thrown == null) {
1358                         Assert.check(exit.tree.hasTag(RETURN));
1359                     } else {
1360                         // uncaught throws will be reported later
1361                         pendingExits.append(exit);
1362                     }
1363                 }
1364 
1365                 errorUncaught();
1366             } finally {
1367                 pendingExits = prevPending;
1368                 caught = prevCaught;
1369                 thrown = prevThrown;
1370             }
1371         }
1372 
1373         public void visitModuleDef(JCModuleDecl tree) {
1374             // Do nothing for modules
1375         }
1376 
1377     /**************************************************************************


1471         @Override
1472         public void visitClassDef(JCClassDecl tree) {
1473             //skip
1474         }
1475     }
1476 
1477     /**
1478      * Specialized pass that performs inference of thrown types for lambdas.
1479      */
1480     class LambdaFlowAnalyzer extends FlowAnalyzer {
1481         List<Type> inferredThrownTypes;
1482         boolean inLambda;
1483         @Override
1484         public void visitLambda(JCLambda tree) {
1485             if ((tree.type != null &&
1486                     tree.type.isErroneous()) || inLambda) {
1487                 return;
1488             }
1489             List<Type> prevCaught = caught;
1490             List<Type> prevThrown = thrown;
1491             ListBuffer<FlowPendingExit> prevPending = pendingExits;
1492             inLambda = true;
1493             try {
1494                 pendingExits = new ListBuffer<>();
1495                 caught = List.of(syms.throwableType);
1496                 thrown = List.nil();
1497                 scan(tree.body);
1498                 inferredThrownTypes = thrown;
1499             } finally {
1500                 pendingExits = prevPending;
1501                 caught = prevCaught;
1502                 thrown = prevThrown;
1503                 inLambda = false;
1504             }
1505         }
1506         @Override
1507         public void visitClassDef(JCClassDecl tree) {
1508             //skip
1509         }
1510     }
1511 
1512     /**
1513      * This pass implements (i) definite assignment analysis, which ensures that
1514      * each variable is assigned when used and (ii) definite unassignment analysis,
1515      * which ensures that no final variable is assigned more than once. This visitor
1516      * depends on the results of the liveliness analyzer. This pass is also used to mark
1517      * effectively-final local variables/parameters.
1518      */
1519 
1520     public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
1521 
1522         /** The set of definitely assigned variables.
1523          */
1524         final Bits inits;
1525 
1526         /** The set of definitely unassigned variables.
1527          */
1528         final Bits uninits;
1529 
1530         /** The set of variables that are definitely unassigned everywhere
1531          *  in current try block. This variable is maintained lazily; it is
1532          *  updated only when something gets removed from uninits,
1533          *  typically by being assigned in reachable code.  To obtain the
1534          *  correct set of variables which are definitely unassigned
1535          *  anywhere in current try block, intersect uninitsTry and
1536          *  uninits.
1537          */
1538         final Bits uninitsTry;
1539 
1540         /** When analyzing a condition, inits and uninits are null.


1818             }
1819         }
1820 
1821         /* ------------ Visitor methods for various sorts of trees -------------*/
1822 
1823         public void visitClassDef(JCClassDecl tree) {
1824             if (tree.sym == null) {
1825                 return;
1826             }
1827 
1828             Lint lintPrev = lint;
1829             lint = lint.augment(tree.sym);
1830             try {
1831                 if (tree.sym == null) {
1832                     return;
1833                 }
1834 
1835                 JCClassDecl classDefPrev = classDef;
1836                 int firstadrPrev = firstadr;
1837                 int nextadrPrev = nextadr;
1838                 ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
1839 
1840                 pendingExits = new ListBuffer<>();
1841                 if (tree.name != names.empty) {
1842                     firstadr = nextadr;
1843                 }
1844                 classDef = tree;
1845                 try {
1846                     // define all the static fields
1847                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1848                         if (l.head.hasTag(VARDEF)) {
1849                             JCVariableDecl def = (JCVariableDecl)l.head;
1850                             if ((def.mods.flags & STATIC) != 0) {
1851                                 VarSymbol sym = def.sym;
1852                                 if (trackable(sym)) {
1853                                     newVar(def);
1854                                 }
1855                             }
1856                         }
1857                     }
1858 


1953                     scan(tree.body);
1954 
1955                     if (isInitialConstructor) {
1956                         boolean isSynthesized = (tree.sym.flags() &
1957                                                  GENERATEDCONSTR) != 0;
1958                         for (int i = firstadr; i < nextadr; i++) {
1959                             JCVariableDecl vardecl = vardecls[i];
1960                             VarSymbol var = vardecl.sym;
1961                             if (var.owner == classDef.sym) {
1962                                 // choose the diagnostic position based on whether
1963                                 // the ctor is default(synthesized) or not
1964                                 if (isSynthesized) {
1965                                     checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
1966                                         var, Errors.VarNotInitializedInDefaultConstructor(var));
1967                                 } else {
1968                                     checkInit(TreeInfo.diagEndPos(tree.body), var);
1969                                 }
1970                             }
1971                         }
1972                     }
1973                     List<AssignPendingExit> exits = pendingExits.toList();
1974                     pendingExits = new ListBuffer<>();
1975                     while (exits.nonEmpty()) {
1976                         AssignPendingExit exit = exits.head;
1977                         exits = exits.tail;
1978                         Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1979                         if (isInitialConstructor) {
1980                             inits.assign(exit.exit_inits);

1981                             for (int i = firstadr; i < nextadr; i++) {
1982                                 checkInit(exit.tree.pos(), vardecls[i].sym);
1983                             }
1984                         }
1985                     }
1986                 } finally {
1987                     inits.assign(initsPrev);
1988                     uninits.assign(uninitsPrev);
1989                     nextadr = nextadrPrev;
1990                     firstadr = firstadrPrev;
1991                     returnadr = returnadrPrev;
1992                     isInitialConstructor = lastInitialConstructor;
1993                 }
1994             } finally {
1995                 lint = lintPrev;
1996             }
1997         }
1998 
1999         protected void initParam(JCVariableDecl def) {
2000             inits.incl(def.sym.adr);


2010                     newVar(tree);
2011                 }
2012                 if (tree.init != null) {
2013                     scanExpr(tree.init);
2014                     if (track) {
2015                         letInit(tree.pos(), tree.sym);
2016                     }
2017                 }
2018             } finally {
2019                 lint = lintPrev;
2020             }
2021         }
2022 
2023         public void visitBlock(JCBlock tree) {
2024             int nextadrPrev = nextadr;
2025             scan(tree.stats);
2026             nextadr = nextadrPrev;
2027         }
2028 
2029         public void visitDoLoop(JCDoWhileLoop tree) {
2030             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2031             FlowKind prevFlowKind = flowKind;
2032             flowKind = FlowKind.NORMAL;
2033             final Bits initsSkip = new Bits(true);
2034             final Bits uninitsSkip = new Bits(true);
2035             pendingExits = new ListBuffer<>();
2036             int prevErrors = log.nerrors;
2037             do {
2038                 final Bits uninitsEntry = new Bits(uninits);
2039                 uninitsEntry.excludeFrom(nextadr);
2040                 scan(tree.body);
2041                 resolveContinues(tree);
2042                 scanCond(tree.cond);
2043                 if (!flowKind.isFinal()) {
2044                     initsSkip.assign(initsWhenFalse);
2045                     uninitsSkip.assign(uninitsWhenFalse);
2046                 }
2047                 if (log.nerrors !=  prevErrors ||
2048                     flowKind.isFinal() ||
2049                     new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
2050                     break;
2051                 inits.assign(initsWhenTrue);
2052                 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
2053                 flowKind = FlowKind.SPECULATIVE_LOOP;
2054             } while (true);
2055             flowKind = prevFlowKind;
2056             inits.assign(initsSkip);
2057             uninits.assign(uninitsSkip);
2058             resolveBreaks(tree, prevPendingExits);
2059         }
2060 
2061         public void visitWhileLoop(JCWhileLoop tree) {
2062             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2063             FlowKind prevFlowKind = flowKind;
2064             flowKind = FlowKind.NORMAL;
2065             final Bits initsSkip = new Bits(true);
2066             final Bits uninitsSkip = new Bits(true);
2067             pendingExits = new ListBuffer<>();
2068             int prevErrors = log.nerrors;
2069             final Bits uninitsEntry = new Bits(uninits);
2070             uninitsEntry.excludeFrom(nextadr);
2071             do {
2072                 scanCond(tree.cond);
2073                 if (!flowKind.isFinal()) {
2074                     initsSkip.assign(initsWhenFalse) ;
2075                     uninitsSkip.assign(uninitsWhenFalse);
2076                 }
2077                 inits.assign(initsWhenTrue);
2078                 uninits.assign(uninitsWhenTrue);
2079                 scan(tree.body);
2080                 resolveContinues(tree);
2081                 if (log.nerrors != prevErrors ||
2082                     flowKind.isFinal() ||
2083                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
2084                     break;
2085                 }
2086                 uninits.assign(uninitsEntry.andSet(uninits));
2087                 flowKind = FlowKind.SPECULATIVE_LOOP;
2088             } while (true);
2089             flowKind = prevFlowKind;
2090             //a variable is DA/DU after the while statement, if it's DA/DU assuming the
2091             //branch is not taken AND if it's DA/DU before any break statement
2092             inits.assign(initsSkip);
2093             uninits.assign(uninitsSkip);
2094             resolveBreaks(tree, prevPendingExits);
2095         }
2096 
2097         public void visitForLoop(JCForLoop tree) {
2098             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2099             FlowKind prevFlowKind = flowKind;
2100             flowKind = FlowKind.NORMAL;
2101             int nextadrPrev = nextadr;
2102             scan(tree.init);
2103             final Bits initsSkip = new Bits(true);
2104             final Bits uninitsSkip = new Bits(true);
2105             pendingExits = new ListBuffer<>();
2106             int prevErrors = log.nerrors;
2107             do {
2108                 final Bits uninitsEntry = new Bits(uninits);
2109                 uninitsEntry.excludeFrom(nextadr);
2110                 if (tree.cond != null) {
2111                     scanCond(tree.cond);
2112                     if (!flowKind.isFinal()) {
2113                         initsSkip.assign(initsWhenFalse);
2114                         uninitsSkip.assign(uninitsWhenFalse);
2115                     }
2116                     inits.assign(initsWhenTrue);
2117                     uninits.assign(uninitsWhenTrue);
2118                 } else if (!flowKind.isFinal()) {


2126                 scan(tree.step);
2127                 if (log.nerrors != prevErrors ||
2128                     flowKind.isFinal() ||
2129                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2130                     break;
2131                 uninits.assign(uninitsEntry.andSet(uninits));
2132                 flowKind = FlowKind.SPECULATIVE_LOOP;
2133             } while (true);
2134             flowKind = prevFlowKind;
2135             //a variable is DA/DU after a for loop, if it's DA/DU assuming the
2136             //branch is not taken AND if it's DA/DU before any break statement
2137             inits.assign(initsSkip);
2138             uninits.assign(uninitsSkip);
2139             resolveBreaks(tree, prevPendingExits);
2140             nextadr = nextadrPrev;
2141         }
2142 
2143         public void visitForeachLoop(JCEnhancedForLoop tree) {
2144             visitVarDef(tree.var);
2145 
2146             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2147             FlowKind prevFlowKind = flowKind;
2148             flowKind = FlowKind.NORMAL;
2149             int nextadrPrev = nextadr;
2150             scan(tree.expr);
2151             final Bits initsStart = new Bits(inits);
2152             final Bits uninitsStart = new Bits(uninits);
2153 
2154             letInit(tree.pos(), tree.var.sym);
2155             pendingExits = new ListBuffer<>();
2156             int prevErrors = log.nerrors;
2157             do {
2158                 final Bits uninitsEntry = new Bits(uninits);
2159                 uninitsEntry.excludeFrom(nextadr);
2160                 scan(tree.body);
2161                 resolveContinues(tree);
2162                 if (log.nerrors != prevErrors ||
2163                     flowKind.isFinal() ||
2164                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2165                     break;
2166                 uninits.assign(uninitsEntry.andSet(uninits));
2167                 flowKind = FlowKind.SPECULATIVE_LOOP;
2168             } while (true);
2169             flowKind = prevFlowKind;
2170             inits.assign(initsStart);
2171             uninits.assign(uninitsStart.andSet(uninits));
2172             resolveBreaks(tree, prevPendingExits);
2173             nextadr = nextadrPrev;
2174         }
2175 
2176         public void visitLabelled(JCLabeledStatement tree) {
2177             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2178             pendingExits = new ListBuffer<>();
2179             scan(tree.body);
2180             resolveBreaks(tree, prevPendingExits);
2181         }
2182 
2183         public void visitSwitch(JCSwitch tree) {
2184             handleSwitch(tree, tree.selector, tree.cases);
2185         }
2186 
2187         public void visitSwitchExpression(JCSwitchExpression tree) {
2188             handleSwitch(tree, tree.selector, tree.cases);
2189         }
2190 
2191         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
2192             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2193             pendingExits = new ListBuffer<>();
2194             int nextadrPrev = nextadr;
2195             scanExpr(selector);
2196             final Bits initsSwitch = new Bits(inits);
2197             final Bits uninitsSwitch = new Bits(uninits);
2198             boolean hasDefault = false;
2199             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
2200                 inits.assign(initsSwitch);
2201                 uninits.assign(uninits.andSet(uninitsSwitch));
2202                 JCCase c = l.head;
2203                 if (c.pats.isEmpty()) {
2204                     hasDefault = true;
2205                 } else {
2206                     for (JCExpression pat : c.pats) {
2207                         scanExpr(pat);
2208                     }
2209                 }
2210                 if (hasDefault) {
2211                     inits.assign(initsSwitch);
2212                     uninits.assign(uninits.andSet(uninitsSwitch));


2228             resolveBreaks(tree, prevPendingExits);
2229             nextadr = nextadrPrev;
2230         }
2231         // where
2232             /** Add any variables defined in stats to inits and uninits. */
2233             private void addVars(List<JCStatement> stats, final Bits inits,
2234                                         final Bits uninits) {
2235                 for (;stats.nonEmpty(); stats = stats.tail) {
2236                     JCTree stat = stats.head;
2237                     if (stat.hasTag(VARDEF)) {
2238                         int adr = ((JCVariableDecl) stat).sym.adr;
2239                         inits.excl(adr);
2240                         uninits.incl(adr);
2241                     }
2242                 }
2243             }
2244 
2245         public void visitTry(JCTry tree) {
2246             ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2247             final Bits uninitsTryPrev = new Bits(uninitsTry);
2248             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2249             pendingExits = new ListBuffer<>();
2250             final Bits initsTry = new Bits(inits);
2251             uninitsTry.assign(uninits);
2252             for (JCTree resource : tree.resources) {
2253                 if (resource instanceof JCVariableDecl) {
2254                     JCVariableDecl vdecl = (JCVariableDecl) resource;
2255                     visitVarDef(vdecl);
2256                     unrefdResources.enter(vdecl.sym);
2257                     resourceVarDecls.append(vdecl);
2258                 } else if (resource instanceof JCExpression) {
2259                     scanExpr((JCExpression) resource);
2260                 } else {
2261                     throw new AssertionError(tree);  // parser error
2262                 }
2263             }
2264             scan(tree.body);
2265             uninitsTry.andSet(uninits);
2266             final Bits initsEnd = new Bits(inits);
2267             final Bits uninitsEnd = new Bits(uninits);
2268             int nextadrCatch = nextadr;


2285             final Bits initsCatchPrev = new Bits(initsTry);
2286             final Bits uninitsCatchPrev = new Bits(uninitsTry);
2287 
2288             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2289                 JCVariableDecl param = l.head.param;
2290                 inits.assign(initsCatchPrev);
2291                 uninits.assign(uninitsCatchPrev);
2292                 scan(param);
2293                 /* If this is a TWR and we are executing the code from Gen,
2294                  * then there can be synthetic variables, ignore them.
2295                  */
2296                 initParam(param);
2297                 scan(l.head.body);
2298                 initsEnd.andSet(inits);
2299                 uninitsEnd.andSet(uninits);
2300                 nextadr = nextadrCatch;
2301             }
2302             if (tree.finalizer != null) {
2303                 inits.assign(initsTry);
2304                 uninits.assign(uninitsTry);
2305                 ListBuffer<AssignPendingExit> exits = pendingExits;
2306                 pendingExits = prevPendingExits;
2307                 scan(tree.finalizer);
2308                 if (!tree.finallyCanCompleteNormally) {
2309                     // discard exits and exceptions from try and finally
2310                 } else {
2311                     uninits.andSet(uninitsEnd);
2312                     // FIX: this doesn't preserve source order of exits in catch
2313                     // versus finally!
2314                     while (exits.nonEmpty()) {
2315                         AssignPendingExit exit = exits.next();
2316                         if (exit.exit_inits != null) {
2317                             exit.exit_inits.orSet(inits);
2318                             exit.exit_uninits.andSet(uninits);
2319                         }
2320                         pendingExits.append(exit);
2321                     }
2322                     inits.orSet(initsEnd);
2323                 }
2324             } else {
2325                 inits.assign(initsEnd);
2326                 uninits.assign(uninitsEnd);
2327                 ListBuffer<AssignPendingExit> exits = pendingExits;
2328                 pendingExits = prevPendingExits;
2329                 while (exits.nonEmpty()) pendingExits.append(exits.next());
2330             }
2331             uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2332         }
2333 
2334         public void visitConditional(JCConditional tree) {
2335             scanCond(tree.cond);
2336             final Bits initsBeforeElse = new Bits(initsWhenFalse);
2337             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2338             inits.assign(initsWhenTrue);
2339             uninits.assign(uninitsWhenTrue);
2340             if (tree.truepart.type.hasTag(BOOLEAN) &&
2341                 tree.falsepart.type.hasTag(BOOLEAN)) {
2342                 // if b and c are boolean valued, then
2343                 // v is (un)assigned after a?b:c when true iff
2344                 //    v is (un)assigned after b when true and
2345                 //    v is (un)assigned after c when true
2346                 scanCond(tree.truepart);
2347                 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);


2373             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2374             inits.assign(initsWhenTrue);
2375             uninits.assign(uninitsWhenTrue);
2376             scan(tree.thenpart);
2377             if (tree.elsepart != null) {
2378                 final Bits initsAfterThen = new Bits(inits);
2379                 final Bits uninitsAfterThen = new Bits(uninits);
2380                 inits.assign(initsBeforeElse);
2381                 uninits.assign(uninitsBeforeElse);
2382                 scan(tree.elsepart);
2383                 inits.andSet(initsAfterThen);
2384                 uninits.andSet(uninitsAfterThen);
2385             } else {
2386                 inits.andSet(initsBeforeElse);
2387                 uninits.andSet(uninitsBeforeElse);
2388             }
2389         }
2390 
2391         @Override
2392         public void visitBreak(JCBreak tree) {
2393             if (tree.isValueBreak())

























2394                 scan(tree.value);

2395             recordExit(new AssignPendingExit(tree, inits, uninits));
2396         }
2397 
2398         @Override
2399         public void visitContinue(JCContinue tree) {
2400             recordExit(new AssignPendingExit(tree, inits, uninits));
2401         }
2402 
2403         @Override
2404         public void visitReturn(JCReturn tree) {
2405             scanExpr(tree.expr);
2406             recordExit(new AssignPendingExit(tree, inits, uninits));
2407         }
2408 
2409         public void visitThrow(JCThrow tree) {
2410             scanExpr(tree.expr);
2411             markDead();
2412         }
2413 
2414         public void visitApply(JCMethodInvocation tree) {
2415             scanExpr(tree.meth);
2416             scanExprs(tree.args);
2417         }
2418 
2419         public void visitNewClass(JCNewClass tree) {
2420             scanExpr(tree.encl);
2421             scanExprs(tree.args);
2422             scan(tree.def);
2423         }
2424 
2425         @Override
2426         public void visitLambda(JCLambda tree) {
2427             final Bits prevUninits = new Bits(uninits);
2428             final Bits prevInits = new Bits(inits);
2429             int returnadrPrev = returnadr;
2430             int nextadrPrev = nextadr;
2431             ListBuffer<AssignPendingExit> prevPending = pendingExits;
2432             try {
2433                 returnadr = nextadr;
2434                 pendingExits = new ListBuffer<>();
2435                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2436                     JCVariableDecl def = l.head;
2437                     scan(def);
2438                     inits.incl(def.sym.adr);
2439                     uninits.excl(def.sym.adr);
2440                 }
2441                 if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
2442                     scanExpr(tree.body);
2443                 } else {
2444                     scan(tree.body);
2445                 }
2446             }
2447             finally {
2448                 returnadr = returnadrPrev;
2449                 uninits.assign(prevUninits);
2450                 inits.assign(prevInits);
2451                 pendingExits = prevPending;


2601                 }
2602                 firstadr = 0;
2603                 nextadr = 0;
2604                 Flow.this.make = null;
2605                 pendingExits = null;
2606                 this.classDef = null;
2607                 unrefdResources = null;
2608             }
2609         }
2610     }
2611 
2612     /**
2613      * This pass implements the last step of the dataflow analysis, namely
2614      * the effectively-final analysis check. This checks that every local variable
2615      * reference from a lambda body/local inner class is either final or effectively final.
2616      * Additional this also checks that every variable that is used as an operand to
2617      * try-with-resources is final or effectively final.
2618      * As effectively final variables are marked as such during DA/DU, this pass must run after
2619      * AssignAnalyzer.
2620      */
2621     class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
2622 
2623         JCTree currentTree; //local class or lambda
2624 
2625         @Override
2626         void markDead() {
2627             //do nothing
2628         }
2629 
2630         @SuppressWarnings("fallthrough")
2631         void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2632             if (currentTree != null &&
2633                     sym.owner.kind == MTH &&
2634                     sym.pos < currentTree.getStartPosition()) {
2635                 switch (currentTree.getTag()) {
2636                     case CLASSDEF:
2637                         if (!allowEffectivelyFinalInInnerClasses) {
2638                             if ((sym.flags() & FINAL) == 0) {
2639                                 reportInnerClsNeedsFinalError(pos, sym);
2640                             }
2641                             break;




 283     }
 284 
 285     protected Flow(Context context) {
 286         context.put(flowKey, this);
 287         names = Names.instance(context);
 288         log = Log.instance(context);
 289         syms = Symtab.instance(context);
 290         types = Types.instance(context);
 291         chk = Check.instance(context);
 292         lint = Lint.instance(context);
 293         rs = Resolve.instance(context);
 294         diags = JCDiagnostic.Factory.instance(context);
 295         Source source = Source.instance(context);
 296         allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source);
 297     }
 298 
 299     /**
 300      * Base visitor class for all visitors implementing dataflow analysis logic.
 301      * This class define the shared logic for handling jumps (break/continue statements).
 302      */
 303     static abstract class BaseAnalyzer extends TreeScanner {
 304 
 305         enum JumpKind {
 306             BREAK(JCTree.Tag.BREAK) {
 307                 @Override
 308                 JCTree getTarget(JCTree tree) {
 309                     return ((JCBreak)tree).target;
 310                 }
 311             },
 312             CONTINUE(JCTree.Tag.CONTINUE) {
 313                 @Override
 314                 JCTree getTarget(JCTree tree) {
 315                     return ((JCContinue)tree).target;
 316                 }
 317             };
 318 
 319             final JCTree.Tag treeTag;
 320 
 321             private JumpKind(Tag treeTag) {
 322                 this.treeTag = treeTag;
 323             }
 324 
 325             abstract JCTree getTarget(JCTree tree);
 326         }
 327 
 328         /** The currently pending exits that go from current inner blocks
 329          *  to an enclosing block, in source order.
 330          */
 331         ListBuffer<PendingExit> pendingExits;
 332 
 333         /** A pending exit.  These are the statements return, break, and
 334          *  continue.  In addition, exception-throwing expressions or
 335          *  statements are put here when not known to be caught.  This
 336          *  will typically result in an error unless it is within a
 337          *  try-finally whose finally block cannot complete normally.
 338          */
 339         static class PendingExit {
 340             JCTree tree;
 341 
 342             PendingExit(JCTree tree) {
 343                 this.tree = tree;
 344             }
 345 
 346             void resolveJump() {
 347                 //do nothing
 348             }
 349         }
 350 
 351         abstract void markDead();
 352 
 353         /** Record an outward transfer of control. */
 354         void recordExit(PendingExit pe) {
 355             pendingExits.append(pe);
 356             markDead();
 357         }
 358 
 359         /** Resolve all jumps of this statement. */
 360         private Liveness resolveJump(JCTree tree,
 361                          ListBuffer<PendingExit> oldPendingExits,
 362                          JumpKind jk) {
 363             boolean resolved = false;
 364             List<PendingExit> exits = pendingExits.toList();
 365             pendingExits = oldPendingExits;
 366             for (; exits.nonEmpty(); exits = exits.tail) {
 367                 PendingExit exit = exits.head;
 368                 if (exit.tree.hasTag(jk.treeTag) &&
 369                         jk.getTarget(exit.tree) == tree) {
 370                     exit.resolveJump();
 371                     resolved = true;
 372                 } else {
 373                     pendingExits.append(exit);
 374                 }
 375             }
 376             return Liveness.from(resolved);
 377         }
 378 
 379         /** Resolve all continues of this statement. */
 380         Liveness resolveContinues(JCTree tree) {
 381             return resolveJump(tree, new ListBuffer<PendingExit>(), JumpKind.CONTINUE);
 382         }
 383 
 384         /** Resolve all breaks of this statement. */
 385         Liveness resolveBreaks(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
 386             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
 387         }
 388 
 389         @Override
 390         public void scan(JCTree tree) {
 391             if (tree != null && (
 392                     tree.type == null ||
 393                     tree.type != Type.stuckType)) {
 394                 super.scan(tree);
 395             }
 396         }
 397 
 398         public void visitPackageDef(JCPackageDecl tree) {
 399             // Do nothing for PackageDecl
 400         }
 401 
 402         protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
 403             JCBreak brk = make.at(Position.NOPOS).Break(null);
 404             brk.target = swtch;
 405             scan(brk);
 406         }
 407     }
 408 
 409     /**
 410      * This pass implements the first step of the dataflow analysis, namely
 411      * the liveness analysis check. This checks that every statement is reachable.
 412      * The output of this analysis pass are used by other analyzers. This analyzer
 413      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
 414      */
 415     class AliveAnalyzer extends BaseAnalyzer {
 416 
 417         /** A flag that indicates whether the last statement could
 418          *  complete normally.
 419          */
 420         private Liveness alive;
 421 
 422         @Override
 423         void markDead() {
 424             alive = Liveness.DEAD;
 425         }
 426 
 427     /*************************************************************************
 428      * Visitor methods for statements and definitions
 429      *************************************************************************/
 430 
 431         /** Analyze a definition.
 432          */
 433         void scanDef(JCTree tree) {
 434             scanStat(tree);
 435             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && alive == Liveness.DEAD) {


 814         public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
 815             try {
 816                 attrEnv = env;
 817                 Flow.this.make = make;
 818                 pendingExits = new ListBuffer<>();
 819                 alive = Liveness.ALIVE;
 820                 scan(tree);
 821             } finally {
 822                 pendingExits = null;
 823                 Flow.this.make = null;
 824             }
 825         }
 826     }
 827 
 828     /**
 829      * This pass implements the second step of the dataflow analysis, namely
 830      * the exception analysis. This is to ensure that every checked exception that is
 831      * thrown is declared or caught. The analyzer uses some info that has been set by
 832      * the liveliness analyzer.
 833      */
 834     class FlowAnalyzer extends BaseAnalyzer {
 835 
 836         /** A flag that indicates whether the last statement could
 837          *  complete normally.
 838          */
 839         HashMap<Symbol, List<Type>> preciseRethrowTypes;
 840 
 841         /** The current class being defined.
 842          */
 843         JCClassDecl classDef;
 844 
 845         /** The list of possibly thrown declarable exceptions.
 846          */
 847         List<Type> thrown;
 848 
 849         /** The list of exceptions that are either caught or declared to be
 850          *  thrown.
 851          */
 852         List<Type> caught;
 853 
 854         class ThrownPendingExit extends BaseAnalyzer.PendingExit {
 855 
 856             Type thrown;
 857 
 858             ThrownPendingExit(JCTree tree, Type thrown) {
 859                 super(tree);
 860                 this.thrown = thrown;
 861             }
 862         }
 863 
 864         @Override
 865         void markDead() {
 866             //do nothing
 867         }
 868 
 869         /*-------------------- Exceptions ----------------------*/
 870 
 871         /** Complain that pending exceptions are not caught.
 872          */
 873         void errorUncaught() {
 874             for (PendingExit exit = pendingExits.next();
 875                  exit != null;
 876                  exit = pendingExits.next()) {
 877                 Assert.check(exit instanceof ThrownPendingExit);
 878                 ThrownPendingExit thrownExit = (ThrownPendingExit) exit;
 879                 if (classDef != null &&
 880                     classDef.pos == exit.tree.pos) {
 881                     log.error(exit.tree.pos(),
 882                               Errors.UnreportedExceptionDefaultConstructor(thrownExit.thrown));
 883                 } else if (exit.tree.hasTag(VARDEF) &&
 884                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
 885                     log.error(exit.tree.pos(),
 886                               Errors.UnreportedExceptionImplicitClose(thrownExit.thrown,
 887                                                                       ((JCVariableDecl)exit.tree).sym.name));
 888                 } else {
 889                     log.error(exit.tree.pos(),
 890                               Errors.UnreportedExceptionNeedToCatchOrThrow(thrownExit.thrown));
 891                 }
 892             }
 893         }
 894 
 895         /** Record that exception is potentially thrown and check that it
 896          *  is caught.
 897          */
 898         void markThrown(JCTree tree, Type exc) {
 899             if (!chk.isUnchecked(tree.pos(), exc)) {
 900                 if (!chk.isHandled(exc, caught)) {
 901                     pendingExits.append(new ThrownPendingExit(tree, exc));
 902                 }
 903                 thrown = chk.incl(exc, thrown);
 904             }
 905         }
 906 
 907     /*************************************************************************
 908      * Visitor methods for statements and definitions
 909      *************************************************************************/
 910 
 911         /* ------------ Visitor methods for various sorts of trees -------------*/
 912 
 913         public void visitClassDef(JCClassDecl tree) {
 914             if (tree.sym == null) return;
 915 
 916             JCClassDecl classDefPrev = classDef;
 917             List<Type> thrownPrev = thrown;
 918             List<Type> caughtPrev = caught;
 919             ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 920             Lint lintPrev = lint;
 921             boolean anonymousClass = tree.name == names.empty;
 922             pendingExits = new ListBuffer<>();
 923             if (!anonymousClass) {
 924                 caught = List.nil();
 925             }
 926             classDef = tree;
 927             thrown = List.nil();
 928             lint = lint.augment(tree.sym);
 929 
 930             try {
 931                 // process all the static initializers
 932                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 933                     if (!l.head.hasTag(METHODDEF) &&
 934                         (TreeInfo.flags(l.head) & STATIC) != 0) {
 935                         scan(l.head);
 936                         errorUncaught();
 937                     }
 938                 }
 939 


1009             Lint lintPrev = lint;
1010 
1011             lint = lint.augment(tree.sym);
1012 
1013             Assert.check(pendingExits.isEmpty());
1014 
1015             try {
1016                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1017                     JCVariableDecl def = l.head;
1018                     scan(def);
1019                 }
1020                 if (TreeInfo.isInitialConstructor(tree))
1021                     caught = chk.union(caught, mthrown);
1022                 else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
1023                     caught = mthrown;
1024                 // else we are in an instance initializer block;
1025                 // leave caught unchanged.
1026 
1027                 scan(tree.body);
1028 
1029                 List<PendingExit> exits = pendingExits.toList();
1030                 pendingExits = new ListBuffer<>();
1031                 while (exits.nonEmpty()) {
1032                     PendingExit exit = exits.head;
1033                     exits = exits.tail;
1034                     if (!(exit instanceof ThrownPendingExit)) {
1035                         Assert.check(exit.tree.hasTag(RETURN));
1036                     } else {
1037                         // uncaught throws will be reported later
1038                         pendingExits.append(exit);
1039                     }
1040                 }
1041             } finally {
1042                 caught = caughtPrev;
1043                 lint = lintPrev;
1044             }
1045         }
1046 
1047         public void visitVarDef(JCVariableDecl tree) {
1048             if (tree.init != null) {
1049                 Lint lintPrev = lint;
1050                 lint = lint.augment(tree.sym);
1051                 try{
1052                     scan(tree.init);
1053                 } finally {
1054                     lint = lintPrev;
1055                 }
1056             }
1057         }
1058 
1059         public void visitBlock(JCBlock tree) {
1060             scan(tree.stats);
1061         }
1062 
1063         public void visitDoLoop(JCDoWhileLoop tree) {
1064             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1065             pendingExits = new ListBuffer<>();
1066             scan(tree.body);
1067             resolveContinues(tree);
1068             scan(tree.cond);
1069             resolveBreaks(tree, prevPendingExits);
1070         }
1071 
1072         public void visitWhileLoop(JCWhileLoop tree) {
1073             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1074             pendingExits = new ListBuffer<>();
1075             scan(tree.cond);
1076             scan(tree.body);
1077             resolveContinues(tree);
1078             resolveBreaks(tree, prevPendingExits);
1079         }
1080 
1081         public void visitForLoop(JCForLoop tree) {
1082             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1083             scan(tree.init);
1084             pendingExits = new ListBuffer<>();
1085             if (tree.cond != null) {
1086                 scan(tree.cond);
1087             }
1088             scan(tree.body);
1089             resolveContinues(tree);
1090             scan(tree.step);
1091             resolveBreaks(tree, prevPendingExits);
1092         }
1093 
1094         public void visitForeachLoop(JCEnhancedForLoop tree) {
1095             visitVarDef(tree.var);
1096             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1097             scan(tree.expr);
1098             pendingExits = new ListBuffer<>();
1099             scan(tree.body);
1100             resolveContinues(tree);
1101             resolveBreaks(tree, prevPendingExits);
1102         }
1103 
1104         public void visitLabelled(JCLabeledStatement tree) {
1105             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1106             pendingExits = new ListBuffer<>();
1107             scan(tree.body);
1108             resolveBreaks(tree, prevPendingExits);
1109         }
1110 
1111         public void visitSwitch(JCSwitch tree) {
1112             handleSwitch(tree, tree.selector, tree.cases);
1113         }
1114 
1115         @Override
1116         public void visitSwitchExpression(JCSwitchExpression tree) {
1117             handleSwitch(tree, tree.selector, tree.cases);
1118         }
1119 
1120         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
1121             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1122             pendingExits = new ListBuffer<>();
1123             scan(selector);
1124             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
1125                 JCCase c = l.head;
1126                 scan(c.pats);
1127                 scan(c.stats);
1128             }
1129             resolveBreaks(tree, prevPendingExits);
1130         }
1131 
1132         public void visitTry(JCTry tree) {
1133             List<Type> caughtPrev = caught;
1134             List<Type> thrownPrev = thrown;
1135             thrown = List.nil();
1136             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1137                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1138                         ((JCTypeUnion)l.head.param.vartype).alternatives :
1139                         List.of(l.head.param.vartype);
1140                 for (JCExpression ct : subClauses) {
1141                     caught = chk.incl(ct.type, caught);
1142                 }
1143             }
1144 
1145             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1146             pendingExits = new ListBuffer<>();
1147             for (JCTree resource : tree.resources) {
1148                 if (resource instanceof JCVariableDecl) {
1149                     JCVariableDecl vdecl = (JCVariableDecl) resource;
1150                     visitVarDef(vdecl);
1151                 } else if (resource instanceof JCExpression) {
1152                     scan((JCExpression) resource);
1153                 } else {
1154                     throw new AssertionError(tree);  // parser error
1155                 }
1156             }
1157             for (JCTree resource : tree.resources) {
1158                 List<Type> closeableSupertypes = resource.type.isCompound() ?
1159                     types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1160                     List.of(resource.type);
1161                 for (Type sup : closeableSupertypes) {
1162                     if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1163                         Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1164                                 attrEnv,
1165                                 types.skipTypeVars(sup, false),


1189                 List<Type> ctypes = List.nil();
1190                 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1191                 for (JCExpression ct : subClauses) {
1192                     Type exc = ct.type;
1193                     if (exc != syms.unknownType) {
1194                         ctypes = ctypes.append(exc);
1195                         if (types.isSameType(exc, syms.objectType))
1196                             continue;
1197                         checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1198                         caughtInTry = chk.incl(exc, caughtInTry);
1199                     }
1200                 }
1201                 scan(param);
1202                 preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1203                 scan(l.head.body);
1204                 preciseRethrowTypes.remove(param.sym);
1205             }
1206             if (tree.finalizer != null) {
1207                 List<Type> savedThrown = thrown;
1208                 thrown = List.nil();
1209                 ListBuffer<PendingExit> exits = pendingExits;
1210                 pendingExits = prevPendingExits;
1211                 scan(tree.finalizer);
1212                 if (!tree.finallyCanCompleteNormally) {
1213                     // discard exits and exceptions from try and finally
1214                     thrown = chk.union(thrown, thrownPrev);
1215                 } else {
1216                     thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1217                     thrown = chk.union(thrown, savedThrown);
1218                     // FIX: this doesn't preserve source order of exits in catch
1219                     // versus finally!
1220                     while (exits.nonEmpty()) {
1221                         pendingExits.append(exits.next());
1222                     }
1223                 }
1224             } else {
1225                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1226                 ListBuffer<PendingExit> exits = pendingExits;
1227                 pendingExits = prevPendingExits;
1228                 while (exits.nonEmpty()) pendingExits.append(exits.next());
1229             }
1230         }
1231 
1232         @Override
1233         public void visitIf(JCIf tree) {
1234             scan(tree.cond);
1235             scan(tree.thenpart);
1236             if (tree.elsepart != null) {
1237                 scan(tree.elsepart);
1238             }
1239         }
1240 
1241         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1242             if (chk.subset(exc, caughtInTry)) {
1243                 log.error(pos, Errors.ExceptAlreadyCaught(exc));
1244             } else if (!chk.isUnchecked(pos, exc) &&
1245                     !isExceptionOrThrowable(exc) &&
1246                     !chk.intersects(exc, thrownInTry)) {


1252                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1253                 // exception, that would have been covered in the branch above
1254                 if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1255                         !isExceptionOrThrowable(exc)) {
1256                     Warning key = catchableThrownTypes.length() == 1 ?
1257                             Warnings.UnreachableCatch(catchableThrownTypes) :
1258                             Warnings.UnreachableCatch1(catchableThrownTypes);
1259                     log.warning(pos, key);
1260                 }
1261             }
1262         }
1263         //where
1264             private boolean isExceptionOrThrowable(Type exc) {
1265                 return exc.tsym == syms.throwableType.tsym ||
1266                     exc.tsym == syms.exceptionType.tsym;
1267             }
1268 
1269         public void visitBreak(JCBreak tree) {
1270             if (tree.isValueBreak())
1271                 scan(tree.value);
1272             recordExit(new PendingExit(tree));
1273         }
1274 
1275         public void visitContinue(JCContinue tree) {
1276             recordExit(new PendingExit(tree));
1277         }
1278 
1279         public void visitReturn(JCReturn tree) {
1280             scan(tree.expr);
1281             recordExit(new PendingExit(tree));
1282         }
1283 
1284         public void visitThrow(JCThrow tree) {
1285             scan(tree.expr);
1286             Symbol sym = TreeInfo.symbol(tree.expr);
1287             if (sym != null &&
1288                 sym.kind == VAR &&
1289                 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1290                 preciseRethrowTypes.get(sym) != null) {
1291                 for (Type t : preciseRethrowTypes.get(sym)) {
1292                     markThrown(tree, t);
1293                 }
1294             }
1295             else {
1296                 markThrown(tree, tree.expr.type);
1297             }
1298             markDead();
1299         }
1300 
1301         public void visitApply(JCMethodInvocation tree) {


1328                     for (List<Type> l = tree.constructor.type.getThrownTypes();
1329                          l.nonEmpty();
1330                          l = l.tail) {
1331                         caught = chk.incl(l.head, caught);
1332                     }
1333                 scan(tree.def);
1334             }
1335             finally {
1336                 caught = caughtPrev;
1337             }
1338         }
1339 
1340         @Override
1341         public void visitLambda(JCLambda tree) {
1342             if (tree.type != null &&
1343                     tree.type.isErroneous()) {
1344                 return;
1345             }
1346             List<Type> prevCaught = caught;
1347             List<Type> prevThrown = thrown;
1348             ListBuffer<PendingExit> prevPending = pendingExits;
1349             try {
1350                 pendingExits = new ListBuffer<>();
1351                 caught = tree.getDescriptorType(types).getThrownTypes();
1352                 thrown = List.nil();
1353                 scan(tree.body);
1354                 List<PendingExit> exits = pendingExits.toList();
1355                 pendingExits = new ListBuffer<>();
1356                 while (exits.nonEmpty()) {
1357                     PendingExit exit = exits.head;
1358                     exits = exits.tail;
1359                     if (!(exit instanceof ThrownPendingExit)) {
1360                         Assert.check(exit.tree.hasTag(RETURN));
1361                     } else {
1362                         // uncaught throws will be reported later
1363                         pendingExits.append(exit);
1364                     }
1365                 }
1366 
1367                 errorUncaught();
1368             } finally {
1369                 pendingExits = prevPending;
1370                 caught = prevCaught;
1371                 thrown = prevThrown;
1372             }
1373         }
1374 
1375         public void visitModuleDef(JCModuleDecl tree) {
1376             // Do nothing for modules
1377         }
1378 
1379     /**************************************************************************


1473         @Override
1474         public void visitClassDef(JCClassDecl tree) {
1475             //skip
1476         }
1477     }
1478 
1479     /**
1480      * Specialized pass that performs inference of thrown types for lambdas.
1481      */
1482     class LambdaFlowAnalyzer extends FlowAnalyzer {
1483         List<Type> inferredThrownTypes;
1484         boolean inLambda;
1485         @Override
1486         public void visitLambda(JCLambda tree) {
1487             if ((tree.type != null &&
1488                     tree.type.isErroneous()) || inLambda) {
1489                 return;
1490             }
1491             List<Type> prevCaught = caught;
1492             List<Type> prevThrown = thrown;
1493             ListBuffer<PendingExit> prevPending = pendingExits;
1494             inLambda = true;
1495             try {
1496                 pendingExits = new ListBuffer<>();
1497                 caught = List.of(syms.throwableType);
1498                 thrown = List.nil();
1499                 scan(tree.body);
1500                 inferredThrownTypes = thrown;
1501             } finally {
1502                 pendingExits = prevPending;
1503                 caught = prevCaught;
1504                 thrown = prevThrown;
1505                 inLambda = false;
1506             }
1507         }
1508         @Override
1509         public void visitClassDef(JCClassDecl tree) {
1510             //skip
1511         }
1512     }
1513 
1514     /**
1515      * This pass implements (i) definite assignment analysis, which ensures that
1516      * each variable is assigned when used and (ii) definite unassignment analysis,
1517      * which ensures that no final variable is assigned more than once. This visitor
1518      * depends on the results of the liveliness analyzer. This pass is also used to mark
1519      * effectively-final local variables/parameters.
1520      */
1521 
1522     public class AssignAnalyzer extends BaseAnalyzer {
1523 
1524         /** The set of definitely assigned variables.
1525          */
1526         final Bits inits;
1527 
1528         /** The set of definitely unassigned variables.
1529          */
1530         final Bits uninits;
1531 
1532         /** The set of variables that are definitely unassigned everywhere
1533          *  in current try block. This variable is maintained lazily; it is
1534          *  updated only when something gets removed from uninits,
1535          *  typically by being assigned in reachable code.  To obtain the
1536          *  correct set of variables which are definitely unassigned
1537          *  anywhere in current try block, intersect uninitsTry and
1538          *  uninits.
1539          */
1540         final Bits uninitsTry;
1541 
1542         /** When analyzing a condition, inits and uninits are null.


1820             }
1821         }
1822 
1823         /* ------------ Visitor methods for various sorts of trees -------------*/
1824 
1825         public void visitClassDef(JCClassDecl tree) {
1826             if (tree.sym == null) {
1827                 return;
1828             }
1829 
1830             Lint lintPrev = lint;
1831             lint = lint.augment(tree.sym);
1832             try {
1833                 if (tree.sym == null) {
1834                     return;
1835                 }
1836 
1837                 JCClassDecl classDefPrev = classDef;
1838                 int firstadrPrev = firstadr;
1839                 int nextadrPrev = nextadr;
1840                 ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
1841 
1842                 pendingExits = new ListBuffer<>();
1843                 if (tree.name != names.empty) {
1844                     firstadr = nextadr;
1845                 }
1846                 classDef = tree;
1847                 try {
1848                     // define all the static fields
1849                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1850                         if (l.head.hasTag(VARDEF)) {
1851                             JCVariableDecl def = (JCVariableDecl)l.head;
1852                             if ((def.mods.flags & STATIC) != 0) {
1853                                 VarSymbol sym = def.sym;
1854                                 if (trackable(sym)) {
1855                                     newVar(def);
1856                                 }
1857                             }
1858                         }
1859                     }
1860 


1955                     scan(tree.body);
1956 
1957                     if (isInitialConstructor) {
1958                         boolean isSynthesized = (tree.sym.flags() &
1959                                                  GENERATEDCONSTR) != 0;
1960                         for (int i = firstadr; i < nextadr; i++) {
1961                             JCVariableDecl vardecl = vardecls[i];
1962                             VarSymbol var = vardecl.sym;
1963                             if (var.owner == classDef.sym) {
1964                                 // choose the diagnostic position based on whether
1965                                 // the ctor is default(synthesized) or not
1966                                 if (isSynthesized) {
1967                                     checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
1968                                         var, Errors.VarNotInitializedInDefaultConstructor(var));
1969                                 } else {
1970                                     checkInit(TreeInfo.diagEndPos(tree.body), var);
1971                                 }
1972                             }
1973                         }
1974                     }
1975                     List<PendingExit> exits = pendingExits.toList();
1976                     pendingExits = new ListBuffer<>();
1977                     while (exits.nonEmpty()) {
1978                         PendingExit exit = exits.head;
1979                         exits = exits.tail;
1980                         Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1981                         if (isInitialConstructor) {
1982                             Assert.check(exit instanceof AssignPendingExit);
1983                             inits.assign(((AssignPendingExit) exit).exit_inits);
1984                             for (int i = firstadr; i < nextadr; i++) {
1985                                 checkInit(exit.tree.pos(), vardecls[i].sym);
1986                             }
1987                         }
1988                     }
1989                 } finally {
1990                     inits.assign(initsPrev);
1991                     uninits.assign(uninitsPrev);
1992                     nextadr = nextadrPrev;
1993                     firstadr = firstadrPrev;
1994                     returnadr = returnadrPrev;
1995                     isInitialConstructor = lastInitialConstructor;
1996                 }
1997             } finally {
1998                 lint = lintPrev;
1999             }
2000         }
2001 
2002         protected void initParam(JCVariableDecl def) {
2003             inits.incl(def.sym.adr);


2013                     newVar(tree);
2014                 }
2015                 if (tree.init != null) {
2016                     scanExpr(tree.init);
2017                     if (track) {
2018                         letInit(tree.pos(), tree.sym);
2019                     }
2020                 }
2021             } finally {
2022                 lint = lintPrev;
2023             }
2024         }
2025 
2026         public void visitBlock(JCBlock tree) {
2027             int nextadrPrev = nextadr;
2028             scan(tree.stats);
2029             nextadr = nextadrPrev;
2030         }
2031 
2032         public void visitDoLoop(JCDoWhileLoop tree) {
2033             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2034             FlowKind prevFlowKind = flowKind;
2035             flowKind = FlowKind.NORMAL;
2036             final Bits initsSkip = new Bits(true);
2037             final Bits uninitsSkip = new Bits(true);
2038             pendingExits = new ListBuffer<>();
2039             int prevErrors = log.nerrors;
2040             do {
2041                 final Bits uninitsEntry = new Bits(uninits);
2042                 uninitsEntry.excludeFrom(nextadr);
2043                 scan(tree.body);
2044                 resolveContinues(tree);
2045                 scanCond(tree.cond);
2046                 if (!flowKind.isFinal()) {
2047                     initsSkip.assign(initsWhenFalse);
2048                     uninitsSkip.assign(uninitsWhenFalse);
2049                 }
2050                 if (log.nerrors !=  prevErrors ||
2051                     flowKind.isFinal() ||
2052                     new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
2053                     break;
2054                 inits.assign(initsWhenTrue);
2055                 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
2056                 flowKind = FlowKind.SPECULATIVE_LOOP;
2057             } while (true);
2058             flowKind = prevFlowKind;
2059             inits.assign(initsSkip);
2060             uninits.assign(uninitsSkip);
2061             resolveBreaks(tree, prevPendingExits);
2062         }
2063 
2064         public void visitWhileLoop(JCWhileLoop tree) {
2065             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2066             FlowKind prevFlowKind = flowKind;
2067             flowKind = FlowKind.NORMAL;
2068             final Bits initsSkip = new Bits(true);
2069             final Bits uninitsSkip = new Bits(true);
2070             pendingExits = new ListBuffer<>();
2071             int prevErrors = log.nerrors;
2072             final Bits uninitsEntry = new Bits(uninits);
2073             uninitsEntry.excludeFrom(nextadr);
2074             do {
2075                 scanCond(tree.cond);
2076                 if (!flowKind.isFinal()) {
2077                     initsSkip.assign(initsWhenFalse) ;
2078                     uninitsSkip.assign(uninitsWhenFalse);
2079                 }
2080                 inits.assign(initsWhenTrue);
2081                 uninits.assign(uninitsWhenTrue);
2082                 scan(tree.body);
2083                 resolveContinues(tree);
2084                 if (log.nerrors != prevErrors ||
2085                     flowKind.isFinal() ||
2086                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
2087                     break;
2088                 }
2089                 uninits.assign(uninitsEntry.andSet(uninits));
2090                 flowKind = FlowKind.SPECULATIVE_LOOP;
2091             } while (true);
2092             flowKind = prevFlowKind;
2093             //a variable is DA/DU after the while statement, if it's DA/DU assuming the
2094             //branch is not taken AND if it's DA/DU before any break statement
2095             inits.assign(initsSkip);
2096             uninits.assign(uninitsSkip);
2097             resolveBreaks(tree, prevPendingExits);
2098         }
2099 
2100         public void visitForLoop(JCForLoop tree) {
2101             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2102             FlowKind prevFlowKind = flowKind;
2103             flowKind = FlowKind.NORMAL;
2104             int nextadrPrev = nextadr;
2105             scan(tree.init);
2106             final Bits initsSkip = new Bits(true);
2107             final Bits uninitsSkip = new Bits(true);
2108             pendingExits = new ListBuffer<>();
2109             int prevErrors = log.nerrors;
2110             do {
2111                 final Bits uninitsEntry = new Bits(uninits);
2112                 uninitsEntry.excludeFrom(nextadr);
2113                 if (tree.cond != null) {
2114                     scanCond(tree.cond);
2115                     if (!flowKind.isFinal()) {
2116                         initsSkip.assign(initsWhenFalse);
2117                         uninitsSkip.assign(uninitsWhenFalse);
2118                     }
2119                     inits.assign(initsWhenTrue);
2120                     uninits.assign(uninitsWhenTrue);
2121                 } else if (!flowKind.isFinal()) {


2129                 scan(tree.step);
2130                 if (log.nerrors != prevErrors ||
2131                     flowKind.isFinal() ||
2132                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2133                     break;
2134                 uninits.assign(uninitsEntry.andSet(uninits));
2135                 flowKind = FlowKind.SPECULATIVE_LOOP;
2136             } while (true);
2137             flowKind = prevFlowKind;
2138             //a variable is DA/DU after a for loop, if it's DA/DU assuming the
2139             //branch is not taken AND if it's DA/DU before any break statement
2140             inits.assign(initsSkip);
2141             uninits.assign(uninitsSkip);
2142             resolveBreaks(tree, prevPendingExits);
2143             nextadr = nextadrPrev;
2144         }
2145 
2146         public void visitForeachLoop(JCEnhancedForLoop tree) {
2147             visitVarDef(tree.var);
2148 
2149             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2150             FlowKind prevFlowKind = flowKind;
2151             flowKind = FlowKind.NORMAL;
2152             int nextadrPrev = nextadr;
2153             scan(tree.expr);
2154             final Bits initsStart = new Bits(inits);
2155             final Bits uninitsStart = new Bits(uninits);
2156 
2157             letInit(tree.pos(), tree.var.sym);
2158             pendingExits = new ListBuffer<>();
2159             int prevErrors = log.nerrors;
2160             do {
2161                 final Bits uninitsEntry = new Bits(uninits);
2162                 uninitsEntry.excludeFrom(nextadr);
2163                 scan(tree.body);
2164                 resolveContinues(tree);
2165                 if (log.nerrors != prevErrors ||
2166                     flowKind.isFinal() ||
2167                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2168                     break;
2169                 uninits.assign(uninitsEntry.andSet(uninits));
2170                 flowKind = FlowKind.SPECULATIVE_LOOP;
2171             } while (true);
2172             flowKind = prevFlowKind;
2173             inits.assign(initsStart);
2174             uninits.assign(uninitsStart.andSet(uninits));
2175             resolveBreaks(tree, prevPendingExits);
2176             nextadr = nextadrPrev;
2177         }
2178 
2179         public void visitLabelled(JCLabeledStatement tree) {
2180             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2181             pendingExits = new ListBuffer<>();
2182             scan(tree.body);
2183             resolveBreaks(tree, prevPendingExits);
2184         }
2185 
2186         public void visitSwitch(JCSwitch tree) {
2187             handleSwitch(tree, tree.selector, tree.cases);
2188         }
2189 
2190         public void visitSwitchExpression(JCSwitchExpression tree) {
2191             handleSwitch(tree, tree.selector, tree.cases);
2192         }
2193 
2194         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
2195             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2196             pendingExits = new ListBuffer<>();
2197             int nextadrPrev = nextadr;
2198             scanExpr(selector);
2199             final Bits initsSwitch = new Bits(inits);
2200             final Bits uninitsSwitch = new Bits(uninits);
2201             boolean hasDefault = false;
2202             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
2203                 inits.assign(initsSwitch);
2204                 uninits.assign(uninits.andSet(uninitsSwitch));
2205                 JCCase c = l.head;
2206                 if (c.pats.isEmpty()) {
2207                     hasDefault = true;
2208                 } else {
2209                     for (JCExpression pat : c.pats) {
2210                         scanExpr(pat);
2211                     }
2212                 }
2213                 if (hasDefault) {
2214                     inits.assign(initsSwitch);
2215                     uninits.assign(uninits.andSet(uninitsSwitch));


2231             resolveBreaks(tree, prevPendingExits);
2232             nextadr = nextadrPrev;
2233         }
2234         // where
2235             /** Add any variables defined in stats to inits and uninits. */
2236             private void addVars(List<JCStatement> stats, final Bits inits,
2237                                         final Bits uninits) {
2238                 for (;stats.nonEmpty(); stats = stats.tail) {
2239                     JCTree stat = stats.head;
2240                     if (stat.hasTag(VARDEF)) {
2241                         int adr = ((JCVariableDecl) stat).sym.adr;
2242                         inits.excl(adr);
2243                         uninits.incl(adr);
2244                     }
2245                 }
2246             }
2247 
2248         public void visitTry(JCTry tree) {
2249             ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2250             final Bits uninitsTryPrev = new Bits(uninitsTry);
2251             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2252             pendingExits = new ListBuffer<>();
2253             final Bits initsTry = new Bits(inits);
2254             uninitsTry.assign(uninits);
2255             for (JCTree resource : tree.resources) {
2256                 if (resource instanceof JCVariableDecl) {
2257                     JCVariableDecl vdecl = (JCVariableDecl) resource;
2258                     visitVarDef(vdecl);
2259                     unrefdResources.enter(vdecl.sym);
2260                     resourceVarDecls.append(vdecl);
2261                 } else if (resource instanceof JCExpression) {
2262                     scanExpr((JCExpression) resource);
2263                 } else {
2264                     throw new AssertionError(tree);  // parser error
2265                 }
2266             }
2267             scan(tree.body);
2268             uninitsTry.andSet(uninits);
2269             final Bits initsEnd = new Bits(inits);
2270             final Bits uninitsEnd = new Bits(uninits);
2271             int nextadrCatch = nextadr;


2288             final Bits initsCatchPrev = new Bits(initsTry);
2289             final Bits uninitsCatchPrev = new Bits(uninitsTry);
2290 
2291             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2292                 JCVariableDecl param = l.head.param;
2293                 inits.assign(initsCatchPrev);
2294                 uninits.assign(uninitsCatchPrev);
2295                 scan(param);
2296                 /* If this is a TWR and we are executing the code from Gen,
2297                  * then there can be synthetic variables, ignore them.
2298                  */
2299                 initParam(param);
2300                 scan(l.head.body);
2301                 initsEnd.andSet(inits);
2302                 uninitsEnd.andSet(uninits);
2303                 nextadr = nextadrCatch;
2304             }
2305             if (tree.finalizer != null) {
2306                 inits.assign(initsTry);
2307                 uninits.assign(uninitsTry);
2308                 ListBuffer<PendingExit> exits = pendingExits;
2309                 pendingExits = prevPendingExits;
2310                 scan(tree.finalizer);
2311                 if (!tree.finallyCanCompleteNormally) {
2312                     // discard exits and exceptions from try and finally
2313                 } else {
2314                     uninits.andSet(uninitsEnd);
2315                     // FIX: this doesn't preserve source order of exits in catch
2316                     // versus finally!
2317                     while (exits.nonEmpty()) {
2318                         PendingExit exit = exits.next();
2319                         if (exit instanceof AssignPendingExit) {
2320                             ((AssignPendingExit) exit).exit_inits.orSet(inits);
2321                             ((AssignPendingExit) exit).exit_uninits.andSet(uninits);
2322                         }
2323                         pendingExits.append(exit);
2324                     }
2325                     inits.orSet(initsEnd);
2326                 }
2327             } else {
2328                 inits.assign(initsEnd);
2329                 uninits.assign(uninitsEnd);
2330                 ListBuffer<PendingExit> exits = pendingExits;
2331                 pendingExits = prevPendingExits;
2332                 while (exits.nonEmpty()) pendingExits.append(exits.next());
2333             }
2334             uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2335         }
2336 
2337         public void visitConditional(JCConditional tree) {
2338             scanCond(tree.cond);
2339             final Bits initsBeforeElse = new Bits(initsWhenFalse);
2340             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2341             inits.assign(initsWhenTrue);
2342             uninits.assign(uninitsWhenTrue);
2343             if (tree.truepart.type.hasTag(BOOLEAN) &&
2344                 tree.falsepart.type.hasTag(BOOLEAN)) {
2345                 // if b and c are boolean valued, then
2346                 // v is (un)assigned after a?b:c when true iff
2347                 //    v is (un)assigned after b when true and
2348                 //    v is (un)assigned after c when true
2349                 scanCond(tree.truepart);
2350                 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);


2376             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2377             inits.assign(initsWhenTrue);
2378             uninits.assign(uninitsWhenTrue);
2379             scan(tree.thenpart);
2380             if (tree.elsepart != null) {
2381                 final Bits initsAfterThen = new Bits(inits);
2382                 final Bits uninitsAfterThen = new Bits(uninits);
2383                 inits.assign(initsBeforeElse);
2384                 uninits.assign(uninitsBeforeElse);
2385                 scan(tree.elsepart);
2386                 inits.andSet(initsAfterThen);
2387                 uninits.andSet(uninitsAfterThen);
2388             } else {
2389                 inits.andSet(initsBeforeElse);
2390                 uninits.andSet(uninitsBeforeElse);
2391             }
2392         }
2393 
2394         @Override
2395         public void visitBreak(JCBreak tree) {
2396             if (tree.isValueBreak()) {
2397                 if (tree.target.hasTag(SWITCH_EXPRESSION)) {
2398                     JCSwitchExpression expr = (JCSwitchExpression) tree.target;
2399                     if (expr.type.hasTag(BOOLEAN)) {
2400                         scanCond(tree.value);
2401                         Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
2402                         Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
2403                         Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
2404                         Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
2405                         PendingExit exit = new PendingExit(tree) {
2406                             @Override
2407                             void resolveJump() {
2408                                 if (!inits.isReset()) {
2409                                     split(true);
2410                                 }
2411                                 initsWhenTrue.andSet(initsAfterBreakWhenTrue);
2412                                 initsWhenFalse.andSet(initsAfterBreakWhenFalse);
2413                                 uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
2414                                 uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
2415                             }
2416                         };
2417                         merge();
2418                         recordExit(exit);
2419                         return ;
2420                     }
2421                 }
2422                 scan(tree.value);
2423             }
2424             recordExit(new AssignPendingExit(tree, inits, uninits));
2425         }
2426 
2427         @Override
2428         public void visitContinue(JCContinue tree) {
2429             recordExit(new AssignPendingExit(tree, inits, uninits));
2430         }
2431 
2432         @Override
2433         public void visitReturn(JCReturn tree) {
2434             scanExpr(tree.expr);
2435             recordExit(new AssignPendingExit(tree, inits, uninits));
2436         }
2437 
2438         public void visitThrow(JCThrow tree) {
2439             scanExpr(tree.expr);
2440             markDead();
2441         }
2442 
2443         public void visitApply(JCMethodInvocation tree) {
2444             scanExpr(tree.meth);
2445             scanExprs(tree.args);
2446         }
2447 
2448         public void visitNewClass(JCNewClass tree) {
2449             scanExpr(tree.encl);
2450             scanExprs(tree.args);
2451             scan(tree.def);
2452         }
2453 
2454         @Override
2455         public void visitLambda(JCLambda tree) {
2456             final Bits prevUninits = new Bits(uninits);
2457             final Bits prevInits = new Bits(inits);
2458             int returnadrPrev = returnadr;
2459             int nextadrPrev = nextadr;
2460             ListBuffer<PendingExit> prevPending = pendingExits;
2461             try {
2462                 returnadr = nextadr;
2463                 pendingExits = new ListBuffer<>();
2464                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2465                     JCVariableDecl def = l.head;
2466                     scan(def);
2467                     inits.incl(def.sym.adr);
2468                     uninits.excl(def.sym.adr);
2469                 }
2470                 if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
2471                     scanExpr(tree.body);
2472                 } else {
2473                     scan(tree.body);
2474                 }
2475             }
2476             finally {
2477                 returnadr = returnadrPrev;
2478                 uninits.assign(prevUninits);
2479                 inits.assign(prevInits);
2480                 pendingExits = prevPending;


2630                 }
2631                 firstadr = 0;
2632                 nextadr = 0;
2633                 Flow.this.make = null;
2634                 pendingExits = null;
2635                 this.classDef = null;
2636                 unrefdResources = null;
2637             }
2638         }
2639     }
2640 
2641     /**
2642      * This pass implements the last step of the dataflow analysis, namely
2643      * the effectively-final analysis check. This checks that every local variable
2644      * reference from a lambda body/local inner class is either final or effectively final.
2645      * Additional this also checks that every variable that is used as an operand to
2646      * try-with-resources is final or effectively final.
2647      * As effectively final variables are marked as such during DA/DU, this pass must run after
2648      * AssignAnalyzer.
2649      */
2650     class CaptureAnalyzer extends BaseAnalyzer {
2651 
2652         JCTree currentTree; //local class or lambda
2653 
2654         @Override
2655         void markDead() {
2656             //do nothing
2657         }
2658 
2659         @SuppressWarnings("fallthrough")
2660         void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2661             if (currentTree != null &&
2662                     sym.owner.kind == MTH &&
2663                     sym.pos < currentTree.getStartPosition()) {
2664                 switch (currentTree.getTag()) {
2665                     case CLASSDEF:
2666                         if (!allowEffectivelyFinalInInnerClasses) {
2667                             if ((sym.flags() & FINAL) == 0) {
2668                                 reportInnerClsNeedsFinalError(pos, sym);
2669                             }
2670                             break;


< prev index next >