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