src/share/classes/com/sun/tools/javac/comp/Flow.java

changeset 2027
4932bb04c4b8
parent 2019
77d395862700
child 2047
5f915a0c9615
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Sat Sep 14 15:23:21 2013 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Sat Sep 14 19:04:47 2013 +0100
     1.3 @@ -207,7 +207,7 @@
     1.4  
     1.5      public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
     1.6          new AliveAnalyzer().analyzeTree(env, make);
     1.7 -        new AssignAnalyzer().analyzeTree(env, make);
     1.8 +        new AssignAnalyzer(log, syms, lint, names).analyzeTree(env);
     1.9          new FlowAnalyzer().analyzeTree(env, make);
    1.10          new CaptureAnalyzer().analyzeTree(env, make);
    1.11      }
    1.12 @@ -239,7 +239,7 @@
    1.13          //related errors, which will allow for more errors to be detected
    1.14          Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
    1.15          try {
    1.16 -            new AssignAnalyzer().analyzeTree(env, that, make);
    1.17 +            new AssignAnalyzer(log, syms, lint, names).analyzeTree(env);
    1.18              LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
    1.19              flowAnalyzer.analyzeTree(env, that, make);
    1.20              return flowAnalyzer.inferredThrownTypes;
    1.21 @@ -292,15 +292,6 @@
    1.22      }
    1.23  
    1.24      /**
    1.25 -     * Utility method to reset several Bits instances.
    1.26 -     */
    1.27 -    private void resetBits(Bits... bits) {
    1.28 -        for (Bits b : bits) {
    1.29 -            b.reset();
    1.30 -        }
    1.31 -    }
    1.32 -
    1.33 -    /**
    1.34       * Base visitor class for all visitors implementing dataflow analysis logic.
    1.35       * This class define the shared logic for handling jumps (break/continue statements).
    1.36       */
    1.37 @@ -347,17 +338,17 @@
    1.38                  this.tree = tree;
    1.39              }
    1.40  
    1.41 -            void resolveJump() {
    1.42 +            void resolveJump(JCTree tree) {
    1.43                  //do nothing
    1.44              }
    1.45          }
    1.46  
    1.47 -        abstract void markDead();
    1.48 +        abstract void markDead(JCTree tree);
    1.49  
    1.50          /** Record an outward transfer of control. */
    1.51          void recordExit(JCTree tree, P pe) {
    1.52              pendingExits.append(pe);
    1.53 -            markDead();
    1.54 +            markDead(tree);
    1.55          }
    1.56  
    1.57          /** Resolve all jumps of this statement. */
    1.58 @@ -371,7 +362,7 @@
    1.59                  P exit = exits.head;
    1.60                  if (exit.tree.hasTag(jk.treeTag) &&
    1.61                          jk.getTarget(exit.tree) == tree) {
    1.62 -                    exit.resolveJump();
    1.63 +                    exit.resolveJump(tree);
    1.64                      resolved = true;
    1.65                  } else {
    1.66                      pendingExits.append(exit);
    1.67 @@ -380,12 +371,12 @@
    1.68              return resolved;
    1.69          }
    1.70  
    1.71 -        /** Resolve all breaks of this statement. */
    1.72 +        /** Resolve all continues of this statement. */
    1.73          boolean resolveContinues(JCTree tree) {
    1.74              return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
    1.75          }
    1.76  
    1.77 -        /** Resolve all continues of this statement. */
    1.78 +        /** Resolve all breaks of this statement. */
    1.79          boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
    1.80              return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
    1.81          }
    1.82 @@ -414,7 +405,7 @@
    1.83          private boolean alive;
    1.84  
    1.85          @Override
    1.86 -        void markDead() {
    1.87 +        void markDead(JCTree tree) {
    1.88              alive = false;
    1.89          }
    1.90  
    1.91 @@ -696,7 +687,7 @@
    1.92  
    1.93          public void visitThrow(JCThrow tree) {
    1.94              scan(tree.expr);
    1.95 -            markDead();
    1.96 +            markDead(tree);
    1.97          }
    1.98  
    1.99          public void visitApply(JCMethodInvocation tree) {
   1.100 @@ -797,7 +788,7 @@
   1.101          }
   1.102  
   1.103          @Override
   1.104 -        void markDead() {
   1.105 +        void markDead(JCTree tree) {
   1.106              //do nothing
   1.107          }
   1.108  
   1.109 @@ -1222,7 +1213,7 @@
   1.110              else {
   1.111                  markThrown(tree, tree.expr.type);
   1.112              }
   1.113 -            markDead();
   1.114 +            markDead(tree);
   1.115          }
   1.116  
   1.117          public void visitApply(JCMethodInvocation tree) {
   1.118 @@ -1372,11 +1363,13 @@
   1.119       * depends on the results of the liveliness analyzer. This pass is also used to mark
   1.120       * effectively-final local variables/parameters.
   1.121       */
   1.122 -    class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
   1.123 +
   1.124 +    public abstract static class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer.AbstractAssignPendingExit>
   1.125 +        extends BaseAnalyzer<P> {
   1.126  
   1.127          /** The set of definitely assigned variables.
   1.128           */
   1.129 -        final Bits inits;
   1.130 +        protected final Bits inits;
   1.131  
   1.132          /** The set of definitely unassigned variables.
   1.133           */
   1.134 @@ -1402,7 +1395,7 @@
   1.135  
   1.136          /** A mapping from addresses to variable symbols.
   1.137           */
   1.138 -        JCVariableDecl[] vardecls;
   1.139 +        protected JCVariableDecl[] vardecls;
   1.140  
   1.141          /** The current class being defined.
   1.142           */
   1.143 @@ -1414,11 +1407,11 @@
   1.144  
   1.145          /** The next available variable sequence number.
   1.146           */
   1.147 -        int nextadr;
   1.148 +        protected int nextadr;
   1.149  
   1.150          /** The first variable sequence number in a block that can return.
   1.151           */
   1.152 -        int returnadr;
   1.153 +        protected int returnadr;
   1.154  
   1.155          /** The list of unreferenced automatic resources.
   1.156           */
   1.157 @@ -1430,35 +1423,46 @@
   1.158          /** The starting position of the analysed tree */
   1.159          int startPos;
   1.160  
   1.161 -        AssignAnalyzer() {
   1.162 -            inits = new Bits();
   1.163 +        final Symtab syms;
   1.164 +
   1.165 +        protected Names names;
   1.166 +
   1.167 +        public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit {
   1.168 +
   1.169 +            final Bits inits;
   1.170 +            final Bits uninits;
   1.171 +            final Bits exit_inits = new Bits(true);
   1.172 +            final Bits exit_uninits = new Bits(true);
   1.173 +
   1.174 +            public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
   1.175 +                super(tree);
   1.176 +                this.inits = inits;
   1.177 +                this.uninits = uninits;
   1.178 +                this.exit_inits.assign(inits);
   1.179 +                this.exit_uninits.assign(uninits);
   1.180 +            }
   1.181 +
   1.182 +            @Override
   1.183 +            public void resolveJump(JCTree tree) {
   1.184 +                inits.andSet(exit_inits);
   1.185 +                uninits.andSet(exit_uninits);
   1.186 +            }
   1.187 +        }
   1.188 +
   1.189 +        public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) {
   1.190 +            this.inits = inits;
   1.191              uninits = new Bits();
   1.192              uninitsTry = new Bits();
   1.193              initsWhenTrue = new Bits(true);
   1.194              initsWhenFalse = new Bits(true);
   1.195              uninitsWhenTrue = new Bits(true);
   1.196              uninitsWhenFalse = new Bits(true);
   1.197 -        }
   1.198 -
   1.199 -        class AssignPendingExit extends BaseAnalyzer.PendingExit {
   1.200 -
   1.201 -            final Bits exit_inits = new Bits(true);
   1.202 -            final Bits exit_uninits = new Bits(true);
   1.203 -
   1.204 -            AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
   1.205 -                super(tree);
   1.206 -                this.exit_inits.assign(inits);
   1.207 -                this.exit_uninits.assign(uninits);
   1.208 -            }
   1.209 -
   1.210 -            void resolveJump() {
   1.211 -                inits.andSet(exit_inits);
   1.212 -                uninits.andSet(exit_uninits);
   1.213 -            }
   1.214 +            this.syms = syms;
   1.215 +            this.names = names;
   1.216          }
   1.217  
   1.218          @Override
   1.219 -        void markDead() {
   1.220 +        protected void markDead(JCTree tree) {
   1.221              inits.inclRange(returnadr, nextadr);
   1.222              uninits.inclRange(returnadr, nextadr);
   1.223          }
   1.224 @@ -1468,7 +1472,7 @@
   1.225          /** Do we need to track init/uninit state of this symbol?
   1.226           *  I.e. is symbol either a local or a blank final variable?
   1.227           */
   1.228 -        boolean trackable(VarSymbol sym) {
   1.229 +        protected boolean trackable(VarSymbol sym) {
   1.230              return
   1.231                  sym.pos >= startPos &&
   1.232                  ((sym.owner.kind == MTH ||
   1.233 @@ -1488,44 +1492,35 @@
   1.234              }
   1.235              sym.adr = nextadr;
   1.236              vardecls[nextadr] = varDecl;
   1.237 -            inits.excl(nextadr);
   1.238 +            exclVarFromInits(varDecl, nextadr);
   1.239              uninits.incl(nextadr);
   1.240              nextadr++;
   1.241          }
   1.242  
   1.243 +        protected void exclVarFromInits(JCTree tree, int adr) {
   1.244 +            inits.excl(adr);
   1.245 +        }
   1.246 +
   1.247 +        protected void assignToInits(JCTree tree, Bits bits) {
   1.248 +            inits.assign(bits);
   1.249 +        }
   1.250 +
   1.251 +        protected void andSetInits(JCTree tree, Bits bits) {
   1.252 +            inits.andSet(bits);
   1.253 +        }
   1.254 +
   1.255 +        protected void orSetInits(JCTree tree, Bits bits) {
   1.256 +            inits.orSet(bits);
   1.257 +        }
   1.258 +
   1.259          /** Record an initialization of a trackable variable.
   1.260           */
   1.261          void letInit(DiagnosticPosition pos, VarSymbol sym) {
   1.262              if (sym.adr >= firstadr && trackable(sym)) {
   1.263 -                if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
   1.264 -                    if (!uninits.isMember(sym.adr)) {
   1.265 -                        //assignment targeting an effectively final variable
   1.266 -                        //makes the variable lose its status of effectively final
   1.267 -                        //if the variable is _not_ definitively unassigned
   1.268 -                        sym.flags_field &= ~EFFECTIVELY_FINAL;
   1.269 -                    } else {
   1.270 -                        uninit(sym);
   1.271 -                    }
   1.272 -                }
   1.273 -                else if ((sym.flags() & FINAL) != 0) {
   1.274 -                    if ((sym.flags() & PARAMETER) != 0) {
   1.275 -                        if ((sym.flags() & UNION) != 0) { //multi-catch parameter
   1.276 -                            log.error(pos, "multicatch.parameter.may.not.be.assigned",
   1.277 -                                      sym);
   1.278 -                        }
   1.279 -                        else {
   1.280 -                            log.error(pos, "final.parameter.may.not.be.assigned",
   1.281 -                                  sym);
   1.282 -                        }
   1.283 -                    } else if (!uninits.isMember(sym.adr)) {
   1.284 -                        log.error(pos, flowKind.errKey, sym);
   1.285 -                    } else {
   1.286 -                        uninit(sym);
   1.287 -                    }
   1.288 +                if (uninits.isMember(sym.adr)) {
   1.289 +                    uninit(sym);
   1.290                  }
   1.291                  inits.incl(sym.adr);
   1.292 -            } else if ((sym.flags() & FINAL) != 0) {
   1.293 -                log.error(pos, "var.might.already.be.assigned", sym);
   1.294              }
   1.295          }
   1.296          //where
   1.297 @@ -1559,12 +1554,14 @@
   1.298          void checkInit(DiagnosticPosition pos, VarSymbol sym) {
   1.299              checkInit(pos, sym, "var.might.not.have.been.initialized");
   1.300          }
   1.301 -        void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
   1.302 -            if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
   1.303 -                trackable(sym) &&
   1.304 -                !inits.isMember(sym.adr)) {
   1.305 -                log.error(pos, errkey, sym);
   1.306 -                inits.incl(sym.adr);
   1.307 +
   1.308 +        void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {}
   1.309 +
   1.310 +        /** Utility method to reset several Bits instances.
   1.311 +         */
   1.312 +        private void resetBits(Bits... bits) {
   1.313 +            for (Bits b : bits) {
   1.314 +                b.reset();
   1.315              }
   1.316          }
   1.317  
   1.318 @@ -1582,7 +1579,7 @@
   1.319  
   1.320          /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
   1.321           */
   1.322 -        void merge() {
   1.323 +        protected void merge(JCTree tree) {
   1.324              inits.assign(initsWhenFalse.andSet(initsWhenTrue));
   1.325              uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
   1.326          }
   1.327 @@ -1597,7 +1594,9 @@
   1.328          void scanExpr(JCTree tree) {
   1.329              if (tree != null) {
   1.330                  scan(tree);
   1.331 -                if (inits.isReset()) merge();
   1.332 +                if (inits.isReset()) {
   1.333 +                    merge(tree);
   1.334 +                }
   1.335              }
   1.336          }
   1.337  
   1.338 @@ -1614,7 +1613,7 @@
   1.339           */
   1.340          void scanCond(JCTree tree) {
   1.341              if (tree.type.isFalse()) {
   1.342 -                if (inits.isReset()) merge();
   1.343 +                if (inits.isReset()) merge(tree);
   1.344                  initsWhenTrue.assign(inits);
   1.345                  initsWhenTrue.inclRange(firstadr, nextadr);
   1.346                  uninitsWhenTrue.assign(uninits);
   1.347 @@ -1622,7 +1621,7 @@
   1.348                  initsWhenFalse.assign(inits);
   1.349                  uninitsWhenFalse.assign(uninits);
   1.350              } else if (tree.type.isTrue()) {
   1.351 -                if (inits.isReset()) merge();
   1.352 +                if (inits.isReset()) merge(tree);
   1.353                  initsWhenFalse.assign(inits);
   1.354                  initsWhenFalse.inclRange(firstadr, nextadr);
   1.355                  uninitsWhenFalse.assign(uninits);
   1.356 @@ -1641,22 +1640,22 @@
   1.357  
   1.358          /* ------------ Visitor methods for various sorts of trees -------------*/
   1.359  
   1.360 +        @Override
   1.361          public void visitClassDef(JCClassDecl tree) {
   1.362 -            if (tree.sym == null) return;
   1.363 +            if (tree.sym == null) {
   1.364 +                return;
   1.365 +            }
   1.366  
   1.367              JCClassDecl classDefPrev = classDef;
   1.368              int firstadrPrev = firstadr;
   1.369              int nextadrPrev = nextadr;
   1.370 -            ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
   1.371 -            Lint lintPrev = lint;
   1.372 +            ListBuffer<P> pendingExitsPrev = pendingExits;
   1.373  
   1.374 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.375 +            pendingExits = new ListBuffer<P>();
   1.376              if (tree.name != names.empty) {
   1.377                  firstadr = nextadr;
   1.378              }
   1.379              classDef = tree;
   1.380 -            lint = lint.augment(tree.sym);
   1.381 -
   1.382              try {
   1.383                  // define all the static fields
   1.384                  for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   1.385 @@ -1664,8 +1663,9 @@
   1.386                          JCVariableDecl def = (JCVariableDecl)l.head;
   1.387                          if ((def.mods.flags & STATIC) != 0) {
   1.388                              VarSymbol sym = def.sym;
   1.389 -                            if (trackable(sym))
   1.390 +                            if (trackable(sym)) {
   1.391                                  newVar(def);
   1.392 +                            }
   1.393                          }
   1.394                      }
   1.395                  }
   1.396 @@ -1684,8 +1684,9 @@
   1.397                          JCVariableDecl def = (JCVariableDecl)l.head;
   1.398                          if ((def.mods.flags & STATIC) == 0) {
   1.399                              VarSymbol sym = def.sym;
   1.400 -                            if (trackable(sym))
   1.401 +                            if (trackable(sym)) {
   1.402                                  newVar(def);
   1.403 +                            }
   1.404                          }
   1.405                      }
   1.406                  }
   1.407 @@ -1709,21 +1710,25 @@
   1.408                  nextadr = nextadrPrev;
   1.409                  firstadr = firstadrPrev;
   1.410                  classDef = classDefPrev;
   1.411 -                lint = lintPrev;
   1.412              }
   1.413          }
   1.414  
   1.415 +        @Override
   1.416          public void visitMethodDef(JCMethodDecl tree) {
   1.417 -            if (tree.body == null) return;
   1.418 +            if (tree.body == null) {
   1.419 +                return;
   1.420 +            }
   1.421 +            /*  MemberEnter can generate synthetic methods, ignore them
   1.422 +             */
   1.423 +            if ((tree.sym.flags() & SYNTHETIC) != 0) {
   1.424 +                return;
   1.425 +            }
   1.426  
   1.427              final Bits initsPrev = new Bits(inits);
   1.428              final Bits uninitsPrev = new Bits(uninits);
   1.429              int nextadrPrev = nextadr;
   1.430              int firstadrPrev = firstadr;
   1.431              int returnadrPrev = returnadr;
   1.432 -            Lint lintPrev = lint;
   1.433 -
   1.434 -            lint = lint.augment(tree.sym);
   1.435  
   1.436              Assert.check(pendingExits.isEmpty());
   1.437  
   1.438 @@ -1731,13 +1736,17 @@
   1.439                  boolean isInitialConstructor =
   1.440                      TreeInfo.isInitialConstructor(tree);
   1.441  
   1.442 -                if (!isInitialConstructor)
   1.443 +                if (!isInitialConstructor) {
   1.444                      firstadr = nextadr;
   1.445 +                }
   1.446                  for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
   1.447                      JCVariableDecl def = l.head;
   1.448                      scan(def);
   1.449 -                    inits.incl(def.sym.adr);
   1.450 -                    uninits.excl(def.sym.adr);
   1.451 +                    Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
   1.452 +                    /*  If we are executing the code from Gen, then there can be
   1.453 +                     *  synthetic or mandated variables, ignore them.
   1.454 +                     */
   1.455 +                    initParam(def);
   1.456                  }
   1.457                  // else we are in an instance initializer block;
   1.458                  // leave caught unchanged.
   1.459 @@ -1761,39 +1770,42 @@
   1.460                          }
   1.461                      }
   1.462                  }
   1.463 -                List<AssignPendingExit> exits = pendingExits.toList();
   1.464 -                pendingExits = new ListBuffer<AssignPendingExit>();
   1.465 +                List<P> exits = pendingExits.toList();
   1.466 +                pendingExits = new ListBuffer<>();
   1.467                  while (exits.nonEmpty()) {
   1.468 -                    AssignPendingExit exit = exits.head;
   1.469 +                    P exit = exits.head;
   1.470                      exits = exits.tail;
   1.471                      Assert.check(exit.tree.hasTag(RETURN), exit.tree);
   1.472                      if (isInitialConstructor) {
   1.473 -                        inits.assign(exit.exit_inits);
   1.474 -                        for (int i = firstadr; i < nextadr; i++)
   1.475 +                        assignToInits(exit.tree, exit.exit_inits);
   1.476 +                        for (int i = firstadr; i < nextadr; i++) {
   1.477                              checkInit(exit.tree.pos(), vardecls[i].sym);
   1.478 +                        }
   1.479                      }
   1.480                  }
   1.481              } finally {
   1.482 -                inits.assign(initsPrev);
   1.483 +                assignToInits(tree, initsPrev);
   1.484                  uninits.assign(uninitsPrev);
   1.485                  nextadr = nextadrPrev;
   1.486                  firstadr = firstadrPrev;
   1.487                  returnadr = returnadrPrev;
   1.488 -                lint = lintPrev;
   1.489              }
   1.490          }
   1.491  
   1.492 +        protected void initParam(JCVariableDecl def) {
   1.493 +            inits.incl(def.sym.adr);
   1.494 +            uninits.excl(def.sym.adr);
   1.495 +        }
   1.496 +
   1.497          public void visitVarDef(JCVariableDecl tree) {
   1.498              boolean track = trackable(tree.sym);
   1.499 -            if (track && tree.sym.owner.kind == MTH) newVar(tree);
   1.500 +            if (track && tree.sym.owner.kind == MTH) {
   1.501 +                newVar(tree);
   1.502 +            }
   1.503              if (tree.init != null) {
   1.504 -                Lint lintPrev = lint;
   1.505 -                lint = lint.augment(tree.sym);
   1.506 -                try{
   1.507 -                    scanExpr(tree.init);
   1.508 -                    if (track) letInit(tree.pos(), tree.sym);
   1.509 -                } finally {
   1.510 -                    lint = lintPrev;
   1.511 +                scanExpr(tree.init);
   1.512 +                if (track) {
   1.513 +                    letInit(tree.pos(), tree.sym);
   1.514                  }
   1.515              }
   1.516          }
   1.517 @@ -1804,14 +1816,18 @@
   1.518              nextadr = nextadrPrev;
   1.519          }
   1.520  
   1.521 +        int getLogNumberOfErrors() {
   1.522 +            return 0;
   1.523 +        }
   1.524 +
   1.525          public void visitDoLoop(JCDoWhileLoop tree) {
   1.526 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.527 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.528              FlowKind prevFlowKind = flowKind;
   1.529              flowKind = FlowKind.NORMAL;
   1.530              final Bits initsSkip = new Bits(true);
   1.531              final Bits uninitsSkip = new Bits(true);
   1.532 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.533 -            int prevErrors = log.nerrors;
   1.534 +            pendingExits = new ListBuffer<P>();
   1.535 +            int prevErrors = getLogNumberOfErrors();
   1.536              do {
   1.537                  final Bits uninitsEntry = new Bits(uninits);
   1.538                  uninitsEntry.excludeFrom(nextadr);
   1.539 @@ -1822,28 +1838,28 @@
   1.540                      initsSkip.assign(initsWhenFalse);
   1.541                      uninitsSkip.assign(uninitsWhenFalse);
   1.542                  }
   1.543 -                if (log.nerrors !=  prevErrors ||
   1.544 +                if (getLogNumberOfErrors() !=  prevErrors ||
   1.545                      flowKind.isFinal() ||
   1.546                      new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
   1.547                      break;
   1.548 -                inits.assign(initsWhenTrue);
   1.549 +                assignToInits(tree.cond, initsWhenTrue);
   1.550                  uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
   1.551                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.552              } while (true);
   1.553              flowKind = prevFlowKind;
   1.554 -            inits.assign(initsSkip);
   1.555 +            assignToInits(tree, initsSkip);
   1.556              uninits.assign(uninitsSkip);
   1.557              resolveBreaks(tree, prevPendingExits);
   1.558          }
   1.559  
   1.560          public void visitWhileLoop(JCWhileLoop tree) {
   1.561 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.562 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.563              FlowKind prevFlowKind = flowKind;
   1.564              flowKind = FlowKind.NORMAL;
   1.565              final Bits initsSkip = new Bits(true);
   1.566              final Bits uninitsSkip = new Bits(true);
   1.567 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.568 -            int prevErrors = log.nerrors;
   1.569 +            pendingExits = new ListBuffer<>();
   1.570 +            int prevErrors = getLogNumberOfErrors();
   1.571              final Bits uninitsEntry = new Bits(uninits);
   1.572              uninitsEntry.excludeFrom(nextadr);
   1.573              do {
   1.574 @@ -1852,35 +1868,36 @@
   1.575                      initsSkip.assign(initsWhenFalse) ;
   1.576                      uninitsSkip.assign(uninitsWhenFalse);
   1.577                  }
   1.578 -                inits.assign(initsWhenTrue);
   1.579 +                assignToInits(tree, initsWhenTrue);
   1.580                  uninits.assign(uninitsWhenTrue);
   1.581                  scan(tree.body);
   1.582                  resolveContinues(tree);
   1.583 -                if (log.nerrors != prevErrors ||
   1.584 +                if (getLogNumberOfErrors() != prevErrors ||
   1.585                      flowKind.isFinal() ||
   1.586 -                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.587 +                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
   1.588                      break;
   1.589 +                }
   1.590                  uninits.assign(uninitsEntry.andSet(uninits));
   1.591                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.592              } while (true);
   1.593              flowKind = prevFlowKind;
   1.594              //a variable is DA/DU after the while statement, if it's DA/DU assuming the
   1.595              //branch is not taken AND if it's DA/DU before any break statement
   1.596 -            inits.assign(initsSkip);
   1.597 +            assignToInits(tree.body, initsSkip);
   1.598              uninits.assign(uninitsSkip);
   1.599              resolveBreaks(tree, prevPendingExits);
   1.600          }
   1.601  
   1.602          public void visitForLoop(JCForLoop tree) {
   1.603 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.604 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.605              FlowKind prevFlowKind = flowKind;
   1.606              flowKind = FlowKind.NORMAL;
   1.607              int nextadrPrev = nextadr;
   1.608              scan(tree.init);
   1.609              final Bits initsSkip = new Bits(true);
   1.610              final Bits uninitsSkip = new Bits(true);
   1.611 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.612 -            int prevErrors = log.nerrors;
   1.613 +            pendingExits = new ListBuffer<P>();
   1.614 +            int prevErrors = getLogNumberOfErrors();
   1.615              do {
   1.616                  final Bits uninitsEntry = new Bits(uninits);
   1.617                  uninitsEntry.excludeFrom(nextadr);
   1.618 @@ -1890,7 +1907,7 @@
   1.619                          initsSkip.assign(initsWhenFalse);
   1.620                          uninitsSkip.assign(uninitsWhenFalse);
   1.621                      }
   1.622 -                    inits.assign(initsWhenTrue);
   1.623 +                    assignToInits(tree.body, initsWhenTrue);
   1.624                      uninits.assign(uninitsWhenTrue);
   1.625                  } else if (!flowKind.isFinal()) {
   1.626                      initsSkip.assign(inits);
   1.627 @@ -1901,7 +1918,7 @@
   1.628                  scan(tree.body);
   1.629                  resolveContinues(tree);
   1.630                  scan(tree.step);
   1.631 -                if (log.nerrors != prevErrors ||
   1.632 +                if (getLogNumberOfErrors() != prevErrors ||
   1.633                      flowKind.isFinal() ||
   1.634                      new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.635                      break;
   1.636 @@ -1911,7 +1928,7 @@
   1.637              flowKind = prevFlowKind;
   1.638              //a variable is DA/DU after a for loop, if it's DA/DU assuming the
   1.639              //branch is not taken AND if it's DA/DU before any break statement
   1.640 -            inits.assign(initsSkip);
   1.641 +            assignToInits(tree.body, initsSkip);
   1.642              uninits.assign(uninitsSkip);
   1.643              resolveBreaks(tree, prevPendingExits);
   1.644              nextadr = nextadrPrev;
   1.645 @@ -1920,7 +1937,7 @@
   1.646          public void visitForeachLoop(JCEnhancedForLoop tree) {
   1.647              visitVarDef(tree.var);
   1.648  
   1.649 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.650 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.651              FlowKind prevFlowKind = flowKind;
   1.652              flowKind = FlowKind.NORMAL;
   1.653              int nextadrPrev = nextadr;
   1.654 @@ -1929,14 +1946,14 @@
   1.655              final Bits uninitsStart = new Bits(uninits);
   1.656  
   1.657              letInit(tree.pos(), tree.var.sym);
   1.658 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.659 -            int prevErrors = log.nerrors;
   1.660 +            pendingExits = new ListBuffer<P>();
   1.661 +            int prevErrors = getLogNumberOfErrors();
   1.662              do {
   1.663                  final Bits uninitsEntry = new Bits(uninits);
   1.664                  uninitsEntry.excludeFrom(nextadr);
   1.665                  scan(tree.body);
   1.666                  resolveContinues(tree);
   1.667 -                if (log.nerrors != prevErrors ||
   1.668 +                if (getLogNumberOfErrors() != prevErrors ||
   1.669                      flowKind.isFinal() ||
   1.670                      new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.671                      break;
   1.672 @@ -1944,41 +1961,50 @@
   1.673                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.674              } while (true);
   1.675              flowKind = prevFlowKind;
   1.676 -            inits.assign(initsStart);
   1.677 +            assignToInits(tree.body, initsStart);
   1.678              uninits.assign(uninitsStart.andSet(uninits));
   1.679              resolveBreaks(tree, prevPendingExits);
   1.680              nextadr = nextadrPrev;
   1.681          }
   1.682  
   1.683          public void visitLabelled(JCLabeledStatement tree) {
   1.684 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.685 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.686 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.687 +            pendingExits = new ListBuffer<P>();
   1.688              scan(tree.body);
   1.689              resolveBreaks(tree, prevPendingExits);
   1.690          }
   1.691  
   1.692          public void visitSwitch(JCSwitch tree) {
   1.693 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.694 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.695 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.696 +            pendingExits = new ListBuffer<>();
   1.697              int nextadrPrev = nextadr;
   1.698              scanExpr(tree.selector);
   1.699              final Bits initsSwitch = new Bits(inits);
   1.700              final Bits uninitsSwitch = new Bits(uninits);
   1.701              boolean hasDefault = false;
   1.702              for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
   1.703 -                inits.assign(initsSwitch);
   1.704 +                assignToInits(l.head, initsSwitch);
   1.705                  uninits.assign(uninits.andSet(uninitsSwitch));
   1.706                  JCCase c = l.head;
   1.707 -                if (c.pat == null)
   1.708 +                if (c.pat == null) {
   1.709                      hasDefault = true;
   1.710 -                else
   1.711 +                } else {
   1.712                      scanExpr(c.pat);
   1.713 +                }
   1.714 +                if (hasDefault) {
   1.715 +                    assignToInits(null, initsSwitch);
   1.716 +                    uninits.assign(uninits.andSet(uninitsSwitch));
   1.717 +                }
   1.718                  scan(c.stats);
   1.719                  addVars(c.stats, initsSwitch, uninitsSwitch);
   1.720 +                if (!hasDefault) {
   1.721 +                    assignToInits(l.head.stats.last(), initsSwitch);
   1.722 +                    uninits.assign(uninits.andSet(uninitsSwitch));
   1.723 +                }
   1.724                  // Warn about fall-through if lint switch fallthrough enabled.
   1.725              }
   1.726              if (!hasDefault) {
   1.727 -                inits.andSet(initsSwitch);
   1.728 +                andSetInits(null, initsSwitch);
   1.729              }
   1.730              resolveBreaks(tree, prevPendingExits);
   1.731              nextadr = nextadrPrev;
   1.732 @@ -1997,11 +2023,17 @@
   1.733                  }
   1.734              }
   1.735  
   1.736 +        boolean isEnabled(Lint.LintCategory lc) {
   1.737 +            return false;
   1.738 +        }
   1.739 +
   1.740 +        void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {}
   1.741 +
   1.742          public void visitTry(JCTry tree) {
   1.743              ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
   1.744              final Bits uninitsTryPrev = new Bits(uninitsTry);
   1.745 -            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.746 -            pendingExits = new ListBuffer<AssignPendingExit>();
   1.747 +            ListBuffer<P> prevPendingExits = pendingExits;
   1.748 +            pendingExits = new ListBuffer<>();
   1.749              final Bits initsTry = new Bits(inits);
   1.750              uninitsTry.assign(uninits);
   1.751              for (JCTree resource : tree.resources) {
   1.752 @@ -2023,10 +2055,10 @@
   1.753              int nextadrCatch = nextadr;
   1.754  
   1.755              if (!resourceVarDecls.isEmpty() &&
   1.756 -                    lint.isEnabled(Lint.LintCategory.TRY)) {
   1.757 +                    isEnabled(Lint.LintCategory.TRY)) {
   1.758                  for (JCVariableDecl resVar : resourceVarDecls) {
   1.759                      if (unrefdResources.includes(resVar.sym)) {
   1.760 -                        log.warning(Lint.LintCategory.TRY, resVar.pos(),
   1.761 +                        reportWarning(Lint.LintCategory.TRY, resVar.pos(),
   1.762                                      "try.resource.not.referenced", resVar.sym);
   1.763                          unrefdResources.remove(resVar.sym);
   1.764                      }
   1.765 @@ -2042,20 +2074,22 @@
   1.766  
   1.767              for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
   1.768                  JCVariableDecl param = l.head.param;
   1.769 -                inits.assign(initsCatchPrev);
   1.770 +                assignToInits(tree.body, initsCatchPrev);
   1.771                  uninits.assign(uninitsCatchPrev);
   1.772                  scan(param);
   1.773 -                inits.incl(param.sym.adr);
   1.774 -                uninits.excl(param.sym.adr);
   1.775 +                /* If this is a TWR and we are executing the code from Gen,
   1.776 +                 * then there can be synthetic variables, ignore them.
   1.777 +                 */
   1.778 +                initParam(param);
   1.779                  scan(l.head.body);
   1.780                  initsEnd.andSet(inits);
   1.781                  uninitsEnd.andSet(uninits);
   1.782                  nextadr = nextadrCatch;
   1.783              }
   1.784              if (tree.finalizer != null) {
   1.785 -                inits.assign(initsTry);
   1.786 +                assignToInits(tree.finalizer, initsTry);
   1.787                  uninits.assign(uninitsTry);
   1.788 -                ListBuffer<AssignPendingExit> exits = pendingExits;
   1.789 +                ListBuffer<P> exits = pendingExits;
   1.790                  pendingExits = prevPendingExits;
   1.791                  scan(tree.finalizer);
   1.792                  if (!tree.finallyCanCompleteNormally) {
   1.793 @@ -2065,19 +2099,19 @@
   1.794                      // FIX: this doesn't preserve source order of exits in catch
   1.795                      // versus finally!
   1.796                      while (exits.nonEmpty()) {
   1.797 -                        AssignPendingExit exit = exits.next();
   1.798 +                        P exit = exits.next();
   1.799                          if (exit.exit_inits != null) {
   1.800                              exit.exit_inits.orSet(inits);
   1.801                              exit.exit_uninits.andSet(uninits);
   1.802                          }
   1.803                          pendingExits.append(exit);
   1.804                      }
   1.805 -                    inits.orSet(initsEnd);
   1.806 +                    orSetInits(tree, initsEnd);
   1.807                  }
   1.808              } else {
   1.809 -                inits.assign(initsEnd);
   1.810 +                assignToInits(tree, initsEnd);
   1.811                  uninits.assign(uninitsEnd);
   1.812 -                ListBuffer<AssignPendingExit> exits = pendingExits;
   1.813 +                ListBuffer<P> exits = pendingExits;
   1.814                  pendingExits = prevPendingExits;
   1.815                  while (exits.nonEmpty()) pendingExits.append(exits.next());
   1.816              }
   1.817 @@ -2088,7 +2122,7 @@
   1.818              scanCond(tree.cond);
   1.819              final Bits initsBeforeElse = new Bits(initsWhenFalse);
   1.820              final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
   1.821 -            inits.assign(initsWhenTrue);
   1.822 +            assignToInits(tree.cond, initsWhenTrue);
   1.823              uninits.assign(uninitsWhenTrue);
   1.824              if (tree.truepart.type.hasTag(BOOLEAN) &&
   1.825                  tree.falsepart.type.hasTag(BOOLEAN)) {
   1.826 @@ -2101,7 +2135,7 @@
   1.827                  final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
   1.828                  final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
   1.829                  final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
   1.830 -                inits.assign(initsBeforeElse);
   1.831 +                assignToInits(tree.truepart, initsBeforeElse);
   1.832                  uninits.assign(uninitsBeforeElse);
   1.833                  scanCond(tree.falsepart);
   1.834                  initsWhenTrue.andSet(initsAfterThenWhenTrue);
   1.835 @@ -2112,10 +2146,10 @@
   1.836                  scanExpr(tree.truepart);
   1.837                  final Bits initsAfterThen = new Bits(inits);
   1.838                  final Bits uninitsAfterThen = new Bits(uninits);
   1.839 -                inits.assign(initsBeforeElse);
   1.840 +                assignToInits(tree.truepart, initsBeforeElse);
   1.841                  uninits.assign(uninitsBeforeElse);
   1.842                  scanExpr(tree.falsepart);
   1.843 -                inits.andSet(initsAfterThen);
   1.844 +                andSetInits(tree.falsepart, initsAfterThen);
   1.845                  uninits.andSet(uninitsAfterThen);
   1.846              }
   1.847          }
   1.848 @@ -2124,39 +2158,46 @@
   1.849              scanCond(tree.cond);
   1.850              final Bits initsBeforeElse = new Bits(initsWhenFalse);
   1.851              final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
   1.852 -            inits.assign(initsWhenTrue);
   1.853 +            assignToInits(tree.cond, initsWhenTrue);
   1.854              uninits.assign(uninitsWhenTrue);
   1.855              scan(tree.thenpart);
   1.856              if (tree.elsepart != null) {
   1.857                  final Bits initsAfterThen = new Bits(inits);
   1.858                  final Bits uninitsAfterThen = new Bits(uninits);
   1.859 -                inits.assign(initsBeforeElse);
   1.860 +                assignToInits(tree.thenpart, initsBeforeElse);
   1.861                  uninits.assign(uninitsBeforeElse);
   1.862                  scan(tree.elsepart);
   1.863 -                inits.andSet(initsAfterThen);
   1.864 +                andSetInits(tree.elsepart, initsAfterThen);
   1.865                  uninits.andSet(uninitsAfterThen);
   1.866              } else {
   1.867 -                inits.andSet(initsBeforeElse);
   1.868 +                andSetInits(tree.thenpart, initsBeforeElse);
   1.869                  uninits.andSet(uninitsBeforeElse);
   1.870              }
   1.871          }
   1.872  
   1.873 -        public void visitBreak(JCBreak tree) {
   1.874 -            recordExit(tree, new AssignPendingExit(tree, inits, uninits));
   1.875 +        protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
   1.876 +            return null;
   1.877          }
   1.878  
   1.879 -        public void visitContinue(JCContinue tree) {
   1.880 -            recordExit(tree, new AssignPendingExit(tree, inits, uninits));
   1.881 +        @Override
   1.882 +        public void visitBreak(JCBreak tree) {
   1.883 +            recordExit(tree, createNewPendingExit(tree, inits, uninits));
   1.884          }
   1.885  
   1.886 +        @Override
   1.887 +        public void visitContinue(JCContinue tree) {
   1.888 +            recordExit(tree, createNewPendingExit(tree, inits, uninits));
   1.889 +        }
   1.890 +
   1.891 +        @Override
   1.892          public void visitReturn(JCReturn tree) {
   1.893              scanExpr(tree.expr);
   1.894 -            recordExit(tree, new AssignPendingExit(tree, inits, uninits));
   1.895 +            recordExit(tree, createNewPendingExit(tree, inits, uninits));
   1.896          }
   1.897  
   1.898          public void visitThrow(JCThrow tree) {
   1.899              scanExpr(tree.expr);
   1.900 -            markDead();
   1.901 +            markDead(tree.expr);
   1.902          }
   1.903  
   1.904          public void visitApply(JCMethodInvocation tree) {
   1.905 @@ -2175,10 +2216,10 @@
   1.906              final Bits prevUninits = new Bits(uninits);
   1.907              final Bits prevInits = new Bits(inits);
   1.908              int returnadrPrev = returnadr;
   1.909 -            ListBuffer<AssignPendingExit> prevPending = pendingExits;
   1.910 +            ListBuffer<P> prevPending = pendingExits;
   1.911              try {
   1.912                  returnadr = nextadr;
   1.913 -                pendingExits = new ListBuffer<AssignPendingExit>();
   1.914 +                pendingExits = new ListBuffer<P>();
   1.915                  for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
   1.916                      JCVariableDecl def = l.head;
   1.917                      scan(def);
   1.918 @@ -2194,7 +2235,7 @@
   1.919              finally {
   1.920                  returnadr = returnadrPrev;
   1.921                  uninits.assign(prevUninits);
   1.922 -                inits.assign(prevInits);
   1.923 +                assignToInits(tree, prevInits);
   1.924                  pendingExits = prevPending;
   1.925              }
   1.926          }
   1.927 @@ -2210,11 +2251,11 @@
   1.928              scanCond(tree.cond);
   1.929              uninitsExit.andSet(uninitsWhenTrue);
   1.930              if (tree.detail != null) {
   1.931 -                inits.assign(initsWhenFalse);
   1.932 +                assignToInits(tree, initsWhenFalse);
   1.933                  uninits.assign(uninitsWhenFalse);
   1.934                  scanExpr(tree.detail);
   1.935              }
   1.936 -            inits.assign(initsExit);
   1.937 +            assignToInits(tree, initsExit);
   1.938              uninits.assign(uninitsExit);
   1.939          }
   1.940  
   1.941 @@ -2260,7 +2301,7 @@
   1.942                  scanCond(tree.lhs);
   1.943                  final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
   1.944                  final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
   1.945 -                inits.assign(initsWhenTrue);
   1.946 +                assignToInits(tree.lhs, initsWhenTrue);
   1.947                  uninits.assign(uninitsWhenTrue);
   1.948                  scanCond(tree.rhs);
   1.949                  initsWhenFalse.andSet(initsWhenFalseLeft);
   1.950 @@ -2270,7 +2311,7 @@
   1.951                  scanCond(tree.lhs);
   1.952                  final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
   1.953                  final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
   1.954 -                inits.assign(initsWhenFalse);
   1.955 +                assignToInits(tree.lhs, initsWhenFalse);
   1.956                  uninits.assign(uninitsWhenFalse);
   1.957                  scanCond(tree.rhs);
   1.958                  initsWhenTrue.andSet(initsWhenTrueLeft);
   1.959 @@ -2308,14 +2349,12 @@
   1.960  
   1.961          /** Perform definite assignment/unassignment analysis on a tree.
   1.962           */
   1.963 -        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
   1.964 -            analyzeTree(env, env.tree, make);
   1.965 -        }
   1.966 +        public void analyzeTree(Env<?> env) {
   1.967 +            analyzeTree(env, env.tree);
   1.968 +         }
   1.969  
   1.970 -        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
   1.971 +        public void analyzeTree(Env<?> env, JCTree tree) {
   1.972              try {
   1.973 -                attrEnv = env;
   1.974 -                Flow.this.make = make;
   1.975                  startPos = tree.pos().getStartPosition();
   1.976  
   1.977                  if (vardecls == null)
   1.978 @@ -2325,7 +2364,7 @@
   1.979                          vardecls[i] = null;
   1.980                  firstadr = 0;
   1.981                  nextadr = 0;
   1.982 -                pendingExits = new ListBuffer<AssignPendingExit>();
   1.983 +                pendingExits = new ListBuffer<>();
   1.984                  this.classDef = null;
   1.985                  unrefdResources = new Scope(env.enclClass.sym);
   1.986                  scan(tree);
   1.987 @@ -2334,18 +2373,160 @@
   1.988                  startPos = -1;
   1.989                  resetBits(inits, uninits, uninitsTry, initsWhenTrue,
   1.990                          initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
   1.991 -                if (vardecls != null) for (int i=0; i<vardecls.length; i++)
   1.992 -                    vardecls[i] = null;
   1.993 +                if (vardecls != null) {
   1.994 +                    for (int i=0; i<vardecls.length; i++)
   1.995 +                        vardecls[i] = null;
   1.996 +                }
   1.997                  firstadr = 0;
   1.998                  nextadr = 0;
   1.999                  pendingExits = null;
  1.1000 -                Flow.this.make = null;
  1.1001                  this.classDef = null;
  1.1002                  unrefdResources = null;
  1.1003              }
  1.1004          }
  1.1005      }
  1.1006  
  1.1007 +    public static class AssignAnalyzer
  1.1008 +        extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> {
  1.1009 +
  1.1010 +        Log log;
  1.1011 +        Lint lint;
  1.1012 +
  1.1013 +        public static class AssignPendingExit
  1.1014 +            extends AbstractAssignAnalyzer.AbstractAssignPendingExit {
  1.1015 +
  1.1016 +            public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
  1.1017 +                super(tree, inits, uninits);
  1.1018 +            }
  1.1019 +        }
  1.1020 +
  1.1021 +        public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) {
  1.1022 +            super(new Bits(), syms, names);
  1.1023 +            this.log = log;
  1.1024 +            this.lint = lint;
  1.1025 +        }
  1.1026 +
  1.1027 +        @Override
  1.1028 +        protected AssignPendingExit createNewPendingExit(JCTree tree,
  1.1029 +            Bits inits, Bits uninits) {
  1.1030 +            return new AssignPendingExit(tree, inits, uninits);
  1.1031 +        }
  1.1032 +
  1.1033 +        /** Record an initialization of a trackable variable.
  1.1034 +         */
  1.1035 +        @Override
  1.1036 +        void letInit(DiagnosticPosition pos, VarSymbol sym) {
  1.1037 +            if (sym.adr >= firstadr && trackable(sym)) {
  1.1038 +                if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
  1.1039 +                    if (!uninits.isMember(sym.adr)) {
  1.1040 +                        //assignment targeting an effectively final variable
  1.1041 +                        //makes the variable lose its status of effectively final
  1.1042 +                        //if the variable is _not_ definitively unassigned
  1.1043 +                        sym.flags_field &= ~EFFECTIVELY_FINAL;
  1.1044 +                    } else {
  1.1045 +                        uninit(sym);
  1.1046 +                    }
  1.1047 +                }
  1.1048 +                else if ((sym.flags() & FINAL) != 0) {
  1.1049 +                    if ((sym.flags() & PARAMETER) != 0) {
  1.1050 +                        if ((sym.flags() & UNION) != 0) { //multi-catch parameter
  1.1051 +                            log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
  1.1052 +                        }
  1.1053 +                        else {
  1.1054 +                            log.error(pos, "final.parameter.may.not.be.assigned",
  1.1055 +                                  sym);
  1.1056 +                        }
  1.1057 +                    } else if (!uninits.isMember(sym.adr)) {
  1.1058 +                        log.error(pos, flowKind.errKey, sym);
  1.1059 +                    } else {
  1.1060 +                        uninit(sym);
  1.1061 +                    }
  1.1062 +                }
  1.1063 +                inits.incl(sym.adr);
  1.1064 +            } else if ((sym.flags() & FINAL) != 0) {
  1.1065 +                log.error(pos, "var.might.already.be.assigned", sym);
  1.1066 +            }
  1.1067 +        }
  1.1068 +
  1.1069 +        @Override
  1.1070 +        void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
  1.1071 +            if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
  1.1072 +                trackable(sym) &&
  1.1073 +                !inits.isMember(sym.adr)) {
  1.1074 +                log.error(pos, errkey, sym);
  1.1075 +                inits.incl(sym.adr);
  1.1076 +            }
  1.1077 +        }
  1.1078 +
  1.1079 +        @Override
  1.1080 +        void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos,
  1.1081 +            String key, Object ... args) {
  1.1082 +            log.warning(lc, pos, key, args);
  1.1083 +        }
  1.1084 +
  1.1085 +        @Override
  1.1086 +        int getLogNumberOfErrors() {
  1.1087 +            return log.nerrors;
  1.1088 +        }
  1.1089 +
  1.1090 +        @Override
  1.1091 +        boolean isEnabled(Lint.LintCategory lc) {
  1.1092 +            return lint.isEnabled(lc);
  1.1093 +        }
  1.1094 +
  1.1095 +        @Override
  1.1096 +        public void visitClassDef(JCClassDecl tree) {
  1.1097 +            if (tree.sym == null) {
  1.1098 +                return;
  1.1099 +            }
  1.1100 +
  1.1101 +            Lint lintPrev = lint;
  1.1102 +            lint = lint.augment(tree.sym);
  1.1103 +            try {
  1.1104 +                super.visitClassDef(tree);
  1.1105 +            } finally {
  1.1106 +                lint = lintPrev;
  1.1107 +            }
  1.1108 +        }
  1.1109 +
  1.1110 +        @Override
  1.1111 +        public void visitMethodDef(JCMethodDecl tree) {
  1.1112 +            if (tree.body == null) {
  1.1113 +                return;
  1.1114 +            }
  1.1115 +
  1.1116 +            /*  MemberEnter can generate synthetic methods ignore them
  1.1117 +             */
  1.1118 +            if ((tree.sym.flags() & SYNTHETIC) != 0) {
  1.1119 +                return;
  1.1120 +            }
  1.1121 +
  1.1122 +            Lint lintPrev = lint;
  1.1123 +            lint = lint.augment(tree.sym);
  1.1124 +            try {
  1.1125 +                super.visitMethodDef(tree);
  1.1126 +            } finally {
  1.1127 +                lint = lintPrev;
  1.1128 +            }
  1.1129 +        }
  1.1130 +
  1.1131 +        @Override
  1.1132 +        public void visitVarDef(JCVariableDecl tree) {
  1.1133 +            if (tree.init == null) {
  1.1134 +                super.visitVarDef(tree);
  1.1135 +            } else {
  1.1136 +                Lint lintPrev = lint;
  1.1137 +                lint = lint.augment(tree.sym);
  1.1138 +                try{
  1.1139 +                    super.visitVarDef(tree);
  1.1140 +                } finally {
  1.1141 +                    lint = lintPrev;
  1.1142 +                }
  1.1143 +            }
  1.1144 +        }
  1.1145 +
  1.1146 +    }
  1.1147 +
  1.1148      /**
  1.1149       * This pass implements the last step of the dataflow analysis, namely
  1.1150       * the effectively-final analysis check. This checks that every local variable
  1.1151 @@ -2358,7 +2539,7 @@
  1.1152          JCTree currentTree; //local class or lambda
  1.1153  
  1.1154          @Override
  1.1155 -        void markDead() {
  1.1156 +        void markDead(JCTree tree) {
  1.1157              //do nothing
  1.1158          }
  1.1159  

mercurial