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