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