1 /*
   2  * Copyright (c) 1999, 2011, 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.Map;
  32 import java.util.LinkedHashMap;
  33 
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.tree.*;
  36 import com.sun.tools.javac.util.*;
  37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  38 
  39 import com.sun.tools.javac.code.Symbol.*;
  40 import com.sun.tools.javac.tree.JCTree.*;
  41 
  42 import static com.sun.tools.javac.code.Flags.*;
  43 import static com.sun.tools.javac.code.Kinds.*;
  44 import static com.sun.tools.javac.code.TypeTags.*;
  45 
  46 /** This pass implements dataflow analysis for Java programs.
  47  *  Liveness analysis checks that every statement is reachable.
  48  *  Exception analysis ensures that every checked exception that is
  49  *  thrown is declared or caught.  Definite assignment analysis
  50  *  ensures that each variable is assigned when used.  Definite
  51  *  unassignment analysis ensures that no final variable is assigned
  52  *  more than once.
  53  *
  54  *  <p>The JLS has a number of problems in the
  55  *  specification of these flow analysis problems. This implementation
  56  *  attempts to address those issues.
  57  *
  58  *  <p>First, there is no accommodation for a finally clause that cannot
  59  *  complete normally. For liveness analysis, an intervening finally
  60  *  clause can cause a break, continue, or return not to reach its
  61  *  target.  For exception analysis, an intervening finally clause can
  62  *  cause any exception to be "caught".  For DA/DU analysis, the finally
  63  *  clause can prevent a transfer of control from propagating DA/DU
  64  *  state to the target.  In addition, code in the finally clause can
  65  *  affect the DA/DU status of variables.
  66  *
  67  *  <p>For try statements, we introduce the idea of a variable being
  68  *  definitely unassigned "everywhere" in a block.  A variable V is
  69  *  "unassigned everywhere" in a block iff it is unassigned at the
  70  *  beginning of the block and there is no reachable assignment to V
  71  *  in the block.  An assignment V=e is reachable iff V is not DA
  72  *  after e.  Then we can say that V is DU at the beginning of the
  73  *  catch block iff V is DU everywhere in the try block.  Similarly, V
  74  *  is DU at the beginning of the finally block iff V is DU everywhere
  75  *  in the try block and in every catch block.  Specifically, the
  76  *  following bullet is added to 16.2.2
  77  *  <pre>
  78  *      V is <em>unassigned everywhere</em> in a block if it is
  79  *      unassigned before the block and there is no reachable
  80  *      assignment to V within the block.
  81  *  </pre>
  82  *  <p>In 16.2.15, the third bullet (and all of its sub-bullets) for all
  83  *  try blocks is changed to
  84  *  <pre>
  85  *      V is definitely unassigned before a catch block iff V is
  86  *      definitely unassigned everywhere in the try block.
  87  *  </pre>
  88  *  <p>The last bullet (and all of its sub-bullets) for try blocks that
  89  *  have a finally block is changed to
  90  *  <pre>
  91  *      V is definitely unassigned before the finally block iff
  92  *      V is definitely unassigned everywhere in the try block
  93  *      and everywhere in each catch block of the try statement.
  94  *  </pre>
  95  *  <p>In addition,
  96  *  <pre>
  97  *      V is definitely assigned at the end of a constructor iff
  98  *      V is definitely assigned after the block that is the body
  99  *      of the constructor and V is definitely assigned at every
 100  *      return that can return from the constructor.
 101  *  </pre>
 102  *  <p>In addition, each continue statement with the loop as its target
 103  *  is treated as a jump to the end of the loop body, and "intervening"
 104  *  finally clauses are treated as follows: V is DA "due to the
 105  *  continue" iff V is DA before the continue statement or V is DA at
 106  *  the end of any intervening finally block.  V is DU "due to the
 107  *  continue" iff any intervening finally cannot complete normally or V
 108  *  is DU at the end of every intervening finally block.  This "due to
 109  *  the continue" concept is then used in the spec for the loops.
 110  *
 111  *  <p>Similarly, break statements must consider intervening finally
 112  *  blocks.  For liveness analysis, a break statement for which any
 113  *  intervening finally cannot complete normally is not considered to
 114  *  cause the target statement to be able to complete normally. Then
 115  *  we say V is DA "due to the break" iff V is DA before the break or
 116  *  V is DA at the end of any intervening finally block.  V is DU "due
 117  *  to the break" iff any intervening finally cannot complete normally
 118  *  or V is DU at the break and at the end of every intervening
 119  *  finally block.  (I suspect this latter condition can be
 120  *  simplified.)  This "due to the break" is then used in the spec for
 121  *  all statements that can be "broken".
 122  *
 123  *  <p>The return statement is treated similarly.  V is DA "due to a
 124  *  return statement" iff V is DA before the return statement or V is
 125  *  DA at the end of any intervening finally block.  Note that we
 126  *  don't have to worry about the return expression because this
 127  *  concept is only used for construcrors.
 128  *
 129  *  <p>There is no spec in the JLS for when a variable is definitely
 130  *  assigned at the end of a constructor, which is needed for final
 131  *  fields (8.3.1.2).  We implement the rule that V is DA at the end
 132  *  of the constructor iff it is DA and the end of the body of the
 133  *  constructor and V is DA "due to" every return of the constructor.
 134  *
 135  *  <p>Intervening finally blocks similarly affect exception analysis.  An
 136  *  intervening finally that cannot complete normally allows us to ignore
 137  *  an otherwise uncaught exception.
 138  *
 139  *  <p>To implement the semantics of intervening finally clauses, all
 140  *  nonlocal transfers (break, continue, return, throw, method call that
 141  *  can throw a checked exception, and a constructor invocation that can
 142  *  thrown a checked exception) are recorded in a queue, and removed
 143  *  from the queue when we complete processing the target of the
 144  *  nonlocal transfer.  This allows us to modify the queue in accordance
 145  *  with the above rules when we encounter a finally clause.  The only
 146  *  exception to this [no pun intended] is that checked exceptions that
 147  *  are known to be caught or declared to be caught in the enclosing
 148  *  method are not recorded in the queue, but instead are recorded in a
 149  *  global variable "Set<Type> thrown" that records the type of all
 150  *  exceptions that can be thrown.
 151  *
 152  *  <p>Other minor issues the treatment of members of other classes
 153  *  (always considered DA except that within an anonymous class
 154  *  constructor, where DA status from the enclosing scope is
 155  *  preserved), treatment of the case expression (V is DA before the
 156  *  case expression iff V is DA after the switch expression),
 157  *  treatment of variables declared in a switch block (the implied
 158  *  DA/DU status after the switch expression is DU and not DA for
 159  *  variables defined in a switch block), the treatment of boolean ?:
 160  *  expressions (The JLS rules only handle b and c non-boolean; the
 161  *  new rule is that if b and c are boolean valued, then V is
 162  *  (un)assigned after a?b:c when true/false iff V is (un)assigned
 163  *  after b when true/false and V is (un)assigned after c when
 164  *  true/false).
 165  *
 166  *  <p>There is the remaining question of what syntactic forms constitute a
 167  *  reference to a variable.  It is conventional to allow this.x on the
 168  *  left-hand-side to initialize a final instance field named x, yet
 169  *  this.x isn't considered a "use" when appearing on a right-hand-side
 170  *  in most implementations.  Should parentheses affect what is
 171  *  considered a variable reference?  The simplest rule would be to
 172  *  allow unqualified forms only, parentheses optional, and phase out
 173  *  support for assigning to a final field via this.x.
 174  *
 175  *  <p><b>This is NOT part of any supported API.
 176  *  If you write code that depends on this, you do so at your own risk.
 177  *  This code and its internal interfaces are subject to change or
 178  *  deletion without notice.</b>
 179  */
 180 public class Flow extends TreeScanner {
 181     protected static final Context.Key<Flow> flowKey =
 182         new Context.Key<Flow>();
 183 
 184     private final Names names;
 185     private final Log log;
 186     private final Symtab syms;
 187     private final Types types;
 188     private final Check chk;
 189     private       TreeMaker make;
 190     private final Resolve rs;
 191     private Env<AttrContext> attrEnv;
 192     private       Lint lint;
 193     private final boolean allowImprovedRethrowAnalysis;
 194     private final boolean allowImprovedCatchAnalysis;
 195 
 196     public static Flow instance(Context context) {
 197         Flow instance = context.get(flowKey);
 198         if (instance == null)
 199             instance = new Flow(context);
 200         return instance;
 201     }
 202 
 203     protected Flow(Context context) {
 204         context.put(flowKey, this);
 205         names = Names.instance(context);
 206         log = Log.instance(context);
 207         syms = Symtab.instance(context);
 208         types = Types.instance(context);
 209         chk = Check.instance(context);
 210         lint = Lint.instance(context);
 211         rs = Resolve.instance(context);
 212         Source source = Source.instance(context);
 213         allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
 214         allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
 215     }
 216 
 217     /** A flag that indicates whether the last statement could
 218      *  complete normally.
 219      */
 220     private boolean alive;
 221 
 222     /** The set of definitely assigned variables.
 223      */
 224     Bits inits;
 225 
 226     /** The set of definitely unassigned variables.
 227      */
 228     Bits uninits;
 229 
 230     HashMap<Symbol, List<Type>> preciseRethrowTypes;
 231 
 232     /** The set of variables that are definitely unassigned everywhere
 233      *  in current try block. This variable is maintained lazily; it is
 234      *  updated only when something gets removed from uninits,
 235      *  typically by being assigned in reachable code.  To obtain the
 236      *  correct set of variables which are definitely unassigned
 237      *  anywhere in current try block, intersect uninitsTry and
 238      *  uninits.
 239      */
 240     Bits uninitsTry;
 241 
 242     /** When analyzing a condition, inits and uninits are null.
 243      *  Instead we have:
 244      */
 245     Bits initsWhenTrue;
 246     Bits initsWhenFalse;
 247     Bits uninitsWhenTrue;
 248     Bits uninitsWhenFalse;
 249 
 250     /** A mapping from addresses to variable symbols.
 251      */
 252     VarSymbol[] vars;
 253 
 254     /** The current class being defined.
 255      */
 256     JCClassDecl classDef;
 257 
 258     /** The first variable sequence number in this class definition.
 259      */
 260     int firstadr;
 261 
 262     /** The next available variable sequence number.
 263      */
 264     int nextadr;
 265 
 266     /** The list of possibly thrown declarable exceptions.
 267      */
 268     List<Type> thrown;
 269 
 270     /** The list of exceptions that are either caught or declared to be
 271      *  thrown.
 272      */
 273     List<Type> caught;
 274 
 275     /** The list of unreferenced automatic resources.
 276      */
 277     Scope unrefdResources;
 278 
 279     /** Set when processing a loop body the second time for DU analysis. */
 280     boolean loopPassTwo = false;
 281 
 282     /*-------------------- Environments ----------------------*/
 283 
 284     /** A pending exit.  These are the statements return, break, and
 285      *  continue.  In addition, exception-throwing expressions or
 286      *  statements are put here when not known to be caught.  This
 287      *  will typically result in an error unless it is within a
 288      *  try-finally whose finally block cannot complete normally.
 289      */
 290     static class PendingExit {
 291         JCTree tree;
 292         Bits inits;
 293         Bits uninits;
 294         Type thrown;
 295         PendingExit(JCTree tree, Bits inits, Bits uninits) {
 296             this.tree = tree;
 297             this.inits = inits.dup();
 298             this.uninits = uninits.dup();
 299         }
 300         PendingExit(JCTree tree, Type thrown) {
 301             this.tree = tree;
 302             this.thrown = thrown;
 303         }
 304     }
 305 
 306     /** The currently pending exits that go from current inner blocks
 307      *  to an enclosing block, in source order.
 308      */
 309     ListBuffer<PendingExit> pendingExits;
 310 
 311     /*-------------------- Exceptions ----------------------*/
 312 
 313     /** Complain that pending exceptions are not caught.
 314      */
 315     void errorUncaught() {
 316         for (PendingExit exit = pendingExits.next();
 317              exit != null;
 318              exit = pendingExits.next()) {
 319             if (classDef != null &&
 320                 classDef.pos == exit.tree.pos) {
 321                 log.error(exit.tree.pos(),
 322                         "unreported.exception.default.constructor",
 323                         exit.thrown);
 324             } else if (exit.tree.getTag() == JCTree.VARDEF &&
 325                     ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
 326                 log.error(exit.tree.pos(),
 327                         "unreported.exception.implicit.close",
 328                         exit.thrown,
 329                         ((JCVariableDecl)exit.tree).sym.name);
 330             } else {
 331                 log.error(exit.tree.pos(),
 332                         "unreported.exception.need.to.catch.or.throw",
 333                         exit.thrown);
 334             }
 335         }
 336     }
 337 
 338     /** Record that exception is potentially thrown and check that it
 339      *  is caught.
 340      */
 341     void markThrown(JCTree tree, Type exc) {
 342         if (!chk.isUnchecked(tree.pos(), exc)) {
 343             if (!chk.isHandled(exc, caught))
 344                 pendingExits.append(new PendingExit(tree, exc));
 345                 thrown = chk.incl(exc, thrown);
 346         }
 347     }
 348 
 349     /*-------------- Processing variables ----------------------*/
 350 
 351     /** Do we need to track init/uninit state of this symbol?
 352      *  I.e. is symbol either a local or a blank final variable?
 353      */
 354     boolean trackable(VarSymbol sym) {
 355         return
 356             (sym.owner.kind == MTH ||
 357              ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
 358               classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)));
 359     }
 360 
 361     /** Initialize new trackable variable by setting its address field
 362      *  to the next available sequence number and entering it under that
 363      *  index into the vars array.
 364      */
 365     void newVar(VarSymbol sym) {
 366         if (nextadr == vars.length) {
 367             VarSymbol[] newvars = new VarSymbol[nextadr * 2];
 368             System.arraycopy(vars, 0, newvars, 0, nextadr);
 369             vars = newvars;
 370         }
 371         sym.adr = nextadr;
 372         vars[nextadr] = sym;
 373         inits.excl(nextadr);
 374         uninits.incl(nextadr);
 375         nextadr++;
 376     }
 377 
 378     /** Record an initialization of a trackable variable.
 379      */
 380     void letInit(DiagnosticPosition pos, VarSymbol sym) {
 381         if (sym.adr >= firstadr && trackable(sym)) {
 382             if ((sym.flags() & FINAL) != 0) {
 383                 if ((sym.flags() & PARAMETER) != 0) {
 384                     if ((sym.flags() & UNION) != 0) { //multi-catch parameter
 385                         log.error(pos, "multicatch.parameter.may.not.be.assigned",
 386                                   sym);
 387                     }
 388                     else {
 389                         log.error(pos, "final.parameter.may.not.be.assigned",
 390                               sym);
 391                     }
 392                 } else if (!uninits.isMember(sym.adr)) {
 393                     log.error(pos,
 394                               loopPassTwo
 395                               ? "var.might.be.assigned.in.loop"
 396                               : "var.might.already.be.assigned",
 397                               sym);
 398                 } else if (!inits.isMember(sym.adr)) {
 399                     // reachable assignment
 400                     uninits.excl(sym.adr);
 401                     uninitsTry.excl(sym.adr);
 402                 } else {
 403                     //log.rawWarning(pos, "unreachable assignment");//DEBUG
 404                     uninits.excl(sym.adr);
 405                 }
 406             }
 407             inits.incl(sym.adr);
 408         } else if ((sym.flags() & FINAL) != 0) {
 409             log.error(pos, "var.might.already.be.assigned", sym);
 410         }
 411     }
 412 
 413     /** If tree is either a simple name or of the form this.name or
 414      *  C.this.name, and tree represents a trackable variable,
 415      *  record an initialization of the variable.
 416      */
 417     void letInit(JCTree tree) {
 418         tree = TreeInfo.skipParens(tree);
 419         if (tree.getTag() == JCTree.IDENT || tree.getTag() == JCTree.SELECT) {
 420             Symbol sym = TreeInfo.symbol(tree);
 421             if (sym.kind == VAR) {
 422                 letInit(tree.pos(), (VarSymbol)sym);
 423             }
 424         }
 425     }
 426 
 427     /** Check that trackable variable is initialized.
 428      */
 429     void checkInit(DiagnosticPosition pos, VarSymbol sym) {
 430         if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
 431             trackable(sym) &&
 432             !inits.isMember(sym.adr)) {
 433             log.error(pos, "var.might.not.have.been.initialized",
 434                       sym);
 435             inits.incl(sym.adr);
 436         }
 437     }
 438 
 439     /*-------------------- Handling jumps ----------------------*/
 440 
 441     /** Record an outward transfer of control. */
 442     void recordExit(JCTree tree) {
 443         pendingExits.append(new PendingExit(tree, inits, uninits));
 444         markDead();
 445     }
 446 
 447     /** Resolve all breaks of this statement. */
 448     boolean resolveBreaks(JCTree tree,
 449                           ListBuffer<PendingExit> oldPendingExits) {
 450         boolean result = false;
 451         List<PendingExit> exits = pendingExits.toList();
 452         pendingExits = oldPendingExits;
 453         for (; exits.nonEmpty(); exits = exits.tail) {
 454             PendingExit exit = exits.head;
 455             if (exit.tree.getTag() == JCTree.BREAK &&
 456                 ((JCBreak) exit.tree).target == tree) {
 457                 inits.andSet(exit.inits);
 458                 uninits.andSet(exit.uninits);
 459                 result = true;
 460             } else {
 461                 pendingExits.append(exit);
 462             }
 463         }
 464         return result;
 465     }
 466 
 467     /** Resolve all continues of this statement. */
 468     boolean resolveContinues(JCTree tree) {
 469         boolean result = false;
 470         List<PendingExit> exits = pendingExits.toList();
 471         pendingExits = new ListBuffer<PendingExit>();
 472         for (; exits.nonEmpty(); exits = exits.tail) {
 473             PendingExit exit = exits.head;
 474             if (exit.tree.getTag() == JCTree.CONTINUE &&
 475                 ((JCContinue) exit.tree).target == tree) {
 476                 inits.andSet(exit.inits);
 477                 uninits.andSet(exit.uninits);
 478                 result = true;
 479             } else {
 480                 pendingExits.append(exit);
 481             }
 482         }
 483         return result;
 484     }
 485 
 486     /** Record that statement is unreachable.
 487      */
 488     void markDead() {
 489         inits.inclRange(firstadr, nextadr);
 490         uninits.inclRange(firstadr, nextadr);
 491         alive = false;
 492     }
 493 
 494     /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
 495      */
 496     void split(boolean setToNull) {
 497         initsWhenFalse = inits.dup();
 498         uninitsWhenFalse = uninits.dup();
 499         initsWhenTrue = inits;
 500         uninitsWhenTrue = uninits;
 501         if (setToNull)
 502             inits = uninits = null;
 503     }
 504 
 505     /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
 506      */
 507     void merge() {
 508         inits = initsWhenFalse.andSet(initsWhenTrue);
 509         uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
 510     }
 511 
 512 /* ************************************************************************
 513  * Visitor methods for statements and definitions
 514  *************************************************************************/
 515 
 516     /** Analyze a definition.
 517      */
 518     void scanDef(JCTree tree) {
 519         scanStat(tree);
 520         if (tree != null && tree.getTag() == JCTree.BLOCK && !alive) {
 521             log.error(tree.pos(),
 522                       "initializer.must.be.able.to.complete.normally");
 523         }
 524     }
 525 
 526     /** Analyze a statement. Check that statement is reachable.
 527      */
 528     void scanStat(JCTree tree) {
 529         if (!alive && tree != null) {
 530             log.error(tree.pos(), "unreachable.stmt");
 531             if (tree.getTag() != JCTree.SKIP) alive = true;
 532         }
 533         scan(tree);
 534     }
 535 
 536     /** Analyze list of statements.
 537      */
 538     void scanStats(List<? extends JCStatement> trees) {
 539         if (trees != null)
 540             for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
 541                 scanStat(l.head);
 542     }
 543 
 544     /** Analyze an expression. Make sure to set (un)inits rather than
 545      *  (un)initsWhenTrue(WhenFalse) on exit.
 546      */
 547     void scanExpr(JCTree tree) {
 548         if (tree != null) {
 549             scan(tree);
 550             if (inits == null) merge();
 551         }
 552     }
 553 
 554     /** Analyze a list of expressions.
 555      */
 556     void scanExprs(List<? extends JCExpression> trees) {
 557         if (trees != null)
 558             for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
 559                 scanExpr(l.head);
 560     }
 561 
 562     /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
 563      *  rather than (un)inits on exit.
 564      */
 565     void scanCond(JCTree tree) {
 566         if (tree.type.isFalse()) {
 567             if (inits == null) merge();
 568             initsWhenTrue = inits.dup();
 569             initsWhenTrue.inclRange(firstadr, nextadr);
 570             uninitsWhenTrue = uninits.dup();
 571             uninitsWhenTrue.inclRange(firstadr, nextadr);
 572             initsWhenFalse = inits;
 573             uninitsWhenFalse = uninits;
 574         } else if (tree.type.isTrue()) {
 575             if (inits == null) merge();
 576             initsWhenFalse = inits.dup();
 577             initsWhenFalse.inclRange(firstadr, nextadr);
 578             uninitsWhenFalse = uninits.dup();
 579             uninitsWhenFalse.inclRange(firstadr, nextadr);
 580             initsWhenTrue = inits;
 581             uninitsWhenTrue = uninits;
 582         } else {
 583             scan(tree);
 584             if (inits != null)
 585                 split(tree.type != syms.unknownType);
 586         }
 587         if (tree.type != syms.unknownType)
 588             inits = uninits = null;
 589     }
 590 
 591     /* ------------ Visitor methods for various sorts of trees -------------*/
 592 
 593     public void visitClassDef(JCClassDecl tree) {
 594         if (tree.sym == null) return;
 595 
 596         JCClassDecl classDefPrev = classDef;
 597         List<Type> thrownPrev = thrown;
 598         List<Type> caughtPrev = caught;
 599         boolean alivePrev = alive;
 600         int firstadrPrev = firstadr;
 601         int nextadrPrev = nextadr;
 602         ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 603         Lint lintPrev = lint;
 604 
 605         pendingExits = new ListBuffer<PendingExit>();
 606         if (tree.name != names.empty) {
 607             caught = List.nil();
 608             firstadr = nextadr;
 609         }
 610         classDef = tree;
 611         thrown = List.nil();
 612         lint = lint.augment(tree.sym.attributes_field);
 613 
 614         try {
 615             // define all the static fields
 616             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 617                 if (l.head.getTag() == JCTree.VARDEF) {
 618                     JCVariableDecl def = (JCVariableDecl)l.head;
 619                     if ((def.mods.flags & STATIC) != 0) {
 620                         VarSymbol sym = def.sym;
 621                         if (trackable(sym))
 622                             newVar(sym);
 623                     }
 624                 }
 625             }
 626 
 627             // process all the static initializers
 628             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 629                 if (l.head.getTag() != JCTree.METHODDEF &&
 630                     (TreeInfo.flags(l.head) & STATIC) != 0) {
 631                     scanDef(l.head);
 632                     errorUncaught();
 633                 }
 634             }
 635 
 636             // add intersection of all thrown clauses of initial constructors
 637             // to set of caught exceptions, unless class is anonymous.
 638             if (tree.name != names.empty) {
 639                 boolean firstConstructor = true;
 640                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 641                     if (TreeInfo.isInitialConstructor(l.head)) {
 642                         List<Type> mthrown =
 643                             ((JCMethodDecl) l.head).sym.type.getThrownTypes();
 644                         if (firstConstructor) {
 645                             caught = mthrown;
 646                             firstConstructor = false;
 647                         } else {
 648                             caught = chk.intersect(mthrown, caught);
 649                         }
 650                     }
 651                 }
 652             }
 653 
 654             // define all the instance fields
 655             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 656                 if (l.head.getTag() == JCTree.VARDEF) {
 657                     JCVariableDecl def = (JCVariableDecl)l.head;
 658                     if ((def.mods.flags & STATIC) == 0) {
 659                         VarSymbol sym = def.sym;
 660                         if (trackable(sym))
 661                             newVar(sym);
 662                     }
 663                 }
 664             }
 665 
 666             // process all the instance initializers
 667             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 668                 if (l.head.getTag() != JCTree.METHODDEF &&
 669                     (TreeInfo.flags(l.head) & STATIC) == 0) {
 670                     scanDef(l.head);
 671                     errorUncaught();
 672                 }
 673             }
 674 
 675             // in an anonymous class, add the set of thrown exceptions to
 676             // the throws clause of the synthetic constructor and propagate
 677             // outwards.
 678             // Changing the throws clause on the fly is okay here because
 679             // the anonymous constructor can't be invoked anywhere else,
 680             // and its type hasn't been cached.
 681             if (tree.name == names.empty) {
 682                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 683                     if (TreeInfo.isInitialConstructor(l.head)) {
 684                         JCMethodDecl mdef = (JCMethodDecl)l.head;
 685                         mdef.thrown = make.Types(thrown);
 686                         mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
 687                     }
 688                 }
 689                 thrownPrev = chk.union(thrown, thrownPrev);
 690             }
 691 
 692             // process all the methods
 693             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 694                 if (l.head.getTag() == JCTree.METHODDEF) {
 695                     scan(l.head);
 696                     errorUncaught();
 697                 }
 698             }
 699 
 700             thrown = thrownPrev;
 701         } finally {
 702             pendingExits = pendingExitsPrev;
 703             alive = alivePrev;
 704             nextadr = nextadrPrev;
 705             firstadr = firstadrPrev;
 706             caught = caughtPrev;
 707             classDef = classDefPrev;
 708             lint = lintPrev;
 709         }
 710     }
 711 
 712     public void visitMethodDef(JCMethodDecl tree) {
 713         if (tree.body == null) return;
 714 
 715         List<Type> caughtPrev = caught;
 716         List<Type> mthrown = tree.sym.type.getThrownTypes();
 717         Bits initsPrev = inits.dup();
 718         Bits uninitsPrev = uninits.dup();
 719         int nextadrPrev = nextadr;
 720         int firstadrPrev = firstadr;
 721         Lint lintPrev = lint;
 722 
 723         lint = lint.augment(tree.sym.attributes_field);
 724 
 725         Assert.check(pendingExits.isEmpty());
 726 
 727         try {
 728             boolean isInitialConstructor =
 729                 TreeInfo.isInitialConstructor(tree);
 730 
 731             if (!isInitialConstructor)
 732                 firstadr = nextadr;
 733             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
 734                 JCVariableDecl def = l.head;
 735                 scan(def);
 736                 inits.incl(def.sym.adr);
 737                 uninits.excl(def.sym.adr);
 738             }
 739             if (isInitialConstructor)
 740                 caught = chk.union(caught, mthrown);
 741             else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
 742                 caught = mthrown;
 743             // else we are in an instance initializer block;
 744             // leave caught unchanged.
 745 
 746             alive = true;
 747             scanStat(tree.body);
 748 
 749             if (alive && tree.sym.type.getReturnType().tag != VOID)
 750                 log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
 751 
 752             if (isInitialConstructor) {
 753                 for (int i = firstadr; i < nextadr; i++)
 754                     if (vars[i].owner == classDef.sym)
 755                         checkInit(TreeInfo.diagEndPos(tree.body), vars[i]);
 756             }
 757             List<PendingExit> exits = pendingExits.toList();
 758             pendingExits = new ListBuffer<PendingExit>();
 759             while (exits.nonEmpty()) {
 760                 PendingExit exit = exits.head;
 761                 exits = exits.tail;
 762                 if (exit.thrown == null) {
 763                     Assert.check(exit.tree.getTag() == JCTree.RETURN);
 764                     if (isInitialConstructor) {
 765                         inits = exit.inits;
 766                         for (int i = firstadr; i < nextadr; i++)
 767                             checkInit(exit.tree.pos(), vars[i]);
 768                     }
 769                 } else {
 770                     // uncaught throws will be reported later
 771                     pendingExits.append(exit);
 772                 }
 773             }
 774         } finally {
 775             inits = initsPrev;
 776             uninits = uninitsPrev;
 777             nextadr = nextadrPrev;
 778             firstadr = firstadrPrev;
 779             caught = caughtPrev;
 780             lint = lintPrev;
 781         }
 782     }
 783 
 784     public void visitVarDef(JCVariableDecl tree) {
 785         boolean track = trackable(tree.sym);
 786         if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
 787         if (tree.init != null) {
 788             Lint lintPrev = lint;
 789             lint = lint.augment(tree.sym.attributes_field);
 790             try{
 791                 scanExpr(tree.init);
 792                 if (track) letInit(tree.pos(), tree.sym);
 793             } finally {
 794                 lint = lintPrev;
 795             }
 796         }
 797     }
 798 
 799     public void visitBlock(JCBlock tree) {
 800         int nextadrPrev = nextadr;
 801         scanStats(tree.stats);
 802         nextadr = nextadrPrev;
 803     }
 804 
 805     public void visitDoLoop(JCDoWhileLoop tree) {
 806         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 807         boolean prevLoopPassTwo = loopPassTwo;
 808         pendingExits = new ListBuffer<PendingExit>();
 809         int prevErrors = log.nerrors;
 810         do {
 811             Bits uninitsEntry = uninits.dup();
 812             uninitsEntry.excludeFrom(nextadr);
 813             scanStat(tree.body);
 814             alive |= resolveContinues(tree);
 815             scanCond(tree.cond);
 816             if (log.nerrors !=  prevErrors ||
 817                 loopPassTwo ||
 818                 uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
 819                 break;
 820             inits = initsWhenTrue;
 821             uninits = uninitsEntry.andSet(uninitsWhenTrue);
 822             loopPassTwo = true;
 823             alive = true;
 824         } while (true);
 825         loopPassTwo = prevLoopPassTwo;
 826         inits = initsWhenFalse;
 827         uninits = uninitsWhenFalse;
 828         alive = alive && !tree.cond.type.isTrue();
 829         alive |= resolveBreaks(tree, prevPendingExits);
 830     }
 831 
 832     public void visitWhileLoop(JCWhileLoop tree) {
 833         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 834         boolean prevLoopPassTwo = loopPassTwo;
 835         Bits initsCond;
 836         Bits uninitsCond;
 837         pendingExits = new ListBuffer<PendingExit>();
 838         int prevErrors = log.nerrors;
 839         do {
 840             Bits uninitsEntry = uninits.dup();
 841             uninitsEntry.excludeFrom(nextadr);
 842             scanCond(tree.cond);
 843             initsCond = initsWhenFalse;
 844             uninitsCond = uninitsWhenFalse;
 845             inits = initsWhenTrue;
 846             uninits = uninitsWhenTrue;
 847             alive = !tree.cond.type.isFalse();
 848             scanStat(tree.body);
 849             alive |= resolveContinues(tree);
 850             if (log.nerrors != prevErrors ||
 851                 loopPassTwo ||
 852                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
 853                 break;
 854             uninits = uninitsEntry.andSet(uninits);
 855             loopPassTwo = true;
 856             alive = true;
 857         } while (true);
 858         loopPassTwo = prevLoopPassTwo;
 859         inits = initsCond;
 860         uninits = uninitsCond;
 861         alive = resolveBreaks(tree, prevPendingExits) ||
 862             !tree.cond.type.isTrue();
 863     }
 864 
 865     public void visitForLoop(JCForLoop tree) {
 866         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 867         boolean prevLoopPassTwo = loopPassTwo;
 868         int nextadrPrev = nextadr;
 869         scanStats(tree.init);
 870         Bits initsCond;
 871         Bits uninitsCond;
 872         pendingExits = new ListBuffer<PendingExit>();
 873         int prevErrors = log.nerrors;
 874         do {
 875             Bits uninitsEntry = uninits.dup();
 876             uninitsEntry.excludeFrom(nextadr);
 877             if (tree.cond != null) {
 878                 scanCond(tree.cond);
 879                 initsCond = initsWhenFalse;
 880                 uninitsCond = uninitsWhenFalse;
 881                 inits = initsWhenTrue;
 882                 uninits = uninitsWhenTrue;
 883                 alive = !tree.cond.type.isFalse();
 884             } else {
 885                 initsCond = inits.dup();
 886                 initsCond.inclRange(firstadr, nextadr);
 887                 uninitsCond = uninits.dup();
 888                 uninitsCond.inclRange(firstadr, nextadr);
 889                 alive = true;
 890             }
 891             scanStat(tree.body);
 892             alive |= resolveContinues(tree);
 893             scan(tree.step);
 894             if (log.nerrors != prevErrors ||
 895                 loopPassTwo ||
 896                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
 897                 break;
 898             uninits = uninitsEntry.andSet(uninits);
 899             loopPassTwo = true;
 900             alive = true;
 901         } while (true);
 902         loopPassTwo = prevLoopPassTwo;
 903         inits = initsCond;
 904         uninits = uninitsCond;
 905         alive = resolveBreaks(tree, prevPendingExits) ||
 906             tree.cond != null && !tree.cond.type.isTrue();
 907         nextadr = nextadrPrev;
 908     }
 909 
 910     public void visitForeachLoop(JCEnhancedForLoop tree) {
 911         visitVarDef(tree.var);
 912 
 913         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 914         boolean prevLoopPassTwo = loopPassTwo;
 915         int nextadrPrev = nextadr;
 916         scan(tree.expr);
 917         Bits initsStart = inits.dup();
 918         Bits uninitsStart = uninits.dup();
 919 
 920         letInit(tree.pos(), tree.var.sym);
 921         pendingExits = new ListBuffer<PendingExit>();
 922         int prevErrors = log.nerrors;
 923         do {
 924             Bits uninitsEntry = uninits.dup();
 925             uninitsEntry.excludeFrom(nextadr);
 926             scanStat(tree.body);
 927             alive |= resolveContinues(tree);
 928             if (log.nerrors != prevErrors ||
 929                 loopPassTwo ||
 930                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
 931                 break;
 932             uninits = uninitsEntry.andSet(uninits);
 933             loopPassTwo = true;
 934             alive = true;
 935         } while (true);
 936         loopPassTwo = prevLoopPassTwo;
 937         inits = initsStart;
 938         uninits = uninitsStart.andSet(uninits);
 939         resolveBreaks(tree, prevPendingExits);
 940         alive = true;
 941         nextadr = nextadrPrev;
 942     }
 943 
 944     public void visitLabelled(JCLabeledStatement tree) {
 945         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 946         pendingExits = new ListBuffer<PendingExit>();
 947         scanStat(tree.body);
 948         alive |= resolveBreaks(tree, prevPendingExits);
 949     }
 950 
 951     public void visitSwitch(JCSwitch tree) {
 952         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 953         pendingExits = new ListBuffer<PendingExit>();
 954         int nextadrPrev = nextadr;
 955         scanExpr(tree.selector);
 956         Bits initsSwitch = inits;
 957         Bits uninitsSwitch = uninits.dup();
 958         boolean hasDefault = false;
 959         for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
 960             alive = true;
 961             inits = initsSwitch.dup();
 962             uninits = uninits.andSet(uninitsSwitch);
 963             JCCase c = l.head;
 964             if (c.pat == null)
 965                 hasDefault = true;
 966             else
 967                 scanExpr(c.pat);
 968             scanStats(c.stats);
 969             addVars(c.stats, initsSwitch, uninitsSwitch);
 970             // Warn about fall-through if lint switch fallthrough enabled.
 971             if (!loopPassTwo &&
 972                 alive &&
 973                 lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
 974                 c.stats.nonEmpty() && l.tail.nonEmpty())
 975                 log.warning(Lint.LintCategory.FALLTHROUGH,
 976                             l.tail.head.pos(),
 977                             "possible.fall-through.into.case");
 978         }
 979         if (!hasDefault) {
 980             inits.andSet(initsSwitch);
 981             alive = true;
 982         }
 983         alive |= resolveBreaks(tree, prevPendingExits);
 984         nextadr = nextadrPrev;
 985     }
 986     // where
 987         /** Add any variables defined in stats to inits and uninits. */
 988         private static void addVars(List<JCStatement> stats, Bits inits,
 989                                     Bits uninits) {
 990             for (;stats.nonEmpty(); stats = stats.tail) {
 991                 JCTree stat = stats.head;
 992                 if (stat.getTag() == JCTree.VARDEF) {
 993                     int adr = ((JCVariableDecl) stat).sym.adr;
 994                     inits.excl(adr);
 995                     uninits.incl(adr);
 996                 }
 997             }
 998         }
 999 
1000     public void visitTry(JCTry tree) {
1001         List<Type> caughtPrev = caught;
1002         List<Type> thrownPrev = thrown;
1003         thrown = List.nil();
1004         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1005             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1006                     ((JCTypeUnion)l.head.param.vartype).alternatives :
1007                     List.of(l.head.param.vartype);
1008             for (JCExpression ct : subClauses) {
1009                 caught = chk.incl(ct.type, caught);
1010             }
1011         }
1012         ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
1013         Bits uninitsTryPrev = uninitsTry;
1014         ListBuffer<PendingExit> prevPendingExits = pendingExits;
1015         pendingExits = new ListBuffer<PendingExit>();
1016         Bits initsTry = inits.dup();
1017         uninitsTry = uninits.dup();
1018         for (JCTree resource : tree.resources) {
1019             if (resource instanceof JCVariableDecl) {
1020                 JCVariableDecl vdecl = (JCVariableDecl) resource;
1021                 visitVarDef(vdecl);
1022                 unrefdResources.enter(vdecl.sym);
1023                 resourceVarDecls.append(vdecl);
1024             } else if (resource instanceof JCExpression) {
1025                 scanExpr((JCExpression) resource);
1026             } else {
1027                 throw new AssertionError(tree);  // parser error
1028             }
1029         }
1030         for (JCTree resource : tree.resources) {
1031             List<Type> closeableSupertypes = resource.type.isCompound() ?
1032                 types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1033                 List.of(resource.type);
1034             for (Type sup : closeableSupertypes) {
1035                 if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1036                     Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1037                             attrEnv,
1038                             sup,
1039                             names.close,
1040                             List.<Type>nil(),
1041                             List.<Type>nil());
1042                     if (closeMethod.kind == MTH) {
1043                         for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) {
1044                             markThrown(resource, t);
1045                         }
1046                     }
1047                 }
1048             }
1049         }
1050         scanStat(tree.body);
1051         List<Type> thrownInTry = allowImprovedCatchAnalysis ?
1052             chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
1053             thrown;
1054         thrown = thrownPrev;
1055         caught = caughtPrev;
1056         boolean aliveEnd = alive;
1057         uninitsTry.andSet(uninits);
1058         Bits initsEnd = inits;
1059         Bits uninitsEnd = uninits;
1060         int nextadrCatch = nextadr;
1061 
1062         if (!resourceVarDecls.isEmpty() &&
1063                 lint.isEnabled(Lint.LintCategory.TRY)) {
1064             for (JCVariableDecl resVar : resourceVarDecls) {
1065                 if (unrefdResources.includes(resVar.sym)) {
1066                     log.warning(Lint.LintCategory.TRY, resVar.pos(),
1067                                 "try.resource.not.referenced", resVar.sym);
1068                     unrefdResources.remove(resVar.sym);
1069                 }
1070             }
1071         }
1072 
1073         List<Type> caughtInTry = List.nil();
1074         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1075             alive = true;
1076             JCVariableDecl param = l.head.param;
1077             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1078                     ((JCTypeUnion)l.head.param.vartype).alternatives :
1079                     List.of(l.head.param.vartype);
1080             List<Type> ctypes = List.nil();
1081             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1082             for (JCExpression ct : subClauses) {
1083                 Type exc = ct.type;
1084                 if (exc != syms.unknownType) {
1085                     ctypes = ctypes.append(exc);
1086                     if (types.isSameType(exc, syms.objectType))
1087                         continue;
1088                     checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1089                     caughtInTry = chk.incl(exc, caughtInTry);
1090                 }
1091             }
1092             inits = initsTry.dup();
1093             uninits = uninitsTry.dup();
1094             scan(param);
1095             inits.incl(param.sym.adr);
1096             uninits.excl(param.sym.adr);
1097             preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1098             scanStat(l.head.body);
1099             initsEnd.andSet(inits);
1100             uninitsEnd.andSet(uninits);
1101             nextadr = nextadrCatch;
1102             preciseRethrowTypes.remove(param.sym);
1103             aliveEnd |= alive;
1104         }
1105         if (tree.finalizer != null) {
1106             List<Type> savedThrown = thrown;
1107             thrown = List.nil();
1108             inits = initsTry.dup();
1109             uninits = uninitsTry.dup();
1110             ListBuffer<PendingExit> exits = pendingExits;
1111             pendingExits = prevPendingExits;
1112             alive = true;
1113             scanStat(tree.finalizer);
1114             if (!alive) {
1115                 // discard exits and exceptions from try and finally
1116                 thrown = chk.union(thrown, thrownPrev);
1117                 if (!loopPassTwo &&
1118                     lint.isEnabled(Lint.LintCategory.FINALLY)) {
1119                     log.warning(Lint.LintCategory.FINALLY,
1120                             TreeInfo.diagEndPos(tree.finalizer),
1121                             "finally.cannot.complete");
1122                 }
1123             } else {
1124                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1125                 thrown = chk.union(thrown, savedThrown);
1126                 uninits.andSet(uninitsEnd);
1127                 // FIX: this doesn't preserve source order of exits in catch
1128                 // versus finally!
1129                 while (exits.nonEmpty()) {
1130                     PendingExit exit = exits.next();
1131                     if (exit.inits != null) {
1132                         exit.inits.orSet(inits);
1133                         exit.uninits.andSet(uninits);
1134                     }
1135                     pendingExits.append(exit);
1136                 }
1137                 inits.orSet(initsEnd);
1138                 alive = aliveEnd;
1139             }
1140         } else {
1141             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1142             inits = initsEnd;
1143             uninits = uninitsEnd;
1144             alive = aliveEnd;
1145             ListBuffer<PendingExit> exits = pendingExits;
1146             pendingExits = prevPendingExits;
1147             while (exits.nonEmpty()) pendingExits.append(exits.next());
1148         }
1149         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1150     }
1151 
1152     void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1153         if (chk.subset(exc, caughtInTry)) {
1154             log.error(pos, "except.already.caught", exc);
1155         } else if (!chk.isUnchecked(pos, exc) &&
1156                 !isExceptionOrThrowable(exc) &&
1157                 !chk.intersects(exc, thrownInTry)) {
1158             log.error(pos, "except.never.thrown.in.try", exc);
1159         } else if (allowImprovedCatchAnalysis) {
1160             List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
1161             // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
1162             // unchecked exception, the result list would not be empty, as the augmented
1163             // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1164             // exception, that would have been covered in the branch above
1165             if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1166                     !isExceptionOrThrowable(exc)) {
1167                 String key = catchableThrownTypes.length() == 1 ?
1168                         "unreachable.catch" :
1169                         "unreachable.catch.1";
1170                 log.warning(pos, key, catchableThrownTypes);
1171             }
1172         }
1173     }
1174     //where
1175         private boolean isExceptionOrThrowable(Type exc) {
1176             return exc.tsym == syms.throwableType.tsym ||
1177                 exc.tsym == syms.exceptionType.tsym;
1178         }
1179 
1180 
1181     public void visitConditional(JCConditional tree) {
1182         scanCond(tree.cond);
1183         Bits initsBeforeElse = initsWhenFalse;
1184         Bits uninitsBeforeElse = uninitsWhenFalse;
1185         inits = initsWhenTrue;
1186         uninits = uninitsWhenTrue;
1187         if (tree.truepart.type.tag == BOOLEAN &&
1188             tree.falsepart.type.tag == BOOLEAN) {
1189             // if b and c are boolean valued, then
1190             // v is (un)assigned after a?b:c when true iff
1191             //    v is (un)assigned after b when true and
1192             //    v is (un)assigned after c when true
1193             scanCond(tree.truepart);
1194             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1195             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1196             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1197             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1198             inits = initsBeforeElse;
1199             uninits = uninitsBeforeElse;
1200             scanCond(tree.falsepart);
1201             initsWhenTrue.andSet(initsAfterThenWhenTrue);
1202             initsWhenFalse.andSet(initsAfterThenWhenFalse);
1203             uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
1204             uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
1205         } else {
1206             scanExpr(tree.truepart);
1207             Bits initsAfterThen = inits.dup();
1208             Bits uninitsAfterThen = uninits.dup();
1209             inits = initsBeforeElse;
1210             uninits = uninitsBeforeElse;
1211             scanExpr(tree.falsepart);
1212             inits.andSet(initsAfterThen);
1213             uninits.andSet(uninitsAfterThen);
1214         }
1215     }
1216 
1217     public void visitIf(JCIf tree) {
1218         scanCond(tree.cond);
1219         Bits initsBeforeElse = initsWhenFalse;
1220         Bits uninitsBeforeElse = uninitsWhenFalse;
1221         inits = initsWhenTrue;
1222         uninits = uninitsWhenTrue;
1223         scanStat(tree.thenpart);
1224         if (tree.elsepart != null) {
1225             boolean aliveAfterThen = alive;
1226             alive = true;
1227             Bits initsAfterThen = inits.dup();
1228             Bits uninitsAfterThen = uninits.dup();
1229             inits = initsBeforeElse;
1230             uninits = uninitsBeforeElse;
1231             scanStat(tree.elsepart);
1232             inits.andSet(initsAfterThen);
1233             uninits.andSet(uninitsAfterThen);
1234             alive = alive | aliveAfterThen;
1235         } else {
1236             inits.andSet(initsBeforeElse);
1237             uninits.andSet(uninitsBeforeElse);
1238             alive = true;
1239         }
1240     }
1241 
1242 
1243 
1244     public void visitBreak(JCBreak tree) {
1245         recordExit(tree);
1246     }
1247 
1248     public void visitContinue(JCContinue tree) {
1249         recordExit(tree);
1250     }
1251 
1252     public void visitReturn(JCReturn tree) {
1253         scanExpr(tree.expr);
1254         // if not initial constructor, should markDead instead of recordExit
1255         recordExit(tree);
1256     }
1257 
1258     public void visitThrow(JCThrow tree) {
1259         scanExpr(tree.expr);
1260         Symbol sym = TreeInfo.symbol(tree.expr);
1261         if (sym != null &&
1262             sym.kind == VAR &&
1263             (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1264             preciseRethrowTypes.get(sym) != null &&
1265             allowImprovedRethrowAnalysis) {
1266             for (Type t : preciseRethrowTypes.get(sym)) {
1267                 markThrown(tree, t);
1268             }
1269         }
1270         else {
1271             markThrown(tree, tree.expr.type);
1272         }
1273         markDead();
1274     }
1275 
1276     public void visitApply(JCMethodInvocation tree) {
1277         scanExpr(tree.meth);
1278         scanExprs(tree.args);
1279         for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1280             markThrown(tree, l.head);
1281     }
1282 
1283     public void visitNewClass(JCNewClass tree) {
1284         scanExpr(tree.encl);
1285         scanExprs(tree.args);
1286        // scan(tree.def);
1287         for (List<Type> l = tree.constructorType.getThrownTypes();
1288              l.nonEmpty();
1289              l = l.tail) {
1290             markThrown(tree, l.head);
1291         }
1292         List<Type> caughtPrev = caught;
1293         try {
1294             // If the new class expression defines an anonymous class,
1295             // analysis of the anonymous constructor may encounter thrown
1296             // types which are unsubstituted type variables.
1297             // However, since the constructor's actual thrown types have
1298             // already been marked as thrown, it is safe to simply include
1299             // each of the constructor's formal thrown types in the set of
1300             // 'caught/declared to be thrown' types, for the duration of
1301             // the class def analysis.
1302             if (tree.def != null)
1303                 for (List<Type> l = tree.constructor.type.getThrownTypes();
1304                      l.nonEmpty();
1305                      l = l.tail) {
1306                     caught = chk.incl(l.head, caught);
1307                 }
1308             scan(tree.def);
1309         }
1310         finally {
1311             caught = caughtPrev;
1312         }
1313     }
1314 
1315     public void visitNewArray(JCNewArray tree) {
1316         scanExprs(tree.dims);
1317         scanExprs(tree.elems);
1318     }
1319 
1320     public void visitAssert(JCAssert tree) {
1321         Bits initsExit = inits.dup();
1322         Bits uninitsExit = uninits.dup();
1323         scanCond(tree.cond);
1324         uninitsExit.andSet(uninitsWhenTrue);
1325         if (tree.detail != null) {
1326             inits = initsWhenFalse;
1327             uninits = uninitsWhenFalse;
1328             scanExpr(tree.detail);
1329         }
1330         inits = initsExit;
1331         uninits = uninitsExit;
1332     }
1333 
1334     public void visitAssign(JCAssign tree) {
1335         JCTree lhs = TreeInfo.skipParens(tree.lhs);
1336         if (!(lhs instanceof JCIdent)) scanExpr(lhs);
1337         scanExpr(tree.rhs);
1338         letInit(lhs);
1339     }
1340 
1341     public void visitAssignop(JCAssignOp tree) {
1342         scanExpr(tree.lhs);
1343         scanExpr(tree.rhs);
1344         letInit(tree.lhs);
1345     }
1346 
1347     public void visitUnary(JCUnary tree) {
1348         switch (tree.getTag()) {
1349         case JCTree.NOT:
1350             scanCond(tree.arg);
1351             Bits t = initsWhenFalse;
1352             initsWhenFalse = initsWhenTrue;
1353             initsWhenTrue = t;
1354             t = uninitsWhenFalse;
1355             uninitsWhenFalse = uninitsWhenTrue;
1356             uninitsWhenTrue = t;
1357             break;
1358         case JCTree.PREINC: case JCTree.POSTINC:
1359         case JCTree.PREDEC: case JCTree.POSTDEC:
1360             scanExpr(tree.arg);
1361             letInit(tree.arg);
1362             break;
1363         default:
1364             scanExpr(tree.arg);
1365         }
1366     }
1367 
1368     public void visitBinary(JCBinary tree) {
1369         switch (tree.getTag()) {
1370         case JCTree.AND:
1371             scanCond(tree.lhs);
1372             Bits initsWhenFalseLeft = initsWhenFalse;
1373             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
1374             inits = initsWhenTrue;
1375             uninits = uninitsWhenTrue;
1376             scanCond(tree.rhs);
1377             initsWhenFalse.andSet(initsWhenFalseLeft);
1378             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
1379             break;
1380         case JCTree.OR:
1381             scanCond(tree.lhs);
1382             Bits initsWhenTrueLeft = initsWhenTrue;
1383             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1384             inits = initsWhenFalse;
1385             uninits = uninitsWhenFalse;
1386             scanCond(tree.rhs);
1387             initsWhenTrue.andSet(initsWhenTrueLeft);
1388             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1389             break;
1390         default:
1391             scanExpr(tree.lhs);
1392             scanExpr(tree.rhs);
1393         }
1394     }
1395 
1396     public void visitIdent(JCIdent tree) {
1397         if (tree.sym.kind == VAR) {
1398             checkInit(tree.pos(), (VarSymbol)tree.sym);
1399             referenced(tree.sym);
1400         }
1401     }
1402 
1403     void referenced(Symbol sym) {
1404         unrefdResources.remove(sym);
1405     }
1406 
1407     public void visitTypeCast(JCTypeCast tree) {
1408         super.visitTypeCast(tree);
1409         if (!tree.type.isErroneous()
1410             && lint.isEnabled(Lint.LintCategory.CAST)
1411             && types.isSameType(tree.expr.type, tree.clazz.type)
1412             && !is292targetTypeCast(tree)) {
1413             log.warning(Lint.LintCategory.CAST,
1414                     tree.pos(), "redundant.cast", tree.expr.type);
1415         }
1416     }
1417     //where
1418         private boolean is292targetTypeCast(JCTypeCast tree) {
1419             boolean is292targetTypeCast = false;
1420             JCExpression expr = TreeInfo.skipParens(tree.expr);
1421             if (expr.getTag() == JCTree.APPLY) {
1422                 JCMethodInvocation apply = (JCMethodInvocation)expr;
1423                 Symbol sym = TreeInfo.symbol(apply.meth);
1424                 is292targetTypeCast = sym != null &&
1425                     sym.kind == MTH &&
1426                     (sym.flags() & POLYMORPHIC_SIGNATURE) != 0;
1427             }
1428             return is292targetTypeCast;
1429         }
1430 
1431     public void visitTopLevel(JCCompilationUnit tree) {
1432         // Do nothing for TopLevel since each class is visited individually
1433     }
1434 
1435 /**************************************************************************
1436  * main method
1437  *************************************************************************/
1438 
1439     /** Perform definite assignment/unassignment analysis on a tree.
1440      */
1441     public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
1442         try {
1443             attrEnv = env;
1444             JCTree tree = env.tree;
1445             this.make = make;
1446             inits = new Bits();
1447             uninits = new Bits();
1448             uninitsTry = new Bits();
1449             initsWhenTrue = initsWhenFalse =
1450                 uninitsWhenTrue = uninitsWhenFalse = null;
1451             if (vars == null)
1452                 vars = new VarSymbol[32];
1453             else
1454                 for (int i=0; i<vars.length; i++)
1455                     vars[i] = null;
1456             firstadr = 0;
1457             nextadr = 0;
1458             pendingExits = new ListBuffer<PendingExit>();
1459             preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
1460             alive = true;
1461             this.thrown = this.caught = null;
1462             this.classDef = null;
1463             unrefdResources = new Scope(env.enclClass.sym);
1464             scan(tree);
1465         } finally {
1466             // note that recursive invocations of this method fail hard
1467             inits = uninits = uninitsTry = null;
1468             initsWhenTrue = initsWhenFalse =
1469                 uninitsWhenTrue = uninitsWhenFalse = null;
1470             if (vars != null) for (int i=0; i<vars.length; i++)
1471                 vars[i] = null;
1472             firstadr = 0;
1473             nextadr = 0;
1474             pendingExits = null;
1475             this.make = null;
1476             this.thrown = this.caught = null;
1477             this.classDef = null;
1478             unrefdResources = null;
1479         }
1480     }
1481 }