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