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