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