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 closeMethod =
 996                         (MethodSymbol)resource.type.tsym.members().lookup(names.close).sym;
 997             for (Type thrownType : closeMethod.getThrownTypes()) {
 998                 markThrown(tree.body, thrownType);
 999             }
1000         }
1001         scanStat(tree.body);
1002         List<Type> thrownInTry = thrown;
1003         thrown = thrownPrev;
1004         caught = caughtPrev;
1005         boolean aliveEnd = alive;
1006         uninitsTry.andSet(uninits);
1007         Bits initsEnd = inits;
1008         Bits uninitsEnd = uninits;
1009         int nextadrCatch = nextadr;
1010 
1011         if (unrefdResources.nonEmpty()) {
1012             for (List<JCTree> l = tree.resources; l.nonEmpty(); l = l.tail) {
1013                 if (l.head instanceof JCVariableDecl) {
1014                     JCVariableDecl v = (JCVariableDecl) l.head;
1015                     if (unrefdResources.contains(v.sym)) {
1016                         log.warning(v.pos(),
1017                                     "automatic.resource.not.referenced", v.sym);
1018                     }
1019                 }
1020             }
1021         }
1022 
1023         List<Type> caughtInTry = List.nil();
1024         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1025             alive = true;
1026             JCVariableDecl param = l.head.param;
1027             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1028                     ((JCTypeDisjoint)l.head.param.vartype).components :
1029                     List.of(l.head.param.vartype);
1030             List<Type> ctypes = List.nil();
1031             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1032             for (JCExpression ct : subClauses) {
1033                 Type exc = ct.type;
1034                 ctypes = ctypes.append(exc);
1035                 if (types.isSameType(exc, syms.objectType))
1036                     continue;
1037                 if (chk.subset(exc, caughtInTry)) {
1038                     log.error(l.head.pos(),
1039                               "except.already.caught", exc);
1040                 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1041                            exc.tsym != syms.throwableType.tsym &&
1042                            exc.tsym != syms.exceptionType.tsym &&
1043                            !chk.intersects(exc, thrownInTry)) {
1044                     log.error(l.head.pos(),
1045                               "except.never.thrown.in.try", exc);
1046                 }
1047                 caughtInTry = chk.incl(exc, caughtInTry);
1048             }
1049             inits = initsTry.dup();
1050             uninits = uninitsTry.dup();
1051             scan(param);
1052             inits.incl(param.sym.adr);
1053             uninits.excl(param.sym.adr);
1054             multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1055             scanStat(l.head.body);
1056             initsEnd.andSet(inits);
1057             uninitsEnd.andSet(uninits);
1058             nextadr = nextadrCatch;
1059             multicatchTypes.remove(param.sym);
1060             aliveEnd |= alive;
1061         }
1062         if (tree.finalizer != null) {
1063             List<Type> savedThrown = thrown;
1064             thrown = List.nil();
1065             inits = initsTry.dup();
1066             uninits = uninitsTry.dup();
1067             ListBuffer<PendingExit> exits = pendingExits;
1068             pendingExits = prevPendingExits;
1069             alive = true;
1070             scanStat(tree.finalizer);
1071             if (!alive) {
1072                 // discard exits and exceptions from try and finally
1073                 thrown = chk.union(thrown, thrownPrev);
1074                 if (!loopPassTwo &&
1075                     lint.isEnabled(Lint.LintCategory.FINALLY)) {
1076                     log.warning(TreeInfo.diagEndPos(tree.finalizer),
1077                                 "finally.cannot.complete");
1078                 }
1079             } else {
1080                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1081                 thrown = chk.union(thrown, savedThrown);
1082                 uninits.andSet(uninitsEnd);
1083                 // FIX: this doesn't preserve source order of exits in catch
1084                 // versus finally!
1085                 while (exits.nonEmpty()) {
1086                     PendingExit exit = exits.next();
1087                     if (exit.inits != null) {
1088                         exit.inits.orSet(inits);
1089                         exit.uninits.andSet(uninits);
1090                     }
1091                     pendingExits.append(exit);
1092                 }
1093                 inits.orSet(initsEnd);
1094                 alive = aliveEnd;
1095             }
1096         } else {
1097             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1098             inits = initsEnd;
1099             uninits = uninitsEnd;
1100             alive = aliveEnd;
1101             ListBuffer<PendingExit> exits = pendingExits;
1102             pendingExits = prevPendingExits;
1103             while (exits.nonEmpty()) pendingExits.append(exits.next());
1104         }
1105         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1106     }
1107 
1108     public void visitConditional(JCConditional tree) {
1109         scanCond(tree.cond);
1110         Bits initsBeforeElse = initsWhenFalse;
1111         Bits uninitsBeforeElse = uninitsWhenFalse;
1112         inits = initsWhenTrue;
1113         uninits = uninitsWhenTrue;
1114         if (tree.truepart.type.tag == BOOLEAN &&
1115             tree.falsepart.type.tag == BOOLEAN) {
1116             // if b and c are boolean valued, then
1117             // v is (un)assigned after a?b:c when true iff
1118             //    v is (un)assigned after b when true and
1119             //    v is (un)assigned after c when true
1120             scanCond(tree.truepart);
1121             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1122             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1123             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1124             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1125             inits = initsBeforeElse;
1126             uninits = uninitsBeforeElse;
1127             scanCond(tree.falsepart);
1128             initsWhenTrue.andSet(initsAfterThenWhenTrue);
1129             initsWhenFalse.andSet(initsAfterThenWhenFalse);
1130             uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
1131             uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
1132         } else {
1133             scanExpr(tree.truepart);
1134             Bits initsAfterThen = inits.dup();
1135             Bits uninitsAfterThen = uninits.dup();
1136             inits = initsBeforeElse;
1137             uninits = uninitsBeforeElse;
1138             scanExpr(tree.falsepart);
1139             inits.andSet(initsAfterThen);
1140             uninits.andSet(uninitsAfterThen);
1141         }
1142     }
1143 
1144     public void visitIf(JCIf tree) {
1145         scanCond(tree.cond);
1146         Bits initsBeforeElse = initsWhenFalse;
1147         Bits uninitsBeforeElse = uninitsWhenFalse;
1148         inits = initsWhenTrue;
1149         uninits = uninitsWhenTrue;
1150         scanStat(tree.thenpart);
1151         if (tree.elsepart != null) {
1152             boolean aliveAfterThen = alive;
1153             alive = true;
1154             Bits initsAfterThen = inits.dup();
1155             Bits uninitsAfterThen = uninits.dup();
1156             inits = initsBeforeElse;
1157             uninits = uninitsBeforeElse;
1158             scanStat(tree.elsepart);
1159             inits.andSet(initsAfterThen);
1160             uninits.andSet(uninitsAfterThen);
1161             alive = alive | aliveAfterThen;
1162         } else {
1163             inits.andSet(initsBeforeElse);
1164             uninits.andSet(uninitsBeforeElse);
1165             alive = true;
1166         }
1167     }
1168 
1169 
1170 
1171     public void visitBreak(JCBreak tree) {
1172         recordExit(tree);
1173     }
1174 
1175     public void visitContinue(JCContinue tree) {
1176         recordExit(tree);
1177     }
1178 
1179     public void visitReturn(JCReturn tree) {
1180         scanExpr(tree.expr);
1181         // if not initial constructor, should markDead instead of recordExit
1182         recordExit(tree);
1183     }
1184 
1185     public void visitThrow(JCThrow tree) {
1186         scanExpr(tree.expr);
1187         Symbol sym = TreeInfo.symbol(tree.expr);
1188         if (sym != null &&
1189             sym.kind == VAR &&
1190             (sym.flags() & FINAL) != 0 &&
1191             multicatchTypes.get(sym) != null &&
1192             allowRethrowAnalysis) {
1193             for (Type t : multicatchTypes.get(sym)) {
1194                 markThrown(tree, t);
1195             }
1196         }
1197         else {
1198             markThrown(tree, tree.expr.type);
1199         }
1200         markDead();
1201     }
1202 
1203     public void visitApply(JCMethodInvocation tree) {
1204         scanExpr(tree.meth);
1205         scanExprs(tree.args);
1206         for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1207             markThrown(tree, l.head);
1208     }
1209 
1210     public void visitNewClass(JCNewClass tree) {
1211         scanExpr(tree.encl);
1212         scanExprs(tree.args);
1213        // scan(tree.def);
1214         for (List<Type> l = tree.constructorType.getThrownTypes();
1215              l.nonEmpty();
1216              l = l.tail) {
1217             markThrown(tree, l.head);
1218         }
1219         List<Type> caughtPrev = caught;
1220         try {
1221             // If the new class expression defines an anonymous class,
1222             // analysis of the anonymous constructor may encounter thrown
1223             // types which are unsubstituted type variables.
1224             // However, since the constructor's actual thrown types have
1225             // already been marked as thrown, it is safe to simply include
1226             // each of the constructor's formal thrown types in the set of
1227             // 'caught/declared to be thrown' types, for the duration of
1228             // the class def analysis.
1229             if (tree.def != null)
1230                 for (List<Type> l = tree.constructor.type.getThrownTypes();
1231                      l.nonEmpty();
1232                      l = l.tail) {
1233                     caught = chk.incl(l.head, caught);
1234                 }
1235             scan(tree.def);
1236         }
1237         finally {
1238             caught = caughtPrev;
1239         }
1240     }
1241 
1242     public void visitNewArray(JCNewArray tree) {
1243         scanExprs(tree.dims);
1244         scanExprs(tree.elems);
1245     }
1246 
1247     public void visitAssert(JCAssert tree) {
1248         Bits initsExit = inits.dup();
1249         Bits uninitsExit = uninits.dup();
1250         scanCond(tree.cond);
1251         uninitsExit.andSet(uninitsWhenTrue);
1252         if (tree.detail != null) {
1253             inits = initsWhenFalse;
1254             uninits = uninitsWhenFalse;
1255             scanExpr(tree.detail);
1256         }
1257         inits = initsExit;
1258         uninits = uninitsExit;
1259     }
1260 
1261     public void visitAssign(JCAssign tree) {
1262         JCTree lhs = TreeInfo.skipParens(tree.lhs);
1263         if (!(lhs instanceof JCIdent)) scanExpr(lhs);
1264         scanExpr(tree.rhs);
1265         letInit(lhs);
1266     }
1267 
1268     public void visitAssignop(JCAssignOp tree) {
1269         scanExpr(tree.lhs);
1270         scanExpr(tree.rhs);
1271         letInit(tree.lhs);
1272     }
1273 
1274     public void visitUnary(JCUnary tree) {
1275         switch (tree.getTag()) {
1276         case JCTree.NOT:
1277             scanCond(tree.arg);
1278             Bits t = initsWhenFalse;
1279             initsWhenFalse = initsWhenTrue;
1280             initsWhenTrue = t;
1281             t = uninitsWhenFalse;
1282             uninitsWhenFalse = uninitsWhenTrue;
1283             uninitsWhenTrue = t;
1284             break;
1285         case JCTree.PREINC: case JCTree.POSTINC:
1286         case JCTree.PREDEC: case JCTree.POSTDEC:
1287             scanExpr(tree.arg);
1288             letInit(tree.arg);
1289             break;
1290         default:
1291             scanExpr(tree.arg);
1292         }
1293     }
1294 
1295     public void visitBinary(JCBinary tree) {
1296         switch (tree.getTag()) {
1297         case JCTree.AND:
1298             scanCond(tree.lhs);
1299             Bits initsWhenFalseLeft = initsWhenFalse;
1300             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
1301             inits = initsWhenTrue;
1302             uninits = uninitsWhenTrue;
1303             scanCond(tree.rhs);
1304             initsWhenFalse.andSet(initsWhenFalseLeft);
1305             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
1306             break;
1307         case JCTree.OR:
1308             scanCond(tree.lhs);
1309             Bits initsWhenTrueLeft = initsWhenTrue;
1310             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1311             inits = initsWhenFalse;
1312             uninits = uninitsWhenFalse;
1313             scanCond(tree.rhs);
1314             initsWhenTrue.andSet(initsWhenTrueLeft);
1315             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1316             break;
1317         default:
1318             scanExpr(tree.lhs);
1319             scanExpr(tree.rhs);
1320         }
1321     }
1322 
1323     public void visitAnnotatedType(JCAnnotatedType tree) {
1324         // annotations don't get scanned
1325         tree.underlyingType.accept(this);
1326     }
1327 
1328     public void visitIdent(JCIdent tree) {
1329         if (tree.sym.kind == VAR) {
1330             checkInit(tree.pos(), (VarSymbol)tree.sym);
1331             referenced(tree.sym);
1332         }
1333     }
1334 
1335     void referenced(Symbol sym) {
1336         if (unrefdResources != null && unrefdResources.contains(sym)) {
1337             ListBuffer<Symbol> lb = new ListBuffer<Symbol>();
1338             for (List<Symbol> l = unrefdResources; l.nonEmpty(); l = l.tail)
1339                 if (l.head != sym)
1340                     lb.add(l.head);
1341             unrefdResources = lb.toList();
1342         }
1343     }
1344 
1345     public void visitTypeCast(JCTypeCast tree) {
1346         super.visitTypeCast(tree);
1347         if (!tree.type.isErroneous()
1348             && lint.isEnabled(Lint.LintCategory.CAST)
1349             && types.isSameType(tree.expr.type, tree.clazz.type)
1350             && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1351             log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1352         }
1353     }
1354 
1355     public void visitTopLevel(JCCompilationUnit tree) {
1356         // Do nothing for TopLevel since each class is visited individually
1357     }
1358 
1359 /**************************************************************************
1360  * utility methods for ignoring type-annotated casts lint checking
1361  *************************************************************************/
1362     private static final boolean ignoreAnnotatedCasts = true;
1363     private static class AnnotationFinder extends TreeScanner {
1364         public boolean foundTypeAnno = false;
1365         public void visitAnnotation(JCAnnotation tree) {
1366             foundTypeAnno = foundTypeAnno || (tree instanceof JCTypeAnnotation);
1367         }
1368     }
1369 
1370     private boolean containsTypeAnnotation(JCTree e) {
1371         AnnotationFinder finder = new AnnotationFinder();
1372         finder.scan(e);
1373         return finder.foundTypeAnno;
1374     }
1375 
1376 /**************************************************************************
1377  * main method
1378  *************************************************************************/
1379 
1380     /** Perform definite assignment/unassignment analysis on a tree.
1381      */
1382     public void analyzeTree(JCTree tree, TreeMaker make) {
1383         try {
1384             this.make = make;
1385             inits = new Bits();
1386             uninits = new Bits();
1387             uninitsTry = new Bits();
1388             initsWhenTrue = initsWhenFalse =
1389                 uninitsWhenTrue = uninitsWhenFalse = null;
1390             if (vars == null)
1391                 vars = new VarSymbol[32];
1392             else
1393                 for (int i=0; i<vars.length; i++)
1394                     vars[i] = null;
1395             firstadr = 0;
1396             nextadr = 0;
1397             pendingExits = new ListBuffer<PendingExit>();
1398             multicatchTypes = new HashMap<Symbol, List<Type>>();
1399             alive = true;
1400             this.thrown = this.caught = null;
1401             this.classDef = null;
1402             scan(tree);
1403         } finally {
1404             // note that recursive invocations of this method fail hard
1405             inits = uninits = uninitsTry = null;
1406             initsWhenTrue = initsWhenFalse =
1407                 uninitsWhenTrue = uninitsWhenFalse = null;
1408             if (vars != null) for (int i=0; i<vars.length; i++)
1409                 vars[i] = null;
1410             firstadr = 0;
1411             nextadr = 0;
1412             pendingExits = null;
1413             this.make = null;
1414             this.thrown = this.caught = null;
1415             this.classDef = null;
1416         }
1417     }
1418 }