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