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     /** Set when processing a loop body the second time for DU analysis. */
 269     boolean loopPassTwo = false;
 270 
 271     /*-------------------- Environments ----------------------*/
 272 
 273     /** A pending exit.  These are the statements return, break, and
 274      *  continue.  In addition, exception-throwing expressions or
 275      *  statements are put here when not known to be caught.  This
 276      *  will typically result in an error unless it is within a
 277      *  try-finally whose finally block cannot complete normally.
 278      */
 279     static class PendingExit {
 280         JCTree tree;
 281         Bits inits;
 282         Bits uninits;
 283         Type thrown;
 284         PendingExit(JCTree tree, Bits inits, Bits uninits) {
 285             this.tree = tree;
 286             this.inits = inits.dup();
 287             this.uninits = uninits.dup();
 288         }
 289         PendingExit(JCTree tree, Type thrown) {
 290             this.tree = tree;
 291             this.thrown = thrown;
 292         }
 293     }
 294 
 295     /** The currently pending exits that go from current inner blocks
 296      *  to an enclosing block, in source order.
 297      */
 298     ListBuffer<PendingExit> pendingExits;
 299 
 300     /*-------------------- Exceptions ----------------------*/
 301 
 302     /** Complain that pending exceptions are not caught.
 303      */
 304     void errorUncaught() {
 305         for (PendingExit exit = pendingExits.next();
 306              exit != null;
 307              exit = pendingExits.next()) {
 308             boolean synthetic = classDef != null &&
 309                 classDef.pos == exit.tree.pos;
 310             log.error(exit.tree.pos(),
 311                       synthetic
 312                       ? "unreported.exception.default.constructor"
 313                       : "unreported.exception.need.to.catch.or.throw",
 314                       exit.thrown);
 315         }
 316     }
 317 
 318     /** Record that exception is potentially thrown and check that it
 319      *  is caught.
 320      */
 321     void markThrown(JCTree tree, Type exc) {
 322         if (!chk.isUnchecked(tree.pos(), exc)) {
 323             if (!chk.isHandled(exc, caught))
 324                 pendingExits.append(new PendingExit(tree, exc));
 325             thrown = chk.incl(exc, thrown);
 326         }
 327     }
 328 
 329     /*-------------- Processing variables ----------------------*/
 330 
 331     /** Do we need to track init/uninit state of this symbol?
 332      *  I.e. is symbol either a local or a blank final variable?
 333      */
 334     boolean trackable(VarSymbol sym) {
 335         return
 336             (sym.owner.kind == MTH ||
 337              ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
 338               classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)));
 339     }
 340 
 341     /** Initialize new trackable variable by setting its address field
 342      *  to the next available sequence number and entering it under that
 343      *  index into the vars array.
 344      */
 345     void newVar(VarSymbol sym) {
 346         if (nextadr == vars.length) {
 347             VarSymbol[] newvars = new VarSymbol[nextadr * 2];
 348             System.arraycopy(vars, 0, newvars, 0, nextadr);
 349             vars = newvars;
 350         }
 351         sym.adr = nextadr;
 352         vars[nextadr] = sym;
 353         inits.excl(nextadr);
 354         uninits.incl(nextadr);
 355         nextadr++;
 356     }
 357 
 358     /** Record an initialization of a trackable variable.
 359      */
 360     void letInit(DiagnosticPosition pos, VarSymbol sym) {
 361         if (sym.adr >= firstadr && trackable(sym)) {
 362             if ((sym.flags() & FINAL) != 0) {
 363                 if ((sym.flags() & PARAMETER) != 0) {
 364                     if ((sym.flags() & DISJOINT) != 0) { //multi-catch parameter
 365                         log.error(pos, "multicatch.parameter.may.not.be.assigned",
 366                                   sym);
 367                     }
 368                     else {
 369                         log.error(pos, "final.parameter.may.not.be.assigned",
 370                               sym);
 371                     }
 372                 } else if (!uninits.isMember(sym.adr)) {
 373                     log.error(pos,
 374                               loopPassTwo
 375                               ? "var.might.be.assigned.in.loop"
 376                               : "var.might.already.be.assigned",
 377                               sym);
 378                 } else if (!inits.isMember(sym.adr)) {
 379                     // reachable assignment
 380                     uninits.excl(sym.adr);
 381                     uninitsTry.excl(sym.adr);
 382                 } else {
 383                     //log.rawWarning(pos, "unreachable assignment");//DEBUG
 384                     uninits.excl(sym.adr);
 385                 }
 386             }
 387             inits.incl(sym.adr);
 388         } else if ((sym.flags() & FINAL) != 0) {
 389             log.error(pos, "var.might.already.be.assigned", sym);
 390         }
 391     }
 392 
 393     /** If tree is either a simple name or of the form this.name or
 394      *  C.this.name, and tree represents a trackable variable,
 395      *  record an initialization of the variable.
 396      */
 397     void letInit(JCTree tree) {
 398         tree = TreeInfo.skipParens(tree);
 399         if (tree.getTag() == JCTree.IDENT || tree.getTag() == JCTree.SELECT) {
 400             Symbol sym = TreeInfo.symbol(tree);
 401             letInit(tree.pos(), (VarSymbol)sym);
 402         }
 403     }
 404 
 405     /** Check that trackable variable is initialized.
 406      */
 407     void checkInit(DiagnosticPosition pos, VarSymbol sym) {
 408         if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
 409             trackable(sym) &&
 410             !inits.isMember(sym.adr)) {
 411             log.error(pos, "var.might.not.have.been.initialized",
 412                       sym);
 413             inits.incl(sym.adr);
 414         }
 415     }
 416 
 417     /*-------------------- Handling jumps ----------------------*/
 418 
 419     /** Record an outward transfer of control. */
 420     void recordExit(JCTree tree) {
 421         pendingExits.append(new PendingExit(tree, inits, uninits));
 422         markDead();
 423     }
 424 
 425     /** Resolve all breaks of this statement. */
 426     boolean resolveBreaks(JCTree tree,
 427                           ListBuffer<PendingExit> oldPendingExits) {
 428         boolean result = false;
 429         List<PendingExit> exits = pendingExits.toList();
 430         pendingExits = oldPendingExits;
 431         for (; exits.nonEmpty(); exits = exits.tail) {
 432             PendingExit exit = exits.head;
 433             if (exit.tree.getTag() == JCTree.BREAK &&
 434                 ((JCBreak) exit.tree).target == tree) {
 435                 inits.andSet(exit.inits);
 436                 uninits.andSet(exit.uninits);
 437                 result = true;
 438             } else {
 439                 pendingExits.append(exit);
 440             }
 441         }
 442         return result;
 443     }
 444 
 445     /** Resolve all continues of this statement. */
 446     boolean resolveContinues(JCTree tree) {
 447         boolean result = false;
 448         List<PendingExit> exits = pendingExits.toList();
 449         pendingExits = new ListBuffer<PendingExit>();
 450         for (; exits.nonEmpty(); exits = exits.tail) {
 451             PendingExit exit = exits.head;
 452             if (exit.tree.getTag() == JCTree.CONTINUE &&
 453                 ((JCContinue) exit.tree).target == tree) {
 454                 inits.andSet(exit.inits);
 455                 uninits.andSet(exit.uninits);
 456                 result = true;
 457             } else {
 458                 pendingExits.append(exit);
 459             }
 460         }
 461         return result;
 462     }
 463 
 464     /** Record that statement is unreachable.
 465      */
 466     void markDead() {
 467         inits.inclRange(firstadr, nextadr);
 468         uninits.inclRange(firstadr, nextadr);
 469         alive = false;
 470     }
 471 
 472     /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
 473      */
 474     void split() {
 475         initsWhenFalse = inits.dup();
 476         uninitsWhenFalse = uninits.dup();
 477         initsWhenTrue = inits;
 478         uninitsWhenTrue = uninits;
 479         inits = uninits = null;
 480     }
 481 
 482     /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
 483      */
 484     void merge() {
 485         inits = initsWhenFalse.andSet(initsWhenTrue);
 486         uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
 487     }
 488 
 489 /* ************************************************************************
 490  * Visitor methods for statements and definitions
 491  *************************************************************************/
 492 
 493     /** Analyze a definition.
 494      */
 495     void scanDef(JCTree tree) {
 496         scanStat(tree);
 497         if (tree != null && tree.getTag() == JCTree.BLOCK && !alive) {
 498             log.error(tree.pos(),
 499                       "initializer.must.be.able.to.complete.normally");
 500         }
 501     }
 502 
 503     /** Analyze a statement. Check that statement is reachable.
 504      */
 505     void scanStat(JCTree tree) {
 506         if (!alive && tree != null) {
 507             log.error(tree.pos(), "unreachable.stmt");
 508             if (tree.getTag() != JCTree.SKIP) alive = true;
 509         }
 510         scan(tree);
 511     }
 512 
 513     /** Analyze list of statements.
 514      */
 515     void scanStats(List<? extends JCStatement> trees) {
 516         if (trees != null)
 517             for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
 518                 scanStat(l.head);
 519     }
 520 
 521     /** Analyze an expression. Make sure to set (un)inits rather than
 522      *  (un)initsWhenTrue(WhenFalse) on exit.
 523      */
 524     void scanExpr(JCTree tree) {
 525         if (tree != null) {
 526             scan(tree);
 527             if (inits == null) merge();
 528         }
 529     }
 530 
 531     /** Analyze a list of expressions.
 532      */
 533     void scanExprs(List<? extends JCExpression> trees) {
 534         if (trees != null)
 535             for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
 536                 scanExpr(l.head);
 537     }
 538 
 539     /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
 540      *  rather than (un)inits on exit.
 541      */
 542     void scanCond(JCTree tree) {
 543         if (tree.type.isFalse()) {
 544             if (inits == null) merge();
 545             initsWhenTrue = inits.dup();
 546             initsWhenTrue.inclRange(firstadr, nextadr);
 547             uninitsWhenTrue = uninits.dup();
 548             uninitsWhenTrue.inclRange(firstadr, nextadr);
 549             initsWhenFalse = inits;
 550             uninitsWhenFalse = uninits;
 551         } else if (tree.type.isTrue()) {
 552             if (inits == null) merge();
 553             initsWhenFalse = inits.dup();
 554             initsWhenFalse.inclRange(firstadr, nextadr);
 555             uninitsWhenFalse = uninits.dup();
 556             uninitsWhenFalse.inclRange(firstadr, nextadr);
 557             initsWhenTrue = inits;
 558             uninitsWhenTrue = uninits;
 559         } else {
 560             scan(tree);
 561             if (inits != null) split();
 562         }
 563         inits = uninits = null;
 564     }
 565 
 566     /* ------------ Visitor methods for various sorts of trees -------------*/
 567 
 568     public void visitClassDef(JCClassDecl tree) {
 569         if (tree.sym == null) return;
 570 
 571         JCClassDecl classDefPrev = classDef;
 572         List<Type> thrownPrev = thrown;
 573         List<Type> caughtPrev = caught;
 574         boolean alivePrev = alive;
 575         int firstadrPrev = firstadr;
 576         int nextadrPrev = nextadr;
 577         ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 578         Lint lintPrev = lint;
 579 
 580         pendingExits = new ListBuffer<PendingExit>();
 581         if (tree.name != names.empty) {
 582             caught = List.nil();
 583             firstadr = nextadr;
 584         }
 585         classDef = tree;
 586         thrown = List.nil();
 587         lint = lint.augment(tree.sym.attributes_field);
 588 
 589         try {
 590             // define all the static fields
 591             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 592                 if (l.head.getTag() == JCTree.VARDEF) {
 593                     JCVariableDecl def = (JCVariableDecl)l.head;
 594                     if ((def.mods.flags & STATIC) != 0) {
 595                         VarSymbol sym = def.sym;
 596                         if (trackable(sym))
 597                             newVar(sym);
 598                     }
 599                 }
 600             }
 601 
 602             // process all the static initializers
 603             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 604                 if (l.head.getTag() != JCTree.METHODDEF &&
 605                     (TreeInfo.flags(l.head) & STATIC) != 0) {
 606                     scanDef(l.head);
 607                     errorUncaught();
 608                 }
 609             }
 610 
 611             // add intersection of all thrown clauses of initial constructors
 612             // to set of caught exceptions, unless class is anonymous.
 613             if (tree.name != names.empty) {
 614                 boolean firstConstructor = true;
 615                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 616                     if (TreeInfo.isInitialConstructor(l.head)) {
 617                         List<Type> mthrown =
 618                             ((JCMethodDecl) l.head).sym.type.getThrownTypes();
 619                         if (firstConstructor) {
 620                             caught = mthrown;
 621                             firstConstructor = false;
 622                         } else {
 623                             caught = chk.intersect(mthrown, caught);
 624                         }
 625                     }
 626                 }
 627             }
 628 
 629             // define all the instance fields
 630             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 631                 if (l.head.getTag() == JCTree.VARDEF) {
 632                     JCVariableDecl def = (JCVariableDecl)l.head;
 633                     if ((def.mods.flags & STATIC) == 0) {
 634                         VarSymbol sym = def.sym;
 635                         if (trackable(sym))
 636                             newVar(sym);
 637                     }
 638                 }
 639             }
 640 
 641             // process all the instance initializers
 642             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 643                 if (l.head.getTag() != JCTree.METHODDEF &&
 644                     (TreeInfo.flags(l.head) & STATIC) == 0) {
 645                     scanDef(l.head);
 646                     errorUncaught();
 647                 }
 648             }
 649 
 650             // in an anonymous class, add the set of thrown exceptions to
 651             // the throws clause of the synthetic constructor and propagate
 652             // outwards.
 653             if (tree.name == names.empty) {
 654                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 655                     if (TreeInfo.isInitialConstructor(l.head)) {
 656                         JCMethodDecl mdef = (JCMethodDecl)l.head;
 657                         mdef.thrown = make.Types(thrown);
 658                         mdef.sym.type.setThrown(thrown);
 659                     }
 660                 }
 661                 thrownPrev = chk.union(thrown, thrownPrev);
 662             }
 663 
 664             // process all the methods
 665             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
 666                 if (l.head.getTag() == JCTree.METHODDEF) {
 667                     scan(l.head);
 668                     errorUncaught();
 669                 }
 670             }
 671 
 672             thrown = thrownPrev;
 673         } finally {
 674             pendingExits = pendingExitsPrev;
 675             alive = alivePrev;
 676             nextadr = nextadrPrev;
 677             firstadr = firstadrPrev;
 678             caught = caughtPrev;
 679             classDef = classDefPrev;
 680             lint = lintPrev;
 681         }
 682     }
 683 
 684     public void visitMethodDef(JCMethodDecl tree) {
 685         if (tree.body == null) return;
 686 
 687         List<Type> caughtPrev = caught;
 688         List<Type> mthrown = tree.sym.type.getThrownTypes();
 689         Bits initsPrev = inits.dup();
 690         Bits uninitsPrev = uninits.dup();
 691         int nextadrPrev = nextadr;
 692         int firstadrPrev = firstadr;
 693         Lint lintPrev = lint;
 694 
 695         lint = lint.augment(tree.sym.attributes_field);
 696 
 697         assert pendingExits.isEmpty();
 698 
 699         try {
 700             boolean isInitialConstructor =
 701                 TreeInfo.isInitialConstructor(tree);
 702 
 703             if (!isInitialConstructor)
 704                 firstadr = nextadr;
 705             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
 706                 JCVariableDecl def = l.head;
 707                 scan(def);
 708                 inits.incl(def.sym.adr);
 709                 uninits.excl(def.sym.adr);
 710             }
 711             if (isInitialConstructor)
 712                 caught = chk.union(caught, mthrown);
 713             else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
 714                 caught = mthrown;
 715             // else we are in an instance initializer block;
 716             // leave caught unchanged.
 717 
 718             alive = true;
 719             scanStat(tree.body);
 720 
 721             if (alive && tree.sym.type.getReturnType().tag != VOID)
 722                 log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
 723 
 724             if (isInitialConstructor) {
 725                 for (int i = firstadr; i < nextadr; i++)
 726                     if (vars[i].owner == classDef.sym)
 727                         checkInit(TreeInfo.diagEndPos(tree.body), vars[i]);
 728             }
 729             List<PendingExit> exits = pendingExits.toList();
 730             pendingExits = new ListBuffer<PendingExit>();
 731             while (exits.nonEmpty()) {
 732                 PendingExit exit = exits.head;
 733                 exits = exits.tail;
 734                 if (exit.thrown == null) {
 735                     assert exit.tree.getTag() == JCTree.RETURN;
 736                     if (isInitialConstructor) {
 737                         inits = exit.inits;
 738                         for (int i = firstadr; i < nextadr; i++)
 739                             checkInit(exit.tree.pos(), vars[i]);
 740                     }
 741                 } else {
 742                     // uncaught throws will be reported later
 743                     pendingExits.append(exit);
 744                 }
 745             }
 746         } finally {
 747             inits = initsPrev;
 748             uninits = uninitsPrev;
 749             nextadr = nextadrPrev;
 750             firstadr = firstadrPrev;
 751             caught = caughtPrev;
 752             lint = lintPrev;
 753         }
 754     }
 755 
 756     public void visitVarDef(JCVariableDecl tree) {
 757         boolean track = trackable(tree.sym);
 758         if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
 759         if (tree.init != null) {
 760             Lint lintPrev = lint;
 761             lint = lint.augment(tree.sym.attributes_field);
 762             try{
 763                 scanExpr(tree.init);
 764                 if (track) letInit(tree.pos(), tree.sym);
 765             } finally {
 766                 lint = lintPrev;
 767             }
 768         }
 769     }
 770 
 771     public void visitBlock(JCBlock tree) {
 772         int nextadrPrev = nextadr;
 773         scanStats(tree.stats);
 774         nextadr = nextadrPrev;
 775     }
 776 
 777     public void visitDoLoop(JCDoWhileLoop tree) {
 778         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 779         boolean prevLoopPassTwo = loopPassTwo;
 780         pendingExits = new ListBuffer<PendingExit>();
 781         do {
 782             Bits uninitsEntry = uninits.dup();
 783             scanStat(tree.body);
 784             alive |= resolveContinues(tree);
 785             scanCond(tree.cond);
 786             if (log.nerrors != 0 ||
 787                 loopPassTwo ||
 788                 uninitsEntry.diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
 789                 break;
 790             inits = initsWhenTrue;
 791             uninits = uninitsEntry.andSet(uninitsWhenTrue);
 792             loopPassTwo = true;
 793             alive = true;
 794         } while (true);
 795         loopPassTwo = prevLoopPassTwo;
 796         inits = initsWhenFalse;
 797         uninits = uninitsWhenFalse;
 798         alive = alive && !tree.cond.type.isTrue();
 799         alive |= resolveBreaks(tree, prevPendingExits);
 800     }
 801 
 802     public void visitWhileLoop(JCWhileLoop tree) {
 803         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 804         boolean prevLoopPassTwo = loopPassTwo;
 805         Bits initsCond;
 806         Bits uninitsCond;
 807         pendingExits = new ListBuffer<PendingExit>();
 808         do {
 809             Bits uninitsEntry = uninits.dup();
 810             scanCond(tree.cond);
 811             initsCond = initsWhenFalse;
 812             uninitsCond = uninitsWhenFalse;
 813             inits = initsWhenTrue;
 814             uninits = uninitsWhenTrue;
 815             alive = !tree.cond.type.isFalse();
 816             scanStat(tree.body);
 817             alive |= resolveContinues(tree);
 818             if (log.nerrors != 0 ||
 819                 loopPassTwo ||
 820                 uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1)
 821                 break;
 822             uninits = uninitsEntry.andSet(uninits);
 823             loopPassTwo = true;
 824             alive = true;
 825         } while (true);
 826         loopPassTwo = prevLoopPassTwo;
 827         inits = initsCond;
 828         uninits = uninitsCond;
 829         alive = resolveBreaks(tree, prevPendingExits) ||
 830             !tree.cond.type.isTrue();
 831     }
 832 
 833     public void visitForLoop(JCForLoop tree) {
 834         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 835         boolean prevLoopPassTwo = loopPassTwo;
 836         int nextadrPrev = nextadr;
 837         scanStats(tree.init);
 838         Bits initsCond;
 839         Bits uninitsCond;
 840         pendingExits = new ListBuffer<PendingExit>();
 841         do {
 842             Bits uninitsEntry = uninits.dup();
 843             if (tree.cond != null) {
 844                 scanCond(tree.cond);
 845                 initsCond = initsWhenFalse;
 846                 uninitsCond = uninitsWhenFalse;
 847                 inits = initsWhenTrue;
 848                 uninits = uninitsWhenTrue;
 849                 alive = !tree.cond.type.isFalse();
 850             } else {
 851                 initsCond = inits.dup();
 852                 initsCond.inclRange(firstadr, nextadr);
 853                 uninitsCond = uninits.dup();
 854                 uninitsCond.inclRange(firstadr, nextadr);
 855                 alive = true;
 856             }
 857             scanStat(tree.body);
 858             alive |= resolveContinues(tree);
 859             scan(tree.step);
 860             if (log.nerrors != 0 ||
 861                 loopPassTwo ||
 862                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
 863                 break;
 864             uninits = uninitsEntry.andSet(uninits);
 865             loopPassTwo = true;
 866             alive = true;
 867         } while (true);
 868         loopPassTwo = prevLoopPassTwo;
 869         inits = initsCond;
 870         uninits = uninitsCond;
 871         alive = resolveBreaks(tree, prevPendingExits) ||
 872             tree.cond != null && !tree.cond.type.isTrue();
 873         nextadr = nextadrPrev;
 874     }
 875 
 876     public void visitForeachLoop(JCEnhancedForLoop tree) {
 877         visitVarDef(tree.var);
 878 
 879         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 880         boolean prevLoopPassTwo = loopPassTwo;
 881         int nextadrPrev = nextadr;
 882         scan(tree.expr);
 883         Bits initsStart = inits.dup();
 884         Bits uninitsStart = uninits.dup();
 885 
 886         letInit(tree.pos(), tree.var.sym);
 887         pendingExits = new ListBuffer<PendingExit>();
 888         do {
 889             Bits uninitsEntry = uninits.dup();
 890             scanStat(tree.body);
 891             alive |= resolveContinues(tree);
 892             if (log.nerrors != 0 ||
 893                 loopPassTwo ||
 894                 uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1)
 895                 break;
 896             uninits = uninitsEntry.andSet(uninits);
 897             loopPassTwo = true;
 898             alive = true;
 899         } while (true);
 900         loopPassTwo = prevLoopPassTwo;
 901         inits = initsStart;
 902         uninits = uninitsStart.andSet(uninits);
 903         resolveBreaks(tree, prevPendingExits);
 904         alive = true;
 905         nextadr = nextadrPrev;
 906     }
 907 
 908     public void visitLabelled(JCLabeledStatement tree) {
 909         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 910         pendingExits = new ListBuffer<PendingExit>();
 911         scanStat(tree.body);
 912         alive |= resolveBreaks(tree, prevPendingExits);
 913     }
 914 
 915     public void visitSwitch(JCSwitch tree) {
 916         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 917         pendingExits = new ListBuffer<PendingExit>();
 918         int nextadrPrev = nextadr;
 919         scanExpr(tree.selector);
 920         Bits initsSwitch = inits;
 921         Bits uninitsSwitch = uninits.dup();
 922         boolean hasDefault = false;
 923         for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
 924             alive = true;
 925             inits = initsSwitch.dup();
 926             uninits = uninits.andSet(uninitsSwitch);
 927             JCCase c = l.head;
 928             if (c.pat == null)
 929                 hasDefault = true;
 930             else
 931                 scanExpr(c.pat);
 932             scanStats(c.stats);
 933             addVars(c.stats, initsSwitch, uninitsSwitch);
 934             // Warn about fall-through if lint switch fallthrough enabled.
 935             if (!loopPassTwo &&
 936                 alive &&
 937                 lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
 938                 c.stats.nonEmpty() && l.tail.nonEmpty())
 939                 log.warning(l.tail.head.pos(),
 940                             "possible.fall-through.into.case");
 941         }
 942         if (!hasDefault) {
 943             inits.andSet(initsSwitch);
 944             alive = true;
 945         }
 946         alive |= resolveBreaks(tree, prevPendingExits);
 947         nextadr = nextadrPrev;
 948     }
 949     // where
 950         /** Add any variables defined in stats to inits and uninits. */
 951         private static void addVars(List<JCStatement> stats, Bits inits,
 952                                     Bits uninits) {
 953             for (;stats.nonEmpty(); stats = stats.tail) {
 954                 JCTree stat = stats.head;
 955                 if (stat.getTag() == JCTree.VARDEF) {
 956                     int adr = ((JCVariableDecl) stat).sym.adr;
 957                     inits.excl(adr);
 958                     uninits.incl(adr);
 959                 }
 960             }
 961         }
 962 
 963     public void visitTry(JCTry tree) {
 964         List<Type> caughtPrev = caught;
 965         List<Type> thrownPrev = thrown;
 966         thrown = List.nil();
 967         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 968             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
 969                     ((JCTypeDisjoint)l.head.param.vartype).components :
 970                     List.of(l.head.param.vartype);
 971             for (JCExpression ct : subClauses) {
 972                 caught = chk.incl(ct.type, caught);
 973             }
 974         }
 975         Bits uninitsTryPrev = uninitsTry;
 976         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 977         pendingExits = new ListBuffer<PendingExit>();
 978         Bits initsTry = inits.dup();
 979         uninitsTry = uninits.dup();
 980         scanStat(tree.body);
 981         List<Type> thrownInTry = thrown;
 982         thrown = thrownPrev;
 983         caught = caughtPrev;
 984         boolean aliveEnd = alive;
 985         uninitsTry.andSet(uninits);
 986         Bits initsEnd = inits;
 987         Bits uninitsEnd = uninits;
 988         int nextadrCatch = nextadr;
 989 
 990         List<Type> caughtInTry = List.nil();
 991         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 992             alive = true;
 993             JCVariableDecl param = l.head.param;
 994             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
 995                     ((JCTypeDisjoint)l.head.param.vartype).components :
 996                     List.of(l.head.param.vartype);
 997             List<Type> ctypes = List.nil();
 998             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
 999             for (JCExpression ct : subClauses) {
1000                 Type exc = ct.type;
1001                 ctypes = ctypes.append(exc);
1002                 if (types.isSameType(exc, syms.objectType))
1003                     continue;
1004                 if (chk.subset(exc, caughtInTry)) {
1005                     log.error(l.head.pos(),
1006                               "except.already.caught", exc);
1007                 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1008                            exc.tsym != syms.throwableType.tsym &&
1009                            exc.tsym != syms.exceptionType.tsym &&
1010                            !chk.intersects(exc, thrownInTry)) {
1011                     log.error(l.head.pos(),
1012                               "except.never.thrown.in.try", exc);
1013                 }
1014                 caughtInTry = chk.incl(exc, caughtInTry);
1015             }
1016             inits = initsTry.dup();
1017             uninits = uninitsTry.dup();
1018             scan(param);
1019             inits.incl(param.sym.adr);
1020             uninits.excl(param.sym.adr);
1021             multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1022             scanStat(l.head.body);
1023             initsEnd.andSet(inits);
1024             uninitsEnd.andSet(uninits);
1025             nextadr = nextadrCatch;
1026             multicatchTypes.remove(param.sym);
1027             aliveEnd |= alive;
1028         }
1029         if (tree.finalizer != null) {
1030             List<Type> savedThrown = thrown;
1031             thrown = List.nil();
1032             inits = initsTry.dup();
1033             uninits = uninitsTry.dup();
1034             ListBuffer<PendingExit> exits = pendingExits;
1035             pendingExits = prevPendingExits;
1036             alive = true;
1037             scanStat(tree.finalizer);
1038             if (!alive) {
1039                 // discard exits and exceptions from try and finally
1040                 thrown = chk.union(thrown, thrownPrev);
1041                 if (!loopPassTwo &&
1042                     lint.isEnabled(Lint.LintCategory.FINALLY)) {
1043                     log.warning(TreeInfo.diagEndPos(tree.finalizer),
1044                                 "finally.cannot.complete");
1045                 }
1046             } else {
1047                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1048                 thrown = chk.union(thrown, savedThrown);
1049                 uninits.andSet(uninitsEnd);
1050                 // FIX: this doesn't preserve source order of exits in catch
1051                 // versus finally!
1052                 while (exits.nonEmpty()) {
1053                     PendingExit exit = exits.next();
1054                     if (exit.inits != null) {
1055                         exit.inits.orSet(inits);
1056                         exit.uninits.andSet(uninits);
1057                     }
1058                     pendingExits.append(exit);
1059                 }
1060                 inits.orSet(initsEnd);
1061                 alive = aliveEnd;
1062             }
1063         } else {
1064             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1065             inits = initsEnd;
1066             uninits = uninitsEnd;
1067             alive = aliveEnd;
1068             ListBuffer<PendingExit> exits = pendingExits;
1069             pendingExits = prevPendingExits;
1070             while (exits.nonEmpty()) pendingExits.append(exits.next());
1071         }
1072         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1073     }
1074 
1075     public void visitConditional(JCConditional tree) {
1076         scanCond(tree.cond);
1077         Bits initsBeforeElse = initsWhenFalse;
1078         Bits uninitsBeforeElse = uninitsWhenFalse;
1079         inits = initsWhenTrue;
1080         uninits = uninitsWhenTrue;
1081         if (tree.truepart.type.tag == BOOLEAN &&
1082             tree.falsepart.type.tag == BOOLEAN) {
1083             // if b and c are boolean valued, then
1084             // v is (un)assigned after a?b:c when true iff
1085             //    v is (un)assigned after b when true and
1086             //    v is (un)assigned after c when true
1087             scanCond(tree.truepart);
1088             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1089             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1090             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1091             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1092             inits = initsBeforeElse;
1093             uninits = uninitsBeforeElse;
1094             scanCond(tree.falsepart);
1095             initsWhenTrue.andSet(initsAfterThenWhenTrue);
1096             initsWhenFalse.andSet(initsAfterThenWhenFalse);
1097             uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
1098             uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
1099         } else {
1100             scanExpr(tree.truepart);
1101             Bits initsAfterThen = inits.dup();
1102             Bits uninitsAfterThen = uninits.dup();
1103             inits = initsBeforeElse;
1104             uninits = uninitsBeforeElse;
1105             scanExpr(tree.falsepart);
1106             inits.andSet(initsAfterThen);
1107             uninits.andSet(uninitsAfterThen);
1108         }
1109     }
1110 
1111     public void visitIf(JCIf tree) {
1112         scanCond(tree.cond);
1113         Bits initsBeforeElse = initsWhenFalse;
1114         Bits uninitsBeforeElse = uninitsWhenFalse;
1115         inits = initsWhenTrue;
1116         uninits = uninitsWhenTrue;
1117         scanStat(tree.thenpart);
1118         if (tree.elsepart != null) {
1119             boolean aliveAfterThen = alive;
1120             alive = true;
1121             Bits initsAfterThen = inits.dup();
1122             Bits uninitsAfterThen = uninits.dup();
1123             inits = initsBeforeElse;
1124             uninits = uninitsBeforeElse;
1125             scanStat(tree.elsepart);
1126             inits.andSet(initsAfterThen);
1127             uninits.andSet(uninitsAfterThen);
1128             alive = alive | aliveAfterThen;
1129         } else {
1130             inits.andSet(initsBeforeElse);
1131             uninits.andSet(uninitsBeforeElse);
1132             alive = true;
1133         }
1134     }
1135 
1136 
1137 
1138     public void visitBreak(JCBreak tree) {
1139         recordExit(tree);
1140     }
1141 
1142     public void visitContinue(JCContinue tree) {
1143         recordExit(tree);
1144     }
1145 
1146     public void visitReturn(JCReturn tree) {
1147         scanExpr(tree.expr);
1148         // if not initial constructor, should markDead instead of recordExit
1149         recordExit(tree);
1150     }
1151 
1152     public void visitThrow(JCThrow tree) {
1153         scanExpr(tree.expr);
1154         Symbol sym = TreeInfo.symbol(tree.expr);
1155         if (sym != null &&
1156             sym.kind == VAR &&
1157             (sym.flags() & FINAL) != 0 &&
1158             multicatchTypes.get(sym) != null &&
1159             allowRethrowAnalysis) {
1160             for (Type t : multicatchTypes.get(sym)) {
1161                 markThrown(tree, t);
1162             }
1163         }
1164         else {
1165             markThrown(tree, tree.expr.type);
1166         }
1167         markDead();
1168     }
1169 
1170     public void visitApply(JCMethodInvocation tree) {
1171         scanExpr(tree.meth);
1172         scanExprs(tree.args);
1173         for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1174             markThrown(tree, l.head);
1175     }
1176 
1177     public void visitNewClass(JCNewClass tree) {
1178         scanExpr(tree.encl);
1179         scanExprs(tree.args);
1180        // scan(tree.def);
1181         for (List<Type> l = tree.constructorType.getThrownTypes();
1182              l.nonEmpty();
1183              l = l.tail) {
1184             markThrown(tree, l.head);
1185         }
1186         List<Type> caughtPrev = caught;
1187         try {
1188             // If the new class expression defines an anonymous class,
1189             // analysis of the anonymous constructor may encounter thrown
1190             // types which are unsubstituted type variables.
1191             // However, since the constructor's actual thrown types have
1192             // already been marked as thrown, it is safe to simply include
1193             // each of the constructor's formal thrown types in the set of
1194             // 'caught/declared to be thrown' types, for the duration of
1195             // the class def analysis.
1196             if (tree.def != null)
1197                 for (List<Type> l = tree.constructor.type.getThrownTypes();
1198                      l.nonEmpty();
1199                      l = l.tail) {
1200                     caught = chk.incl(l.head, caught);
1201                 }
1202             scan(tree.def);
1203         }
1204         finally {
1205             caught = caughtPrev;
1206         }
1207     }
1208 
1209     public void visitNewArray(JCNewArray tree) {
1210         scanExprs(tree.dims);
1211         scanExprs(tree.elems);
1212     }
1213 
1214     public void visitAssert(JCAssert tree) {
1215         Bits initsExit = inits.dup();
1216         Bits uninitsExit = uninits.dup();
1217         scanCond(tree.cond);
1218         uninitsExit.andSet(uninitsWhenTrue);
1219         if (tree.detail != null) {
1220             inits = initsWhenFalse;
1221             uninits = uninitsWhenFalse;
1222             scanExpr(tree.detail);
1223         }
1224         inits = initsExit;
1225         uninits = uninitsExit;
1226     }
1227 
1228     public void visitAssign(JCAssign tree) {
1229         JCTree lhs = TreeInfo.skipParens(tree.lhs);
1230         if (!(lhs instanceof JCIdent)) scanExpr(lhs);
1231         scanExpr(tree.rhs);
1232         letInit(lhs);
1233     }
1234 
1235     public void visitAssignop(JCAssignOp tree) {
1236         scanExpr(tree.lhs);
1237         scanExpr(tree.rhs);
1238         letInit(tree.lhs);
1239     }
1240 
1241     public void visitUnary(JCUnary tree) {
1242         switch (tree.getTag()) {
1243         case JCTree.NOT:
1244             scanCond(tree.arg);
1245             Bits t = initsWhenFalse;
1246             initsWhenFalse = initsWhenTrue;
1247             initsWhenTrue = t;
1248             t = uninitsWhenFalse;
1249             uninitsWhenFalse = uninitsWhenTrue;
1250             uninitsWhenTrue = t;
1251             break;
1252         case JCTree.PREINC: case JCTree.POSTINC:
1253         case JCTree.PREDEC: case JCTree.POSTDEC:
1254             scanExpr(tree.arg);
1255             letInit(tree.arg);
1256             break;
1257         default:
1258             scanExpr(tree.arg);
1259         }
1260     }
1261 
1262     public void visitBinary(JCBinary tree) {
1263         switch (tree.getTag()) {
1264         case JCTree.AND:
1265             scanCond(tree.lhs);
1266             Bits initsWhenFalseLeft = initsWhenFalse;
1267             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
1268             inits = initsWhenTrue;
1269             uninits = uninitsWhenTrue;
1270             scanCond(tree.rhs);
1271             initsWhenFalse.andSet(initsWhenFalseLeft);
1272             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
1273             break;
1274         case JCTree.OR:
1275             scanCond(tree.lhs);
1276             Bits initsWhenTrueLeft = initsWhenTrue;
1277             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1278             inits = initsWhenFalse;
1279             uninits = uninitsWhenFalse;
1280             scanCond(tree.rhs);
1281             initsWhenTrue.andSet(initsWhenTrueLeft);
1282             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1283             break;
1284         default:
1285             scanExpr(tree.lhs);
1286             scanExpr(tree.rhs);
1287         }
1288     }
1289 
1290     public void visitAnnotatedType(JCAnnotatedType tree) {
1291         // annotations don't get scanned
1292         tree.underlyingType.accept(this);
1293     }
1294 
1295     public void visitIdent(JCIdent tree) {
1296         if (tree.sym.kind == VAR)
1297             checkInit(tree.pos(), (VarSymbol)tree.sym);
1298     }
1299 
1300     public void visitTypeCast(JCTypeCast tree) {
1301         super.visitTypeCast(tree);
1302         if (!tree.type.isErroneous()
1303             && lint.isEnabled(Lint.LintCategory.CAST)
1304             && types.isSameType(tree.expr.type, tree.clazz.type)
1305             && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1306             log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1307         }
1308     }
1309 
1310     public void visitTopLevel(JCCompilationUnit tree) {
1311         // Do nothing for TopLevel since each class is visited individually
1312     }
1313 
1314 /**************************************************************************
1315  * utility methods for ignoring type-annotated casts lint checking
1316  *************************************************************************/
1317     private static final boolean ignoreAnnotatedCasts = true;
1318     private static class AnnotationFinder extends TreeScanner {
1319         public boolean foundTypeAnno = false;
1320         public void visitAnnotation(JCAnnotation tree) {
1321             foundTypeAnno = foundTypeAnno || (tree instanceof JCTypeAnnotation);
1322         }
1323     }
1324 
1325     private boolean containsTypeAnnotation(JCTree e) {
1326         AnnotationFinder finder = new AnnotationFinder();
1327         finder.scan(e);
1328         return finder.foundTypeAnno;
1329     }
1330 
1331 /**************************************************************************
1332  * main method
1333  *************************************************************************/
1334 
1335     /** Perform definite assignment/unassignment analysis on a tree.
1336      */
1337     public void analyzeTree(JCTree tree, TreeMaker make) {
1338         try {
1339             this.make = make;
1340             inits = new Bits();
1341             uninits = new Bits();
1342             uninitsTry = new Bits();
1343             initsWhenTrue = initsWhenFalse =
1344                 uninitsWhenTrue = uninitsWhenFalse = null;
1345             if (vars == null)
1346                 vars = new VarSymbol[32];
1347             else
1348                 for (int i=0; i<vars.length; i++)
1349                     vars[i] = null;
1350             firstadr = 0;
1351             nextadr = 0;
1352             pendingExits = new ListBuffer<PendingExit>();
1353             multicatchTypes = new HashMap<Symbol, List<Type>>();
1354             alive = true;
1355             this.thrown = this.caught = null;
1356             this.classDef = null;
1357             scan(tree);
1358         } finally {
1359             // note that recursive invocations of this method fail hard
1360             inits = uninits = uninitsTry = null;
1361             initsWhenTrue = initsWhenFalse =
1362                 uninitsWhenTrue = uninitsWhenFalse = null;
1363             if (vars != null) for (int i=0; i<vars.length; i++)
1364                 vars[i] = null;
1365             firstadr = 0;
1366             nextadr = 0;
1367             pendingExits = null;
1368             this.make = null;
1369             this.thrown = this.caught = null;
1370             this.classDef = null;
1371         }
1372     }
1373 }