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