langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 12333 7b02d0529a97
parent 10950 e87b50888909
child 13273 d597bc5e3935
equal deleted inserted replaced
12215:25d9238c9b75 12333:7b02d0529a97
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    26 //todo: one might eliminate uninits.andSets when monotonic
    26 //todo: one might eliminate uninits.andSets when monotonic
    27 
    27 
    28 package com.sun.tools.javac.comp;
    28 package com.sun.tools.javac.comp;
    29 
    29 
    30 import java.util.HashMap;
    30 import java.util.HashMap;
    31 import java.util.Map;
       
    32 import java.util.LinkedHashMap;
       
    33 
    31 
    34 import com.sun.tools.javac.code.*;
    32 import com.sun.tools.javac.code.*;
    35 import com.sun.tools.javac.tree.*;
    33 import com.sun.tools.javac.tree.*;
    36 import com.sun.tools.javac.util.*;
    34 import com.sun.tools.javac.util.*;
    37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
   177  *  <p><b>This is NOT part of any supported API.
   175  *  <p><b>This is NOT part of any supported API.
   178  *  If you write code that depends on this, you do so at your own risk.
   176  *  If you write code that depends on this, you do so at your own risk.
   179  *  This code and its internal interfaces are subject to change or
   177  *  This code and its internal interfaces are subject to change or
   180  *  deletion without notice.</b>
   178  *  deletion without notice.</b>
   181  */
   179  */
   182 public class Flow extends TreeScanner {
   180 public class Flow {
   183     protected static final Context.Key<Flow> flowKey =
   181     protected static final Context.Key<Flow> flowKey =
   184         new Context.Key<Flow>();
   182         new Context.Key<Flow>();
   185 
   183 
   186     private final Names names;
   184     private final Names names;
   187     private final Log log;
   185     private final Log log;
   198     public static Flow instance(Context context) {
   196     public static Flow instance(Context context) {
   199         Flow instance = context.get(flowKey);
   197         Flow instance = context.get(flowKey);
   200         if (instance == null)
   198         if (instance == null)
   201             instance = new Flow(context);
   199             instance = new Flow(context);
   202         return instance;
   200         return instance;
       
   201     }
       
   202 
       
   203     public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
       
   204         new FlowAnalyzer().analyzeTree(env, make);
       
   205         new AssignAnalyzer().analyzeTree(env, make);
   203     }
   206     }
   204 
   207 
   205     protected Flow(Context context) {
   208     protected Flow(Context context) {
   206         context.put(flowKey, this);
   209         context.put(flowKey, this);
   207         names = Names.instance(context);
   210         names = Names.instance(context);
   214         Source source = Source.instance(context);
   217         Source source = Source.instance(context);
   215         allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
   218         allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
   216         allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
   219         allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
   217     }
   220     }
   218 
   221 
   219     /** A flag that indicates whether the last statement could
   222     /**
   220      *  complete normally.
   223      * Base visitor class for all visitors implementing dataflow analysis logic.
       
   224      * This class define the shared logic for handling jumps (break/continue statements).
   221      */
   225      */
   222     private boolean alive;
   226     static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
   223 
   227 
   224     /** The set of definitely assigned variables.
   228         enum JumpKind {
       
   229             BREAK(JCTree.Tag.BREAK) {
       
   230                 @Override
       
   231                 JCTree getTarget(JCTree tree) {
       
   232                     return ((JCBreak)tree).target;
       
   233                 }
       
   234             },
       
   235             CONTINUE(JCTree.Tag.CONTINUE) {
       
   236                 @Override
       
   237                 JCTree getTarget(JCTree tree) {
       
   238                     return ((JCContinue)tree).target;
       
   239                 }
       
   240             };
       
   241 
       
   242             JCTree.Tag treeTag;
       
   243 
       
   244             private JumpKind(Tag treeTag) {
       
   245                 this.treeTag = treeTag;
       
   246             }
       
   247 
       
   248             abstract JCTree getTarget(JCTree tree);
       
   249         }
       
   250 
       
   251         /** The currently pending exits that go from current inner blocks
       
   252          *  to an enclosing block, in source order.
       
   253          */
       
   254         ListBuffer<P> pendingExits;
       
   255 
       
   256         /** A pending exit.  These are the statements return, break, and
       
   257          *  continue.  In addition, exception-throwing expressions or
       
   258          *  statements are put here when not known to be caught.  This
       
   259          *  will typically result in an error unless it is within a
       
   260          *  try-finally whose finally block cannot complete normally.
       
   261          */
       
   262         abstract static class PendingExit {
       
   263             JCTree tree;
       
   264 
       
   265             PendingExit(JCTree tree) {
       
   266                 this.tree = tree;
       
   267             }
       
   268 
       
   269             abstract void resolveJump();
       
   270         }
       
   271 
       
   272         abstract void markDead();
       
   273 
       
   274         /** Record an outward transfer of control. */
       
   275         void recordExit(JCTree tree, P pe) {
       
   276             pendingExits.append(pe);
       
   277             markDead();
       
   278         }
       
   279 
       
   280         /** Resolve all jumps of this statement. */
       
   281         private boolean resolveJump(JCTree tree,
       
   282                         ListBuffer<P> oldPendingExits,
       
   283                         JumpKind jk) {
       
   284             boolean resolved = false;
       
   285             List<P> exits = pendingExits.toList();
       
   286             pendingExits = oldPendingExits;
       
   287             for (; exits.nonEmpty(); exits = exits.tail) {
       
   288                 P exit = exits.head;
       
   289                 if (exit.tree.hasTag(jk.treeTag) &&
       
   290                         jk.getTarget(exit.tree) == tree) {
       
   291                     exit.resolveJump();
       
   292                     resolved = true;
       
   293                 } else {
       
   294                     pendingExits.append(exit);
       
   295                 }
       
   296             }
       
   297             return resolved;
       
   298         }
       
   299 
       
   300         /** Resolve all breaks of this statement. */
       
   301         boolean resolveContinues(JCTree tree) {
       
   302             return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
       
   303         }
       
   304 
       
   305         /** Resolve all continues of this statement. */
       
   306         boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
       
   307             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
       
   308         }
       
   309     }
       
   310 
       
   311     /**
       
   312      * This pass implements the first two steps of the dataflow analysis:
       
   313      * (i) liveness analysis checks that every statement is reachable and (ii)
       
   314      *  exception analysis to ensure that every checked exception that is
       
   315      *  thrown is declared or caught.
   225      */
   316      */
   226     Bits inits;
   317     class FlowAnalyzer extends BaseAnalyzer<FlowAnalyzer.FlowPendingExit> {
   227 
   318 
   228     /** The set of definitely unassigned variables.
   319         /** A flag that indicates whether the last statement could
   229      */
   320          *  complete normally.
   230     Bits uninits;
   321          */
   231 
   322         private boolean alive;
   232     HashMap<Symbol, List<Type>> preciseRethrowTypes;
   323 
   233 
   324         HashMap<Symbol, List<Type>> preciseRethrowTypes;
   234     /** The set of variables that are definitely unassigned everywhere
   325 
   235      *  in current try block. This variable is maintained lazily; it is
   326         /** The current class being defined.
   236      *  updated only when something gets removed from uninits,
   327          */
   237      *  typically by being assigned in reachable code.  To obtain the
   328         JCClassDecl classDef;
   238      *  correct set of variables which are definitely unassigned
   329 
   239      *  anywhere in current try block, intersect uninitsTry and
   330         /** The list of possibly thrown declarable exceptions.
   240      *  uninits.
   331          */
   241      */
   332         List<Type> thrown;
   242     Bits uninitsTry;
   333 
   243 
   334         /** The list of exceptions that are either caught or declared to be
   244     /** When analyzing a condition, inits and uninits are null.
   335          *  thrown.
   245      *  Instead we have:
   336          */
   246      */
   337         List<Type> caught;
   247     Bits initsWhenTrue;
   338 
   248     Bits initsWhenFalse;
   339         class FlowPendingExit extends BaseAnalyzer.PendingExit {
   249     Bits uninitsWhenTrue;
   340 
   250     Bits uninitsWhenFalse;
   341             Type thrown;
   251 
   342 
   252     /** A mapping from addresses to variable symbols.
   343             FlowPendingExit(JCTree tree, Type thrown) {
   253      */
   344                 super(tree);
   254     VarSymbol[] vars;
   345                 this.thrown = thrown;
   255 
   346             }
   256     /** The current class being defined.
   347 
   257      */
   348             void resolveJump() { /*do nothing*/ }
   258     JCClassDecl classDef;
   349         }
   259 
   350 
   260     /** The first variable sequence number in this class definition.
   351         @Override
   261      */
   352         void markDead() {
   262     int firstadr;
   353             alive = false;
   263 
   354         }
   264     /** The next available variable sequence number.
   355 
   265      */
   356         /*-------------------- Exceptions ----------------------*/
   266     int nextadr;
   357 
   267 
   358         /** Complain that pending exceptions are not caught.
   268     /** The list of possibly thrown declarable exceptions.
   359          */
   269      */
   360         void errorUncaught() {
   270     List<Type> thrown;
   361             for (FlowPendingExit exit = pendingExits.next();
   271 
   362                  exit != null;
   272     /** The list of exceptions that are either caught or declared to be
   363                  exit = pendingExits.next()) {
   273      *  thrown.
   364                 if (classDef != null &&
   274      */
   365                     classDef.pos == exit.tree.pos) {
   275     List<Type> caught;
   366                     log.error(exit.tree.pos(),
   276 
   367                             "unreported.exception.default.constructor",
   277     /** The list of unreferenced automatic resources.
   368                             exit.thrown);
   278      */
   369                 } else if (exit.tree.hasTag(VARDEF) &&
   279     Scope unrefdResources;
   370                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
   280 
   371                     log.error(exit.tree.pos(),
   281     /** Set when processing a loop body the second time for DU analysis. */
   372                             "unreported.exception.implicit.close",
   282     boolean loopPassTwo = false;
   373                             exit.thrown,
   283 
   374                             ((JCVariableDecl)exit.tree).sym.name);
   284     /*-------------------- Environments ----------------------*/
       
   285 
       
   286     /** A pending exit.  These are the statements return, break, and
       
   287      *  continue.  In addition, exception-throwing expressions or
       
   288      *  statements are put here when not known to be caught.  This
       
   289      *  will typically result in an error unless it is within a
       
   290      *  try-finally whose finally block cannot complete normally.
       
   291      */
       
   292     static class PendingExit {
       
   293         JCTree tree;
       
   294         Bits inits;
       
   295         Bits uninits;
       
   296         Type thrown;
       
   297         PendingExit(JCTree tree, Bits inits, Bits uninits) {
       
   298             this.tree = tree;
       
   299             this.inits = inits.dup();
       
   300             this.uninits = uninits.dup();
       
   301         }
       
   302         PendingExit(JCTree tree, Type thrown) {
       
   303             this.tree = tree;
       
   304             this.thrown = thrown;
       
   305         }
       
   306     }
       
   307 
       
   308     /** The currently pending exits that go from current inner blocks
       
   309      *  to an enclosing block, in source order.
       
   310      */
       
   311     ListBuffer<PendingExit> pendingExits;
       
   312 
       
   313     /*-------------------- Exceptions ----------------------*/
       
   314 
       
   315     /** Complain that pending exceptions are not caught.
       
   316      */
       
   317     void errorUncaught() {
       
   318         for (PendingExit exit = pendingExits.next();
       
   319              exit != null;
       
   320              exit = pendingExits.next()) {
       
   321             if (classDef != null &&
       
   322                 classDef.pos == exit.tree.pos) {
       
   323                 log.error(exit.tree.pos(),
       
   324                         "unreported.exception.default.constructor",
       
   325                         exit.thrown);
       
   326             } else if (exit.tree.hasTag(VARDEF) &&
       
   327                     ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
       
   328                 log.error(exit.tree.pos(),
       
   329                         "unreported.exception.implicit.close",
       
   330                         exit.thrown,
       
   331                         ((JCVariableDecl)exit.tree).sym.name);
       
   332             } else {
       
   333                 log.error(exit.tree.pos(),
       
   334                         "unreported.exception.need.to.catch.or.throw",
       
   335                         exit.thrown);
       
   336             }
       
   337         }
       
   338     }
       
   339 
       
   340     /** Record that exception is potentially thrown and check that it
       
   341      *  is caught.
       
   342      */
       
   343     void markThrown(JCTree tree, Type exc) {
       
   344         if (!chk.isUnchecked(tree.pos(), exc)) {
       
   345             if (!chk.isHandled(exc, caught))
       
   346                 pendingExits.append(new PendingExit(tree, exc));
       
   347                 thrown = chk.incl(exc, thrown);
       
   348         }
       
   349     }
       
   350 
       
   351     /*-------------- Processing variables ----------------------*/
       
   352 
       
   353     /** Do we need to track init/uninit state of this symbol?
       
   354      *  I.e. is symbol either a local or a blank final variable?
       
   355      */
       
   356     boolean trackable(VarSymbol sym) {
       
   357         return
       
   358             (sym.owner.kind == MTH ||
       
   359              ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
       
   360               classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)));
       
   361     }
       
   362 
       
   363     /** Initialize new trackable variable by setting its address field
       
   364      *  to the next available sequence number and entering it under that
       
   365      *  index into the vars array.
       
   366      */
       
   367     void newVar(VarSymbol sym) {
       
   368         if (nextadr == vars.length) {
       
   369             VarSymbol[] newvars = new VarSymbol[nextadr * 2];
       
   370             System.arraycopy(vars, 0, newvars, 0, nextadr);
       
   371             vars = newvars;
       
   372         }
       
   373         sym.adr = nextadr;
       
   374         vars[nextadr] = sym;
       
   375         inits.excl(nextadr);
       
   376         uninits.incl(nextadr);
       
   377         nextadr++;
       
   378     }
       
   379 
       
   380     /** Record an initialization of a trackable variable.
       
   381      */
       
   382     void letInit(DiagnosticPosition pos, VarSymbol sym) {
       
   383         if (sym.adr >= firstadr && trackable(sym)) {
       
   384             if ((sym.flags() & FINAL) != 0) {
       
   385                 if ((sym.flags() & PARAMETER) != 0) {
       
   386                     if ((sym.flags() & UNION) != 0) { //multi-catch parameter
       
   387                         log.error(pos, "multicatch.parameter.may.not.be.assigned",
       
   388                                   sym);
       
   389                     }
       
   390                     else {
       
   391                         log.error(pos, "final.parameter.may.not.be.assigned",
       
   392                               sym);
       
   393                     }
       
   394                 } else if (!uninits.isMember(sym.adr)) {
       
   395                     log.error(pos,
       
   396                               loopPassTwo
       
   397                               ? "var.might.be.assigned.in.loop"
       
   398                               : "var.might.already.be.assigned",
       
   399                               sym);
       
   400                 } else if (!inits.isMember(sym.adr)) {
       
   401                     // reachable assignment
       
   402                     uninits.excl(sym.adr);
       
   403                     uninitsTry.excl(sym.adr);
       
   404                 } else {
   375                 } else {
   405                     //log.rawWarning(pos, "unreachable assignment");//DEBUG
   376                     log.error(exit.tree.pos(),
   406                     uninits.excl(sym.adr);
   377                             "unreported.exception.need.to.catch.or.throw",
   407                 }
   378                             exit.thrown);
   408             }
   379                 }
   409             inits.incl(sym.adr);
   380             }
   410         } else if ((sym.flags() & FINAL) != 0) {
   381         }
   411             log.error(pos, "var.might.already.be.assigned", sym);
   382 
   412         }
   383         /** Record that exception is potentially thrown and check that it
   413     }
   384          *  is caught.
   414 
   385          */
   415     /** If tree is either a simple name or of the form this.name or
   386         void markThrown(JCTree tree, Type exc) {
   416      *  C.this.name, and tree represents a trackable variable,
   387             if (!chk.isUnchecked(tree.pos(), exc)) {
   417      *  record an initialization of the variable.
   388                 if (!chk.isHandled(exc, caught))
   418      */
   389                     pendingExits.append(new FlowPendingExit(tree, exc));
   419     void letInit(JCTree tree) {
   390                     thrown = chk.incl(exc, thrown);
   420         tree = TreeInfo.skipParens(tree);
   391             }
   421         if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
   392         }
   422             Symbol sym = TreeInfo.symbol(tree);
   393 
   423             if (sym.kind == VAR) {
   394     /*************************************************************************
   424                 letInit(tree.pos(), (VarSymbol)sym);
   395      * Visitor methods for statements and definitions
   425             }
   396      *************************************************************************/
   426         }
   397 
   427     }
   398         /** Analyze a definition.
   428 
   399          */
   429     /** Check that trackable variable is initialized.
   400         void scanDef(JCTree tree) {
   430      */
   401             scanStat(tree);
   431     void checkInit(DiagnosticPosition pos, VarSymbol sym) {
   402             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
   432         if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
   403                 log.error(tree.pos(),
   433             trackable(sym) &&
   404                           "initializer.must.be.able.to.complete.normally");
   434             !inits.isMember(sym.adr)) {
   405             }
   435             log.error(pos, "var.might.not.have.been.initialized",
   406         }
   436                       sym);
   407 
   437             inits.incl(sym.adr);
   408         /** Analyze a statement. Check that statement is reachable.
   438         }
   409          */
   439     }
   410         void scanStat(JCTree tree) {
   440 
   411             if (!alive && tree != null) {
   441     /*-------------------- Handling jumps ----------------------*/
   412                 log.error(tree.pos(), "unreachable.stmt");
   442 
   413                 if (!tree.hasTag(SKIP)) alive = true;
   443     /** Record an outward transfer of control. */
   414             }
   444     void recordExit(JCTree tree) {
       
   445         pendingExits.append(new PendingExit(tree, inits, uninits));
       
   446         markDead();
       
   447     }
       
   448 
       
   449     /** Resolve all breaks of this statement. */
       
   450     boolean resolveBreaks(JCTree tree,
       
   451                           ListBuffer<PendingExit> oldPendingExits) {
       
   452         boolean result = false;
       
   453         List<PendingExit> exits = pendingExits.toList();
       
   454         pendingExits = oldPendingExits;
       
   455         for (; exits.nonEmpty(); exits = exits.tail) {
       
   456             PendingExit exit = exits.head;
       
   457             if (exit.tree.hasTag(BREAK) &&
       
   458                 ((JCBreak) exit.tree).target == tree) {
       
   459                 inits.andSet(exit.inits);
       
   460                 uninits.andSet(exit.uninits);
       
   461                 result = true;
       
   462             } else {
       
   463                 pendingExits.append(exit);
       
   464             }
       
   465         }
       
   466         return result;
       
   467     }
       
   468 
       
   469     /** Resolve all continues of this statement. */
       
   470     boolean resolveContinues(JCTree tree) {
       
   471         boolean result = false;
       
   472         List<PendingExit> exits = pendingExits.toList();
       
   473         pendingExits = new ListBuffer<PendingExit>();
       
   474         for (; exits.nonEmpty(); exits = exits.tail) {
       
   475             PendingExit exit = exits.head;
       
   476             if (exit.tree.hasTag(CONTINUE) &&
       
   477                 ((JCContinue) exit.tree).target == tree) {
       
   478                 inits.andSet(exit.inits);
       
   479                 uninits.andSet(exit.uninits);
       
   480                 result = true;
       
   481             } else {
       
   482                 pendingExits.append(exit);
       
   483             }
       
   484         }
       
   485         return result;
       
   486     }
       
   487 
       
   488     /** Record that statement is unreachable.
       
   489      */
       
   490     void markDead() {
       
   491         inits.inclRange(firstadr, nextadr);
       
   492         uninits.inclRange(firstadr, nextadr);
       
   493         alive = false;
       
   494     }
       
   495 
       
   496     /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
       
   497      */
       
   498     void split(boolean setToNull) {
       
   499         initsWhenFalse = inits.dup();
       
   500         uninitsWhenFalse = uninits.dup();
       
   501         initsWhenTrue = inits;
       
   502         uninitsWhenTrue = uninits;
       
   503         if (setToNull)
       
   504             inits = uninits = null;
       
   505     }
       
   506 
       
   507     /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
       
   508      */
       
   509     void merge() {
       
   510         inits = initsWhenFalse.andSet(initsWhenTrue);
       
   511         uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
       
   512     }
       
   513 
       
   514 /* ************************************************************************
       
   515  * Visitor methods for statements and definitions
       
   516  *************************************************************************/
       
   517 
       
   518     /** Analyze a definition.
       
   519      */
       
   520     void scanDef(JCTree tree) {
       
   521         scanStat(tree);
       
   522         if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
       
   523             log.error(tree.pos(),
       
   524                       "initializer.must.be.able.to.complete.normally");
       
   525         }
       
   526     }
       
   527 
       
   528     /** Analyze a statement. Check that statement is reachable.
       
   529      */
       
   530     void scanStat(JCTree tree) {
       
   531         if (!alive && tree != null) {
       
   532             log.error(tree.pos(), "unreachable.stmt");
       
   533             if (!tree.hasTag(SKIP)) alive = true;
       
   534         }
       
   535         scan(tree);
       
   536     }
       
   537 
       
   538     /** Analyze list of statements.
       
   539      */
       
   540     void scanStats(List<? extends JCStatement> trees) {
       
   541         if (trees != null)
       
   542             for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
       
   543                 scanStat(l.head);
       
   544     }
       
   545 
       
   546     /** Analyze an expression. Make sure to set (un)inits rather than
       
   547      *  (un)initsWhenTrue(WhenFalse) on exit.
       
   548      */
       
   549     void scanExpr(JCTree tree) {
       
   550         if (tree != null) {
       
   551             scan(tree);
   415             scan(tree);
   552             if (inits == null) merge();
   416         }
   553         }
   417 
   554     }
   418         /** Analyze list of statements.
   555 
   419          */
   556     /** Analyze a list of expressions.
   420         void scanStats(List<? extends JCStatement> trees) {
   557      */
   421             if (trees != null)
   558     void scanExprs(List<? extends JCExpression> trees) {
   422                 for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
   559         if (trees != null)
   423                     scanStat(l.head);
   560             for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
   424         }
   561                 scanExpr(l.head);
   425 
   562     }
   426         /* ------------ Visitor methods for various sorts of trees -------------*/
   563 
   427 
   564     /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
   428         public void visitClassDef(JCClassDecl tree) {
   565      *  rather than (un)inits on exit.
   429             if (tree.sym == null) return;
   566      */
   430 
   567     void scanCond(JCTree tree) {
   431             JCClassDecl classDefPrev = classDef;
   568         if (tree.type.isFalse()) {
   432             List<Type> thrownPrev = thrown;
   569             if (inits == null) merge();
   433             List<Type> caughtPrev = caught;
   570             initsWhenTrue = inits.dup();
   434             boolean alivePrev = alive;
   571             initsWhenTrue.inclRange(firstadr, nextadr);
   435             ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
   572             uninitsWhenTrue = uninits.dup();
   436             Lint lintPrev = lint;
   573             uninitsWhenTrue.inclRange(firstadr, nextadr);
   437 
   574             initsWhenFalse = inits;
   438             pendingExits = new ListBuffer<FlowPendingExit>();
   575             uninitsWhenFalse = uninits;
       
   576         } else if (tree.type.isTrue()) {
       
   577             if (inits == null) merge();
       
   578             initsWhenFalse = inits.dup();
       
   579             initsWhenFalse.inclRange(firstadr, nextadr);
       
   580             uninitsWhenFalse = uninits.dup();
       
   581             uninitsWhenFalse.inclRange(firstadr, nextadr);
       
   582             initsWhenTrue = inits;
       
   583             uninitsWhenTrue = uninits;
       
   584         } else {
       
   585             scan(tree);
       
   586             if (inits != null)
       
   587                 split(tree.type != syms.unknownType);
       
   588         }
       
   589         if (tree.type != syms.unknownType)
       
   590             inits = uninits = null;
       
   591     }
       
   592 
       
   593     /* ------------ Visitor methods for various sorts of trees -------------*/
       
   594 
       
   595     public void visitClassDef(JCClassDecl tree) {
       
   596         if (tree.sym == null) return;
       
   597 
       
   598         JCClassDecl classDefPrev = classDef;
       
   599         List<Type> thrownPrev = thrown;
       
   600         List<Type> caughtPrev = caught;
       
   601         boolean alivePrev = alive;
       
   602         int firstadrPrev = firstadr;
       
   603         int nextadrPrev = nextadr;
       
   604         ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
       
   605         Lint lintPrev = lint;
       
   606 
       
   607         pendingExits = new ListBuffer<PendingExit>();
       
   608         if (tree.name != names.empty) {
       
   609             caught = List.nil();
       
   610             firstadr = nextadr;
       
   611         }
       
   612         classDef = tree;
       
   613         thrown = List.nil();
       
   614         lint = lint.augment(tree.sym.attributes_field);
       
   615 
       
   616         try {
       
   617             // define all the static fields
       
   618             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
   619                 if (l.head.hasTag(VARDEF)) {
       
   620                     JCVariableDecl def = (JCVariableDecl)l.head;
       
   621                     if ((def.mods.flags & STATIC) != 0) {
       
   622                         VarSymbol sym = def.sym;
       
   623                         if (trackable(sym))
       
   624                             newVar(sym);
       
   625                     }
       
   626                 }
       
   627             }
       
   628 
       
   629             // process all the static initializers
       
   630             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
   631                 if (!l.head.hasTag(METHODDEF) &&
       
   632                     (TreeInfo.flags(l.head) & STATIC) != 0) {
       
   633                     scanDef(l.head);
       
   634                     errorUncaught();
       
   635                 }
       
   636             }
       
   637 
       
   638             // add intersection of all thrown clauses of initial constructors
       
   639             // to set of caught exceptions, unless class is anonymous.
       
   640             if (tree.name != names.empty) {
   439             if (tree.name != names.empty) {
   641                 boolean firstConstructor = true;
   440                 caught = List.nil();
       
   441             }
       
   442             classDef = tree;
       
   443             thrown = List.nil();
       
   444             lint = lint.augment(tree.sym.attributes_field);
       
   445 
       
   446             try {
       
   447                 // process all the static initializers
   642                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   448                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   643                     if (TreeInfo.isInitialConstructor(l.head)) {
   449                     if (!l.head.hasTag(METHODDEF) &&
   644                         List<Type> mthrown =
   450                         (TreeInfo.flags(l.head) & STATIC) != 0) {
   645                             ((JCMethodDecl) l.head).sym.type.getThrownTypes();
   451                         scanDef(l.head);
   646                         if (firstConstructor) {
   452                         errorUncaught();
   647                             caught = mthrown;
   453                     }
   648                             firstConstructor = false;
   454                 }
   649                         } else {
   455 
   650                             caught = chk.intersect(mthrown, caught);
   456                 // add intersection of all thrown clauses of initial constructors
       
   457                 // to set of caught exceptions, unless class is anonymous.
       
   458                 if (tree.name != names.empty) {
       
   459                     boolean firstConstructor = true;
       
   460                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
   461                         if (TreeInfo.isInitialConstructor(l.head)) {
       
   462                             List<Type> mthrown =
       
   463                                 ((JCMethodDecl) l.head).sym.type.getThrownTypes();
       
   464                             if (firstConstructor) {
       
   465                                 caught = mthrown;
       
   466                                 firstConstructor = false;
       
   467                             } else {
       
   468                                 caught = chk.intersect(mthrown, caught);
       
   469                             }
   651                         }
   470                         }
   652                     }
   471                     }
   653                 }
   472                 }
   654             }
   473 
   655 
   474                 // process all the instance initializers
   656             // define all the instance fields
       
   657             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
   658                 if (l.head.hasTag(VARDEF)) {
       
   659                     JCVariableDecl def = (JCVariableDecl)l.head;
       
   660                     if ((def.mods.flags & STATIC) == 0) {
       
   661                         VarSymbol sym = def.sym;
       
   662                         if (trackable(sym))
       
   663                             newVar(sym);
       
   664                     }
       
   665                 }
       
   666             }
       
   667 
       
   668             // process all the instance initializers
       
   669             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
   670                 if (!l.head.hasTag(METHODDEF) &&
       
   671                     (TreeInfo.flags(l.head) & STATIC) == 0) {
       
   672                     scanDef(l.head);
       
   673                     errorUncaught();
       
   674                 }
       
   675             }
       
   676 
       
   677             // in an anonymous class, add the set of thrown exceptions to
       
   678             // the throws clause of the synthetic constructor and propagate
       
   679             // outwards.
       
   680             // Changing the throws clause on the fly is okay here because
       
   681             // the anonymous constructor can't be invoked anywhere else,
       
   682             // and its type hasn't been cached.
       
   683             if (tree.name == names.empty) {
       
   684                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   475                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   685                     if (TreeInfo.isInitialConstructor(l.head)) {
   476                     if (!l.head.hasTag(METHODDEF) &&
   686                         JCMethodDecl mdef = (JCMethodDecl)l.head;
   477                         (TreeInfo.flags(l.head) & STATIC) == 0) {
   687                         mdef.thrown = make.Types(thrown);
   478                         scanDef(l.head);
   688                         mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
   479                         errorUncaught();
   689                     }
   480                     }
   690                 }
   481                 }
   691                 thrownPrev = chk.union(thrown, thrownPrev);
   482 
   692             }
   483                 // in an anonymous class, add the set of thrown exceptions to
   693 
   484                 // the throws clause of the synthetic constructor and propagate
   694             // process all the methods
   485                 // outwards.
   695             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   486                 // Changing the throws clause on the fly is okay here because
   696                 if (l.head.hasTag(METHODDEF)) {
   487                 // the anonymous constructor can't be invoked anywhere else,
   697                     scan(l.head);
   488                 // and its type hasn't been cached.
   698                     errorUncaught();
   489                 if (tree.name == names.empty) {
   699                 }
   490                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   700             }
   491                         if (TreeInfo.isInitialConstructor(l.head)) {
   701 
   492                             JCMethodDecl mdef = (JCMethodDecl)l.head;
   702             thrown = thrownPrev;
   493                             mdef.thrown = make.Types(thrown);
   703         } finally {
   494                             mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
   704             pendingExits = pendingExitsPrev;
   495                         }
   705             alive = alivePrev;
   496                     }
   706             nextadr = nextadrPrev;
   497                     thrownPrev = chk.union(thrown, thrownPrev);
   707             firstadr = firstadrPrev;
   498                 }
   708             caught = caughtPrev;
   499 
   709             classDef = classDefPrev;
   500                 // process all the methods
   710             lint = lintPrev;
   501                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   711         }
   502                     if (l.head.hasTag(METHODDEF)) {
   712     }
   503                         scan(l.head);
   713 
   504                         errorUncaught();
   714     public void visitMethodDef(JCMethodDecl tree) {
   505                     }
   715         if (tree.body == null) return;
   506                 }
   716 
   507 
   717         List<Type> caughtPrev = caught;
   508                 thrown = thrownPrev;
   718         List<Type> mthrown = tree.sym.type.getThrownTypes();
   509             } finally {
   719         Bits initsPrev = inits.dup();
   510                 pendingExits = pendingExitsPrev;
   720         Bits uninitsPrev = uninits.dup();
   511                 alive = alivePrev;
   721         int nextadrPrev = nextadr;
   512                 caught = caughtPrev;
   722         int firstadrPrev = firstadr;
   513                 classDef = classDefPrev;
   723         Lint lintPrev = lint;
   514                 lint = lintPrev;
   724 
   515             }
   725         lint = lint.augment(tree.sym.attributes_field);
   516         }
   726 
   517 
   727         Assert.check(pendingExits.isEmpty());
   518         public void visitMethodDef(JCMethodDecl tree) {
   728 
   519             if (tree.body == null) return;
   729         try {
   520 
   730             boolean isInitialConstructor =
   521             List<Type> caughtPrev = caught;
   731                 TreeInfo.isInitialConstructor(tree);
   522             List<Type> mthrown = tree.sym.type.getThrownTypes();
   732 
       
   733             if (!isInitialConstructor)
       
   734                 firstadr = nextadr;
       
   735             for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
       
   736                 JCVariableDecl def = l.head;
       
   737                 scan(def);
       
   738                 inits.incl(def.sym.adr);
       
   739                 uninits.excl(def.sym.adr);
       
   740             }
       
   741             if (isInitialConstructor)
       
   742                 caught = chk.union(caught, mthrown);
       
   743             else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
       
   744                 caught = mthrown;
       
   745             // else we are in an instance initializer block;
       
   746             // leave caught unchanged.
       
   747 
       
   748             alive = true;
       
   749             scanStat(tree.body);
       
   750 
       
   751             if (alive && tree.sym.type.getReturnType().tag != VOID)
       
   752                 log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
       
   753 
       
   754             if (isInitialConstructor) {
       
   755                 for (int i = firstadr; i < nextadr; i++)
       
   756                     if (vars[i].owner == classDef.sym)
       
   757                         checkInit(TreeInfo.diagEndPos(tree.body), vars[i]);
       
   758             }
       
   759             List<PendingExit> exits = pendingExits.toList();
       
   760             pendingExits = new ListBuffer<PendingExit>();
       
   761             while (exits.nonEmpty()) {
       
   762                 PendingExit exit = exits.head;
       
   763                 exits = exits.tail;
       
   764                 if (exit.thrown == null) {
       
   765                     Assert.check(exit.tree.hasTag(RETURN));
       
   766                     if (isInitialConstructor) {
       
   767                         inits = exit.inits;
       
   768                         for (int i = firstadr; i < nextadr; i++)
       
   769                             checkInit(exit.tree.pos(), vars[i]);
       
   770                     }
       
   771                 } else {
       
   772                     // uncaught throws will be reported later
       
   773                     pendingExits.append(exit);
       
   774                 }
       
   775             }
       
   776         } finally {
       
   777             inits = initsPrev;
       
   778             uninits = uninitsPrev;
       
   779             nextadr = nextadrPrev;
       
   780             firstadr = firstadrPrev;
       
   781             caught = caughtPrev;
       
   782             lint = lintPrev;
       
   783         }
       
   784     }
       
   785 
       
   786     public void visitVarDef(JCVariableDecl tree) {
       
   787         boolean track = trackable(tree.sym);
       
   788         if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
       
   789         if (tree.init != null) {
       
   790             Lint lintPrev = lint;
   523             Lint lintPrev = lint;
       
   524 
   791             lint = lint.augment(tree.sym.attributes_field);
   525             lint = lint.augment(tree.sym.attributes_field);
   792             try{
   526 
   793                 scanExpr(tree.init);
   527             Assert.check(pendingExits.isEmpty());
   794                 if (track) letInit(tree.pos(), tree.sym);
   528 
       
   529             try {
       
   530                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
       
   531                     JCVariableDecl def = l.head;
       
   532                     scan(def);
       
   533                 }
       
   534                 if (TreeInfo.isInitialConstructor(tree))
       
   535                     caught = chk.union(caught, mthrown);
       
   536                 else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
       
   537                     caught = mthrown;
       
   538                 // else we are in an instance initializer block;
       
   539                 // leave caught unchanged.
       
   540 
       
   541                 alive = true;
       
   542                 scanStat(tree.body);
       
   543 
       
   544                 if (alive && tree.sym.type.getReturnType().tag != VOID)
       
   545                     log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
       
   546 
       
   547                 List<FlowPendingExit> exits = pendingExits.toList();
       
   548                 pendingExits = new ListBuffer<FlowPendingExit>();
       
   549                 while (exits.nonEmpty()) {
       
   550                     FlowPendingExit exit = exits.head;
       
   551                     exits = exits.tail;
       
   552                     if (exit.thrown == null) {
       
   553                         Assert.check(exit.tree.hasTag(RETURN));
       
   554                     } else {
       
   555                         // uncaught throws will be reported later
       
   556                         pendingExits.append(exit);
       
   557                     }
       
   558                 }
   795             } finally {
   559             } finally {
       
   560                 caught = caughtPrev;
   796                 lint = lintPrev;
   561                 lint = lintPrev;
   797             }
   562             }
   798         }
   563         }
   799     }
   564 
   800 
   565         public void visitVarDef(JCVariableDecl tree) {
   801     public void visitBlock(JCBlock tree) {
   566             if (tree.init != null) {
   802         int nextadrPrev = nextadr;
   567                 Lint lintPrev = lint;
   803         scanStats(tree.stats);
   568                 lint = lint.augment(tree.sym.attributes_field);
   804         nextadr = nextadrPrev;
   569                 try{
   805     }
   570                     scan(tree.init);
   806 
   571                 } finally {
   807     public void visitDoLoop(JCDoWhileLoop tree) {
   572                     lint = lintPrev;
   808         ListBuffer<PendingExit> prevPendingExits = pendingExits;
   573                 }
   809         boolean prevLoopPassTwo = loopPassTwo;
   574             }
   810         pendingExits = new ListBuffer<PendingExit>();
   575         }
   811         int prevErrors = log.nerrors;
   576 
   812         do {
   577         public void visitBlock(JCBlock tree) {
   813             Bits uninitsEntry = uninits.dup();
   578             scanStats(tree.stats);
   814             uninitsEntry.excludeFrom(nextadr);
   579         }
       
   580 
       
   581         public void visitDoLoop(JCDoWhileLoop tree) {
       
   582             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
       
   583             pendingExits = new ListBuffer<FlowPendingExit>();
   815             scanStat(tree.body);
   584             scanStat(tree.body);
   816             alive |= resolveContinues(tree);
   585             alive |= resolveContinues(tree);
   817             scanCond(tree.cond);
   586             scan(tree.cond);
   818             if (log.nerrors !=  prevErrors ||
   587             alive = alive && !tree.cond.type.isTrue();
   819                 loopPassTwo ||
   588             alive |= resolveBreaks(tree, prevPendingExits);
   820                 uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
   589         }
   821                 break;
   590 
   822             inits = initsWhenTrue;
   591         public void visitWhileLoop(JCWhileLoop tree) {
   823             uninits = uninitsEntry.andSet(uninitsWhenTrue);
   592             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
   824             loopPassTwo = true;
   593             pendingExits = new ListBuffer<FlowPendingExit>();
   825             alive = true;
   594             scan(tree.cond);
   826         } while (true);
       
   827         loopPassTwo = prevLoopPassTwo;
       
   828         inits = initsWhenFalse;
       
   829         uninits = uninitsWhenFalse;
       
   830         alive = alive && !tree.cond.type.isTrue();
       
   831         alive |= resolveBreaks(tree, prevPendingExits);
       
   832     }
       
   833 
       
   834     public void visitWhileLoop(JCWhileLoop tree) {
       
   835         ListBuffer<PendingExit> prevPendingExits = pendingExits;
       
   836         boolean prevLoopPassTwo = loopPassTwo;
       
   837         Bits initsCond;
       
   838         Bits uninitsCond;
       
   839         pendingExits = new ListBuffer<PendingExit>();
       
   840         int prevErrors = log.nerrors;
       
   841         do {
       
   842             Bits uninitsEntry = uninits.dup();
       
   843             uninitsEntry.excludeFrom(nextadr);
       
   844             scanCond(tree.cond);
       
   845             initsCond = initsWhenFalse;
       
   846             uninitsCond = uninitsWhenFalse;
       
   847             inits = initsWhenTrue;
       
   848             uninits = uninitsWhenTrue;
       
   849             alive = !tree.cond.type.isFalse();
   595             alive = !tree.cond.type.isFalse();
   850             scanStat(tree.body);
   596             scanStat(tree.body);
   851             alive |= resolveContinues(tree);
   597             alive |= resolveContinues(tree);
   852             if (log.nerrors != prevErrors ||
   598             alive = resolveBreaks(tree, prevPendingExits) ||
   853                 loopPassTwo ||
   599                 !tree.cond.type.isTrue();
   854                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
   600         }
   855                 break;
   601 
   856             uninits = uninitsEntry.andSet(uninits);
   602         public void visitForLoop(JCForLoop tree) {
   857             loopPassTwo = true;
   603             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
       
   604             scanStats(tree.init);
       
   605             pendingExits = new ListBuffer<FlowPendingExit>();
       
   606             if (tree.cond != null) {
       
   607                 scan(tree.cond);
       
   608                 alive = !tree.cond.type.isFalse();
       
   609             } else {
       
   610                 alive = true;
       
   611             }
       
   612             scanStat(tree.body);
       
   613             alive |= resolveContinues(tree);
       
   614             scan(tree.step);
       
   615             alive = resolveBreaks(tree, prevPendingExits) ||
       
   616                 tree.cond != null && !tree.cond.type.isTrue();
       
   617         }
       
   618 
       
   619         public void visitForeachLoop(JCEnhancedForLoop tree) {
       
   620             visitVarDef(tree.var);
       
   621             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
       
   622             scan(tree.expr);
       
   623             pendingExits = new ListBuffer<FlowPendingExit>();
       
   624             scanStat(tree.body);
       
   625             alive |= resolveContinues(tree);
       
   626             resolveBreaks(tree, prevPendingExits);
   858             alive = true;
   627             alive = true;
   859         } while (true);
   628         }
   860         loopPassTwo = prevLoopPassTwo;
   629 
   861         inits = initsCond;
   630         public void visitLabelled(JCLabeledStatement tree) {
   862         uninits = uninitsCond;
   631             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
   863         alive = resolveBreaks(tree, prevPendingExits) ||
   632             pendingExits = new ListBuffer<FlowPendingExit>();
   864             !tree.cond.type.isTrue();
   633             scanStat(tree.body);
       
   634             alive |= resolveBreaks(tree, prevPendingExits);
       
   635         }
       
   636 
       
   637         public void visitSwitch(JCSwitch tree) {
       
   638             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
       
   639             pendingExits = new ListBuffer<FlowPendingExit>();
       
   640             scan(tree.selector);
       
   641             boolean hasDefault = false;
       
   642             for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
       
   643                 alive = true;
       
   644                 JCCase c = l.head;
       
   645                 if (c.pat == null)
       
   646                     hasDefault = true;
       
   647                 else
       
   648                     scan(c.pat);
       
   649                 scanStats(c.stats);
       
   650                 // Warn about fall-through if lint switch fallthrough enabled.
       
   651                 if (alive &&
       
   652                     lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
       
   653                     c.stats.nonEmpty() && l.tail.nonEmpty())
       
   654                     log.warning(Lint.LintCategory.FALLTHROUGH,
       
   655                                 l.tail.head.pos(),
       
   656                                 "possible.fall-through.into.case");
       
   657             }
       
   658             if (!hasDefault) {
       
   659                 alive = true;
       
   660             }
       
   661             alive |= resolveBreaks(tree, prevPendingExits);
       
   662         }
       
   663 
       
   664         public void visitTry(JCTry tree) {
       
   665             List<Type> caughtPrev = caught;
       
   666             List<Type> thrownPrev = thrown;
       
   667             thrown = List.nil();
       
   668             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
       
   669                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
       
   670                         ((JCTypeUnion)l.head.param.vartype).alternatives :
       
   671                         List.of(l.head.param.vartype);
       
   672                 for (JCExpression ct : subClauses) {
       
   673                     caught = chk.incl(ct.type, caught);
       
   674                 }
       
   675             }
       
   676 
       
   677             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
       
   678             pendingExits = new ListBuffer<FlowPendingExit>();
       
   679             for (JCTree resource : tree.resources) {
       
   680                 if (resource instanceof JCVariableDecl) {
       
   681                     JCVariableDecl vdecl = (JCVariableDecl) resource;
       
   682                     visitVarDef(vdecl);
       
   683                 } else if (resource instanceof JCExpression) {
       
   684                     scan((JCExpression) resource);
       
   685                 } else {
       
   686                     throw new AssertionError(tree);  // parser error
       
   687                 }
       
   688             }
       
   689             for (JCTree resource : tree.resources) {
       
   690                 List<Type> closeableSupertypes = resource.type.isCompound() ?
       
   691                     types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
       
   692                     List.of(resource.type);
       
   693                 for (Type sup : closeableSupertypes) {
       
   694                     if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
       
   695                         Symbol closeMethod = rs.resolveQualifiedMethod(tree,
       
   696                                 attrEnv,
       
   697                                 sup,
       
   698                                 names.close,
       
   699                                 List.<Type>nil(),
       
   700                                 List.<Type>nil());
       
   701                         if (closeMethod.kind == MTH) {
       
   702                             for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) {
       
   703                                 markThrown(resource, t);
       
   704                             }
       
   705                         }
       
   706                     }
       
   707                 }
       
   708             }
       
   709             scanStat(tree.body);
       
   710             List<Type> thrownInTry = allowImprovedCatchAnalysis ?
       
   711                 chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
       
   712                 thrown;
       
   713             thrown = thrownPrev;
       
   714             caught = caughtPrev;
       
   715             boolean aliveEnd = alive;
       
   716 
       
   717             List<Type> caughtInTry = List.nil();
       
   718             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
       
   719                 alive = true;
       
   720                 JCVariableDecl param = l.head.param;
       
   721                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
       
   722                         ((JCTypeUnion)l.head.param.vartype).alternatives :
       
   723                         List.of(l.head.param.vartype);
       
   724                 List<Type> ctypes = List.nil();
       
   725                 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
       
   726                 for (JCExpression ct : subClauses) {
       
   727                     Type exc = ct.type;
       
   728                     if (exc != syms.unknownType) {
       
   729                         ctypes = ctypes.append(exc);
       
   730                         if (types.isSameType(exc, syms.objectType))
       
   731                             continue;
       
   732                         checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
       
   733                         caughtInTry = chk.incl(exc, caughtInTry);
       
   734                     }
       
   735                 }
       
   736                 scan(param);
       
   737                 preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
       
   738                 scanStat(l.head.body);
       
   739                 preciseRethrowTypes.remove(param.sym);
       
   740                 aliveEnd |= alive;
       
   741             }
       
   742             if (tree.finalizer != null) {
       
   743                 List<Type> savedThrown = thrown;
       
   744                 thrown = List.nil();
       
   745                 ListBuffer<FlowPendingExit> exits = pendingExits;
       
   746                 pendingExits = prevPendingExits;
       
   747                 alive = true;
       
   748                 scanStat(tree.finalizer);
       
   749                 if (!alive) {
       
   750                     // discard exits and exceptions from try and finally
       
   751                     thrown = chk.union(thrown, thrownPrev);
       
   752                     if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
       
   753                         log.warning(Lint.LintCategory.FINALLY,
       
   754                                 TreeInfo.diagEndPos(tree.finalizer),
       
   755                                 "finally.cannot.complete");
       
   756                     }
       
   757                 } else {
       
   758                     thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
       
   759                     thrown = chk.union(thrown, savedThrown);
       
   760                     // FIX: this doesn't preserve source order of exits in catch
       
   761                     // versus finally!
       
   762                     while (exits.nonEmpty()) {
       
   763                         pendingExits.append(exits.next());
       
   764                     }
       
   765                     alive = aliveEnd;
       
   766                 }
       
   767                 tree.finallyCanCompleteNormally = alive;
       
   768             } else {
       
   769                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
       
   770                 alive = aliveEnd;
       
   771                 ListBuffer<FlowPendingExit> exits = pendingExits;
       
   772                 pendingExits = prevPendingExits;
       
   773                 while (exits.nonEmpty()) pendingExits.append(exits.next());
       
   774             }
       
   775         }
       
   776 
       
   777         @Override
       
   778         public void visitIf(JCIf tree) {
       
   779             scan(tree.cond);
       
   780             scanStat(tree.thenpart);
       
   781             if (tree.elsepart != null) {
       
   782                 boolean aliveAfterThen = alive;
       
   783                 alive = true;
       
   784                 scanStat(tree.elsepart);
       
   785                 alive = alive | aliveAfterThen;
       
   786             } else {
       
   787                 alive = true;
       
   788             }
       
   789         }
       
   790 
       
   791         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
       
   792             if (chk.subset(exc, caughtInTry)) {
       
   793                 log.error(pos, "except.already.caught", exc);
       
   794             } else if (!chk.isUnchecked(pos, exc) &&
       
   795                     !isExceptionOrThrowable(exc) &&
       
   796                     !chk.intersects(exc, thrownInTry)) {
       
   797                 log.error(pos, "except.never.thrown.in.try", exc);
       
   798             } else if (allowImprovedCatchAnalysis) {
       
   799                 List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
       
   800                 // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
       
   801                 // unchecked exception, the result list would not be empty, as the augmented
       
   802                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
       
   803                 // exception, that would have been covered in the branch above
       
   804                 if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
       
   805                         !isExceptionOrThrowable(exc)) {
       
   806                     String key = catchableThrownTypes.length() == 1 ?
       
   807                             "unreachable.catch" :
       
   808                             "unreachable.catch.1";
       
   809                     log.warning(pos, key, catchableThrownTypes);
       
   810                 }
       
   811             }
       
   812         }
       
   813         //where
       
   814             private boolean isExceptionOrThrowable(Type exc) {
       
   815                 return exc.tsym == syms.throwableType.tsym ||
       
   816                     exc.tsym == syms.exceptionType.tsym;
       
   817             }
       
   818 
       
   819         public void visitBreak(JCBreak tree) {
       
   820             recordExit(tree, new FlowPendingExit(tree, null));
       
   821         }
       
   822 
       
   823         public void visitContinue(JCContinue tree) {
       
   824             recordExit(tree, new FlowPendingExit(tree, null));
       
   825         }
       
   826 
       
   827         public void visitReturn(JCReturn tree) {
       
   828             scan(tree.expr);
       
   829             // if not initial constructor, should markDead instead of recordExit
       
   830             recordExit(tree, new FlowPendingExit(tree, null));
       
   831         }
       
   832 
       
   833         public void visitThrow(JCThrow tree) {
       
   834             scan(tree.expr);
       
   835             Symbol sym = TreeInfo.symbol(tree.expr);
       
   836             if (sym != null &&
       
   837                 sym.kind == VAR &&
       
   838                 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
       
   839                 preciseRethrowTypes.get(sym) != null &&
       
   840                 allowImprovedRethrowAnalysis) {
       
   841                 for (Type t : preciseRethrowTypes.get(sym)) {
       
   842                     markThrown(tree, t);
       
   843                 }
       
   844             }
       
   845             else {
       
   846                 markThrown(tree, tree.expr.type);
       
   847             }
       
   848             markDead();
       
   849         }
       
   850 
       
   851         public void visitApply(JCMethodInvocation tree) {
       
   852             scan(tree.meth);
       
   853             scan(tree.args);
       
   854             for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
       
   855                 markThrown(tree, l.head);
       
   856         }
       
   857 
       
   858         public void visitNewClass(JCNewClass tree) {
       
   859             scan(tree.encl);
       
   860             scan(tree.args);
       
   861            // scan(tree.def);
       
   862             for (List<Type> l = tree.constructorType.getThrownTypes();
       
   863                  l.nonEmpty();
       
   864                  l = l.tail) {
       
   865                 markThrown(tree, l.head);
       
   866             }
       
   867             List<Type> caughtPrev = caught;
       
   868             try {
       
   869                 // If the new class expression defines an anonymous class,
       
   870                 // analysis of the anonymous constructor may encounter thrown
       
   871                 // types which are unsubstituted type variables.
       
   872                 // However, since the constructor's actual thrown types have
       
   873                 // already been marked as thrown, it is safe to simply include
       
   874                 // each of the constructor's formal thrown types in the set of
       
   875                 // 'caught/declared to be thrown' types, for the duration of
       
   876                 // the class def analysis.
       
   877                 if (tree.def != null)
       
   878                     for (List<Type> l = tree.constructor.type.getThrownTypes();
       
   879                          l.nonEmpty();
       
   880                          l = l.tail) {
       
   881                         caught = chk.incl(l.head, caught);
       
   882                     }
       
   883                 scan(tree.def);
       
   884             }
       
   885             finally {
       
   886                 caught = caughtPrev;
       
   887             }
       
   888         }
       
   889 
       
   890         public void visitTopLevel(JCCompilationUnit tree) {
       
   891             // Do nothing for TopLevel since each class is visited individually
       
   892         }
       
   893 
       
   894     /**************************************************************************
       
   895      * main method
       
   896      *************************************************************************/
       
   897 
       
   898         /** Perform definite assignment/unassignment analysis on a tree.
       
   899          */
       
   900         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
       
   901             try {
       
   902                 attrEnv = env;
       
   903                 JCTree tree = env.tree;
       
   904                 Flow.this.make = make;
       
   905                 pendingExits = new ListBuffer<FlowPendingExit>();
       
   906                 preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
       
   907                 alive = true;
       
   908                 this.thrown = this.caught = null;
       
   909                 this.classDef = null;
       
   910                 scan(tree);
       
   911             } finally {
       
   912                 pendingExits = null;
       
   913                 Flow.this.make = null;
       
   914                 this.thrown = this.caught = null;
       
   915                 this.classDef = null;
       
   916             }
       
   917         }
   865     }
   918     }
   866 
   919 
   867     public void visitForLoop(JCForLoop tree) {
   920     /**
   868         ListBuffer<PendingExit> prevPendingExits = pendingExits;
   921      * This pass implements (i) definite assignment analysis, which ensures that
   869         boolean prevLoopPassTwo = loopPassTwo;
   922      * each variable is assigned when used and (ii) definite unassignment analysis,
   870         int nextadrPrev = nextadr;
   923      * which ensures that no final variable is assigned more than once. This visitor
   871         scanStats(tree.init);
   924      * depends on the results of the liveliness analyzer.
   872         Bits initsCond;
   925      */
   873         Bits uninitsCond;
   926     class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
   874         pendingExits = new ListBuffer<PendingExit>();
   927 
   875         int prevErrors = log.nerrors;
   928         /** The set of definitely assigned variables.
   876         do {
   929          */
   877             Bits uninitsEntry = uninits.dup();
   930         Bits inits;
   878             uninitsEntry.excludeFrom(nextadr);
   931 
   879             if (tree.cond != null) {
   932         /** The set of definitely unassigned variables.
       
   933          */
       
   934         Bits uninits;
       
   935 
       
   936         /** The set of variables that are definitely unassigned everywhere
       
   937          *  in current try block. This variable is maintained lazily; it is
       
   938          *  updated only when something gets removed from uninits,
       
   939          *  typically by being assigned in reachable code.  To obtain the
       
   940          *  correct set of variables which are definitely unassigned
       
   941          *  anywhere in current try block, intersect uninitsTry and
       
   942          *  uninits.
       
   943          */
       
   944         Bits uninitsTry;
       
   945 
       
   946         /** When analyzing a condition, inits and uninits are null.
       
   947          *  Instead we have:
       
   948          */
       
   949         Bits initsWhenTrue;
       
   950         Bits initsWhenFalse;
       
   951         Bits uninitsWhenTrue;
       
   952         Bits uninitsWhenFalse;
       
   953 
       
   954         /** A mapping from addresses to variable symbols.
       
   955          */
       
   956         VarSymbol[] vars;
       
   957 
       
   958         /** The current class being defined.
       
   959          */
       
   960         JCClassDecl classDef;
       
   961 
       
   962         /** The first variable sequence number in this class definition.
       
   963          */
       
   964         int firstadr;
       
   965 
       
   966         /** The next available variable sequence number.
       
   967          */
       
   968         int nextadr;
       
   969 
       
   970         /** The list of unreferenced automatic resources.
       
   971          */
       
   972         Scope unrefdResources;
       
   973 
       
   974         /** Set when processing a loop body the second time for DU analysis. */
       
   975         boolean loopPassTwo = false;
       
   976 
       
   977         class AssignPendingExit extends BaseAnalyzer.PendingExit {
       
   978 
       
   979             Bits exit_inits;
       
   980             Bits exit_uninits;
       
   981 
       
   982             AssignPendingExit(JCTree tree, Bits inits, Bits uninits) {
       
   983                 super(tree);
       
   984                 this.exit_inits = inits.dup();
       
   985                 this.exit_uninits = uninits.dup();
       
   986             }
       
   987 
       
   988             void resolveJump() {
       
   989                 inits.andSet(exit_inits);
       
   990                 uninits.andSet(exit_uninits);
       
   991             }
       
   992         }
       
   993 
       
   994         @Override
       
   995         void markDead() {
       
   996             inits.inclRange(firstadr, nextadr);
       
   997             uninits.inclRange(firstadr, nextadr);
       
   998         }
       
   999 
       
  1000         /*-------------- Processing variables ----------------------*/
       
  1001 
       
  1002         /** Do we need to track init/uninit state of this symbol?
       
  1003          *  I.e. is symbol either a local or a blank final variable?
       
  1004          */
       
  1005         boolean trackable(VarSymbol sym) {
       
  1006             return
       
  1007                 (sym.owner.kind == MTH ||
       
  1008                  ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
       
  1009                   classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)));
       
  1010         }
       
  1011 
       
  1012         /** Initialize new trackable variable by setting its address field
       
  1013          *  to the next available sequence number and entering it under that
       
  1014          *  index into the vars array.
       
  1015          */
       
  1016         void newVar(VarSymbol sym) {
       
  1017             if (nextadr == vars.length) {
       
  1018                 VarSymbol[] newvars = new VarSymbol[nextadr * 2];
       
  1019                 System.arraycopy(vars, 0, newvars, 0, nextadr);
       
  1020                 vars = newvars;
       
  1021             }
       
  1022             sym.adr = nextadr;
       
  1023             vars[nextadr] = sym;
       
  1024             inits.excl(nextadr);
       
  1025             uninits.incl(nextadr);
       
  1026             nextadr++;
       
  1027         }
       
  1028 
       
  1029         /** Record an initialization of a trackable variable.
       
  1030          */
       
  1031         void letInit(DiagnosticPosition pos, VarSymbol sym) {
       
  1032             if (sym.adr >= firstadr && trackable(sym)) {
       
  1033                 if ((sym.flags() & FINAL) != 0) {
       
  1034                     if ((sym.flags() & PARAMETER) != 0) {
       
  1035                         if ((sym.flags() & UNION) != 0) { //multi-catch parameter
       
  1036                             log.error(pos, "multicatch.parameter.may.not.be.assigned",
       
  1037                                       sym);
       
  1038                         }
       
  1039                         else {
       
  1040                             log.error(pos, "final.parameter.may.not.be.assigned",
       
  1041                                   sym);
       
  1042                         }
       
  1043                     } else if (!uninits.isMember(sym.adr)) {
       
  1044                         log.error(pos,
       
  1045                                   loopPassTwo
       
  1046                                   ? "var.might.be.assigned.in.loop"
       
  1047                                   : "var.might.already.be.assigned",
       
  1048                                   sym);
       
  1049                     } else if (!inits.isMember(sym.adr)) {
       
  1050                         // reachable assignment
       
  1051                         uninits.excl(sym.adr);
       
  1052                         uninitsTry.excl(sym.adr);
       
  1053                     } else {
       
  1054                         //log.rawWarning(pos, "unreachable assignment");//DEBUG
       
  1055                         uninits.excl(sym.adr);
       
  1056                     }
       
  1057                 }
       
  1058                 inits.incl(sym.adr);
       
  1059             } else if ((sym.flags() & FINAL) != 0) {
       
  1060                 log.error(pos, "var.might.already.be.assigned", sym);
       
  1061             }
       
  1062         }
       
  1063 
       
  1064         /** If tree is either a simple name or of the form this.name or
       
  1065          *  C.this.name, and tree represents a trackable variable,
       
  1066          *  record an initialization of the variable.
       
  1067          */
       
  1068         void letInit(JCTree tree) {
       
  1069             tree = TreeInfo.skipParens(tree);
       
  1070             if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
       
  1071                 Symbol sym = TreeInfo.symbol(tree);
       
  1072                 if (sym.kind == VAR) {
       
  1073                     letInit(tree.pos(), (VarSymbol)sym);
       
  1074                 }
       
  1075             }
       
  1076         }
       
  1077 
       
  1078         /** Check that trackable variable is initialized.
       
  1079          */
       
  1080         void checkInit(DiagnosticPosition pos, VarSymbol sym) {
       
  1081             if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
       
  1082                 trackable(sym) &&
       
  1083                 !inits.isMember(sym.adr)) {
       
  1084                 log.error(pos, "var.might.not.have.been.initialized",
       
  1085                           sym);
       
  1086                 inits.incl(sym.adr);
       
  1087             }
       
  1088         }
       
  1089 
       
  1090         /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
       
  1091          */
       
  1092         void split(boolean setToNull) {
       
  1093             initsWhenFalse = inits.dup();
       
  1094             uninitsWhenFalse = uninits.dup();
       
  1095             initsWhenTrue = inits;
       
  1096             uninitsWhenTrue = uninits;
       
  1097             if (setToNull)
       
  1098                 inits = uninits = null;
       
  1099         }
       
  1100 
       
  1101         /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
       
  1102          */
       
  1103         void merge() {
       
  1104             inits = initsWhenFalse.andSet(initsWhenTrue);
       
  1105             uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
       
  1106         }
       
  1107 
       
  1108     /* ************************************************************************
       
  1109      * Visitor methods for statements and definitions
       
  1110      *************************************************************************/
       
  1111 
       
  1112         /** Analyze an expression. Make sure to set (un)inits rather than
       
  1113          *  (un)initsWhenTrue(WhenFalse) on exit.
       
  1114          */
       
  1115         void scanExpr(JCTree tree) {
       
  1116             if (tree != null) {
       
  1117                 scan(tree);
       
  1118                 if (inits == null) merge();
       
  1119             }
       
  1120         }
       
  1121 
       
  1122         /** Analyze a list of expressions.
       
  1123          */
       
  1124         void scanExprs(List<? extends JCExpression> trees) {
       
  1125             if (trees != null)
       
  1126                 for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
       
  1127                     scanExpr(l.head);
       
  1128         }
       
  1129 
       
  1130         /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
       
  1131          *  rather than (un)inits on exit.
       
  1132          */
       
  1133         void scanCond(JCTree tree) {
       
  1134             if (tree.type.isFalse()) {
       
  1135                 if (inits == null) merge();
       
  1136                 initsWhenTrue = inits.dup();
       
  1137                 initsWhenTrue.inclRange(firstadr, nextadr);
       
  1138                 uninitsWhenTrue = uninits.dup();
       
  1139                 uninitsWhenTrue.inclRange(firstadr, nextadr);
       
  1140                 initsWhenFalse = inits;
       
  1141                 uninitsWhenFalse = uninits;
       
  1142             } else if (tree.type.isTrue()) {
       
  1143                 if (inits == null) merge();
       
  1144                 initsWhenFalse = inits.dup();
       
  1145                 initsWhenFalse.inclRange(firstadr, nextadr);
       
  1146                 uninitsWhenFalse = uninits.dup();
       
  1147                 uninitsWhenFalse.inclRange(firstadr, nextadr);
       
  1148                 initsWhenTrue = inits;
       
  1149                 uninitsWhenTrue = uninits;
       
  1150             } else {
       
  1151                 scan(tree);
       
  1152                 if (inits != null)
       
  1153                     split(tree.type != syms.unknownType);
       
  1154             }
       
  1155             if (tree.type != syms.unknownType)
       
  1156                 inits = uninits = null;
       
  1157         }
       
  1158 
       
  1159         /* ------------ Visitor methods for various sorts of trees -------------*/
       
  1160 
       
  1161         public void visitClassDef(JCClassDecl tree) {
       
  1162             if (tree.sym == null) return;
       
  1163 
       
  1164             JCClassDecl classDefPrev = classDef;
       
  1165             int firstadrPrev = firstadr;
       
  1166             int nextadrPrev = nextadr;
       
  1167             ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
       
  1168             Lint lintPrev = lint;
       
  1169 
       
  1170             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1171             if (tree.name != names.empty) {
       
  1172                 firstadr = nextadr;
       
  1173             }
       
  1174             classDef = tree;
       
  1175             lint = lint.augment(tree.sym.attributes_field);
       
  1176 
       
  1177             try {
       
  1178                 // define all the static fields
       
  1179                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
  1180                     if (l.head.hasTag(VARDEF)) {
       
  1181                         JCVariableDecl def = (JCVariableDecl)l.head;
       
  1182                         if ((def.mods.flags & STATIC) != 0) {
       
  1183                             VarSymbol sym = def.sym;
       
  1184                             if (trackable(sym))
       
  1185                                 newVar(sym);
       
  1186                         }
       
  1187                     }
       
  1188                 }
       
  1189 
       
  1190                 // process all the static initializers
       
  1191                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
  1192                     if (!l.head.hasTag(METHODDEF) &&
       
  1193                         (TreeInfo.flags(l.head) & STATIC) != 0) {
       
  1194                         scan(l.head);
       
  1195                     }
       
  1196                 }
       
  1197 
       
  1198                 // define all the instance fields
       
  1199                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
  1200                     if (l.head.hasTag(VARDEF)) {
       
  1201                         JCVariableDecl def = (JCVariableDecl)l.head;
       
  1202                         if ((def.mods.flags & STATIC) == 0) {
       
  1203                             VarSymbol sym = def.sym;
       
  1204                             if (trackable(sym))
       
  1205                                 newVar(sym);
       
  1206                         }
       
  1207                     }
       
  1208                 }
       
  1209 
       
  1210                 // process all the instance initializers
       
  1211                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
  1212                     if (!l.head.hasTag(METHODDEF) &&
       
  1213                         (TreeInfo.flags(l.head) & STATIC) == 0) {
       
  1214                         scan(l.head);
       
  1215                     }
       
  1216                 }
       
  1217 
       
  1218                 // process all the methods
       
  1219                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
       
  1220                     if (l.head.hasTag(METHODDEF)) {
       
  1221                         scan(l.head);
       
  1222                     }
       
  1223                 }
       
  1224             } finally {
       
  1225                 pendingExits = pendingExitsPrev;
       
  1226                 nextadr = nextadrPrev;
       
  1227                 firstadr = firstadrPrev;
       
  1228                 classDef = classDefPrev;
       
  1229                 lint = lintPrev;
       
  1230             }
       
  1231         }
       
  1232 
       
  1233         public void visitMethodDef(JCMethodDecl tree) {
       
  1234             if (tree.body == null) return;
       
  1235 
       
  1236             Bits initsPrev = inits.dup();
       
  1237             Bits uninitsPrev = uninits.dup();
       
  1238             int nextadrPrev = nextadr;
       
  1239             int firstadrPrev = firstadr;
       
  1240             Lint lintPrev = lint;
       
  1241 
       
  1242             lint = lint.augment(tree.sym.attributes_field);
       
  1243 
       
  1244             Assert.check(pendingExits.isEmpty());
       
  1245 
       
  1246             try {
       
  1247                 boolean isInitialConstructor =
       
  1248                     TreeInfo.isInitialConstructor(tree);
       
  1249 
       
  1250                 if (!isInitialConstructor)
       
  1251                     firstadr = nextadr;
       
  1252                 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
       
  1253                     JCVariableDecl def = l.head;
       
  1254                     scan(def);
       
  1255                     inits.incl(def.sym.adr);
       
  1256                     uninits.excl(def.sym.adr);
       
  1257                 }
       
  1258                 // else we are in an instance initializer block;
       
  1259                 // leave caught unchanged.
       
  1260                 scan(tree.body);
       
  1261 
       
  1262                 if (isInitialConstructor) {
       
  1263                     for (int i = firstadr; i < nextadr; i++)
       
  1264                         if (vars[i].owner == classDef.sym)
       
  1265                             checkInit(TreeInfo.diagEndPos(tree.body), vars[i]);
       
  1266                 }
       
  1267                 List<AssignPendingExit> exits = pendingExits.toList();
       
  1268                 pendingExits = new ListBuffer<AssignPendingExit>();
       
  1269                 while (exits.nonEmpty()) {
       
  1270                     AssignPendingExit exit = exits.head;
       
  1271                     exits = exits.tail;
       
  1272                     Assert.check(exit.tree.hasTag(RETURN), exit.tree);
       
  1273                     if (isInitialConstructor) {
       
  1274                         inits = exit.exit_inits;
       
  1275                         for (int i = firstadr; i < nextadr; i++)
       
  1276                             checkInit(exit.tree.pos(), vars[i]);
       
  1277                     }
       
  1278                 }
       
  1279             } finally {
       
  1280                 inits = initsPrev;
       
  1281                 uninits = uninitsPrev;
       
  1282                 nextadr = nextadrPrev;
       
  1283                 firstadr = firstadrPrev;
       
  1284                 lint = lintPrev;
       
  1285             }
       
  1286         }
       
  1287 
       
  1288         public void visitVarDef(JCVariableDecl tree) {
       
  1289             boolean track = trackable(tree.sym);
       
  1290             if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
       
  1291             if (tree.init != null) {
       
  1292                 Lint lintPrev = lint;
       
  1293                 lint = lint.augment(tree.sym.attributes_field);
       
  1294                 try{
       
  1295                     scanExpr(tree.init);
       
  1296                     if (track) letInit(tree.pos(), tree.sym);
       
  1297                 } finally {
       
  1298                     lint = lintPrev;
       
  1299                 }
       
  1300             }
       
  1301         }
       
  1302 
       
  1303         public void visitBlock(JCBlock tree) {
       
  1304             int nextadrPrev = nextadr;
       
  1305             scan(tree.stats);
       
  1306             nextadr = nextadrPrev;
       
  1307         }
       
  1308 
       
  1309         public void visitDoLoop(JCDoWhileLoop tree) {
       
  1310             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1311             boolean prevLoopPassTwo = loopPassTwo;
       
  1312             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1313             int prevErrors = log.nerrors;
       
  1314             do {
       
  1315                 Bits uninitsEntry = uninits.dup();
       
  1316                 uninitsEntry.excludeFrom(nextadr);
       
  1317             scan(tree.body);
       
  1318             resolveContinues(tree);
       
  1319                 scanCond(tree.cond);
       
  1320                 if (log.nerrors !=  prevErrors ||
       
  1321                     loopPassTwo ||
       
  1322                     uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
       
  1323                     break;
       
  1324                 inits = initsWhenTrue;
       
  1325                 uninits = uninitsEntry.andSet(uninitsWhenTrue);
       
  1326                 loopPassTwo = true;
       
  1327             } while (true);
       
  1328             loopPassTwo = prevLoopPassTwo;
       
  1329             inits = initsWhenFalse;
       
  1330             uninits = uninitsWhenFalse;
       
  1331             resolveBreaks(tree, prevPendingExits);
       
  1332         }
       
  1333 
       
  1334         public void visitWhileLoop(JCWhileLoop tree) {
       
  1335             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1336             boolean prevLoopPassTwo = loopPassTwo;
       
  1337             Bits initsCond;
       
  1338             Bits uninitsCond;
       
  1339             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1340             int prevErrors = log.nerrors;
       
  1341             do {
       
  1342                 Bits uninitsEntry = uninits.dup();
       
  1343                 uninitsEntry.excludeFrom(nextadr);
   880                 scanCond(tree.cond);
  1344                 scanCond(tree.cond);
   881                 initsCond = initsWhenFalse;
  1345                 initsCond = initsWhenFalse;
   882                 uninitsCond = uninitsWhenFalse;
  1346                 uninitsCond = uninitsWhenFalse;
   883                 inits = initsWhenTrue;
  1347                 inits = initsWhenTrue;
   884                 uninits = uninitsWhenTrue;
  1348                 uninits = uninitsWhenTrue;
   885                 alive = !tree.cond.type.isFalse();
  1349                 scan(tree.body);
       
  1350                 resolveContinues(tree);
       
  1351                 if (log.nerrors != prevErrors ||
       
  1352                     loopPassTwo ||
       
  1353                     uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
       
  1354                     break;
       
  1355                 uninits = uninitsEntry.andSet(uninits);
       
  1356                 loopPassTwo = true;
       
  1357             } while (true);
       
  1358             loopPassTwo = prevLoopPassTwo;
       
  1359             inits = initsCond;
       
  1360             uninits = uninitsCond;
       
  1361             resolveBreaks(tree, prevPendingExits);
       
  1362         }
       
  1363 
       
  1364         public void visitForLoop(JCForLoop tree) {
       
  1365             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1366             boolean prevLoopPassTwo = loopPassTwo;
       
  1367             int nextadrPrev = nextadr;
       
  1368             scan(tree.init);
       
  1369             Bits initsCond;
       
  1370             Bits uninitsCond;
       
  1371             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1372             int prevErrors = log.nerrors;
       
  1373             do {
       
  1374                 Bits uninitsEntry = uninits.dup();
       
  1375                 uninitsEntry.excludeFrom(nextadr);
       
  1376                 if (tree.cond != null) {
       
  1377                     scanCond(tree.cond);
       
  1378                     initsCond = initsWhenFalse;
       
  1379                     uninitsCond = uninitsWhenFalse;
       
  1380                     inits = initsWhenTrue;
       
  1381                     uninits = uninitsWhenTrue;
       
  1382                 } else {
       
  1383                     initsCond = inits.dup();
       
  1384                     initsCond.inclRange(firstadr, nextadr);
       
  1385                     uninitsCond = uninits.dup();
       
  1386                     uninitsCond.inclRange(firstadr, nextadr);
       
  1387                 }
       
  1388                 scan(tree.body);
       
  1389                 resolveContinues(tree);
       
  1390                 scan(tree.step);
       
  1391                 if (log.nerrors != prevErrors ||
       
  1392                     loopPassTwo ||
       
  1393                     uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
       
  1394                     break;
       
  1395                 uninits = uninitsEntry.andSet(uninits);
       
  1396                 loopPassTwo = true;
       
  1397             } while (true);
       
  1398             loopPassTwo = prevLoopPassTwo;
       
  1399             inits = initsCond;
       
  1400             uninits = uninitsCond;
       
  1401             resolveBreaks(tree, prevPendingExits);
       
  1402             nextadr = nextadrPrev;
       
  1403         }
       
  1404 
       
  1405         public void visitForeachLoop(JCEnhancedForLoop tree) {
       
  1406             visitVarDef(tree.var);
       
  1407 
       
  1408             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1409             boolean prevLoopPassTwo = loopPassTwo;
       
  1410             int nextadrPrev = nextadr;
       
  1411             scan(tree.expr);
       
  1412             Bits initsStart = inits.dup();
       
  1413             Bits uninitsStart = uninits.dup();
       
  1414 
       
  1415             letInit(tree.pos(), tree.var.sym);
       
  1416             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1417             int prevErrors = log.nerrors;
       
  1418             do {
       
  1419                 Bits uninitsEntry = uninits.dup();
       
  1420                 uninitsEntry.excludeFrom(nextadr);
       
  1421                 scan(tree.body);
       
  1422                 resolveContinues(tree);
       
  1423                 if (log.nerrors != prevErrors ||
       
  1424                     loopPassTwo ||
       
  1425                     uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
       
  1426                     break;
       
  1427                 uninits = uninitsEntry.andSet(uninits);
       
  1428                 loopPassTwo = true;
       
  1429             } while (true);
       
  1430             loopPassTwo = prevLoopPassTwo;
       
  1431             inits = initsStart;
       
  1432             uninits = uninitsStart.andSet(uninits);
       
  1433             resolveBreaks(tree, prevPendingExits);
       
  1434             nextadr = nextadrPrev;
       
  1435         }
       
  1436 
       
  1437         public void visitLabelled(JCLabeledStatement tree) {
       
  1438             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1439             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1440             scan(tree.body);
       
  1441             resolveBreaks(tree, prevPendingExits);
       
  1442         }
       
  1443 
       
  1444         public void visitSwitch(JCSwitch tree) {
       
  1445             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1446             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1447             int nextadrPrev = nextadr;
       
  1448             scanExpr(tree.selector);
       
  1449             Bits initsSwitch = inits;
       
  1450             Bits uninitsSwitch = uninits.dup();
       
  1451             boolean hasDefault = false;
       
  1452             for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
       
  1453                 inits = initsSwitch.dup();
       
  1454                 uninits = uninits.andSet(uninitsSwitch);
       
  1455                 JCCase c = l.head;
       
  1456                 if (c.pat == null)
       
  1457                     hasDefault = true;
       
  1458                 else
       
  1459                     scanExpr(c.pat);
       
  1460                 scan(c.stats);
       
  1461                 addVars(c.stats, initsSwitch, uninitsSwitch);
       
  1462                 // Warn about fall-through if lint switch fallthrough enabled.
       
  1463             }
       
  1464             if (!hasDefault) {
       
  1465                 inits.andSet(initsSwitch);
       
  1466             }
       
  1467             resolveBreaks(tree, prevPendingExits);
       
  1468             nextadr = nextadrPrev;
       
  1469         }
       
  1470         // where
       
  1471             /** Add any variables defined in stats to inits and uninits. */
       
  1472             private void addVars(List<JCStatement> stats, Bits inits,
       
  1473                                         Bits uninits) {
       
  1474                 for (;stats.nonEmpty(); stats = stats.tail) {
       
  1475                     JCTree stat = stats.head;
       
  1476                     if (stat.hasTag(VARDEF)) {
       
  1477                         int adr = ((JCVariableDecl) stat).sym.adr;
       
  1478                         inits.excl(adr);
       
  1479                         uninits.incl(adr);
       
  1480                     }
       
  1481                 }
       
  1482             }
       
  1483 
       
  1484         public void visitTry(JCTry tree) {
       
  1485             ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
       
  1486             Bits uninitsTryPrev = uninitsTry;
       
  1487             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
       
  1488             pendingExits = new ListBuffer<AssignPendingExit>();
       
  1489             Bits initsTry = inits.dup();
       
  1490             uninitsTry = uninits.dup();
       
  1491             for (JCTree resource : tree.resources) {
       
  1492                 if (resource instanceof JCVariableDecl) {
       
  1493                     JCVariableDecl vdecl = (JCVariableDecl) resource;
       
  1494                     visitVarDef(vdecl);
       
  1495                     unrefdResources.enter(vdecl.sym);
       
  1496                     resourceVarDecls.append(vdecl);
       
  1497                 } else if (resource instanceof JCExpression) {
       
  1498                     scanExpr((JCExpression) resource);
       
  1499                 } else {
       
  1500                     throw new AssertionError(tree);  // parser error
       
  1501                 }
       
  1502             }
       
  1503             scan(tree.body);
       
  1504             uninitsTry.andSet(uninits);
       
  1505             Bits initsEnd = inits;
       
  1506             Bits uninitsEnd = uninits;
       
  1507             int nextadrCatch = nextadr;
       
  1508 
       
  1509             if (!resourceVarDecls.isEmpty() &&
       
  1510                     lint.isEnabled(Lint.LintCategory.TRY)) {
       
  1511                 for (JCVariableDecl resVar : resourceVarDecls) {
       
  1512                     if (unrefdResources.includes(resVar.sym)) {
       
  1513                         log.warning(Lint.LintCategory.TRY, resVar.pos(),
       
  1514                                     "try.resource.not.referenced", resVar.sym);
       
  1515                         unrefdResources.remove(resVar.sym);
       
  1516                     }
       
  1517                 }
       
  1518             }
       
  1519 
       
  1520             for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
       
  1521                 JCVariableDecl param = l.head.param;
       
  1522                 inits = initsTry.dup();
       
  1523                 uninits = uninitsTry.dup();
       
  1524                 scan(param);
       
  1525                 inits.incl(param.sym.adr);
       
  1526                 uninits.excl(param.sym.adr);
       
  1527                 scan(l.head.body);
       
  1528                 initsEnd.andSet(inits);
       
  1529                 uninitsEnd.andSet(uninits);
       
  1530                 nextadr = nextadrCatch;
       
  1531             }
       
  1532             if (tree.finalizer != null) {
       
  1533                 inits = initsTry.dup();
       
  1534                 uninits = uninitsTry.dup();
       
  1535                 ListBuffer<AssignPendingExit> exits = pendingExits;
       
  1536                 pendingExits = prevPendingExits;
       
  1537                 scan(tree.finalizer);
       
  1538                 if (!tree.finallyCanCompleteNormally) {
       
  1539                     // discard exits and exceptions from try and finally
       
  1540                 } else {
       
  1541                     uninits.andSet(uninitsEnd);
       
  1542                     // FIX: this doesn't preserve source order of exits in catch
       
  1543                     // versus finally!
       
  1544                     while (exits.nonEmpty()) {
       
  1545                         AssignPendingExit exit = exits.next();
       
  1546                         if (exit.exit_inits != null) {
       
  1547                             exit.exit_inits.orSet(inits);
       
  1548                             exit.exit_uninits.andSet(uninits);
       
  1549                         }
       
  1550                         pendingExits.append(exit);
       
  1551                     }
       
  1552                     inits.orSet(initsEnd);
       
  1553                 }
   886             } else {
  1554             } else {
   887                 initsCond = inits.dup();
  1555                 inits = initsEnd;
   888                 initsCond.inclRange(firstadr, nextadr);
  1556                 uninits = uninitsEnd;
   889                 uninitsCond = uninits.dup();
  1557                 ListBuffer<AssignPendingExit> exits = pendingExits;
   890                 uninitsCond.inclRange(firstadr, nextadr);
  1558                 pendingExits = prevPendingExits;
   891                 alive = true;
  1559                 while (exits.nonEmpty()) pendingExits.append(exits.next());
   892             }
  1560             }
   893             scanStat(tree.body);
  1561             uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
   894             alive |= resolveContinues(tree);
  1562         }
   895             scan(tree.step);
  1563 
   896             if (log.nerrors != prevErrors ||
  1564         public void visitConditional(JCConditional tree) {
   897                 loopPassTwo ||
  1565             scanCond(tree.cond);
   898                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
  1566             Bits initsBeforeElse = initsWhenFalse;
   899                 break;
  1567             Bits uninitsBeforeElse = uninitsWhenFalse;
   900             uninits = uninitsEntry.andSet(uninits);
       
   901             loopPassTwo = true;
       
   902             alive = true;
       
   903         } while (true);
       
   904         loopPassTwo = prevLoopPassTwo;
       
   905         inits = initsCond;
       
   906         uninits = uninitsCond;
       
   907         alive = resolveBreaks(tree, prevPendingExits) ||
       
   908             tree.cond != null && !tree.cond.type.isTrue();
       
   909         nextadr = nextadrPrev;
       
   910     }
       
   911 
       
   912     public void visitForeachLoop(JCEnhancedForLoop tree) {
       
   913         visitVarDef(tree.var);
       
   914 
       
   915         ListBuffer<PendingExit> prevPendingExits = pendingExits;
       
   916         boolean prevLoopPassTwo = loopPassTwo;
       
   917         int nextadrPrev = nextadr;
       
   918         scan(tree.expr);
       
   919         Bits initsStart = inits.dup();
       
   920         Bits uninitsStart = uninits.dup();
       
   921 
       
   922         letInit(tree.pos(), tree.var.sym);
       
   923         pendingExits = new ListBuffer<PendingExit>();
       
   924         int prevErrors = log.nerrors;
       
   925         do {
       
   926             Bits uninitsEntry = uninits.dup();
       
   927             uninitsEntry.excludeFrom(nextadr);
       
   928             scanStat(tree.body);
       
   929             alive |= resolveContinues(tree);
       
   930             if (log.nerrors != prevErrors ||
       
   931                 loopPassTwo ||
       
   932                 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
       
   933                 break;
       
   934             uninits = uninitsEntry.andSet(uninits);
       
   935             loopPassTwo = true;
       
   936             alive = true;
       
   937         } while (true);
       
   938         loopPassTwo = prevLoopPassTwo;
       
   939         inits = initsStart;
       
   940         uninits = uninitsStart.andSet(uninits);
       
   941         resolveBreaks(tree, prevPendingExits);
       
   942         alive = true;
       
   943         nextadr = nextadrPrev;
       
   944     }
       
   945 
       
   946     public void visitLabelled(JCLabeledStatement tree) {
       
   947         ListBuffer<PendingExit> prevPendingExits = pendingExits;
       
   948         pendingExits = new ListBuffer<PendingExit>();
       
   949         scanStat(tree.body);
       
   950         alive |= resolveBreaks(tree, prevPendingExits);
       
   951     }
       
   952 
       
   953     public void visitSwitch(JCSwitch tree) {
       
   954         ListBuffer<PendingExit> prevPendingExits = pendingExits;
       
   955         pendingExits = new ListBuffer<PendingExit>();
       
   956         int nextadrPrev = nextadr;
       
   957         scanExpr(tree.selector);
       
   958         Bits initsSwitch = inits;
       
   959         Bits uninitsSwitch = uninits.dup();
       
   960         boolean hasDefault = false;
       
   961         for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
       
   962             alive = true;
       
   963             inits = initsSwitch.dup();
       
   964             uninits = uninits.andSet(uninitsSwitch);
       
   965             JCCase c = l.head;
       
   966             if (c.pat == null)
       
   967                 hasDefault = true;
       
   968             else
       
   969                 scanExpr(c.pat);
       
   970             scanStats(c.stats);
       
   971             addVars(c.stats, initsSwitch, uninitsSwitch);
       
   972             // Warn about fall-through if lint switch fallthrough enabled.
       
   973             if (!loopPassTwo &&
       
   974                 alive &&
       
   975                 lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
       
   976                 c.stats.nonEmpty() && l.tail.nonEmpty())
       
   977                 log.warning(Lint.LintCategory.FALLTHROUGH,
       
   978                             l.tail.head.pos(),
       
   979                             "possible.fall-through.into.case");
       
   980         }
       
   981         if (!hasDefault) {
       
   982             inits.andSet(initsSwitch);
       
   983             alive = true;
       
   984         }
       
   985         alive |= resolveBreaks(tree, prevPendingExits);
       
   986         nextadr = nextadrPrev;
       
   987     }
       
   988     // where
       
   989         /** Add any variables defined in stats to inits and uninits. */
       
   990         private static void addVars(List<JCStatement> stats, Bits inits,
       
   991                                     Bits uninits) {
       
   992             for (;stats.nonEmpty(); stats = stats.tail) {
       
   993                 JCTree stat = stats.head;
       
   994                 if (stat.hasTag(VARDEF)) {
       
   995                     int adr = ((JCVariableDecl) stat).sym.adr;
       
   996                     inits.excl(adr);
       
   997                     uninits.incl(adr);
       
   998                 }
       
   999             }
       
  1000         }
       
  1001 
       
  1002     public void visitTry(JCTry tree) {
       
  1003         List<Type> caughtPrev = caught;
       
  1004         List<Type> thrownPrev = thrown;
       
  1005         thrown = List.nil();
       
  1006         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
       
  1007             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
       
  1008                     ((JCTypeUnion)l.head.param.vartype).alternatives :
       
  1009                     List.of(l.head.param.vartype);
       
  1010             for (JCExpression ct : subClauses) {
       
  1011                 caught = chk.incl(ct.type, caught);
       
  1012             }
       
  1013         }
       
  1014         ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
       
  1015         Bits uninitsTryPrev = uninitsTry;
       
  1016         ListBuffer<PendingExit> prevPendingExits = pendingExits;
       
  1017         pendingExits = new ListBuffer<PendingExit>();
       
  1018         Bits initsTry = inits.dup();
       
  1019         uninitsTry = uninits.dup();
       
  1020         for (JCTree resource : tree.resources) {
       
  1021             if (resource instanceof JCVariableDecl) {
       
  1022                 JCVariableDecl vdecl = (JCVariableDecl) resource;
       
  1023                 visitVarDef(vdecl);
       
  1024                 unrefdResources.enter(vdecl.sym);
       
  1025                 resourceVarDecls.append(vdecl);
       
  1026             } else if (resource instanceof JCExpression) {
       
  1027                 scanExpr((JCExpression) resource);
       
  1028             } else {
       
  1029                 throw new AssertionError(tree);  // parser error
       
  1030             }
       
  1031         }
       
  1032         for (JCTree resource : tree.resources) {
       
  1033             List<Type> closeableSupertypes = resource.type.isCompound() ?
       
  1034                 types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
       
  1035                 List.of(resource.type);
       
  1036             for (Type sup : closeableSupertypes) {
       
  1037                 if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
       
  1038                     Symbol closeMethod = rs.resolveQualifiedMethod(tree,
       
  1039                             attrEnv,
       
  1040                             sup,
       
  1041                             names.close,
       
  1042                             List.<Type>nil(),
       
  1043                             List.<Type>nil());
       
  1044                     if (closeMethod.kind == MTH) {
       
  1045                         for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) {
       
  1046                             markThrown(resource, t);
       
  1047                         }
       
  1048                     }
       
  1049                 }
       
  1050             }
       
  1051         }
       
  1052         scanStat(tree.body);
       
  1053         List<Type> thrownInTry = allowImprovedCatchAnalysis ?
       
  1054             chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
       
  1055             thrown;
       
  1056         thrown = thrownPrev;
       
  1057         caught = caughtPrev;
       
  1058         boolean aliveEnd = alive;
       
  1059         uninitsTry.andSet(uninits);
       
  1060         Bits initsEnd = inits;
       
  1061         Bits uninitsEnd = uninits;
       
  1062         int nextadrCatch = nextadr;
       
  1063 
       
  1064         if (!resourceVarDecls.isEmpty() &&
       
  1065                 lint.isEnabled(Lint.LintCategory.TRY)) {
       
  1066             for (JCVariableDecl resVar : resourceVarDecls) {
       
  1067                 if (unrefdResources.includes(resVar.sym)) {
       
  1068                     log.warning(Lint.LintCategory.TRY, resVar.pos(),
       
  1069                                 "try.resource.not.referenced", resVar.sym);
       
  1070                     unrefdResources.remove(resVar.sym);
       
  1071                 }
       
  1072             }
       
  1073         }
       
  1074 
       
  1075         List<Type> caughtInTry = List.nil();
       
  1076         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
       
  1077             alive = true;
       
  1078             JCVariableDecl param = l.head.param;
       
  1079             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
       
  1080                     ((JCTypeUnion)l.head.param.vartype).alternatives :
       
  1081                     List.of(l.head.param.vartype);
       
  1082             List<Type> ctypes = List.nil();
       
  1083             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
       
  1084             for (JCExpression ct : subClauses) {
       
  1085                 Type exc = ct.type;
       
  1086                 if (exc != syms.unknownType) {
       
  1087                     ctypes = ctypes.append(exc);
       
  1088                     if (types.isSameType(exc, syms.objectType))
       
  1089                         continue;
       
  1090                     checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
       
  1091                     caughtInTry = chk.incl(exc, caughtInTry);
       
  1092                 }
       
  1093             }
       
  1094             inits = initsTry.dup();
       
  1095             uninits = uninitsTry.dup();
       
  1096             scan(param);
       
  1097             inits.incl(param.sym.adr);
       
  1098             uninits.excl(param.sym.adr);
       
  1099             preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
       
  1100             scanStat(l.head.body);
       
  1101             initsEnd.andSet(inits);
       
  1102             uninitsEnd.andSet(uninits);
       
  1103             nextadr = nextadrCatch;
       
  1104             preciseRethrowTypes.remove(param.sym);
       
  1105             aliveEnd |= alive;
       
  1106         }
       
  1107         if (tree.finalizer != null) {
       
  1108             List<Type> savedThrown = thrown;
       
  1109             thrown = List.nil();
       
  1110             inits = initsTry.dup();
       
  1111             uninits = uninitsTry.dup();
       
  1112             ListBuffer<PendingExit> exits = pendingExits;
       
  1113             pendingExits = prevPendingExits;
       
  1114             alive = true;
       
  1115             scanStat(tree.finalizer);
       
  1116             if (!alive) {
       
  1117                 // discard exits and exceptions from try and finally
       
  1118                 thrown = chk.union(thrown, thrownPrev);
       
  1119                 if (!loopPassTwo &&
       
  1120                     lint.isEnabled(Lint.LintCategory.FINALLY)) {
       
  1121                     log.warning(Lint.LintCategory.FINALLY,
       
  1122                             TreeInfo.diagEndPos(tree.finalizer),
       
  1123                             "finally.cannot.complete");
       
  1124                 }
       
  1125             } else {
       
  1126                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
       
  1127                 thrown = chk.union(thrown, savedThrown);
       
  1128                 uninits.andSet(uninitsEnd);
       
  1129                 // FIX: this doesn't preserve source order of exits in catch
       
  1130                 // versus finally!
       
  1131                 while (exits.nonEmpty()) {
       
  1132                     PendingExit exit = exits.next();
       
  1133                     if (exit.inits != null) {
       
  1134                         exit.inits.orSet(inits);
       
  1135                         exit.uninits.andSet(uninits);
       
  1136                     }
       
  1137                     pendingExits.append(exit);
       
  1138                 }
       
  1139                 inits.orSet(initsEnd);
       
  1140                 alive = aliveEnd;
       
  1141             }
       
  1142         } else {
       
  1143             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
       
  1144             inits = initsEnd;
       
  1145             uninits = uninitsEnd;
       
  1146             alive = aliveEnd;
       
  1147             ListBuffer<PendingExit> exits = pendingExits;
       
  1148             pendingExits = prevPendingExits;
       
  1149             while (exits.nonEmpty()) pendingExits.append(exits.next());
       
  1150         }
       
  1151         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
       
  1152     }
       
  1153 
       
  1154     void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
       
  1155         if (chk.subset(exc, caughtInTry)) {
       
  1156             log.error(pos, "except.already.caught", exc);
       
  1157         } else if (!chk.isUnchecked(pos, exc) &&
       
  1158                 !isExceptionOrThrowable(exc) &&
       
  1159                 !chk.intersects(exc, thrownInTry)) {
       
  1160             log.error(pos, "except.never.thrown.in.try", exc);
       
  1161         } else if (allowImprovedCatchAnalysis) {
       
  1162             List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
       
  1163             // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
       
  1164             // unchecked exception, the result list would not be empty, as the augmented
       
  1165             // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
       
  1166             // exception, that would have been covered in the branch above
       
  1167             if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
       
  1168                     !isExceptionOrThrowable(exc)) {
       
  1169                 String key = catchableThrownTypes.length() == 1 ?
       
  1170                         "unreachable.catch" :
       
  1171                         "unreachable.catch.1";
       
  1172                 log.warning(pos, key, catchableThrownTypes);
       
  1173             }
       
  1174         }
       
  1175     }
       
  1176     //where
       
  1177         private boolean isExceptionOrThrowable(Type exc) {
       
  1178             return exc.tsym == syms.throwableType.tsym ||
       
  1179                 exc.tsym == syms.exceptionType.tsym;
       
  1180         }
       
  1181 
       
  1182 
       
  1183     public void visitConditional(JCConditional tree) {
       
  1184         scanCond(tree.cond);
       
  1185         Bits initsBeforeElse = initsWhenFalse;
       
  1186         Bits uninitsBeforeElse = uninitsWhenFalse;
       
  1187         inits = initsWhenTrue;
       
  1188         uninits = uninitsWhenTrue;
       
  1189         if (tree.truepart.type.tag == BOOLEAN &&
       
  1190             tree.falsepart.type.tag == BOOLEAN) {
       
  1191             // if b and c are boolean valued, then
       
  1192             // v is (un)assigned after a?b:c when true iff
       
  1193             //    v is (un)assigned after b when true and
       
  1194             //    v is (un)assigned after c when true
       
  1195             scanCond(tree.truepart);
       
  1196             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
       
  1197             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
       
  1198             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
       
  1199             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
       
  1200             inits = initsBeforeElse;
       
  1201             uninits = uninitsBeforeElse;
       
  1202             scanCond(tree.falsepart);
       
  1203             initsWhenTrue.andSet(initsAfterThenWhenTrue);
       
  1204             initsWhenFalse.andSet(initsAfterThenWhenFalse);
       
  1205             uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
       
  1206             uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
       
  1207         } else {
       
  1208             scanExpr(tree.truepart);
       
  1209             Bits initsAfterThen = inits.dup();
       
  1210             Bits uninitsAfterThen = uninits.dup();
       
  1211             inits = initsBeforeElse;
       
  1212             uninits = uninitsBeforeElse;
       
  1213             scanExpr(tree.falsepart);
       
  1214             inits.andSet(initsAfterThen);
       
  1215             uninits.andSet(uninitsAfterThen);
       
  1216         }
       
  1217     }
       
  1218 
       
  1219     public void visitIf(JCIf tree) {
       
  1220         scanCond(tree.cond);
       
  1221         Bits initsBeforeElse = initsWhenFalse;
       
  1222         Bits uninitsBeforeElse = uninitsWhenFalse;
       
  1223         inits = initsWhenTrue;
       
  1224         uninits = uninitsWhenTrue;
       
  1225         scanStat(tree.thenpart);
       
  1226         if (tree.elsepart != null) {
       
  1227             boolean aliveAfterThen = alive;
       
  1228             alive = true;
       
  1229             Bits initsAfterThen = inits.dup();
       
  1230             Bits uninitsAfterThen = uninits.dup();
       
  1231             inits = initsBeforeElse;
       
  1232             uninits = uninitsBeforeElse;
       
  1233             scanStat(tree.elsepart);
       
  1234             inits.andSet(initsAfterThen);
       
  1235             uninits.andSet(uninitsAfterThen);
       
  1236             alive = alive | aliveAfterThen;
       
  1237         } else {
       
  1238             inits.andSet(initsBeforeElse);
       
  1239             uninits.andSet(uninitsBeforeElse);
       
  1240             alive = true;
       
  1241         }
       
  1242     }
       
  1243 
       
  1244 
       
  1245 
       
  1246     public void visitBreak(JCBreak tree) {
       
  1247         recordExit(tree);
       
  1248     }
       
  1249 
       
  1250     public void visitContinue(JCContinue tree) {
       
  1251         recordExit(tree);
       
  1252     }
       
  1253 
       
  1254     public void visitReturn(JCReturn tree) {
       
  1255         scanExpr(tree.expr);
       
  1256         // if not initial constructor, should markDead instead of recordExit
       
  1257         recordExit(tree);
       
  1258     }
       
  1259 
       
  1260     public void visitThrow(JCThrow tree) {
       
  1261         scanExpr(tree.expr);
       
  1262         Symbol sym = TreeInfo.symbol(tree.expr);
       
  1263         if (sym != null &&
       
  1264             sym.kind == VAR &&
       
  1265             (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
       
  1266             preciseRethrowTypes.get(sym) != null &&
       
  1267             allowImprovedRethrowAnalysis) {
       
  1268             for (Type t : preciseRethrowTypes.get(sym)) {
       
  1269                 markThrown(tree, t);
       
  1270             }
       
  1271         }
       
  1272         else {
       
  1273             markThrown(tree, tree.expr.type);
       
  1274         }
       
  1275         markDead();
       
  1276     }
       
  1277 
       
  1278     public void visitApply(JCMethodInvocation tree) {
       
  1279         scanExpr(tree.meth);
       
  1280         scanExprs(tree.args);
       
  1281         for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
       
  1282             markThrown(tree, l.head);
       
  1283     }
       
  1284 
       
  1285     public void visitNewClass(JCNewClass tree) {
       
  1286         scanExpr(tree.encl);
       
  1287         scanExprs(tree.args);
       
  1288        // scan(tree.def);
       
  1289         for (List<Type> l = tree.constructorType.getThrownTypes();
       
  1290              l.nonEmpty();
       
  1291              l = l.tail) {
       
  1292             markThrown(tree, l.head);
       
  1293         }
       
  1294         List<Type> caughtPrev = caught;
       
  1295         try {
       
  1296             // If the new class expression defines an anonymous class,
       
  1297             // analysis of the anonymous constructor may encounter thrown
       
  1298             // types which are unsubstituted type variables.
       
  1299             // However, since the constructor's actual thrown types have
       
  1300             // already been marked as thrown, it is safe to simply include
       
  1301             // each of the constructor's formal thrown types in the set of
       
  1302             // 'caught/declared to be thrown' types, for the duration of
       
  1303             // the class def analysis.
       
  1304             if (tree.def != null)
       
  1305                 for (List<Type> l = tree.constructor.type.getThrownTypes();
       
  1306                      l.nonEmpty();
       
  1307                      l = l.tail) {
       
  1308                     caught = chk.incl(l.head, caught);
       
  1309                 }
       
  1310             scan(tree.def);
       
  1311         }
       
  1312         finally {
       
  1313             caught = caughtPrev;
       
  1314         }
       
  1315     }
       
  1316 
       
  1317     public void visitNewArray(JCNewArray tree) {
       
  1318         scanExprs(tree.dims);
       
  1319         scanExprs(tree.elems);
       
  1320     }
       
  1321 
       
  1322     public void visitAssert(JCAssert tree) {
       
  1323         Bits initsExit = inits.dup();
       
  1324         Bits uninitsExit = uninits.dup();
       
  1325         scanCond(tree.cond);
       
  1326         uninitsExit.andSet(uninitsWhenTrue);
       
  1327         if (tree.detail != null) {
       
  1328             inits = initsWhenFalse;
       
  1329             uninits = uninitsWhenFalse;
       
  1330             scanExpr(tree.detail);
       
  1331         }
       
  1332         inits = initsExit;
       
  1333         uninits = uninitsExit;
       
  1334     }
       
  1335 
       
  1336     public void visitAssign(JCAssign tree) {
       
  1337         JCTree lhs = TreeInfo.skipParens(tree.lhs);
       
  1338         if (!(lhs instanceof JCIdent)) scanExpr(lhs);
       
  1339         scanExpr(tree.rhs);
       
  1340         letInit(lhs);
       
  1341     }
       
  1342 
       
  1343     public void visitAssignop(JCAssignOp tree) {
       
  1344         scanExpr(tree.lhs);
       
  1345         scanExpr(tree.rhs);
       
  1346         letInit(tree.lhs);
       
  1347     }
       
  1348 
       
  1349     public void visitUnary(JCUnary tree) {
       
  1350         switch (tree.getTag()) {
       
  1351         case NOT:
       
  1352             scanCond(tree.arg);
       
  1353             Bits t = initsWhenFalse;
       
  1354             initsWhenFalse = initsWhenTrue;
       
  1355             initsWhenTrue = t;
       
  1356             t = uninitsWhenFalse;
       
  1357             uninitsWhenFalse = uninitsWhenTrue;
       
  1358             uninitsWhenTrue = t;
       
  1359             break;
       
  1360         case PREINC: case POSTINC:
       
  1361         case PREDEC: case POSTDEC:
       
  1362             scanExpr(tree.arg);
       
  1363             letInit(tree.arg);
       
  1364             break;
       
  1365         default:
       
  1366             scanExpr(tree.arg);
       
  1367         }
       
  1368     }
       
  1369 
       
  1370     public void visitBinary(JCBinary tree) {
       
  1371         switch (tree.getTag()) {
       
  1372         case AND:
       
  1373             scanCond(tree.lhs);
       
  1374             Bits initsWhenFalseLeft = initsWhenFalse;
       
  1375             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
       
  1376             inits = initsWhenTrue;
  1568             inits = initsWhenTrue;
  1377             uninits = uninitsWhenTrue;
  1569             uninits = uninitsWhenTrue;
  1378             scanCond(tree.rhs);
  1570             if (tree.truepart.type.tag == BOOLEAN &&
  1379             initsWhenFalse.andSet(initsWhenFalseLeft);
  1571                 tree.falsepart.type.tag == BOOLEAN) {
  1380             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
  1572                 // if b and c are boolean valued, then
  1381             break;
  1573                 // v is (un)assigned after a?b:c when true iff
  1382         case OR:
  1574                 //    v is (un)assigned after b when true and
  1383             scanCond(tree.lhs);
  1575                 //    v is (un)assigned after c when true
  1384             Bits initsWhenTrueLeft = initsWhenTrue;
  1576                 scanCond(tree.truepart);
  1385             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
  1577                 Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
  1386             inits = initsWhenFalse;
  1578                 Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
  1387             uninits = uninitsWhenFalse;
  1579                 Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
  1388             scanCond(tree.rhs);
  1580                 Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
  1389             initsWhenTrue.andSet(initsWhenTrueLeft);
  1581                 inits = initsBeforeElse;
  1390             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
  1582                 uninits = uninitsBeforeElse;
  1391             break;
  1583                 scanCond(tree.falsepart);
  1392         default:
  1584                 initsWhenTrue.andSet(initsAfterThenWhenTrue);
       
  1585                 initsWhenFalse.andSet(initsAfterThenWhenFalse);
       
  1586                 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
       
  1587                 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
       
  1588             } else {
       
  1589                 scanExpr(tree.truepart);
       
  1590                 Bits initsAfterThen = inits.dup();
       
  1591                 Bits uninitsAfterThen = uninits.dup();
       
  1592                 inits = initsBeforeElse;
       
  1593                 uninits = uninitsBeforeElse;
       
  1594                 scanExpr(tree.falsepart);
       
  1595                 inits.andSet(initsAfterThen);
       
  1596                 uninits.andSet(uninitsAfterThen);
       
  1597             }
       
  1598         }
       
  1599 
       
  1600         public void visitIf(JCIf tree) {
       
  1601             scanCond(tree.cond);
       
  1602             Bits initsBeforeElse = initsWhenFalse;
       
  1603             Bits uninitsBeforeElse = uninitsWhenFalse;
       
  1604             inits = initsWhenTrue;
       
  1605             uninits = uninitsWhenTrue;
       
  1606             scan(tree.thenpart);
       
  1607             if (tree.elsepart != null) {
       
  1608                 Bits initsAfterThen = inits.dup();
       
  1609                 Bits uninitsAfterThen = uninits.dup();
       
  1610                 inits = initsBeforeElse;
       
  1611                 uninits = uninitsBeforeElse;
       
  1612                 scan(tree.elsepart);
       
  1613                 inits.andSet(initsAfterThen);
       
  1614                 uninits.andSet(uninitsAfterThen);
       
  1615             } else {
       
  1616                 inits.andSet(initsBeforeElse);
       
  1617                 uninits.andSet(uninitsBeforeElse);
       
  1618             }
       
  1619         }
       
  1620 
       
  1621         public void visitBreak(JCBreak tree) {
       
  1622             recordExit(tree, new AssignPendingExit(tree, inits, uninits));
       
  1623         }
       
  1624 
       
  1625         public void visitContinue(JCContinue tree) {
       
  1626             recordExit(tree, new AssignPendingExit(tree, inits, uninits));
       
  1627         }
       
  1628 
       
  1629         public void visitReturn(JCReturn tree) {
       
  1630             scanExpr(tree.expr);
       
  1631             // if not initial constructor, should markDead instead of recordExit
       
  1632             recordExit(tree, new AssignPendingExit(tree, inits, uninits));
       
  1633         }
       
  1634 
       
  1635         public void visitThrow(JCThrow tree) {
       
  1636             scanExpr(tree.expr);
       
  1637             markDead();
       
  1638         }
       
  1639 
       
  1640         public void visitApply(JCMethodInvocation tree) {
       
  1641             scanExpr(tree.meth);
       
  1642             scanExprs(tree.args);
       
  1643         }
       
  1644 
       
  1645         public void visitNewClass(JCNewClass tree) {
       
  1646             scanExpr(tree.encl);
       
  1647             scanExprs(tree.args);
       
  1648             scan(tree.def);
       
  1649         }
       
  1650 
       
  1651         public void visitNewArray(JCNewArray tree) {
       
  1652             scanExprs(tree.dims);
       
  1653             scanExprs(tree.elems);
       
  1654         }
       
  1655 
       
  1656         public void visitAssert(JCAssert tree) {
       
  1657             Bits initsExit = inits.dup();
       
  1658             Bits uninitsExit = uninits.dup();
       
  1659             scanCond(tree.cond);
       
  1660             uninitsExit.andSet(uninitsWhenTrue);
       
  1661             if (tree.detail != null) {
       
  1662                 inits = initsWhenFalse;
       
  1663                 uninits = uninitsWhenFalse;
       
  1664                 scanExpr(tree.detail);
       
  1665             }
       
  1666             inits = initsExit;
       
  1667             uninits = uninitsExit;
       
  1668         }
       
  1669 
       
  1670         public void visitAssign(JCAssign tree) {
       
  1671             JCTree lhs = TreeInfo.skipParens(tree.lhs);
       
  1672             if (!(lhs instanceof JCIdent)) scanExpr(lhs);
       
  1673             scanExpr(tree.rhs);
       
  1674             letInit(lhs);
       
  1675         }
       
  1676 
       
  1677         public void visitAssignop(JCAssignOp tree) {
  1393             scanExpr(tree.lhs);
  1678             scanExpr(tree.lhs);
  1394             scanExpr(tree.rhs);
  1679             scanExpr(tree.rhs);
  1395         }
  1680             letInit(tree.lhs);
  1396     }
  1681         }
  1397 
  1682 
  1398     public void visitIdent(JCIdent tree) {
  1683         public void visitUnary(JCUnary tree) {
  1399         if (tree.sym.kind == VAR) {
  1684             switch (tree.getTag()) {
  1400             checkInit(tree.pos(), (VarSymbol)tree.sym);
  1685             case NOT:
  1401             referenced(tree.sym);
  1686                 scanCond(tree.arg);
  1402         }
  1687                 Bits t = initsWhenFalse;
  1403     }
  1688                 initsWhenFalse = initsWhenTrue;
  1404 
  1689                 initsWhenTrue = t;
  1405     void referenced(Symbol sym) {
  1690                 t = uninitsWhenFalse;
  1406         unrefdResources.remove(sym);
  1691                 uninitsWhenFalse = uninitsWhenTrue;
  1407     }
  1692                 uninitsWhenTrue = t;
  1408 
  1693                 break;
  1409     public void visitTypeCast(JCTypeCast tree) {
  1694             case PREINC: case POSTINC:
  1410         super.visitTypeCast(tree);
  1695             case PREDEC: case POSTDEC:
  1411         if (!tree.type.isErroneous()
  1696                 scanExpr(tree.arg);
  1412             && lint.isEnabled(Lint.LintCategory.CAST)
  1697                 letInit(tree.arg);
  1413             && types.isSameType(tree.expr.type, tree.clazz.type)
  1698                 break;
  1414             && !is292targetTypeCast(tree)) {
  1699             default:
  1415             log.warning(Lint.LintCategory.CAST,
  1700                 scanExpr(tree.arg);
  1416                     tree.pos(), "redundant.cast", tree.expr.type);
  1701             }
  1417         }
  1702         }
  1418     }
  1703 
  1419     //where
  1704         public void visitBinary(JCBinary tree) {
  1420         private boolean is292targetTypeCast(JCTypeCast tree) {
  1705             switch (tree.getTag()) {
  1421             boolean is292targetTypeCast = false;
  1706             case AND:
  1422             JCExpression expr = TreeInfo.skipParens(tree.expr);
  1707                 scanCond(tree.lhs);
  1423             if (expr.hasTag(APPLY)) {
  1708                 Bits initsWhenFalseLeft = initsWhenFalse;
  1424                 JCMethodInvocation apply = (JCMethodInvocation)expr;
  1709                 Bits uninitsWhenFalseLeft = uninitsWhenFalse;
  1425                 Symbol sym = TreeInfo.symbol(apply.meth);
  1710                 inits = initsWhenTrue;
  1426                 is292targetTypeCast = sym != null &&
  1711                 uninits = uninitsWhenTrue;
  1427                     sym.kind == MTH &&
  1712                 scanCond(tree.rhs);
  1428                     (sym.flags() & POLYMORPHIC_SIGNATURE) != 0;
  1713                 initsWhenFalse.andSet(initsWhenFalseLeft);
  1429             }
  1714                 uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
  1430             return is292targetTypeCast;
  1715                 break;
  1431         }
  1716             case OR:
  1432 
  1717                 scanCond(tree.lhs);
  1433     public void visitTopLevel(JCCompilationUnit tree) {
  1718                 Bits initsWhenTrueLeft = initsWhenTrue;
  1434         // Do nothing for TopLevel since each class is visited individually
  1719                 Bits uninitsWhenTrueLeft = uninitsWhenTrue;
  1435     }
  1720                 inits = initsWhenFalse;
  1436 
  1721                 uninits = uninitsWhenFalse;
  1437 /**************************************************************************
  1722                 scanCond(tree.rhs);
  1438  * main method
  1723                 initsWhenTrue.andSet(initsWhenTrueLeft);
  1439  *************************************************************************/
  1724                 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
  1440 
  1725                 break;
  1441     /** Perform definite assignment/unassignment analysis on a tree.
  1726             default:
  1442      */
  1727                 scanExpr(tree.lhs);
  1443     public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
  1728                 scanExpr(tree.rhs);
  1444         try {
  1729             }
  1445             attrEnv = env;
  1730         }
  1446             JCTree tree = env.tree;
  1731 
  1447             this.make = make;
  1732         public void visitIdent(JCIdent tree) {
  1448             inits = new Bits();
  1733             if (tree.sym.kind == VAR) {
  1449             uninits = new Bits();
  1734                 checkInit(tree.pos(), (VarSymbol)tree.sym);
  1450             uninitsTry = new Bits();
  1735                 referenced(tree.sym);
  1451             initsWhenTrue = initsWhenFalse =
  1736             }
  1452                 uninitsWhenTrue = uninitsWhenFalse = null;
  1737         }
  1453             if (vars == null)
  1738 
  1454                 vars = new VarSymbol[32];
  1739         void referenced(Symbol sym) {
  1455             else
  1740             unrefdResources.remove(sym);
  1456                 for (int i=0; i<vars.length; i++)
  1741         }
       
  1742 
       
  1743         public void visitTopLevel(JCCompilationUnit tree) {
       
  1744             // Do nothing for TopLevel since each class is visited individually
       
  1745         }
       
  1746 
       
  1747     /**************************************************************************
       
  1748      * main method
       
  1749      *************************************************************************/
       
  1750 
       
  1751         /** Perform definite assignment/unassignment analysis on a tree.
       
  1752          */
       
  1753         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
       
  1754             try {
       
  1755                 attrEnv = env;
       
  1756                 JCTree tree = env.tree;
       
  1757                 Flow.this.make = make;
       
  1758                 inits = new Bits();
       
  1759                 uninits = new Bits();
       
  1760                 uninitsTry = new Bits();
       
  1761                 initsWhenTrue = initsWhenFalse =
       
  1762                     uninitsWhenTrue = uninitsWhenFalse = null;
       
  1763                 if (vars == null)
       
  1764                     vars = new VarSymbol[32];
       
  1765                 else
       
  1766                     for (int i=0; i<vars.length; i++)
       
  1767                         vars[i] = null;
       
  1768                 firstadr = 0;
       
  1769                 nextadr = 0;
       
  1770                 pendingExits = new ListBuffer<AssignPendingExit>();
       
  1771                 this.classDef = null;
       
  1772                 unrefdResources = new Scope(env.enclClass.sym);
       
  1773                 scan(tree);
       
  1774             } finally {
       
  1775                 // note that recursive invocations of this method fail hard
       
  1776                 inits = uninits = uninitsTry = null;
       
  1777                 initsWhenTrue = initsWhenFalse =
       
  1778                     uninitsWhenTrue = uninitsWhenFalse = null;
       
  1779                 if (vars != null) for (int i=0; i<vars.length; i++)
  1457                     vars[i] = null;
  1780                     vars[i] = null;
  1458             firstadr = 0;
  1781                 firstadr = 0;
  1459             nextadr = 0;
  1782                 nextadr = 0;
  1460             pendingExits = new ListBuffer<PendingExit>();
  1783                 pendingExits = null;
  1461             preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
  1784                 Flow.this.make = null;
  1462             alive = true;
  1785                 this.classDef = null;
  1463             this.thrown = this.caught = null;
  1786                 unrefdResources = null;
  1464             this.classDef = null;
  1787             }
  1465             unrefdResources = new Scope(env.enclClass.sym);
       
  1466             scan(tree);
       
  1467         } finally {
       
  1468             // note that recursive invocations of this method fail hard
       
  1469             inits = uninits = uninitsTry = null;
       
  1470             initsWhenTrue = initsWhenFalse =
       
  1471                 uninitsWhenTrue = uninitsWhenFalse = null;
       
  1472             if (vars != null) for (int i=0; i<vars.length; i++)
       
  1473                 vars[i] = null;
       
  1474             firstadr = 0;
       
  1475             nextadr = 0;
       
  1476             pendingExits = null;
       
  1477             this.make = null;
       
  1478             this.thrown = this.caught = null;
       
  1479             this.classDef = null;
       
  1480             unrefdResources = null;
       
  1481         }
  1788         }
  1482     }
  1789     }
  1483 }
  1790 }