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