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