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