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