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