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