1 /*
   2  * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 //todo: one might eliminate uninits.andSets when monotonic
  27 
  28 package com.sun.tools.javac.comp;
  29 
  30 import java.util.HashMap;
  31 import java.util.HashSet;
  32 import java.util.Set;
  33 import java.util.stream.Collectors;
  34 
  35 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
  36 import com.sun.tools.javac.code.*;
  37 import com.sun.tools.javac.code.Scope.WriteableScope;
  38 import com.sun.tools.javac.code.Source.Feature;
  39 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  40 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  41 import com.sun.tools.javac.tree.*;
  42 import com.sun.tools.javac.util.*;
  43 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  44 import com.sun.tools.javac.util.JCDiagnostic.Error;
  45 import com.sun.tools.javac.util.JCDiagnostic.Warning;
  46 
  47 import com.sun.tools.javac.code.Symbol.*;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 
  50 import static com.sun.tools.javac.code.Flags.*;
  51 import static com.sun.tools.javac.code.Flags.BLOCK;
  52 import static com.sun.tools.javac.code.Kinds.Kind.*;
  53 import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
  54 import static com.sun.tools.javac.code.TypeTag.VOID;
  55 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  56 
  57 /** This pass implements dataflow analysis for Java programs though
  58  *  different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that
  59  *  every statement is reachable. Exception analysis (see FlowAnalyzer) ensures that
  60  *  every checked exception that is thrown is declared or caught.  Definite assignment analysis
  61  *  (see AssignAnalyzer) ensures that each variable is assigned when used.  Definite
  62  *  unassignment analysis (see AssignAnalyzer) in ensures that no final variable
  63  *  is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
  64  *  determines that local variables accessed within the scope of an inner class/lambda
  65  *  are either final or effectively-final.
  66  *
  67  *  <p>The JLS has a number of problems in the
  68  *  specification of these flow analysis problems. This implementation
  69  *  attempts to address those issues.
  70  *
  71  *  <p>First, there is no accommodation for a finally clause that cannot
  72  *  complete normally. For liveness analysis, an intervening finally
  73  *  clause can cause a break, continue, or return not to reach its
  74  *  target.  For exception analysis, an intervening finally clause can
  75  *  cause any exception to be "caught".  For DA/DU analysis, the finally
  76  *  clause can prevent a transfer of control from propagating DA/DU
  77  *  state to the target.  In addition, code in the finally clause can
  78  *  affect the DA/DU status of variables.
  79  *
  80  *  <p>For try statements, we introduce the idea of a variable being
  81  *  definitely unassigned "everywhere" in a block.  A variable V is
  82  *  "unassigned everywhere" in a block iff it is unassigned at the
  83  *  beginning of the block and there is no reachable assignment to V
  84  *  in the block.  An assignment V=e is reachable iff V is not DA
  85  *  after e.  Then we can say that V is DU at the beginning of the
  86  *  catch block iff V is DU everywhere in the try block.  Similarly, V
  87  *  is DU at the beginning of the finally block iff V is DU everywhere
  88  *  in the try block and in every catch block.  Specifically, the
  89  *  following bullet is added to 16.2.2
  90  *  <pre>
  91  *      V is <em>unassigned everywhere</em> in a block if it is
  92  *      unassigned before the block and there is no reachable
  93  *      assignment to V within the block.
  94  *  </pre>
  95  *  <p>In 16.2.15, the third bullet (and all of its sub-bullets) for all
  96  *  try blocks is changed to
  97  *  <pre>
  98  *      V is definitely unassigned before a catch block iff V is
  99  *      definitely unassigned everywhere in the try block.
 100  *  </pre>
 101  *  <p>The last bullet (and all of its sub-bullets) for try blocks that
 102  *  have a finally block is changed to
 103  *  <pre>
 104  *      V is definitely unassigned before the finally block iff
 105  *      V is definitely unassigned everywhere in the try block
 106  *      and everywhere in each catch block of the try statement.
 107  *  </pre>
 108  *  <p>In addition,
 109  *  <pre>
 110  *      V is definitely assigned at the end of a constructor iff
 111  *      V is definitely assigned after the block that is the body
 112  *      of the constructor and V is definitely assigned at every
 113  *      return that can return from the constructor.
 114  *  </pre>
 115  *  <p>In addition, each continue statement with the loop as its target
 116  *  is treated as a jump to the end of the loop body, and "intervening"
 117  *  finally clauses are treated as follows: V is DA "due to the
 118  *  continue" iff V is DA before the continue statement or V is DA at
 119  *  the end of any intervening finally block.  V is DU "due to the
 120  *  continue" iff any intervening finally cannot complete normally or V
 121  *  is DU at the end of every intervening finally block.  This "due to
 122  *  the continue" concept is then used in the spec for the loops.
 123  *
 124  *  <p>Similarly, break statements must consider intervening finally
 125  *  blocks.  For liveness analysis, a break statement for which any
 126  *  intervening finally cannot complete normally is not considered to
 127  *  cause the target statement to be able to complete normally. Then
 128  *  we say V is DA "due to the break" iff V is DA before the break or
 129  *  V is DA at the end of any intervening finally block.  V is DU "due
 130  *  to the break" iff any intervening finally cannot complete normally
 131  *  or V is DU at the break and at the end of every intervening
 132  *  finally block.  (I suspect this latter condition can be
 133  *  simplified.)  This "due to the break" is then used in the spec for
 134  *  all statements that can be "broken".
 135  *
 136  *  <p>The return statement is treated similarly.  V is DA "due to a
 137  *  return statement" iff V is DA before the return statement or V is
 138  *  DA at the end of any intervening finally block.  Note that we
 139  *  don't have to worry about the return expression because this
 140  *  concept is only used for construcrors.
 141  *
 142  *  <p>There is no spec in the JLS for when a variable is definitely
 143  *  assigned at the end of a constructor, which is needed for final
 144  *  fields (8.3.1.2).  We implement the rule that V is DA at the end
 145  *  of the constructor iff it is DA and the end of the body of the
 146  *  constructor and V is DA "due to" every return of the constructor.
 147  *
 148  *  <p>Intervening finally blocks similarly affect exception analysis.  An
 149  *  intervening finally that cannot complete normally allows us to ignore
 150  *  an otherwise uncaught exception.
 151  *
 152  *  <p>To implement the semantics of intervening finally clauses, all
 153  *  nonlocal transfers (break, continue, return, throw, method call that
 154  *  can throw a checked exception, and a constructor invocation that can
 155  *  thrown a checked exception) are recorded in a queue, and removed
 156  *  from the queue when we complete processing the target of the
 157  *  nonlocal transfer.  This allows us to modify the queue in accordance
 158  *  with the above rules when we encounter a finally clause.  The only
 159  *  exception to this [no pun intended] is that checked exceptions that
 160  *  are known to be caught or declared to be caught in the enclosing
 161  *  method are not recorded in the queue, but instead are recorded in a
 162  *  global variable "{@code Set<Type> thrown}" that records the type of all
 163  *  exceptions that can be thrown.
 164  *
 165  *  <p>Other minor issues the treatment of members of other classes
 166  *  (always considered DA except that within an anonymous class
 167  *  constructor, where DA status from the enclosing scope is
 168  *  preserved), treatment of the case expression (V is DA before the
 169  *  case expression iff V is DA after the switch expression),
 170  *  treatment of variables declared in a switch block (the implied
 171  *  DA/DU status after the switch expression is DU and not DA for
 172  *  variables defined in a switch block), the treatment of boolean ?:
 173  *  expressions (The JLS rules only handle b and c non-boolean; the
 174  *  new rule is that if b and c are boolean valued, then V is
 175  *  (un)assigned after a?b:c when true/false iff V is (un)assigned
 176  *  after b when true/false and V is (un)assigned after c when
 177  *  true/false).
 178  *
 179  *  <p>There is the remaining question of what syntactic forms constitute a
 180  *  reference to a variable.  It is conventional to allow this.x on the
 181  *  left-hand-side to initialize a final instance field named x, yet
 182  *  this.x isn't considered a "use" when appearing on a right-hand-side
 183  *  in most implementations.  Should parentheses affect what is
 184  *  considered a variable reference?  The simplest rule would be to
 185  *  allow unqualified forms only, parentheses optional, and phase out
 186  *  support for assigning to a final field via this.x.
 187  *
 188  *  <p><b>This is NOT part of any supported API.
 189  *  If you write code that depends on this, you do so at your own risk.
 190  *  This code and its internal interfaces are subject to change or
 191  *  deletion without notice.</b>
 192  */
 193 public class Flow {
 194     protected static final Context.Key<Flow> flowKey = new Context.Key<>();
 195 
 196     private final Names names;
 197     private final Log log;
 198     private final Symtab syms;
 199     private final Types types;
 200     private final Check chk;
 201     private       TreeMaker make;
 202     private final Resolve rs;
 203     private final JCDiagnostic.Factory diags;
 204     private Env<AttrContext> attrEnv;
 205     private       Lint lint;
 206     private final boolean allowEffectivelyFinalInInnerClasses;
 207 
 208     public static Flow instance(Context context) {
 209         Flow instance = context.get(flowKey);
 210         if (instance == null)
 211             instance = new Flow(context);
 212         return instance;
 213     }
 214 
 215     public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
 216         new AliveAnalyzer().analyzeTree(env, make);
 217         new AssignAnalyzer().analyzeTree(env, make);
 218         new FlowAnalyzer().analyzeTree(env, make);
 219         new CaptureAnalyzer().analyzeTree(env, make);
 220     }
 221 
 222     public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
 223         Log.DiagnosticHandler diagHandler = null;
 224         //we need to disable diagnostics temporarily; the problem is that if
 225         //a lambda expression contains e.g. an unreachable statement, an error
 226         //message will be reported and will cause compilation to skip the flow analyis
 227         //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
 228         //related errors, which will allow for more errors to be detected
 229         if (!speculative) {
 230             diagHandler = new Log.DiscardDiagnosticHandler(log);
 231         }
 232         try {
 233             new LambdaAliveAnalyzer().analyzeTree(env, that, make);
 234         } finally {
 235             if (!speculative) {
 236                 log.popDiagnosticHandler(diagHandler);
 237             }
 238         }
 239     }
 240 
 241     public List<Type> analyzeLambdaThrownTypes(final Env<AttrContext> env,
 242             JCLambda that, TreeMaker make) {
 243         //we need to disable diagnostics temporarily; the problem is that if
 244         //a lambda expression contains e.g. an unreachable statement, an error
 245         //message will be reported and will cause compilation to skip the flow analyis
 246         //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
 247         //related errors, which will allow for more errors to be detected
 248         Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
 249         try {
 250             new LambdaAssignAnalyzer(env).analyzeTree(env, that, make);
 251             LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
 252             flowAnalyzer.analyzeTree(env, that, make);
 253             return flowAnalyzer.inferredThrownTypes;
 254         } finally {
 255             log.popDiagnosticHandler(diagHandler);
 256         }
 257     }
 258 
 259     /**
 260      * Definite assignment scan mode
 261      */
 262     enum FlowKind {
 263         /**
 264          * This is the normal DA/DU analysis mode
 265          */
 266         NORMAL("var.might.already.be.assigned", false),
 267         /**
 268          * This is the speculative DA/DU analysis mode used to speculatively
 269          * derive assertions within loop bodies
 270          */
 271         SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true);
 272 
 273         final String errKey;
 274         final boolean isFinal;
 275 
 276         FlowKind(String errKey, boolean isFinal) {
 277             this.errKey = errKey;
 278             this.isFinal = isFinal;
 279         }
 280 
 281         boolean isFinal() {
 282             return isFinal;
 283         }
 284     }
 285 
 286     protected Flow(Context context) {
 287         context.put(flowKey, this);
 288         names = Names.instance(context);
 289         log = Log.instance(context);
 290         syms = Symtab.instance(context);
 291         types = Types.instance(context);
 292         chk = Check.instance(context);
 293         lint = Lint.instance(context);
 294         rs = Resolve.instance(context);
 295         diags = JCDiagnostic.Factory.instance(context);
 296         Source source = Source.instance(context);
 297         allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source);
 298     }
 299 
 300     /**
 301      * Base visitor class for all visitors implementing dataflow analysis logic.
 302      * This class define the shared logic for handling jumps (break/continue statements).
 303      */
 304     static abstract class BaseAnalyzer extends TreeScanner {
 305 
 306         enum JumpKind {
 307             BREAK(JCTree.Tag.BREAK) {
 308                 @Override
 309                 JCTree getTarget(JCTree tree) {
 310                     return ((JCBreak)tree).target;
 311                 }
 312             },
 313             CONTINUE(JCTree.Tag.CONTINUE) {
 314                 @Override
 315                 JCTree getTarget(JCTree tree) {
 316                     return ((JCContinue)tree).target;
 317                 }
 318             };
 319 
 320             final JCTree.Tag treeTag;
 321 
 322             private JumpKind(Tag treeTag) {
 323                 this.treeTag = treeTag;
 324             }
 325 
 326             abstract JCTree getTarget(JCTree tree);
 327         }
 328 
 329         /** The currently pending exits that go from current inner blocks
 330          *  to an enclosing block, in source order.
 331          */
 332         ListBuffer<PendingExit> pendingExits;
 333 
 334         /** A pending exit.  These are the statements return, break, and
 335          *  continue.  In addition, exception-throwing expressions or
 336          *  statements are put here when not known to be caught.  This
 337          *  will typically result in an error unless it is within a
 338          *  try-finally whose finally block cannot complete normally.
 339          */
 340         static class PendingExit {
 341             JCTree tree;
 342 
 343             PendingExit(JCTree tree) {
 344                 this.tree = tree;
 345             }
 346 
 347             void resolveJump() {
 348                 //do nothing
 349             }
 350         }
 351 
 352         abstract void markDead();
 353 
 354         /** Record an outward transfer of control. */
 355         void recordExit(PendingExit pe) {
 356             pendingExits.append(pe);
 357             markDead();
 358         }
 359 
 360         /** Resolve all jumps of this statement. */
 361         private Liveness resolveJump(JCTree tree,
 362                          ListBuffer<PendingExit> oldPendingExits,
 363                          JumpKind jk) {
 364             boolean resolved = false;
 365             List<PendingExit> exits = pendingExits.toList();
 366             pendingExits = oldPendingExits;
 367             for (; exits.nonEmpty(); exits = exits.tail) {
 368                 PendingExit exit = exits.head;
 369                 if (exit.tree.hasTag(jk.treeTag) &&
 370                         jk.getTarget(exit.tree) == tree) {
 371                     exit.resolveJump();
 372                     resolved = true;
 373                 } else {
 374                     pendingExits.append(exit);
 375                 }
 376             }
 377             return Liveness.from(resolved);
 378         }
 379 
 380         /** Resolve all continues of this statement. */
 381         Liveness resolveContinues(JCTree tree) {
 382             return resolveJump(tree, new ListBuffer<PendingExit>(), JumpKind.CONTINUE);
 383         }
 384 
 385         /** Resolve all breaks of this statement. */
 386         Liveness resolveBreaks(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
 387             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
 388         }
 389 
 390         @Override
 391         public void scan(JCTree tree) {
 392             if (tree != null && (
 393                     tree.type == null ||
 394                     tree.type != Type.stuckType)) {
 395                 super.scan(tree);
 396             }
 397         }
 398 
 399         public void visitPackageDef(JCPackageDecl tree) {
 400             // Do nothing for PackageDecl
 401         }
 402 
 403         protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
 404             JCBreak brk = make.at(Position.NOPOS).Break(null);
 405             brk.target = swtch;
 406             scan(brk);
 407         }
 408     }
 409 
 410     /**
 411      * This pass implements the first step of the dataflow analysis, namely
 412      * the liveness analysis check. This checks that every statement is reachable.
 413      * The output of this analysis pass are used by other analyzers. This analyzer
 414      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
 415      */
 416     class AliveAnalyzer extends BaseAnalyzer {
 417 
 418         /** A flag that indicates whether the last statement could
 419          *  complete normally.
 420          */
 421         private Liveness alive;
 422 
 423         @Override
 424         void markDead() {
 425             alive = Liveness.DEAD;
 426         }
 427 
 428     /*************************************************************************
 429      * Visitor methods for statements and definitions
 430      *************************************************************************/
 431 
 432         /** Analyze a definition.
 433          */
 434         void scanDef(JCTree tree) {
 435             scanStat(tree);
 436             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && alive == Liveness.DEAD) {
 437                 log.error(tree.pos(),
 438                           Errors.InitializerMustBeAbleToCompleteNormally);
 439             }
 440         }
 441 
 442         /** Analyze a statement. Check that statement is reachable.
 443          */
 444         void scanStat(JCTree tree) {
 445             if (alive == Liveness.DEAD && tree != null) {
 446                 log.error(tree.pos(), Errors.UnreachableStmt);
 447                 if (!tree.hasTag(SKIP)) alive = Liveness.RECOVERY;
 448             }
 449             scan(tree);
 450         }
 451 
 452         /** Analyze list of statements.
 453          */
 454         void scanStats(List<? extends JCStatement> trees) {
 455             if (trees != null)
 456                 for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
 457                     scanStat(l.head);
 458         }
 459 
 460         /* ------------ Visitor methods for various sorts of trees -------------*/
 461 
 462         public void visitClassDef(JCClassDecl tree) {
 463             if (tree.sym == null) return;
 464             Liveness alivePrev = alive;
 465             ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 466             Lint lintPrev = lint;
 467 
 468             pendingExits = new ListBuffer<>();
 469             lint = lint.augment(tree.sym);
 470 
 471             try {
 472                 // process all the static initializers
 473                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 474                     if (!l.head.hasTag(METHODDEF) &&
 475                         (TreeInfo.flags(l.head) & STATIC) != 0) {
 476                         scanDef(l.head);
 477                     }
 478                 }
 479 
 480                 // process all the instance initializers
 481                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 482                     if (!l.head.hasTag(METHODDEF) &&
 483                         (TreeInfo.flags(l.head) & STATIC) == 0) {
 484                         scanDef(l.head);
 485                     }
 486                 }
 487 
 488                 // process all the methods
 489                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 490                     if (l.head.hasTag(METHODDEF)) {
 491                         scan(l.head);
 492                     }
 493                 }
 494             } finally {
 495                 pendingExits = pendingExitsPrev;
 496                 alive = alivePrev;
 497                 lint = lintPrev;
 498             }
 499         }
 500 
 501         public void visitMethodDef(JCMethodDecl tree) {
 502             if (tree.body == null) return;
 503             Lint lintPrev = lint;
 504 
 505             lint = lint.augment(tree.sym);
 506 
 507             Assert.check(pendingExits.isEmpty());
 508 
 509             try {
 510                 alive = Liveness.ALIVE;
 511                 scanStat(tree.body);
 512 
 513                 if (alive == Liveness.ALIVE && !tree.sym.type.getReturnType().hasTag(VOID))
 514                     log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
 515 
 516                 List<PendingExit> exits = pendingExits.toList();
 517                 pendingExits = new ListBuffer<>();
 518                 while (exits.nonEmpty()) {
 519                     PendingExit exit = exits.head;
 520                     exits = exits.tail;
 521                     Assert.check(exit.tree.hasTag(RETURN));
 522                 }
 523             } finally {
 524                 lint = lintPrev;
 525             }
 526         }
 527 
 528         public void visitVarDef(JCVariableDecl tree) {
 529             if (tree.init != null) {
 530                 Lint lintPrev = lint;
 531                 lint = lint.augment(tree.sym);
 532                 try{
 533                     scan(tree.init);
 534                 } finally {
 535                     lint = lintPrev;
 536                 }
 537             }
 538         }
 539 
 540         public void visitBlock(JCBlock tree) {
 541             scanStats(tree.stats);
 542         }
 543 
 544         public void visitDoLoop(JCDoWhileLoop tree) {
 545             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 546             pendingExits = new ListBuffer<>();
 547             scanStat(tree.body);
 548             alive = alive.or(resolveContinues(tree));
 549             scan(tree.cond);
 550             alive = alive.and(!tree.cond.type.isTrue());
 551             alive = alive.or(resolveBreaks(tree, prevPendingExits));
 552         }
 553 
 554         public void visitWhileLoop(JCWhileLoop tree) {
 555             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 556             pendingExits = new ListBuffer<>();
 557             scan(tree.cond);
 558             alive = Liveness.from(!tree.cond.type.isFalse());
 559             scanStat(tree.body);
 560             alive = alive.or(resolveContinues(tree));
 561             alive = resolveBreaks(tree, prevPendingExits).or(
 562                 !tree.cond.type.isTrue());
 563         }
 564 
 565         public void visitForLoop(JCForLoop tree) {
 566             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 567             scanStats(tree.init);
 568             pendingExits = new ListBuffer<>();
 569             if (tree.cond != null) {
 570                 scan(tree.cond);
 571                 alive = Liveness.from(!tree.cond.type.isFalse());
 572             } else {
 573                 alive = Liveness.ALIVE;
 574             }
 575             scanStat(tree.body);
 576             alive = alive.or(resolveContinues(tree));
 577             scan(tree.step);
 578             alive = resolveBreaks(tree, prevPendingExits).or(
 579                 tree.cond != null && !tree.cond.type.isTrue());
 580         }
 581 
 582         public void visitForeachLoop(JCEnhancedForLoop tree) {
 583             visitVarDef(tree.var);
 584             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 585             scan(tree.expr);
 586             pendingExits = new ListBuffer<>();
 587             scanStat(tree.body);
 588             alive = alive.or(resolveContinues(tree));
 589             resolveBreaks(tree, prevPendingExits);
 590             alive = Liveness.ALIVE;
 591         }
 592 
 593         public void visitLabelled(JCLabeledStatement tree) {
 594             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 595             pendingExits = new ListBuffer<>();
 596             scanStat(tree.body);
 597             alive = alive.or(resolveBreaks(tree, prevPendingExits));
 598         }
 599 
 600         public void visitSwitch(JCSwitch tree) {
 601             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 602             pendingExits = new ListBuffer<>();
 603             scan(tree.selector);
 604             boolean hasDefault = false;
 605             for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
 606                 alive = Liveness.ALIVE;
 607                 JCCase c = l.head;
 608                 if (c.pats.isEmpty())
 609                     hasDefault = true;
 610                 else {
 611                     for (JCExpression pat : c.pats) {
 612                         scan(pat);
 613                     }
 614                 }
 615                 scanStats(c.stats);
 616                 c.completesNormally = alive != Liveness.DEAD;
 617                 if (alive != Liveness.DEAD && c.caseKind == JCCase.RULE) {
 618                     scanSyntheticBreak(make, tree);
 619                     alive = Liveness.DEAD;
 620                 }
 621                 // Warn about fall-through if lint switch fallthrough enabled.
 622                 if (alive == Liveness.ALIVE &&
 623                     lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
 624                     c.stats.nonEmpty() && l.tail.nonEmpty())
 625                     log.warning(Lint.LintCategory.FALLTHROUGH,
 626                                 l.tail.head.pos(),
 627                                 Warnings.PossibleFallThroughIntoCase);
 628             }
 629             if (!hasDefault) {
 630                 alive = Liveness.ALIVE;
 631             }
 632             alive = alive.or(resolveBreaks(tree, prevPendingExits));
 633         }
 634 
 635         @Override
 636         public void visitSwitchExpression(JCSwitchExpression tree) {
 637             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 638             pendingExits = new ListBuffer<>();
 639             scan(tree.selector);
 640             Set<Object> constants = null;
 641             if ((tree.selector.type.tsym.flags() & ENUM) != 0) {
 642                 constants = new HashSet<>();
 643                 for (Symbol s : tree.selector.type.tsym.members().getSymbols(s -> (s.flags() & ENUM) != 0)) {
 644                     constants.add(s.name);
 645                 }
 646             }
 647             boolean hasDefault = false;
 648             Liveness prevAlive = alive;
 649             for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
 650                 alive = Liveness.ALIVE;
 651                 JCCase c = l.head;
 652                 if (c.pats.isEmpty())
 653                     hasDefault = true;
 654                 else {
 655                     for (JCExpression pat : c.pats) {
 656                         scan(pat);
 657                         if (constants != null) {
 658                             if (pat.hasTag(IDENT))
 659                                 constants.remove(((JCIdent) pat).name);
 660                             if (pat.type != null)
 661                                 constants.remove(pat.type.constValue());
 662                         }
 663                     }
 664                 }
 665                 scanStats(c.stats);
 666                 if (alive == Liveness.ALIVE) {
 667                     if (c.caseKind == JCCase.RULE) {
 668                         log.error(TreeInfo.diagEndPos(c.body),
 669                                   Errors.RuleCompletesNormally);
 670                     } else if (l.tail.isEmpty()) {
 671                         log.error(TreeInfo.diagEndPos(tree),
 672                                   Errors.SwitchExpressionCompletesNormally);
 673                     }
 674                 }
 675                 c.completesNormally = alive != Liveness.DEAD;
 676             }
 677             if ((constants == null || !constants.isEmpty()) && !hasDefault) {
 678                 log.error(tree, Errors.NotExhaustive);
 679             }
 680             alive = prevAlive;
 681             alive = alive.or(resolveBreaks(tree, prevPendingExits));
 682         }
 683 
 684         public void visitTry(JCTry tree) {
 685             ListBuffer<PendingExit> prevPendingExits = pendingExits;
 686             pendingExits = new ListBuffer<>();
 687             for (JCTree resource : tree.resources) {
 688                 if (resource instanceof JCVariableDecl) {
 689                     JCVariableDecl vdecl = (JCVariableDecl) resource;
 690                     visitVarDef(vdecl);
 691                 } else if (resource instanceof JCExpression) {
 692                     scan((JCExpression) resource);
 693                 } else {
 694                     throw new AssertionError(tree);  // parser error
 695                 }
 696             }
 697 
 698             scanStat(tree.body);
 699             Liveness aliveEnd = alive;
 700 
 701             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 702                 alive = Liveness.ALIVE;
 703                 JCVariableDecl param = l.head.param;
 704                 scan(param);
 705                 scanStat(l.head.body);
 706                 aliveEnd = aliveEnd.or(alive);
 707             }
 708             if (tree.finalizer != null) {
 709                 ListBuffer<PendingExit> exits = pendingExits;
 710                 pendingExits = prevPendingExits;
 711                 alive = Liveness.ALIVE;
 712                 scanStat(tree.finalizer);
 713                 tree.finallyCanCompleteNormally = alive != Liveness.DEAD;
 714                 if (alive == Liveness.DEAD) {
 715                     if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
 716                         log.warning(Lint.LintCategory.FINALLY,
 717                                 TreeInfo.diagEndPos(tree.finalizer),
 718                                 Warnings.FinallyCannotComplete);
 719                     }
 720                 } else {
 721                     while (exits.nonEmpty()) {
 722                         pendingExits.append(exits.next());
 723                     }
 724                     alive = aliveEnd;
 725                 }
 726             } else {
 727                 alive = aliveEnd;
 728                 ListBuffer<PendingExit> exits = pendingExits;
 729                 pendingExits = prevPendingExits;
 730                 while (exits.nonEmpty()) pendingExits.append(exits.next());
 731             }
 732         }
 733 
 734         @Override
 735         public void visitIf(JCIf tree) {
 736             scan(tree.cond);
 737             scanStat(tree.thenpart);
 738             if (tree.elsepart != null) {
 739                 Liveness aliveAfterThen = alive;
 740                 alive = Liveness.ALIVE;
 741                 scanStat(tree.elsepart);
 742                 alive = alive.or(aliveAfterThen);
 743             } else {
 744                 alive = Liveness.ALIVE;
 745             }
 746         }
 747 
 748         public void visitBreak(JCBreak tree) {
 749             if (tree.isValueBreak())
 750                 scan(tree.value);
 751             recordExit(new PendingExit(tree));
 752         }
 753 
 754         public void visitContinue(JCContinue tree) {
 755             recordExit(new PendingExit(tree));
 756         }
 757 
 758         public void visitReturn(JCReturn tree) {
 759             scan(tree.expr);
 760             recordExit(new PendingExit(tree));
 761         }
 762 
 763         public void visitThrow(JCThrow tree) {
 764             scan(tree.expr);
 765             markDead();
 766         }
 767 
 768         public void visitApply(JCMethodInvocation tree) {
 769             scan(tree.meth);
 770             scan(tree.args);
 771         }
 772 
 773         public void visitNewClass(JCNewClass tree) {
 774             scan(tree.encl);
 775             scan(tree.args);
 776             if (tree.def != null) {
 777                 scan(tree.def);
 778             }
 779         }
 780 
 781         @Override
 782         public void visitLambda(JCLambda tree) {
 783             if (tree.type != null &&
 784                     tree.type.isErroneous()) {
 785                 return;
 786             }
 787 
 788             ListBuffer<PendingExit> prevPending = pendingExits;
 789             Liveness prevAlive = alive;
 790             try {
 791                 pendingExits = new ListBuffer<>();
 792                 alive = Liveness.ALIVE;
 793                 scanStat(tree.body);
 794                 tree.canCompleteNormally = alive != Liveness.DEAD;
 795             }
 796             finally {
 797                 pendingExits = prevPending;
 798                 alive = prevAlive;
 799             }
 800         }
 801 
 802         public void visitModuleDef(JCModuleDecl tree) {
 803             // Do nothing for modules
 804         }
 805 
 806     /**************************************************************************
 807      * main method
 808      *************************************************************************/
 809 
 810         /** Perform definite assignment/unassignment analysis on a tree.
 811          */
 812         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
 813             analyzeTree(env, env.tree, make);
 814         }
 815         public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
 816             try {
 817                 attrEnv = env;
 818                 Flow.this.make = make;
 819                 pendingExits = new ListBuffer<>();
 820                 alive = Liveness.ALIVE;
 821                 scan(tree);
 822             } finally {
 823                 pendingExits = null;
 824                 Flow.this.make = null;
 825             }
 826         }
 827     }
 828 
 829     /**
 830      * This pass implements the second step of the dataflow analysis, namely
 831      * the exception analysis. This is to ensure that every checked exception that is
 832      * thrown is declared or caught. The analyzer uses some info that has been set by
 833      * the liveliness analyzer.
 834      */
 835     class FlowAnalyzer extends BaseAnalyzer {
 836 
 837         /** A flag that indicates whether the last statement could
 838          *  complete normally.
 839          */
 840         HashMap<Symbol, List<Type>> preciseRethrowTypes;
 841 
 842         /** The current class being defined.
 843          */
 844         JCClassDecl classDef;
 845 
 846         /** The list of possibly thrown declarable exceptions.
 847          */
 848         List<Type> thrown;
 849 
 850         /** The list of exceptions that are either caught or declared to be
 851          *  thrown.
 852          */
 853         List<Type> caught;
 854 
 855         class ThrownPendingExit extends BaseAnalyzer.PendingExit {
 856 
 857             Type thrown;
 858 
 859             ThrownPendingExit(JCTree tree, Type thrown) {
 860                 super(tree);
 861                 this.thrown = thrown;
 862             }
 863         }
 864 
 865         @Override
 866         void markDead() {
 867             //do nothing
 868         }
 869 
 870         /*-------------------- Exceptions ----------------------*/
 871 
 872         /** Complain that pending exceptions are not caught.
 873          */
 874         void errorUncaught() {
 875             for (PendingExit exit = pendingExits.next();
 876                  exit != null;
 877                  exit = pendingExits.next()) {
 878                 Assert.check(exit instanceof ThrownPendingExit);
 879                 ThrownPendingExit thrownExit = (ThrownPendingExit) exit;
 880                 if (classDef != null &&
 881                     classDef.pos == exit.tree.pos) {
 882                     log.error(exit.tree.pos(),
 883                               Errors.UnreportedExceptionDefaultConstructor(thrownExit.thrown));
 884                 } else if (exit.tree.hasTag(VARDEF) &&
 885                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
 886                     log.error(exit.tree.pos(),
 887                               Errors.UnreportedExceptionImplicitClose(thrownExit.thrown,
 888                                                                       ((JCVariableDecl)exit.tree).sym.name));
 889                 } else {
 890                     log.error(exit.tree.pos(),
 891                               Errors.UnreportedExceptionNeedToCatchOrThrow(thrownExit.thrown));
 892                 }
 893             }
 894         }
 895 
 896         /** Record that exception is potentially thrown and check that it
 897          *  is caught.
 898          */
 899         void markThrown(JCTree tree, Type exc) {
 900             if (!chk.isUnchecked(tree.pos(), exc)) {
 901                 if (!chk.isHandled(exc, caught)) {
 902                     pendingExits.append(new ThrownPendingExit(tree, exc));
 903                 }
 904                 thrown = chk.incl(exc, thrown);
 905             }
 906         }
 907 
 908     /*************************************************************************
 909      * Visitor methods for statements and definitions
 910      *************************************************************************/
 911 
 912         /* ------------ Visitor methods for various sorts of trees -------------*/
 913 
 914         public void visitClassDef(JCClassDecl tree) {
 915             if (tree.sym == null) return;
 916 
 917             JCClassDecl classDefPrev = classDef;
 918             List<Type> thrownPrev = thrown;
 919             List<Type> caughtPrev = caught;
 920             ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 921             Lint lintPrev = lint;
 922             boolean anonymousClass = tree.name == names.empty;
 923             pendingExits = new ListBuffer<>();
 924             if (!anonymousClass) {
 925                 caught = List.nil();
 926             }
 927             classDef = tree;
 928             thrown = List.nil();
 929             lint = lint.augment(tree.sym);
 930 
 931             try {
 932                 // process all the static initializers
 933                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 934                     if (!l.head.hasTag(METHODDEF) &&
 935                         (TreeInfo.flags(l.head) & STATIC) != 0) {
 936                         scan(l.head);
 937                         errorUncaught();
 938                     }
 939                 }
 940 
 941                 // add intersection of all thrown clauses of initial constructors
 942                 // to set of caught exceptions, unless class is anonymous.
 943                 if (!anonymousClass) {
 944                     boolean firstConstructor = true;
 945                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 946                         if (TreeInfo.isInitialConstructor(l.head)) {
 947                             List<Type> mthrown =
 948                                 ((JCMethodDecl) l.head).sym.type.getThrownTypes();
 949                             if (firstConstructor) {
 950                                 caught = mthrown;
 951                                 firstConstructor = false;
 952                             } else {
 953                                 caught = chk.intersect(mthrown, caught);
 954                             }
 955                         }
 956                     }
 957                 }
 958 
 959                 // process all the instance initializers
 960                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 961                     if (!l.head.hasTag(METHODDEF) &&
 962                         (TreeInfo.flags(l.head) & STATIC) == 0) {
 963                         scan(l.head);
 964                         errorUncaught();
 965                     }
 966                 }
 967 
 968                 // in an anonymous class, add the set of thrown exceptions to
 969                 // the throws clause of the synthetic constructor and propagate
 970                 // outwards.
 971                 // Changing the throws clause on the fly is okay here because
 972                 // the anonymous constructor can't be invoked anywhere else,
 973                 // and its type hasn't been cached.
 974                 if (anonymousClass) {
 975                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 976                         if (TreeInfo.isConstructor(l.head)) {
 977                             JCMethodDecl mdef = (JCMethodDecl)l.head;
 978                             scan(mdef);
 979                             mdef.thrown = make.Types(thrown);
 980                             mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
 981                         }
 982                     }
 983                     thrownPrev = chk.union(thrown, thrownPrev);
 984                 }
 985 
 986                 // process all the methods
 987                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 988                     if (anonymousClass && TreeInfo.isConstructor(l.head))
 989                         continue; // there can never be an uncaught exception.
 990                     if (l.head.hasTag(METHODDEF)) {
 991                         scan(l.head);
 992                         errorUncaught();
 993                     }
 994                 }
 995 
 996                 thrown = thrownPrev;
 997             } finally {
 998                 pendingExits = pendingExitsPrev;
 999                 caught = caughtPrev;
1000                 classDef = classDefPrev;
1001                 lint = lintPrev;
1002             }
1003         }
1004 
1005         public void visitMethodDef(JCMethodDecl tree) {
1006             if (tree.body == null) return;
1007 
1008             List<Type> caughtPrev = caught;
1009             List<Type> mthrown = tree.sym.type.getThrownTypes();
1010             Lint lintPrev = lint;
1011 
1012             lint = lint.augment(tree.sym);
1013 
1014             Assert.check(pendingExits.isEmpty());
1015 
1016             try {
1017                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1018                     JCVariableDecl def = l.head;
1019                     scan(def);
1020                 }
1021                 if (TreeInfo.isInitialConstructor(tree))
1022                     caught = chk.union(caught, mthrown);
1023                 else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
1024                     caught = mthrown;
1025                 // else we are in an instance initializer block;
1026                 // leave caught unchanged.
1027 
1028                 scan(tree.body);
1029 
1030                 List<PendingExit> exits = pendingExits.toList();
1031                 pendingExits = new ListBuffer<>();
1032                 while (exits.nonEmpty()) {
1033                     PendingExit exit = exits.head;
1034                     exits = exits.tail;
1035                     if (!(exit instanceof ThrownPendingExit)) {
1036                         Assert.check(exit.tree.hasTag(RETURN));
1037                     } else {
1038                         // uncaught throws will be reported later
1039                         pendingExits.append(exit);
1040                     }
1041                 }
1042             } finally {
1043                 caught = caughtPrev;
1044                 lint = lintPrev;
1045             }
1046         }
1047 
1048         public void visitVarDef(JCVariableDecl tree) {
1049             if (tree.init != null) {
1050                 Lint lintPrev = lint;
1051                 lint = lint.augment(tree.sym);
1052                 try{
1053                     scan(tree.init);
1054                 } finally {
1055                     lint = lintPrev;
1056                 }
1057             }
1058         }
1059 
1060         public void visitBlock(JCBlock tree) {
1061             scan(tree.stats);
1062         }
1063 
1064         public void visitDoLoop(JCDoWhileLoop tree) {
1065             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1066             pendingExits = new ListBuffer<>();
1067             scan(tree.body);
1068             resolveContinues(tree);
1069             scan(tree.cond);
1070             resolveBreaks(tree, prevPendingExits);
1071         }
1072 
1073         public void visitWhileLoop(JCWhileLoop tree) {
1074             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1075             pendingExits = new ListBuffer<>();
1076             scan(tree.cond);
1077             scan(tree.body);
1078             resolveContinues(tree);
1079             resolveBreaks(tree, prevPendingExits);
1080         }
1081 
1082         public void visitForLoop(JCForLoop tree) {
1083             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1084             scan(tree.init);
1085             pendingExits = new ListBuffer<>();
1086             if (tree.cond != null) {
1087                 scan(tree.cond);
1088             }
1089             scan(tree.body);
1090             resolveContinues(tree);
1091             scan(tree.step);
1092             resolveBreaks(tree, prevPendingExits);
1093         }
1094 
1095         public void visitForeachLoop(JCEnhancedForLoop tree) {
1096             visitVarDef(tree.var);
1097             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1098             scan(tree.expr);
1099             pendingExits = new ListBuffer<>();
1100             scan(tree.body);
1101             resolveContinues(tree);
1102             resolveBreaks(tree, prevPendingExits);
1103         }
1104 
1105         public void visitLabelled(JCLabeledStatement tree) {
1106             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1107             pendingExits = new ListBuffer<>();
1108             scan(tree.body);
1109             resolveBreaks(tree, prevPendingExits);
1110         }
1111 
1112         public void visitSwitch(JCSwitch tree) {
1113             handleSwitch(tree, tree.selector, tree.cases);
1114         }
1115 
1116         @Override
1117         public void visitSwitchExpression(JCSwitchExpression tree) {
1118             handleSwitch(tree, tree.selector, tree.cases);
1119         }
1120 
1121         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
1122             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1123             pendingExits = new ListBuffer<>();
1124             scan(selector);
1125             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
1126                 JCCase c = l.head;
1127                 scan(c.pats);
1128                 scan(c.stats);
1129             }
1130             resolveBreaks(tree, prevPendingExits);
1131         }
1132 
1133         public void visitTry(JCTry tree) {
1134             List<Type> caughtPrev = caught;
1135             List<Type> thrownPrev = thrown;
1136             thrown = List.nil();
1137             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1138                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1139                         ((JCTypeUnion)l.head.param.vartype).alternatives :
1140                         List.of(l.head.param.vartype);
1141                 for (JCExpression ct : subClauses) {
1142                     caught = chk.incl(ct.type, caught);
1143                 }
1144             }
1145 
1146             ListBuffer<PendingExit> prevPendingExits = pendingExits;
1147             pendingExits = new ListBuffer<>();
1148             for (JCTree resource : tree.resources) {
1149                 if (resource instanceof JCVariableDecl) {
1150                     JCVariableDecl vdecl = (JCVariableDecl) resource;
1151                     visitVarDef(vdecl);
1152                 } else if (resource instanceof JCExpression) {
1153                     scan((JCExpression) resource);
1154                 } else {
1155                     throw new AssertionError(tree);  // parser error
1156                 }
1157             }
1158             for (JCTree resource : tree.resources) {
1159                 List<Type> closeableSupertypes = resource.type.isCompound() ?
1160                     types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1161                     List.of(resource.type);
1162                 for (Type sup : closeableSupertypes) {
1163                     if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1164                         Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1165                                 attrEnv,
1166                                 types.skipTypeVars(sup, false),
1167                                 names.close,
1168                                 List.nil(),
1169                                 List.nil());
1170                         Type mt = types.memberType(resource.type, closeMethod);
1171                         if (closeMethod.kind == MTH) {
1172                             for (Type t : mt.getThrownTypes()) {
1173                                 markThrown(resource, t);
1174                             }
1175                         }
1176                     }
1177                 }
1178             }
1179             scan(tree.body);
1180             List<Type> thrownInTry = chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType));
1181             thrown = thrownPrev;
1182             caught = caughtPrev;
1183 
1184             List<Type> caughtInTry = List.nil();
1185             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1186                 JCVariableDecl param = l.head.param;
1187                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1188                         ((JCTypeUnion)l.head.param.vartype).alternatives :
1189                         List.of(l.head.param.vartype);
1190                 List<Type> ctypes = List.nil();
1191                 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1192                 for (JCExpression ct : subClauses) {
1193                     Type exc = ct.type;
1194                     if (exc != syms.unknownType) {
1195                         ctypes = ctypes.append(exc);
1196                         if (types.isSameType(exc, syms.objectType))
1197                             continue;
1198                         checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1199                         caughtInTry = chk.incl(exc, caughtInTry);
1200                     }
1201                 }
1202                 scan(param);
1203                 preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1204                 scan(l.head.body);
1205                 preciseRethrowTypes.remove(param.sym);
1206             }
1207             if (tree.finalizer != null) {
1208                 List<Type> savedThrown = thrown;
1209                 thrown = List.nil();
1210                 ListBuffer<PendingExit> exits = pendingExits;
1211                 pendingExits = prevPendingExits;
1212                 scan(tree.finalizer);
1213                 if (!tree.finallyCanCompleteNormally) {
1214                     // discard exits and exceptions from try and finally
1215                     thrown = chk.union(thrown, thrownPrev);
1216                 } else {
1217                     thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1218                     thrown = chk.union(thrown, savedThrown);
1219                     // FIX: this doesn't preserve source order of exits in catch
1220                     // versus finally!
1221                     while (exits.nonEmpty()) {
1222                         pendingExits.append(exits.next());
1223                     }
1224                 }
1225             } else {
1226                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1227                 ListBuffer<PendingExit> exits = pendingExits;
1228                 pendingExits = prevPendingExits;
1229                 while (exits.nonEmpty()) pendingExits.append(exits.next());
1230             }
1231         }
1232 
1233         @Override
1234         public void visitIf(JCIf tree) {
1235             scan(tree.cond);
1236             scan(tree.thenpart);
1237             if (tree.elsepart != null) {
1238                 scan(tree.elsepart);
1239             }
1240         }
1241 
1242         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1243             if (chk.subset(exc, caughtInTry)) {
1244                 log.error(pos, Errors.ExceptAlreadyCaught(exc));
1245             } else if (!chk.isUnchecked(pos, exc) &&
1246                     !isExceptionOrThrowable(exc) &&
1247                     !chk.intersects(exc, thrownInTry)) {
1248                 log.error(pos, Errors.ExceptNeverThrownInTry(exc));
1249             } else {
1250                 List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
1251                 // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
1252                 // unchecked exception, the result list would not be empty, as the augmented
1253                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1254                 // exception, that would have been covered in the branch above
1255                 if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1256                         !isExceptionOrThrowable(exc)) {
1257                     Warning key = catchableThrownTypes.length() == 1 ?
1258                             Warnings.UnreachableCatch(catchableThrownTypes) :
1259                             Warnings.UnreachableCatch1(catchableThrownTypes);
1260                     log.warning(pos, key);
1261                 }
1262             }
1263         }
1264         //where
1265             private boolean isExceptionOrThrowable(Type exc) {
1266                 return exc.tsym == syms.throwableType.tsym ||
1267                     exc.tsym == syms.exceptionType.tsym;
1268             }
1269 
1270         public void visitBreak(JCBreak tree) {
1271             if (tree.isValueBreak())
1272                 scan(tree.value);
1273             recordExit(new PendingExit(tree));
1274         }
1275 
1276         public void visitContinue(JCContinue tree) {
1277             recordExit(new PendingExit(tree));
1278         }
1279 
1280         public void visitReturn(JCReturn tree) {
1281             scan(tree.expr);
1282             recordExit(new PendingExit(tree));
1283         }
1284 
1285         public void visitThrow(JCThrow tree) {
1286             scan(tree.expr);
1287             Symbol sym = TreeInfo.symbol(tree.expr);
1288             if (sym != null &&
1289                 sym.kind == VAR &&
1290                 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1291                 preciseRethrowTypes.get(sym) != null) {
1292                 for (Type t : preciseRethrowTypes.get(sym)) {
1293                     markThrown(tree, t);
1294                 }
1295             }
1296             else {
1297                 markThrown(tree, tree.expr.type);
1298             }
1299             markDead();
1300         }
1301 
1302         public void visitApply(JCMethodInvocation tree) {
1303             scan(tree.meth);
1304             scan(tree.args);
1305             for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1306                 markThrown(tree, l.head);
1307         }
1308 
1309         public void visitNewClass(JCNewClass tree) {
1310             scan(tree.encl);
1311             scan(tree.args);
1312            // scan(tree.def);
1313             for (List<Type> l = tree.constructorType.getThrownTypes();
1314                  l.nonEmpty();
1315                  l = l.tail) {
1316                 markThrown(tree, l.head);
1317             }
1318             List<Type> caughtPrev = caught;
1319             try {
1320                 // If the new class expression defines an anonymous class,
1321                 // analysis of the anonymous constructor may encounter thrown
1322                 // types which are unsubstituted type variables.
1323                 // However, since the constructor's actual thrown types have
1324                 // already been marked as thrown, it is safe to simply include
1325                 // each of the constructor's formal thrown types in the set of
1326                 // 'caught/declared to be thrown' types, for the duration of
1327                 // the class def analysis.
1328                 if (tree.def != null)
1329                     for (List<Type> l = tree.constructor.type.getThrownTypes();
1330                          l.nonEmpty();
1331                          l = l.tail) {
1332                         caught = chk.incl(l.head, caught);
1333                     }
1334                 scan(tree.def);
1335             }
1336             finally {
1337                 caught = caughtPrev;
1338             }
1339         }
1340 
1341         @Override
1342         public void visitLambda(JCLambda tree) {
1343             if (tree.type != null &&
1344                     tree.type.isErroneous()) {
1345                 return;
1346             }
1347             List<Type> prevCaught = caught;
1348             List<Type> prevThrown = thrown;
1349             ListBuffer<PendingExit> prevPending = pendingExits;
1350             try {
1351                 pendingExits = new ListBuffer<>();
1352                 caught = tree.getDescriptorType(types).getThrownTypes();
1353                 thrown = List.nil();
1354                 scan(tree.body);
1355                 List<PendingExit> exits = pendingExits.toList();
1356                 pendingExits = new ListBuffer<>();
1357                 while (exits.nonEmpty()) {
1358                     PendingExit exit = exits.head;
1359                     exits = exits.tail;
1360                     if (!(exit instanceof ThrownPendingExit)) {
1361                         Assert.check(exit.tree.hasTag(RETURN));
1362                     } else {
1363                         // uncaught throws will be reported later
1364                         pendingExits.append(exit);
1365                     }
1366                 }
1367 
1368                 errorUncaught();
1369             } finally {
1370                 pendingExits = prevPending;
1371                 caught = prevCaught;
1372                 thrown = prevThrown;
1373             }
1374         }
1375 
1376         public void visitModuleDef(JCModuleDecl tree) {
1377             // Do nothing for modules
1378         }
1379 
1380     /**************************************************************************
1381      * main method
1382      *************************************************************************/
1383 
1384         /** Perform definite assignment/unassignment analysis on a tree.
1385          */
1386         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
1387             analyzeTree(env, env.tree, make);
1388         }
1389         public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
1390             try {
1391                 attrEnv = env;
1392                 Flow.this.make = make;
1393                 pendingExits = new ListBuffer<>();
1394                 preciseRethrowTypes = new HashMap<>();
1395                 this.thrown = this.caught = null;
1396                 this.classDef = null;
1397                 scan(tree);
1398             } finally {
1399                 pendingExits = null;
1400                 Flow.this.make = null;
1401                 this.thrown = this.caught = null;
1402                 this.classDef = null;
1403             }
1404         }
1405     }
1406 
1407     /**
1408      * Specialized pass that performs reachability analysis on a lambda
1409      */
1410     class LambdaAliveAnalyzer extends AliveAnalyzer {
1411 
1412         boolean inLambda;
1413 
1414         @Override
1415         public void visitReturn(JCReturn tree) {
1416             //ignore lambda return expression (which might not even be attributed)
1417             recordExit(new PendingExit(tree));
1418         }
1419 
1420         @Override
1421         public void visitLambda(JCLambda tree) {
1422             if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) {
1423                 return;
1424             }
1425             inLambda = true;
1426             try {
1427                 super.visitLambda(tree);
1428             } finally {
1429                 inLambda = false;
1430             }
1431         }
1432 
1433         @Override
1434         public void visitClassDef(JCClassDecl tree) {
1435             //skip
1436         }
1437     }
1438 
1439     /**
1440      * Specialized pass that performs DA/DU on a lambda
1441      */
1442     class LambdaAssignAnalyzer extends AssignAnalyzer {
1443         WriteableScope enclosedSymbols;
1444         boolean inLambda;
1445 
1446         LambdaAssignAnalyzer(Env<AttrContext> env) {
1447             enclosedSymbols = WriteableScope.create(env.enclClass.sym);
1448         }
1449 
1450         @Override
1451         public void visitLambda(JCLambda tree) {
1452             if (inLambda) {
1453                 return;
1454             }
1455             inLambda = true;
1456             try {
1457                 super.visitLambda(tree);
1458             } finally {
1459                 inLambda = false;
1460             }
1461         }
1462 
1463         @Override
1464         public void visitVarDef(JCVariableDecl tree) {
1465             enclosedSymbols.enter(tree.sym);
1466             super.visitVarDef(tree);
1467         }
1468         @Override
1469         protected boolean trackable(VarSymbol sym) {
1470             return enclosedSymbols.includes(sym) &&
1471                    sym.owner.kind == MTH;
1472         }
1473 
1474         @Override
1475         public void visitClassDef(JCClassDecl tree) {
1476             //skip
1477         }
1478     }
1479 
1480     /**
1481      * Specialized pass that performs inference of thrown types for lambdas.
1482      */
1483     class LambdaFlowAnalyzer extends FlowAnalyzer {
1484         List<Type> inferredThrownTypes;
1485         boolean inLambda;
1486         @Override
1487         public void visitLambda(JCLambda tree) {
1488             if ((tree.type != null &&
1489                     tree.type.isErroneous()) || inLambda) {
1490                 return;
1491             }
1492             List<Type> prevCaught = caught;
1493             List<Type> prevThrown = thrown;
1494             ListBuffer<PendingExit> prevPending = pendingExits;
1495             inLambda = true;
1496             try {
1497                 pendingExits = new ListBuffer<>();
1498                 caught = List.of(syms.throwableType);
1499                 thrown = List.nil();
1500                 scan(tree.body);
1501                 inferredThrownTypes = thrown;
1502             } finally {
1503                 pendingExits = prevPending;
1504                 caught = prevCaught;
1505                 thrown = prevThrown;
1506                 inLambda = false;
1507             }
1508         }
1509         @Override
1510         public void visitClassDef(JCClassDecl tree) {
1511             //skip
1512         }
1513     }
1514 
1515     /**
1516      * This pass implements (i) definite assignment analysis, which ensures that
1517      * each variable is assigned when used and (ii) definite unassignment analysis,
1518      * which ensures that no final variable is assigned more than once. This visitor
1519      * depends on the results of the liveliness analyzer. This pass is also used to mark
1520      * effectively-final local variables/parameters.
1521      */
1522 
1523     public class AssignAnalyzer extends BaseAnalyzer {
1524 
1525         /** The set of definitely assigned variables.
1526          */
1527         final Bits inits;
1528 
1529         /** The set of definitely unassigned variables.
1530          */
1531         final Bits uninits;
1532 
1533         /** The set of variables that are definitely unassigned everywhere
1534          *  in current try block. This variable is maintained lazily; it is
1535          *  updated only when something gets removed from uninits,
1536          *  typically by being assigned in reachable code.  To obtain the
1537          *  correct set of variables which are definitely unassigned
1538          *  anywhere in current try block, intersect uninitsTry and
1539          *  uninits.
1540          */
1541         final Bits uninitsTry;
1542 
1543         /** When analyzing a condition, inits and uninits are null.
1544          *  Instead we have:
1545          */
1546         final Bits initsWhenTrue;
1547         final Bits initsWhenFalse;
1548         final Bits uninitsWhenTrue;
1549         final Bits uninitsWhenFalse;
1550 
1551         /** A mapping from addresses to variable symbols.
1552          */
1553         protected JCVariableDecl[] vardecls;
1554 
1555         /** The current class being defined.
1556          */
1557         JCClassDecl classDef;
1558 
1559         /** The first variable sequence number in this class definition.
1560          */
1561         int firstadr;
1562 
1563         /** The next available variable sequence number.
1564          */
1565         protected int nextadr;
1566 
1567         /** The first variable sequence number in a block that can return.
1568          */
1569         protected int returnadr;
1570 
1571         /** The list of unreferenced automatic resources.
1572          */
1573         WriteableScope unrefdResources;
1574 
1575         /** Modified when processing a loop body the second time for DU analysis. */
1576         FlowKind flowKind = FlowKind.NORMAL;
1577 
1578         /** The starting position of the analyzed tree */
1579         int startPos;
1580 
1581         public class AssignPendingExit extends BaseAnalyzer.PendingExit {
1582 
1583             final Bits inits;
1584             final Bits uninits;
1585             final Bits exit_inits = new Bits(true);
1586             final Bits exit_uninits = new Bits(true);
1587 
1588             public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1589                 super(tree);
1590                 this.inits = inits;
1591                 this.uninits = uninits;
1592                 this.exit_inits.assign(inits);
1593                 this.exit_uninits.assign(uninits);
1594             }
1595 
1596             @Override
1597             public void resolveJump() {
1598                 inits.andSet(exit_inits);
1599                 uninits.andSet(exit_uninits);
1600             }
1601         }
1602 
1603         public AssignAnalyzer() {
1604             this.inits = new Bits();
1605             uninits = new Bits();
1606             uninitsTry = new Bits();
1607             initsWhenTrue = new Bits(true);
1608             initsWhenFalse = new Bits(true);
1609             uninitsWhenTrue = new Bits(true);
1610             uninitsWhenFalse = new Bits(true);
1611         }
1612 
1613         private boolean isInitialConstructor = false;
1614 
1615         @Override
1616         protected void markDead() {
1617             if (!isInitialConstructor) {
1618                 inits.inclRange(returnadr, nextadr);
1619             } else {
1620                 for (int address = returnadr; address < nextadr; address++) {
1621                     if (!(isFinalUninitializedStaticField(vardecls[address].sym))) {
1622                         inits.incl(address);
1623                     }
1624                 }
1625             }
1626             uninits.inclRange(returnadr, nextadr);
1627         }
1628 
1629         /*-------------- Processing variables ----------------------*/
1630 
1631         /** Do we need to track init/uninit state of this symbol?
1632          *  I.e. is symbol either a local or a blank final variable?
1633          */
1634         protected boolean trackable(VarSymbol sym) {
1635             return
1636                 sym.pos >= startPos &&
1637                 ((sym.owner.kind == MTH || sym.owner.kind == VAR ||
1638                 isFinalUninitializedField(sym)));
1639         }
1640 
1641         boolean isFinalUninitializedField(VarSymbol sym) {
1642             return sym.owner.kind == TYP &&
1643                    ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
1644                    classDef.sym.isEnclosedBy((ClassSymbol)sym.owner));
1645         }
1646 
1647         boolean isFinalUninitializedStaticField(VarSymbol sym) {
1648             return isFinalUninitializedField(sym) && sym.isStatic();
1649         }
1650 
1651         /** Initialize new trackable variable by setting its address field
1652          *  to the next available sequence number and entering it under that
1653          *  index into the vars array.
1654          */
1655         void newVar(JCVariableDecl varDecl) {
1656             VarSymbol sym = varDecl.sym;
1657             vardecls = ArrayUtils.ensureCapacity(vardecls, nextadr);
1658             if ((sym.flags() & FINAL) == 0) {
1659                 sym.flags_field |= EFFECTIVELY_FINAL;
1660             }
1661             sym.adr = nextadr;
1662             vardecls[nextadr] = varDecl;
1663             inits.excl(nextadr);
1664             uninits.incl(nextadr);
1665             nextadr++;
1666         }
1667 
1668         /** Record an initialization of a trackable variable.
1669          */
1670         void letInit(DiagnosticPosition pos, VarSymbol sym) {
1671             if (sym.adr >= firstadr && trackable(sym)) {
1672                 if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
1673                     if (!uninits.isMember(sym.adr)) {
1674                         //assignment targeting an effectively final variable
1675                         //makes the variable lose its status of effectively final
1676                         //if the variable is _not_ definitively unassigned
1677                         sym.flags_field &= ~EFFECTIVELY_FINAL;
1678                     } else {
1679                         uninit(sym);
1680                     }
1681                 }
1682                 else if ((sym.flags() & FINAL) != 0) {
1683                     if ((sym.flags() & PARAMETER) != 0) {
1684                         if ((sym.flags() & UNION) != 0) { //multi-catch parameter
1685                             log.error(pos, Errors.MulticatchParameterMayNotBeAssigned(sym));
1686                         }
1687                         else {
1688                             log.error(pos,
1689                                       Errors.FinalParameterMayNotBeAssigned(sym));
1690                         }
1691                     } else if (!uninits.isMember(sym.adr)) {
1692                         log.error(pos, diags.errorKey(flowKind.errKey, sym));
1693                     } else {
1694                         uninit(sym);
1695                     }
1696                 }
1697                 inits.incl(sym.adr);
1698             } else if ((sym.flags() & FINAL) != 0) {
1699                 log.error(pos, Errors.VarMightAlreadyBeAssigned(sym));
1700             }
1701         }
1702         //where
1703             void uninit(VarSymbol sym) {
1704                 if (!inits.isMember(sym.adr)) {
1705                     // reachable assignment
1706                     uninits.excl(sym.adr);
1707                     uninitsTry.excl(sym.adr);
1708                 } else {
1709                     //log.rawWarning(pos, "unreachable assignment");//DEBUG
1710                     uninits.excl(sym.adr);
1711                 }
1712             }
1713 
1714         /** If tree is either a simple name or of the form this.name or
1715          *  C.this.name, and tree represents a trackable variable,
1716          *  record an initialization of the variable.
1717          */
1718         void letInit(JCTree tree) {
1719             tree = TreeInfo.skipParens(tree);
1720             if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
1721                 Symbol sym = TreeInfo.symbol(tree);
1722                 if (sym.kind == VAR) {
1723                     letInit(tree.pos(), (VarSymbol)sym);
1724                 }
1725             }
1726         }
1727 
1728         /** Check that trackable variable is initialized.
1729          */
1730         void checkInit(DiagnosticPosition pos, VarSymbol sym) {
1731             checkInit(pos, sym, Errors.VarMightNotHaveBeenInitialized(sym));
1732         }
1733 
1734         void checkInit(DiagnosticPosition pos, VarSymbol sym, Error errkey) {
1735             if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
1736                 trackable(sym) &&
1737                 !inits.isMember(sym.adr)) {
1738                 log.error(pos, errkey);
1739                 inits.incl(sym.adr);
1740             }
1741         }
1742 
1743         /** Utility method to reset several Bits instances.
1744          */
1745         private void resetBits(Bits... bits) {
1746             for (Bits b : bits) {
1747                 b.reset();
1748             }
1749         }
1750 
1751         /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
1752          */
1753         void split(boolean setToNull) {
1754             initsWhenFalse.assign(inits);
1755             uninitsWhenFalse.assign(uninits);
1756             initsWhenTrue.assign(inits);
1757             uninitsWhenTrue.assign(uninits);
1758             if (setToNull) {
1759                 resetBits(inits, uninits);
1760             }
1761         }
1762 
1763         /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1764          */
1765         protected void merge() {
1766             inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1767             uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1768         }
1769 
1770     /* ************************************************************************
1771      * Visitor methods for statements and definitions
1772      *************************************************************************/
1773 
1774         /** Analyze an expression. Make sure to set (un)inits rather than
1775          *  (un)initsWhenTrue(WhenFalse) on exit.
1776          */
1777         void scanExpr(JCTree tree) {
1778             if (tree != null) {
1779                 scan(tree);
1780                 if (inits.isReset()) {
1781                     merge();
1782                 }
1783             }
1784         }
1785 
1786         /** Analyze a list of expressions.
1787          */
1788         void scanExprs(List<? extends JCExpression> trees) {
1789             if (trees != null)
1790                 for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
1791                     scanExpr(l.head);
1792         }
1793 
1794         /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1795          *  rather than (un)inits on exit.
1796          */
1797         void scanCond(JCTree tree) {
1798             if (tree.type.isFalse()) {
1799                 if (inits.isReset()) merge();
1800                 initsWhenTrue.assign(inits);
1801                 initsWhenTrue.inclRange(firstadr, nextadr);
1802                 uninitsWhenTrue.assign(uninits);
1803                 uninitsWhenTrue.inclRange(firstadr, nextadr);
1804                 initsWhenFalse.assign(inits);
1805                 uninitsWhenFalse.assign(uninits);
1806             } else if (tree.type.isTrue()) {
1807                 if (inits.isReset()) merge();
1808                 initsWhenFalse.assign(inits);
1809                 initsWhenFalse.inclRange(firstadr, nextadr);
1810                 uninitsWhenFalse.assign(uninits);
1811                 uninitsWhenFalse.inclRange(firstadr, nextadr);
1812                 initsWhenTrue.assign(inits);
1813                 uninitsWhenTrue.assign(uninits);
1814             } else {
1815                 scan(tree);
1816                 if (!inits.isReset())
1817                     split(tree.type != syms.unknownType);
1818             }
1819             if (tree.type != syms.unknownType) {
1820                 resetBits(inits, uninits);
1821             }
1822         }
1823 
1824         /* ------------ Visitor methods for various sorts of trees -------------*/
1825 
1826         public void visitClassDef(JCClassDecl tree) {
1827             if (tree.sym == null) {
1828                 return;
1829             }
1830 
1831             Lint lintPrev = lint;
1832             lint = lint.augment(tree.sym);
1833             try {
1834                 if (tree.sym == null) {
1835                     return;
1836                 }
1837 
1838                 JCClassDecl classDefPrev = classDef;
1839                 int firstadrPrev = firstadr;
1840                 int nextadrPrev = nextadr;
1841                 ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
1842 
1843                 pendingExits = new ListBuffer<>();
1844                 if (tree.name != names.empty) {
1845                     firstadr = nextadr;
1846                 }
1847                 classDef = tree;
1848                 try {
1849                     // define all the static fields
1850                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1851                         if (l.head.hasTag(VARDEF)) {
1852                             JCVariableDecl def = (JCVariableDecl)l.head;
1853                             if ((def.mods.flags & STATIC) != 0) {
1854                                 VarSymbol sym = def.sym;
1855                                 if (trackable(sym)) {
1856                                     newVar(def);
1857                                 }
1858                             }
1859                         }
1860                     }
1861 
1862                     // process all the static initializers
1863                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1864                         if (!l.head.hasTag(METHODDEF) &&
1865                             (TreeInfo.flags(l.head) & STATIC) != 0) {
1866                             scan(l.head);
1867                         }
1868                     }
1869 
1870                     // define all the instance fields
1871                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1872                         if (l.head.hasTag(VARDEF)) {
1873                             JCVariableDecl def = (JCVariableDecl)l.head;
1874                             if ((def.mods.flags & STATIC) == 0) {
1875                                 VarSymbol sym = def.sym;
1876                                 if (trackable(sym)) {
1877                                     newVar(def);
1878                                 }
1879                             }
1880                         }
1881                     }
1882 
1883                     // process all the instance initializers
1884                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1885                         if (!l.head.hasTag(METHODDEF) &&
1886                             (TreeInfo.flags(l.head) & STATIC) == 0) {
1887                             scan(l.head);
1888                         }
1889                     }
1890 
1891                     // process all the methods
1892                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1893                         if (l.head.hasTag(METHODDEF)) {
1894                             scan(l.head);
1895                         }
1896                     }
1897                 } finally {
1898                     pendingExits = pendingExitsPrev;
1899                     nextadr = nextadrPrev;
1900                     firstadr = firstadrPrev;
1901                     classDef = classDefPrev;
1902                 }
1903             } finally {
1904                 lint = lintPrev;
1905             }
1906         }
1907 
1908         public void visitMethodDef(JCMethodDecl tree) {
1909             if (tree.body == null) {
1910                 return;
1911             }
1912 
1913             /*  MemberEnter can generate synthetic methods ignore them
1914              */
1915             if ((tree.sym.flags() & SYNTHETIC) != 0) {
1916                 return;
1917             }
1918 
1919             Lint lintPrev = lint;
1920             lint = lint.augment(tree.sym);
1921             try {
1922                 if (tree.body == null) {
1923                     return;
1924                 }
1925                 /*  Ignore synthetic methods, except for translated lambda methods.
1926                  */
1927                 if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
1928                     return;
1929                 }
1930 
1931                 final Bits initsPrev = new Bits(inits);
1932                 final Bits uninitsPrev = new Bits(uninits);
1933                 int nextadrPrev = nextadr;
1934                 int firstadrPrev = firstadr;
1935                 int returnadrPrev = returnadr;
1936 
1937                 Assert.check(pendingExits.isEmpty());
1938                 boolean lastInitialConstructor = isInitialConstructor;
1939                 try {
1940                     isInitialConstructor = TreeInfo.isInitialConstructor(tree);
1941 
1942                     if (!isInitialConstructor) {
1943                         firstadr = nextadr;
1944                     }
1945                     for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1946                         JCVariableDecl def = l.head;
1947                         scan(def);
1948                         Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
1949                         /*  If we are executing the code from Gen, then there can be
1950                          *  synthetic or mandated variables, ignore them.
1951                          */
1952                         initParam(def);
1953                     }
1954                     // else we are in an instance initializer block;
1955                     // leave caught unchanged.
1956                     scan(tree.body);
1957 
1958                     if (isInitialConstructor) {
1959                         boolean isSynthesized = (tree.sym.flags() &
1960                                                  GENERATEDCONSTR) != 0;
1961                         boolean isRecord = (tree.sym.owner.flags() & Flags.RECORD) != 0;
1962                         // skip record as they are generated by the compiler and guaranteed to be correct
1963                         if (!isRecord || !isSynthesized) {
1964                             for (int i = firstadr; i < nextadr; i++) {
1965                                 JCVariableDecl vardecl = vardecls[i];
1966                                 VarSymbol var = vardecl.sym;
1967                                 if (var.owner == classDef.sym) {
1968                                     // choose the diagnostic position based on whether
1969                                     // the ctor is default(synthesized) or not
1970                                     if (isSynthesized) {
1971                                         checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
1972                                             var, Errors.VarNotInitializedInDefaultConstructor(var));
1973                                     } else {
1974                                         checkInit(TreeInfo.diagEndPos(tree.body), var);
1975                                     }
1976                                 }
1977                             }
1978                         }
1979                     }
1980                     List<PendingExit> exits = pendingExits.toList();
1981                     pendingExits = new ListBuffer<>();
1982                     while (exits.nonEmpty()) {
1983                         PendingExit exit = exits.head;
1984                         exits = exits.tail;
1985                         Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1986                         if (isInitialConstructor) {
1987                             Assert.check(exit instanceof AssignPendingExit);
1988                             inits.assign(((AssignPendingExit) exit).exit_inits);
1989                             for (int i = firstadr; i < nextadr; i++) {
1990                                 checkInit(exit.tree.pos(), vardecls[i].sym);
1991                             }
1992                         }
1993                     }
1994                 } finally {
1995                     inits.assign(initsPrev);
1996                     uninits.assign(uninitsPrev);
1997                     nextadr = nextadrPrev;
1998                     firstadr = firstadrPrev;
1999                     returnadr = returnadrPrev;
2000                     isInitialConstructor = lastInitialConstructor;
2001                 }
2002             } finally {
2003                 lint = lintPrev;
2004             }
2005         }
2006 
2007         protected void initParam(JCVariableDecl def) {
2008             inits.incl(def.sym.adr);
2009             uninits.excl(def.sym.adr);
2010         }
2011 
2012         public void visitVarDef(JCVariableDecl tree) {
2013             Lint lintPrev = lint;
2014             lint = lint.augment(tree.sym);
2015             try{
2016                 boolean track = trackable(tree.sym);
2017                 if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
2018                     newVar(tree);
2019                 }
2020                 if (tree.init != null) {
2021                     scanExpr(tree.init);
2022                     if (track) {
2023                         letInit(tree.pos(), tree.sym);
2024                     }
2025                 }
2026             } finally {
2027                 lint = lintPrev;
2028             }
2029         }
2030 
2031         public void visitBlock(JCBlock tree) {
2032             int nextadrPrev = nextadr;
2033             scan(tree.stats);
2034             nextadr = nextadrPrev;
2035         }
2036 
2037         public void visitDoLoop(JCDoWhileLoop tree) {
2038             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2039             FlowKind prevFlowKind = flowKind;
2040             flowKind = FlowKind.NORMAL;
2041             final Bits initsSkip = new Bits(true);
2042             final Bits uninitsSkip = new Bits(true);
2043             pendingExits = new ListBuffer<>();
2044             int prevErrors = log.nerrors;
2045             do {
2046                 final Bits uninitsEntry = new Bits(uninits);
2047                 uninitsEntry.excludeFrom(nextadr);
2048                 scan(tree.body);
2049                 resolveContinues(tree);
2050                 scanCond(tree.cond);
2051                 if (!flowKind.isFinal()) {
2052                     initsSkip.assign(initsWhenFalse);
2053                     uninitsSkip.assign(uninitsWhenFalse);
2054                 }
2055                 if (log.nerrors !=  prevErrors ||
2056                     flowKind.isFinal() ||
2057                     new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
2058                     break;
2059                 inits.assign(initsWhenTrue);
2060                 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
2061                 flowKind = FlowKind.SPECULATIVE_LOOP;
2062             } while (true);
2063             flowKind = prevFlowKind;
2064             inits.assign(initsSkip);
2065             uninits.assign(uninitsSkip);
2066             resolveBreaks(tree, prevPendingExits);
2067         }
2068 
2069         public void visitWhileLoop(JCWhileLoop tree) {
2070             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2071             FlowKind prevFlowKind = flowKind;
2072             flowKind = FlowKind.NORMAL;
2073             final Bits initsSkip = new Bits(true);
2074             final Bits uninitsSkip = new Bits(true);
2075             pendingExits = new ListBuffer<>();
2076             int prevErrors = log.nerrors;
2077             final Bits uninitsEntry = new Bits(uninits);
2078             uninitsEntry.excludeFrom(nextadr);
2079             do {
2080                 scanCond(tree.cond);
2081                 if (!flowKind.isFinal()) {
2082                     initsSkip.assign(initsWhenFalse) ;
2083                     uninitsSkip.assign(uninitsWhenFalse);
2084                 }
2085                 inits.assign(initsWhenTrue);
2086                 uninits.assign(uninitsWhenTrue);
2087                 scan(tree.body);
2088                 resolveContinues(tree);
2089                 if (log.nerrors != prevErrors ||
2090                     flowKind.isFinal() ||
2091                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
2092                     break;
2093                 }
2094                 uninits.assign(uninitsEntry.andSet(uninits));
2095                 flowKind = FlowKind.SPECULATIVE_LOOP;
2096             } while (true);
2097             flowKind = prevFlowKind;
2098             //a variable is DA/DU after the while statement, if it's DA/DU assuming the
2099             //branch is not taken AND if it's DA/DU before any break statement
2100             inits.assign(initsSkip);
2101             uninits.assign(uninitsSkip);
2102             resolveBreaks(tree, prevPendingExits);
2103         }
2104 
2105         public void visitForLoop(JCForLoop tree) {
2106             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2107             FlowKind prevFlowKind = flowKind;
2108             flowKind = FlowKind.NORMAL;
2109             int nextadrPrev = nextadr;
2110             scan(tree.init);
2111             final Bits initsSkip = new Bits(true);
2112             final Bits uninitsSkip = new Bits(true);
2113             pendingExits = new ListBuffer<>();
2114             int prevErrors = log.nerrors;
2115             do {
2116                 final Bits uninitsEntry = new Bits(uninits);
2117                 uninitsEntry.excludeFrom(nextadr);
2118                 if (tree.cond != null) {
2119                     scanCond(tree.cond);
2120                     if (!flowKind.isFinal()) {
2121                         initsSkip.assign(initsWhenFalse);
2122                         uninitsSkip.assign(uninitsWhenFalse);
2123                     }
2124                     inits.assign(initsWhenTrue);
2125                     uninits.assign(uninitsWhenTrue);
2126                 } else if (!flowKind.isFinal()) {
2127                     initsSkip.assign(inits);
2128                     initsSkip.inclRange(firstadr, nextadr);
2129                     uninitsSkip.assign(uninits);
2130                     uninitsSkip.inclRange(firstadr, nextadr);
2131                 }
2132                 scan(tree.body);
2133                 resolveContinues(tree);
2134                 scan(tree.step);
2135                 if (log.nerrors != prevErrors ||
2136                     flowKind.isFinal() ||
2137                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2138                     break;
2139                 uninits.assign(uninitsEntry.andSet(uninits));
2140                 flowKind = FlowKind.SPECULATIVE_LOOP;
2141             } while (true);
2142             flowKind = prevFlowKind;
2143             //a variable is DA/DU after a for loop, if it's DA/DU assuming the
2144             //branch is not taken AND if it's DA/DU before any break statement
2145             inits.assign(initsSkip);
2146             uninits.assign(uninitsSkip);
2147             resolveBreaks(tree, prevPendingExits);
2148             nextadr = nextadrPrev;
2149         }
2150 
2151         public void visitForeachLoop(JCEnhancedForLoop tree) {
2152             visitVarDef(tree.var);
2153 
2154             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2155             FlowKind prevFlowKind = flowKind;
2156             flowKind = FlowKind.NORMAL;
2157             int nextadrPrev = nextadr;
2158             scan(tree.expr);
2159             final Bits initsStart = new Bits(inits);
2160             final Bits uninitsStart = new Bits(uninits);
2161 
2162             letInit(tree.pos(), tree.var.sym);
2163             pendingExits = new ListBuffer<>();
2164             int prevErrors = log.nerrors;
2165             do {
2166                 final Bits uninitsEntry = new Bits(uninits);
2167                 uninitsEntry.excludeFrom(nextadr);
2168                 scan(tree.body);
2169                 resolveContinues(tree);
2170                 if (log.nerrors != prevErrors ||
2171                     flowKind.isFinal() ||
2172                     new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2173                     break;
2174                 uninits.assign(uninitsEntry.andSet(uninits));
2175                 flowKind = FlowKind.SPECULATIVE_LOOP;
2176             } while (true);
2177             flowKind = prevFlowKind;
2178             inits.assign(initsStart);
2179             uninits.assign(uninitsStart.andSet(uninits));
2180             resolveBreaks(tree, prevPendingExits);
2181             nextadr = nextadrPrev;
2182         }
2183 
2184         public void visitLabelled(JCLabeledStatement tree) {
2185             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2186             pendingExits = new ListBuffer<>();
2187             scan(tree.body);
2188             resolveBreaks(tree, prevPendingExits);
2189         }
2190 
2191         public void visitSwitch(JCSwitch tree) {
2192             handleSwitch(tree, tree.selector, tree.cases);
2193         }
2194 
2195         public void visitSwitchExpression(JCSwitchExpression tree) {
2196             handleSwitch(tree, tree.selector, tree.cases);
2197         }
2198 
2199         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
2200             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2201             pendingExits = new ListBuffer<>();
2202             int nextadrPrev = nextadr;
2203             scanExpr(selector);
2204             final Bits initsSwitch = new Bits(inits);
2205             final Bits uninitsSwitch = new Bits(uninits);
2206             boolean hasDefault = false;
2207             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
2208                 inits.assign(initsSwitch);
2209                 uninits.assign(uninits.andSet(uninitsSwitch));
2210                 JCCase c = l.head;
2211                 if (c.pats.isEmpty()) {
2212                     hasDefault = true;
2213                 } else {
2214                     for (JCExpression pat : c.pats) {
2215                         scanExpr(pat);
2216                     }
2217                 }
2218                 if (hasDefault) {
2219                     inits.assign(initsSwitch);
2220                     uninits.assign(uninits.andSet(uninitsSwitch));
2221                 }
2222                 scan(c.stats);
2223                 if (c.completesNormally && c.caseKind == JCCase.RULE) {
2224                     scanSyntheticBreak(make, tree);
2225                 }
2226                 addVars(c.stats, initsSwitch, uninitsSwitch);
2227                 if (!hasDefault) {
2228                     inits.assign(initsSwitch);
2229                     uninits.assign(uninits.andSet(uninitsSwitch));
2230                 }
2231                 // Warn about fall-through if lint switch fallthrough enabled.
2232             }
2233             if (!hasDefault) {
2234                 inits.andSet(initsSwitch);
2235             }
2236             resolveBreaks(tree, prevPendingExits);
2237             nextadr = nextadrPrev;
2238         }
2239         // where
2240             /** Add any variables defined in stats to inits and uninits. */
2241             private void addVars(List<JCStatement> stats, final Bits inits,
2242                                         final Bits uninits) {
2243                 for (;stats.nonEmpty(); stats = stats.tail) {
2244                     JCTree stat = stats.head;
2245                     if (stat.hasTag(VARDEF)) {
2246                         int adr = ((JCVariableDecl) stat).sym.adr;
2247                         inits.excl(adr);
2248                         uninits.incl(adr);
2249                     }
2250                 }
2251             }
2252 
2253         public void visitTry(JCTry tree) {
2254             ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2255             final Bits uninitsTryPrev = new Bits(uninitsTry);
2256             ListBuffer<PendingExit> prevPendingExits = pendingExits;
2257             pendingExits = new ListBuffer<>();
2258             final Bits initsTry = new Bits(inits);
2259             uninitsTry.assign(uninits);
2260             for (JCTree resource : tree.resources) {
2261                 if (resource instanceof JCVariableDecl) {
2262                     JCVariableDecl vdecl = (JCVariableDecl) resource;
2263                     visitVarDef(vdecl);
2264                     unrefdResources.enter(vdecl.sym);
2265                     resourceVarDecls.append(vdecl);
2266                 } else if (resource instanceof JCExpression) {
2267                     scanExpr((JCExpression) resource);
2268                 } else {
2269                     throw new AssertionError(tree);  // parser error
2270                 }
2271             }
2272             scan(tree.body);
2273             uninitsTry.andSet(uninits);
2274             final Bits initsEnd = new Bits(inits);
2275             final Bits uninitsEnd = new Bits(uninits);
2276             int nextadrCatch = nextadr;
2277 
2278             if (!resourceVarDecls.isEmpty() &&
2279                     lint.isEnabled(Lint.LintCategory.TRY)) {
2280                 for (JCVariableDecl resVar : resourceVarDecls) {
2281                     if (unrefdResources.includes(resVar.sym)) {
2282                         log.warning(Lint.LintCategory.TRY, resVar.pos(),
2283                                     Warnings.TryResourceNotReferenced(resVar.sym));
2284                         unrefdResources.remove(resVar.sym);
2285                     }
2286                 }
2287             }
2288 
2289             /*  The analysis of each catch should be independent.
2290              *  Each one should have the same initial values of inits and
2291              *  uninits.
2292              */
2293             final Bits initsCatchPrev = new Bits(initsTry);
2294             final Bits uninitsCatchPrev = new Bits(uninitsTry);
2295 
2296             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2297                 JCVariableDecl param = l.head.param;
2298                 inits.assign(initsCatchPrev);
2299                 uninits.assign(uninitsCatchPrev);
2300                 scan(param);
2301                 /* If this is a TWR and we are executing the code from Gen,
2302                  * then there can be synthetic variables, ignore them.
2303                  */
2304                 initParam(param);
2305                 scan(l.head.body);
2306                 initsEnd.andSet(inits);
2307                 uninitsEnd.andSet(uninits);
2308                 nextadr = nextadrCatch;
2309             }
2310             if (tree.finalizer != null) {
2311                 inits.assign(initsTry);
2312                 uninits.assign(uninitsTry);
2313                 ListBuffer<PendingExit> exits = pendingExits;
2314                 pendingExits = prevPendingExits;
2315                 scan(tree.finalizer);
2316                 if (!tree.finallyCanCompleteNormally) {
2317                     // discard exits and exceptions from try and finally
2318                 } else {
2319                     uninits.andSet(uninitsEnd);
2320                     // FIX: this doesn't preserve source order of exits in catch
2321                     // versus finally!
2322                     while (exits.nonEmpty()) {
2323                         PendingExit exit = exits.next();
2324                         if (exit instanceof AssignPendingExit) {
2325                             ((AssignPendingExit) exit).exit_inits.orSet(inits);
2326                             ((AssignPendingExit) exit).exit_uninits.andSet(uninits);
2327                         }
2328                         pendingExits.append(exit);
2329                     }
2330                     inits.orSet(initsEnd);
2331                 }
2332             } else {
2333                 inits.assign(initsEnd);
2334                 uninits.assign(uninitsEnd);
2335                 ListBuffer<PendingExit> exits = pendingExits;
2336                 pendingExits = prevPendingExits;
2337                 while (exits.nonEmpty()) pendingExits.append(exits.next());
2338             }
2339             uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2340         }
2341 
2342         public void visitConditional(JCConditional tree) {
2343             scanCond(tree.cond);
2344             final Bits initsBeforeElse = new Bits(initsWhenFalse);
2345             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2346             inits.assign(initsWhenTrue);
2347             uninits.assign(uninitsWhenTrue);
2348             if (tree.truepart.type.hasTag(BOOLEAN) &&
2349                 tree.falsepart.type.hasTag(BOOLEAN)) {
2350                 // if b and c are boolean valued, then
2351                 // v is (un)assigned after a?b:c when true iff
2352                 //    v is (un)assigned after b when true and
2353                 //    v is (un)assigned after c when true
2354                 scanCond(tree.truepart);
2355                 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
2356                 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
2357                 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
2358                 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
2359                 inits.assign(initsBeforeElse);
2360                 uninits.assign(uninitsBeforeElse);
2361                 scanCond(tree.falsepart);
2362                 initsWhenTrue.andSet(initsAfterThenWhenTrue);
2363                 initsWhenFalse.andSet(initsAfterThenWhenFalse);
2364                 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
2365                 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
2366             } else {
2367                 scanExpr(tree.truepart);
2368                 final Bits initsAfterThen = new Bits(inits);
2369                 final Bits uninitsAfterThen = new Bits(uninits);
2370                 inits.assign(initsBeforeElse);
2371                 uninits.assign(uninitsBeforeElse);
2372                 scanExpr(tree.falsepart);
2373                 inits.andSet(initsAfterThen);
2374                 uninits.andSet(uninitsAfterThen);
2375             }
2376         }
2377 
2378         public void visitIf(JCIf tree) {
2379             scanCond(tree.cond);
2380             final Bits initsBeforeElse = new Bits(initsWhenFalse);
2381             final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2382             inits.assign(initsWhenTrue);
2383             uninits.assign(uninitsWhenTrue);
2384             scan(tree.thenpart);
2385             if (tree.elsepart != null) {
2386                 final Bits initsAfterThen = new Bits(inits);
2387                 final Bits uninitsAfterThen = new Bits(uninits);
2388                 inits.assign(initsBeforeElse);
2389                 uninits.assign(uninitsBeforeElse);
2390                 scan(tree.elsepart);
2391                 inits.andSet(initsAfterThen);
2392                 uninits.andSet(uninitsAfterThen);
2393             } else {
2394                 inits.andSet(initsBeforeElse);
2395                 uninits.andSet(uninitsBeforeElse);
2396             }
2397         }
2398 
2399         @Override
2400         public void visitBreak(JCBreak tree) {
2401             if (tree.isValueBreak()) {
2402                 if (tree.target.hasTag(SWITCH_EXPRESSION)) {
2403                     JCSwitchExpression expr = (JCSwitchExpression) tree.target;
2404                     if (expr.type.hasTag(BOOLEAN)) {
2405                         scanCond(tree.value);
2406                         Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
2407                         Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
2408                         Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
2409                         Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
2410                         PendingExit exit = new PendingExit(tree) {
2411                             @Override
2412                             void resolveJump() {
2413                                 if (!inits.isReset()) {
2414                                     split(true);
2415                                 }
2416                                 initsWhenTrue.andSet(initsAfterBreakWhenTrue);
2417                                 initsWhenFalse.andSet(initsAfterBreakWhenFalse);
2418                                 uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
2419                                 uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
2420                             }
2421                         };
2422                         merge();
2423                         recordExit(exit);
2424                         return ;
2425                     }
2426                 }
2427                 scan(tree.value);
2428             }
2429             recordExit(new AssignPendingExit(tree, inits, uninits));
2430         }
2431 
2432         @Override
2433         public void visitContinue(JCContinue tree) {
2434             recordExit(new AssignPendingExit(tree, inits, uninits));
2435         }
2436 
2437         @Override
2438         public void visitReturn(JCReturn tree) {
2439             scanExpr(tree.expr);
2440             recordExit(new AssignPendingExit(tree, inits, uninits));
2441         }
2442 
2443         public void visitThrow(JCThrow tree) {
2444             scanExpr(tree.expr);
2445             markDead();
2446         }
2447 
2448         public void visitApply(JCMethodInvocation tree) {
2449             scanExpr(tree.meth);
2450             scanExprs(tree.args);
2451         }
2452 
2453         public void visitNewClass(JCNewClass tree) {
2454             scanExpr(tree.encl);
2455             scanExprs(tree.args);
2456             scan(tree.def);
2457         }
2458 
2459         @Override
2460         public void visitLambda(JCLambda tree) {
2461             final Bits prevUninits = new Bits(uninits);
2462             final Bits prevInits = new Bits(inits);
2463             int returnadrPrev = returnadr;
2464             int nextadrPrev = nextadr;
2465             ListBuffer<PendingExit> prevPending = pendingExits;
2466             try {
2467                 returnadr = nextadr;
2468                 pendingExits = new ListBuffer<>();
2469                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2470                     JCVariableDecl def = l.head;
2471                     scan(def);
2472                     inits.incl(def.sym.adr);
2473                     uninits.excl(def.sym.adr);
2474                 }
2475                 if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
2476                     scanExpr(tree.body);
2477                 } else {
2478                     scan(tree.body);
2479                 }
2480             }
2481             finally {
2482                 returnadr = returnadrPrev;
2483                 uninits.assign(prevUninits);
2484                 inits.assign(prevInits);
2485                 pendingExits = prevPending;
2486                 nextadr = nextadrPrev;
2487             }
2488         }
2489 
2490         public void visitNewArray(JCNewArray tree) {
2491             scanExprs(tree.dims);
2492             scanExprs(tree.elems);
2493         }
2494 
2495         public void visitAssert(JCAssert tree) {
2496             final Bits initsExit = new Bits(inits);
2497             final Bits uninitsExit = new Bits(uninits);
2498             scanCond(tree.cond);
2499             uninitsExit.andSet(uninitsWhenTrue);
2500             if (tree.detail != null) {
2501                 inits.assign(initsWhenFalse);
2502                 uninits.assign(uninitsWhenFalse);
2503                 scanExpr(tree.detail);
2504             }
2505             inits.assign(initsExit);
2506             uninits.assign(uninitsExit);
2507         }
2508 
2509         public void visitAssign(JCAssign tree) {
2510             if (!TreeInfo.isIdentOrThisDotIdent(tree.lhs))
2511                 scanExpr(tree.lhs);
2512             scanExpr(tree.rhs);
2513             letInit(tree.lhs);
2514         }
2515 
2516         // check fields accessed through this.<field> are definitely
2517         // assigned before reading their value
2518         public void visitSelect(JCFieldAccess tree) {
2519             super.visitSelect(tree);
2520             if (TreeInfo.isThisQualifier(tree.selected) &&
2521                 tree.sym.kind == VAR) {
2522                 checkInit(tree.pos(), (VarSymbol)tree.sym);
2523             }
2524         }
2525 
2526         public void visitAssignop(JCAssignOp tree) {
2527             scanExpr(tree.lhs);
2528             scanExpr(tree.rhs);
2529             letInit(tree.lhs);
2530         }
2531 
2532         public void visitUnary(JCUnary tree) {
2533             switch (tree.getTag()) {
2534             case NOT:
2535                 scanCond(tree.arg);
2536                 final Bits t = new Bits(initsWhenFalse);
2537                 initsWhenFalse.assign(initsWhenTrue);
2538                 initsWhenTrue.assign(t);
2539                 t.assign(uninitsWhenFalse);
2540                 uninitsWhenFalse.assign(uninitsWhenTrue);
2541                 uninitsWhenTrue.assign(t);
2542                 break;
2543             case PREINC: case POSTINC:
2544             case PREDEC: case POSTDEC:
2545                 scanExpr(tree.arg);
2546                 letInit(tree.arg);
2547                 break;
2548             default:
2549                 scanExpr(tree.arg);
2550             }
2551         }
2552 
2553         public void visitBinary(JCBinary tree) {
2554             switch (tree.getTag()) {
2555             case AND:
2556                 scanCond(tree.lhs);
2557                 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2558                 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2559                 inits.assign(initsWhenTrue);
2560                 uninits.assign(uninitsWhenTrue);
2561                 scanCond(tree.rhs);
2562                 initsWhenFalse.andSet(initsWhenFalseLeft);
2563                 uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2564                 break;
2565             case OR:
2566                 scanCond(tree.lhs);
2567                 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2568                 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2569                 inits.assign(initsWhenFalse);
2570                 uninits.assign(uninitsWhenFalse);
2571                 scanCond(tree.rhs);
2572                 initsWhenTrue.andSet(initsWhenTrueLeft);
2573                 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2574                 break;
2575             default:
2576                 scanExpr(tree.lhs);
2577                 scanExpr(tree.rhs);
2578             }
2579         }
2580 
2581         public void visitIdent(JCIdent tree) {
2582             if (tree.sym.kind == VAR) {
2583                 checkInit(tree.pos(), (VarSymbol)tree.sym);
2584                 referenced(tree.sym);
2585             }
2586         }
2587 
2588         void referenced(Symbol sym) {
2589             unrefdResources.remove(sym);
2590         }
2591 
2592         public void visitAnnotatedType(JCAnnotatedType tree) {
2593             // annotations don't get scanned
2594             tree.underlyingType.accept(this);
2595         }
2596 
2597         public void visitModuleDef(JCModuleDecl tree) {
2598             // Do nothing for modules
2599         }
2600 
2601     /**************************************************************************
2602      * main method
2603      *************************************************************************/
2604 
2605         /** Perform definite assignment/unassignment analysis on a tree.
2606          */
2607         public void analyzeTree(Env<?> env, TreeMaker make) {
2608             analyzeTree(env, env.tree, make);
2609          }
2610 
2611         public void analyzeTree(Env<?> env, JCTree tree, TreeMaker make) {
2612             try {
2613                 startPos = tree.pos().getStartPosition();
2614 
2615                 if (vardecls == null)
2616                     vardecls = new JCVariableDecl[32];
2617                 else
2618                     for (int i=0; i<vardecls.length; i++)
2619                         vardecls[i] = null;
2620                 firstadr = 0;
2621                 nextadr = 0;
2622                 Flow.this.make = make;
2623                 pendingExits = new ListBuffer<>();
2624                 this.classDef = null;
2625                 unrefdResources = WriteableScope.create(env.enclClass.sym);
2626                 scan(tree);
2627             } finally {
2628                 // note that recursive invocations of this method fail hard
2629                 startPos = -1;
2630                 resetBits(inits, uninits, uninitsTry, initsWhenTrue,
2631                         initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
2632                 if (vardecls != null) {
2633                     for (int i=0; i<vardecls.length; i++)
2634                         vardecls[i] = null;
2635                 }
2636                 firstadr = 0;
2637                 nextadr = 0;
2638                 Flow.this.make = null;
2639                 pendingExits = null;
2640                 this.classDef = null;
2641                 unrefdResources = null;
2642             }
2643         }
2644     }
2645 
2646     /**
2647      * This pass implements the last step of the dataflow analysis, namely
2648      * the effectively-final analysis check. This checks that every local variable
2649      * reference from a lambda body/local inner class is either final or effectively final.
2650      * Additional this also checks that every variable that is used as an operand to
2651      * try-with-resources is final or effectively final.
2652      * As effectively final variables are marked as such during DA/DU, this pass must run after
2653      * AssignAnalyzer.
2654      */
2655     class CaptureAnalyzer extends BaseAnalyzer {
2656 
2657         JCTree currentTree; //local class or lambda
2658 
2659         @Override
2660         void markDead() {
2661             //do nothing
2662         }
2663 
2664         @SuppressWarnings("fallthrough")
2665         void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2666             if (currentTree != null &&
2667                     sym.owner.kind == MTH &&
2668                     sym.pos < currentTree.getStartPosition()) {
2669                 switch (currentTree.getTag()) {
2670                     case CLASSDEF:
2671                         if (!allowEffectivelyFinalInInnerClasses) {
2672                             if ((sym.flags() & FINAL) == 0) {
2673                                 reportInnerClsNeedsFinalError(pos, sym);
2674                             }
2675                             break;
2676                         }
2677                     case LAMBDA:
2678                         if ((sym.flags() & (EFFECTIVELY_FINAL | FINAL)) == 0) {
2679                            reportEffectivelyFinalError(pos, sym);
2680                         }
2681                 }
2682             }
2683         }
2684 
2685         @SuppressWarnings("fallthrough")
2686         void letInit(JCTree tree) {
2687             tree = TreeInfo.skipParens(tree);
2688             if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
2689                 Symbol sym = TreeInfo.symbol(tree);
2690                 if (currentTree != null &&
2691                         sym.kind == VAR &&
2692                         sym.owner.kind == MTH &&
2693                         ((VarSymbol)sym).pos < currentTree.getStartPosition()) {
2694                     switch (currentTree.getTag()) {
2695                         case CLASSDEF:
2696                             if (!allowEffectivelyFinalInInnerClasses) {
2697                                 reportInnerClsNeedsFinalError(tree, sym);
2698                                 break;
2699                             }
2700                         case LAMBDA:
2701                             reportEffectivelyFinalError(tree, sym);
2702                     }
2703                 }
2704             }
2705         }
2706 
2707         void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
2708             String subKey = currentTree.hasTag(LAMBDA) ?
2709                   "lambda"  : "inner.cls";
2710             log.error(pos, Errors.CantRefNonEffectivelyFinalVar(sym, diags.fragment(subKey)));
2711         }
2712 
2713         void reportInnerClsNeedsFinalError(DiagnosticPosition pos, Symbol sym) {
2714             log.error(pos,
2715                       Errors.LocalVarAccessedFromIclsNeedsFinal(sym));
2716         }
2717 
2718     /*************************************************************************
2719      * Visitor methods for statements and definitions
2720      *************************************************************************/
2721 
2722         /* ------------ Visitor methods for various sorts of trees -------------*/
2723 
2724         public void visitClassDef(JCClassDecl tree) {
2725             JCTree prevTree = currentTree;
2726             try {
2727                 currentTree = tree.sym.isLocal() ? tree : null;
2728                 super.visitClassDef(tree);
2729             } finally {
2730                 currentTree = prevTree;
2731             }
2732         }
2733 
2734         @Override
2735         public void visitLambda(JCLambda tree) {
2736             JCTree prevTree = currentTree;
2737             try {
2738                 currentTree = tree;
2739                 super.visitLambda(tree);
2740             } finally {
2741                 currentTree = prevTree;
2742             }
2743         }
2744 
2745         @Override
2746         public void visitIdent(JCIdent tree) {
2747             if (tree.sym.kind == VAR) {
2748                 checkEffectivelyFinal(tree, (VarSymbol)tree.sym);
2749             }
2750         }
2751 
2752         public void visitAssign(JCAssign tree) {
2753             JCTree lhs = TreeInfo.skipParens(tree.lhs);
2754             if (!(lhs instanceof JCIdent)) {
2755                 scan(lhs);
2756             }
2757             scan(tree.rhs);
2758             letInit(lhs);
2759         }
2760 
2761         public void visitAssignop(JCAssignOp tree) {
2762             scan(tree.lhs);
2763             scan(tree.rhs);
2764             letInit(tree.lhs);
2765         }
2766 
2767         public void visitUnary(JCUnary tree) {
2768             switch (tree.getTag()) {
2769                 case PREINC: case POSTINC:
2770                 case PREDEC: case POSTDEC:
2771                     scan(tree.arg);
2772                     letInit(tree.arg);
2773                     break;
2774                 default:
2775                     scan(tree.arg);
2776             }
2777         }
2778 
2779         public void visitTry(JCTry tree) {
2780             for (JCTree resource : tree.resources) {
2781                 if (!resource.hasTag(VARDEF)) {
2782                     Symbol var = TreeInfo.symbol(resource);
2783                     if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
2784                         log.error(resource.pos(), Errors.TryWithResourcesExprEffectivelyFinalVar(var));
2785                     }
2786                 }
2787             }
2788             super.visitTry(tree);
2789         }
2790 
2791         @Override
2792         public void visitBreak(JCBreak tree) {
2793             if (tree.isValueBreak())
2794                 scan(tree.value);
2795         }
2796 
2797         public void visitModuleDef(JCModuleDecl tree) {
2798             // Do nothing for modules
2799         }
2800 
2801     /**************************************************************************
2802      * main method
2803      *************************************************************************/
2804 
2805         /** Perform definite assignment/unassignment analysis on a tree.
2806          */
2807         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
2808             analyzeTree(env, env.tree, make);
2809         }
2810         public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
2811             try {
2812                 attrEnv = env;
2813                 Flow.this.make = make;
2814                 pendingExits = new ListBuffer<>();
2815                 scan(tree);
2816             } finally {
2817                 pendingExits = null;
2818                 Flow.this.make = null;
2819             }
2820         }
2821     }
2822 
2823     enum Liveness {
2824         ALIVE {
2825             @Override
2826             public Liveness or(Liveness other) {
2827                 return this;
2828             }
2829             @Override
2830             public Liveness and(Liveness other) {
2831                 return other;
2832             }
2833         },
2834         DEAD {
2835             @Override
2836             public Liveness or(Liveness other) {
2837                 return other;
2838             }
2839             @Override
2840             public Liveness and(Liveness other) {
2841                 return this;
2842             }
2843         },
2844         RECOVERY {
2845             @Override
2846             public Liveness or(Liveness other) {
2847                 if (other == ALIVE) {
2848                     return ALIVE;
2849                 } else {
2850                     return this;
2851                 }
2852             }
2853             @Override
2854             public Liveness and(Liveness other) {
2855                 if (other == DEAD) {
2856                     return DEAD;
2857                 } else {
2858                     return this;
2859                 }
2860             }
2861         };
2862 
2863         public abstract Liveness or(Liveness other);
2864         public abstract Liveness and(Liveness other);
2865         public Liveness or(boolean value) {
2866             return or(from(value));
2867         }
2868         public Liveness and(boolean value) {
2869             return and(from(value));
2870         }
2871         public static Liveness from(boolean value) {
2872             return value ? ALIVE : DEAD;
2873         }
2874     }
2875 
2876 }