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