Flow.java revision 3398:a81036905c63
1/*
2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26//todo: one might eliminate uninits.andSets when monotonic
27
28package com.sun.tools.javac.comp;
29
30import java.util.HashMap;
31
32import com.sun.tools.javac.code.*;
33import com.sun.tools.javac.code.Scope.WriteableScope;
34import com.sun.tools.javac.tree.*;
35import com.sun.tools.javac.util.*;
36import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
37
38import com.sun.tools.javac.code.Symbol.*;
39import com.sun.tools.javac.tree.JCTree.*;
40
41import static com.sun.tools.javac.code.Flags.*;
42import static com.sun.tools.javac.code.Flags.BLOCK;
43import static com.sun.tools.javac.code.Kinds.Kind.*;
44import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
45import static com.sun.tools.javac.code.TypeTag.VOID;
46import static com.sun.tools.javac.tree.JCTree.Tag.*;
47
48/** This pass implements dataflow analysis for Java programs though
49 *  different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that
50 *  every statement is reachable. Exception analysis (see FlowAnalyzer) ensures that
51 *  every checked exception that is thrown is declared or caught.  Definite assignment analysis
52 *  (see AssignAnalyzer) ensures that each variable is assigned when used.  Definite
53 *  unassignment analysis (see AssignAnalyzer) in ensures that no final variable
54 *  is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
55 *  determines that local variables accessed within the scope of an inner class/lambda
56 *  are either final or effectively-final.
57 *
58 *  <p>The JLS has a number of problems in the
59 *  specification of these flow analysis problems. This implementation
60 *  attempts to address those issues.
61 *
62 *  <p>First, there is no accommodation for a finally clause that cannot
63 *  complete normally. For liveness analysis, an intervening finally
64 *  clause can cause a break, continue, or return not to reach its
65 *  target.  For exception analysis, an intervening finally clause can
66 *  cause any exception to be "caught".  For DA/DU analysis, the finally
67 *  clause can prevent a transfer of control from propagating DA/DU
68 *  state to the target.  In addition, code in the finally clause can
69 *  affect the DA/DU status of variables.
70 *
71 *  <p>For try statements, we introduce the idea of a variable being
72 *  definitely unassigned "everywhere" in a block.  A variable V is
73 *  "unassigned everywhere" in a block iff it is unassigned at the
74 *  beginning of the block and there is no reachable assignment to V
75 *  in the block.  An assignment V=e is reachable iff V is not DA
76 *  after e.  Then we can say that V is DU at the beginning of the
77 *  catch block iff V is DU everywhere in the try block.  Similarly, V
78 *  is DU at the beginning of the finally block iff V is DU everywhere
79 *  in the try block and in every catch block.  Specifically, the
80 *  following bullet is added to 16.2.2
81 *  <pre>
82 *      V is <em>unassigned everywhere</em> in a block if it is
83 *      unassigned before the block and there is no reachable
84 *      assignment to V within the block.
85 *  </pre>
86 *  <p>In 16.2.15, the third bullet (and all of its sub-bullets) for all
87 *  try blocks is changed to
88 *  <pre>
89 *      V is definitely unassigned before a catch block iff V is
90 *      definitely unassigned everywhere in the try block.
91 *  </pre>
92 *  <p>The last bullet (and all of its sub-bullets) for try blocks that
93 *  have a finally block is changed to
94 *  <pre>
95 *      V is definitely unassigned before the finally block iff
96 *      V is definitely unassigned everywhere in the try block
97 *      and everywhere in each catch block of the try statement.
98 *  </pre>
99 *  <p>In addition,
100 *  <pre>
101 *      V is definitely assigned at the end of a constructor iff
102 *      V is definitely assigned after the block that is the body
103 *      of the constructor and V is definitely assigned at every
104 *      return that can return from the constructor.
105 *  </pre>
106 *  <p>In addition, each continue statement with the loop as its target
107 *  is treated as a jump to the end of the loop body, and "intervening"
108 *  finally clauses are treated as follows: V is DA "due to the
109 *  continue" iff V is DA before the continue statement or V is DA at
110 *  the end of any intervening finally block.  V is DU "due to the
111 *  continue" iff any intervening finally cannot complete normally or V
112 *  is DU at the end of every intervening finally block.  This "due to
113 *  the continue" concept is then used in the spec for the loops.
114 *
115 *  <p>Similarly, break statements must consider intervening finally
116 *  blocks.  For liveness analysis, a break statement for which any
117 *  intervening finally cannot complete normally is not considered to
118 *  cause the target statement to be able to complete normally. Then
119 *  we say V is DA "due to the break" iff V is DA before the break or
120 *  V is DA at the end of any intervening finally block.  V is DU "due
121 *  to the break" iff any intervening finally cannot complete normally
122 *  or V is DU at the break and at the end of every intervening
123 *  finally block.  (I suspect this latter condition can be
124 *  simplified.)  This "due to the break" is then used in the spec for
125 *  all statements that can be "broken".
126 *
127 *  <p>The return statement is treated similarly.  V is DA "due to a
128 *  return statement" iff V is DA before the return statement or V is
129 *  DA at the end of any intervening finally block.  Note that we
130 *  don't have to worry about the return expression because this
131 *  concept is only used for construcrors.
132 *
133 *  <p>There is no spec in the JLS for when a variable is definitely
134 *  assigned at the end of a constructor, which is needed for final
135 *  fields (8.3.1.2).  We implement the rule that V is DA at the end
136 *  of the constructor iff it is DA and the end of the body of the
137 *  constructor and V is DA "due to" every return of the constructor.
138 *
139 *  <p>Intervening finally blocks similarly affect exception analysis.  An
140 *  intervening finally that cannot complete normally allows us to ignore
141 *  an otherwise uncaught exception.
142 *
143 *  <p>To implement the semantics of intervening finally clauses, all
144 *  nonlocal transfers (break, continue, return, throw, method call that
145 *  can throw a checked exception, and a constructor invocation that can
146 *  thrown a checked exception) are recorded in a queue, and removed
147 *  from the queue when we complete processing the target of the
148 *  nonlocal transfer.  This allows us to modify the queue in accordance
149 *  with the above rules when we encounter a finally clause.  The only
150 *  exception to this [no pun intended] is that checked exceptions that
151 *  are known to be caught or declared to be caught in the enclosing
152 *  method are not recorded in the queue, but instead are recorded in a
153 *  global variable "{@code Set<Type> thrown}" that records the type of all
154 *  exceptions that can be thrown.
155 *
156 *  <p>Other minor issues the treatment of members of other classes
157 *  (always considered DA except that within an anonymous class
158 *  constructor, where DA status from the enclosing scope is
159 *  preserved), treatment of the case expression (V is DA before the
160 *  case expression iff V is DA after the switch expression),
161 *  treatment of variables declared in a switch block (the implied
162 *  DA/DU status after the switch expression is DU and not DA for
163 *  variables defined in a switch block), the treatment of boolean ?:
164 *  expressions (The JLS rules only handle b and c non-boolean; the
165 *  new rule is that if b and c are boolean valued, then V is
166 *  (un)assigned after a?b:c when true/false iff V is (un)assigned
167 *  after b when true/false and V is (un)assigned after c when
168 *  true/false).
169 *
170 *  <p>There is the remaining question of what syntactic forms constitute a
171 *  reference to a variable.  It is conventional to allow this.x on the
172 *  left-hand-side to initialize a final instance field named x, yet
173 *  this.x isn't considered a "use" when appearing on a right-hand-side
174 *  in most implementations.  Should parentheses affect what is
175 *  considered a variable reference?  The simplest rule would be to
176 *  allow unqualified forms only, parentheses optional, and phase out
177 *  support for assigning to a final field via this.x.
178 *
179 *  <p><b>This is NOT part of any supported API.
180 *  If you write code that depends on this, you do so at your own risk.
181 *  This code and its internal interfaces are subject to change or
182 *  deletion without notice.</b>
183 */
184public class Flow {
185    protected static final Context.Key<Flow> flowKey = new Context.Key<>();
186
187    private final Names names;
188    private final Log log;
189    private final Symtab syms;
190    private final Types types;
191    private final Check chk;
192    private       TreeMaker make;
193    private final Resolve rs;
194    private final JCDiagnostic.Factory diags;
195    private Env<AttrContext> attrEnv;
196    private       Lint lint;
197    private final boolean allowImprovedRethrowAnalysis;
198    private final boolean allowImprovedCatchAnalysis;
199    private final boolean allowEffectivelyFinalInInnerClasses;
200    private final boolean enforceThisDotInit;
201
202    public static Flow instance(Context context) {
203        Flow instance = context.get(flowKey);
204        if (instance == null)
205            instance = new Flow(context);
206        return instance;
207    }
208
209    public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
210        new AliveAnalyzer().analyzeTree(env, make);
211        new AssignAnalyzer().analyzeTree(env);
212        new FlowAnalyzer().analyzeTree(env, make);
213        new CaptureAnalyzer().analyzeTree(env, make);
214    }
215
216    public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
217        Log.DiagnosticHandler diagHandler = null;
218        //we need to disable diagnostics temporarily; the problem is that if
219        //a lambda expression contains e.g. an unreachable statement, an error
220        //message will be reported and will cause compilation to skip the flow analyis
221        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
222        //related errors, which will allow for more errors to be detected
223        if (!speculative) {
224            diagHandler = new Log.DiscardDiagnosticHandler(log);
225        }
226        try {
227            new AliveAnalyzer().analyzeTree(env, that, make);
228        } finally {
229            if (!speculative) {
230                log.popDiagnosticHandler(diagHandler);
231            }
232        }
233    }
234
235    public List<Type> analyzeLambdaThrownTypes(final Env<AttrContext> env,
236            JCLambda that, TreeMaker make) {
237        //we need to disable diagnostics temporarily; the problem is that if
238        //a lambda expression contains e.g. an unreachable statement, an error
239        //message will be reported and will cause compilation to skip the flow analyis
240        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
241        //related errors, which will allow for more errors to be detected
242        Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
243        try {
244            new AssignAnalyzer() {
245                WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym);
246                @Override
247                public void visitVarDef(JCVariableDecl tree) {
248                    enclosedSymbols.enter(tree.sym);
249                    super.visitVarDef(tree);
250                }
251                @Override
252                protected boolean trackable(VarSymbol sym) {
253                    return enclosedSymbols.includes(sym) &&
254                           sym.owner.kind == MTH;
255                }
256            }.analyzeTree(env, that);
257            LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
258            flowAnalyzer.analyzeTree(env, that, make);
259            return flowAnalyzer.inferredThrownTypes;
260        } finally {
261            log.popDiagnosticHandler(diagHandler);
262        }
263    }
264
265    /**
266     * Definite assignment scan mode
267     */
268    enum FlowKind {
269        /**
270         * This is the normal DA/DU analysis mode
271         */
272        NORMAL("var.might.already.be.assigned", false),
273        /**
274         * This is the speculative DA/DU analysis mode used to speculatively
275         * derive assertions within loop bodies
276         */
277        SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true);
278
279        final String errKey;
280        final boolean isFinal;
281
282        FlowKind(String errKey, boolean isFinal) {
283            this.errKey = errKey;
284            this.isFinal = isFinal;
285        }
286
287        boolean isFinal() {
288            return isFinal;
289        }
290    }
291
292    protected Flow(Context context) {
293        context.put(flowKey, this);
294        names = Names.instance(context);
295        log = Log.instance(context);
296        syms = Symtab.instance(context);
297        types = Types.instance(context);
298        chk = Check.instance(context);
299        lint = Lint.instance(context);
300        rs = Resolve.instance(context);
301        diags = JCDiagnostic.Factory.instance(context);
302        Source source = Source.instance(context);
303        allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
304        allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
305        allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
306        enforceThisDotInit = source.enforceThisDotInit();
307    }
308
309    /**
310     * Base visitor class for all visitors implementing dataflow analysis logic.
311     * This class define the shared logic for handling jumps (break/continue statements).
312     */
313    static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
314
315        enum JumpKind {
316            BREAK(JCTree.Tag.BREAK) {
317                @Override
318                JCTree getTarget(JCTree tree) {
319                    return ((JCBreak)tree).target;
320                }
321            },
322            CONTINUE(JCTree.Tag.CONTINUE) {
323                @Override
324                JCTree getTarget(JCTree tree) {
325                    return ((JCContinue)tree).target;
326                }
327            };
328
329            final JCTree.Tag treeTag;
330
331            private JumpKind(Tag treeTag) {
332                this.treeTag = treeTag;
333            }
334
335            abstract JCTree getTarget(JCTree tree);
336        }
337
338        /** The currently pending exits that go from current inner blocks
339         *  to an enclosing block, in source order.
340         */
341        ListBuffer<P> pendingExits;
342
343        /** A pending exit.  These are the statements return, break, and
344         *  continue.  In addition, exception-throwing expressions or
345         *  statements are put here when not known to be caught.  This
346         *  will typically result in an error unless it is within a
347         *  try-finally whose finally block cannot complete normally.
348         */
349        static class PendingExit {
350            JCTree tree;
351
352            PendingExit(JCTree tree) {
353                this.tree = tree;
354            }
355
356            void resolveJump() {
357                //do nothing
358            }
359        }
360
361        abstract void markDead();
362
363        /** Record an outward transfer of control. */
364        void recordExit(P pe) {
365            pendingExits.append(pe);
366            markDead();
367        }
368
369        /** Resolve all jumps of this statement. */
370        private boolean resolveJump(JCTree tree,
371                        ListBuffer<P> oldPendingExits,
372                        JumpKind jk) {
373            boolean resolved = false;
374            List<P> exits = pendingExits.toList();
375            pendingExits = oldPendingExits;
376            for (; exits.nonEmpty(); exits = exits.tail) {
377                P exit = exits.head;
378                if (exit.tree.hasTag(jk.treeTag) &&
379                        jk.getTarget(exit.tree) == tree) {
380                    exit.resolveJump();
381                    resolved = true;
382                } else {
383                    pendingExits.append(exit);
384                }
385            }
386            return resolved;
387        }
388
389        /** Resolve all continues of this statement. */
390        boolean resolveContinues(JCTree tree) {
391            return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
392        }
393
394        /** Resolve all breaks of this statement. */
395        boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
396            return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
397        }
398
399        @Override
400        public void scan(JCTree tree) {
401            if (tree != null && (
402                    tree.type == null ||
403                    tree.type != Type.stuckType)) {
404                super.scan(tree);
405            }
406        }
407
408        public void visitPackageDef(JCPackageDecl tree) {
409            // Do nothing for PackageDecl
410        }
411    }
412
413    /**
414     * This pass implements the first step of the dataflow analysis, namely
415     * the liveness analysis check. This checks that every statement is reachable.
416     * The output of this analysis pass are used by other analyzers. This analyzer
417     * sets the 'finallyCanCompleteNormally' field in the JCTry class.
418     */
419    class AliveAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
420
421        /** A flag that indicates whether the last statement could
422         *  complete normally.
423         */
424        private boolean alive;
425
426        @Override
427        void markDead() {
428            alive = false;
429        }
430
431    /*************************************************************************
432     * Visitor methods for statements and definitions
433     *************************************************************************/
434
435        /** Analyze a definition.
436         */
437        void scanDef(JCTree tree) {
438            scanStat(tree);
439            if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
440                log.error(tree.pos(),
441                          "initializer.must.be.able.to.complete.normally");
442            }
443        }
444
445        /** Analyze a statement. Check that statement is reachable.
446         */
447        void scanStat(JCTree tree) {
448            if (!alive && tree != null) {
449                log.error(tree.pos(), "unreachable.stmt");
450                if (!tree.hasTag(SKIP)) alive = true;
451            }
452            scan(tree);
453        }
454
455        /** Analyze list of statements.
456         */
457        void scanStats(List<? extends JCStatement> trees) {
458            if (trees != null)
459                for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
460                    scanStat(l.head);
461        }
462
463        /* ------------ Visitor methods for various sorts of trees -------------*/
464
465        public void visitClassDef(JCClassDecl tree) {
466            if (tree.sym == null) return;
467            boolean alivePrev = alive;
468            ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
469            Lint lintPrev = lint;
470
471            pendingExits = new ListBuffer<>();
472            lint = lint.augment(tree.sym);
473
474            try {
475                // process all the static initializers
476                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
477                    if (!l.head.hasTag(METHODDEF) &&
478                        (TreeInfo.flags(l.head) & STATIC) != 0) {
479                        scanDef(l.head);
480                    }
481                }
482
483                // process all the instance initializers
484                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
485                    if (!l.head.hasTag(METHODDEF) &&
486                        (TreeInfo.flags(l.head) & STATIC) == 0) {
487                        scanDef(l.head);
488                    }
489                }
490
491                // process all the methods
492                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
493                    if (l.head.hasTag(METHODDEF)) {
494                        scan(l.head);
495                    }
496                }
497            } finally {
498                pendingExits = pendingExitsPrev;
499                alive = alivePrev;
500                lint = lintPrev;
501            }
502        }
503
504        public void visitMethodDef(JCMethodDecl tree) {
505            if (tree.body == null) return;
506            Lint lintPrev = lint;
507
508            lint = lint.augment(tree.sym);
509
510            Assert.check(pendingExits.isEmpty());
511
512            try {
513                alive = true;
514                scanStat(tree.body);
515
516                if (alive && !tree.sym.type.getReturnType().hasTag(VOID))
517                    log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
518
519                List<PendingExit> exits = pendingExits.toList();
520                pendingExits = new ListBuffer<>();
521                while (exits.nonEmpty()) {
522                    PendingExit exit = exits.head;
523                    exits = exits.tail;
524                    Assert.check(exit.tree.hasTag(RETURN));
525                }
526            } finally {
527                lint = lintPrev;
528            }
529        }
530
531        public void visitVarDef(JCVariableDecl tree) {
532            if (tree.init != null) {
533                Lint lintPrev = lint;
534                lint = lint.augment(tree.sym);
535                try{
536                    scan(tree.init);
537                } finally {
538                    lint = lintPrev;
539                }
540            }
541        }
542
543        public void visitBlock(JCBlock tree) {
544            scanStats(tree.stats);
545        }
546
547        public void visitDoLoop(JCDoWhileLoop tree) {
548            ListBuffer<PendingExit> prevPendingExits = pendingExits;
549            pendingExits = new ListBuffer<>();
550            scanStat(tree.body);
551            alive |= resolveContinues(tree);
552            scan(tree.cond);
553            alive = alive && !tree.cond.type.isTrue();
554            alive |= resolveBreaks(tree, prevPendingExits);
555        }
556
557        public void visitWhileLoop(JCWhileLoop tree) {
558            ListBuffer<PendingExit> prevPendingExits = pendingExits;
559            pendingExits = new ListBuffer<>();
560            scan(tree.cond);
561            alive = !tree.cond.type.isFalse();
562            scanStat(tree.body);
563            alive |= resolveContinues(tree);
564            alive = resolveBreaks(tree, prevPendingExits) ||
565                !tree.cond.type.isTrue();
566        }
567
568        public void visitForLoop(JCForLoop tree) {
569            ListBuffer<PendingExit> prevPendingExits = pendingExits;
570            scanStats(tree.init);
571            pendingExits = new ListBuffer<>();
572            if (tree.cond != null) {
573                scan(tree.cond);
574                alive = !tree.cond.type.isFalse();
575            } else {
576                alive = true;
577            }
578            scanStat(tree.body);
579            alive |= resolveContinues(tree);
580            scan(tree.step);
581            alive = resolveBreaks(tree, prevPendingExits) ||
582                tree.cond != null && !tree.cond.type.isTrue();
583        }
584
585        public void visitForeachLoop(JCEnhancedForLoop tree) {
586            visitVarDef(tree.var);
587            ListBuffer<PendingExit> prevPendingExits = pendingExits;
588            scan(tree.expr);
589            pendingExits = new ListBuffer<>();
590            scanStat(tree.body);
591            alive |= resolveContinues(tree);
592            resolveBreaks(tree, prevPendingExits);
593            alive = true;
594        }
595
596        public void visitLabelled(JCLabeledStatement tree) {
597            ListBuffer<PendingExit> prevPendingExits = pendingExits;
598            pendingExits = new ListBuffer<>();
599            scanStat(tree.body);
600            alive |= resolveBreaks(tree, prevPendingExits);
601        }
602
603        public void visitSwitch(JCSwitch tree) {
604            ListBuffer<PendingExit> prevPendingExits = pendingExits;
605            pendingExits = new ListBuffer<>();
606            scan(tree.selector);
607            boolean hasDefault = false;
608            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
609                alive = true;
610                JCCase c = l.head;
611                if (c.pat == null)
612                    hasDefault = true;
613                else
614                    scan(c.pat);
615                scanStats(c.stats);
616                // Warn about fall-through if lint switch fallthrough enabled.
617                if (alive &&
618                    lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
619                    c.stats.nonEmpty() && l.tail.nonEmpty())
620                    log.warning(Lint.LintCategory.FALLTHROUGH,
621                                l.tail.head.pos(),
622                                "possible.fall-through.into.case");
623            }
624            if (!hasDefault) {
625                alive = true;
626            }
627            alive |= resolveBreaks(tree, prevPendingExits);
628        }
629
630        public void visitTry(JCTry tree) {
631            ListBuffer<PendingExit> prevPendingExits = pendingExits;
632            pendingExits = new ListBuffer<>();
633            for (JCTree resource : tree.resources) {
634                if (resource instanceof JCVariableDecl) {
635                    JCVariableDecl vdecl = (JCVariableDecl) resource;
636                    visitVarDef(vdecl);
637                } else if (resource instanceof JCExpression) {
638                    scan((JCExpression) resource);
639                } else {
640                    throw new AssertionError(tree);  // parser error
641                }
642            }
643
644            scanStat(tree.body);
645            boolean aliveEnd = alive;
646
647            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
648                alive = true;
649                JCVariableDecl param = l.head.param;
650                scan(param);
651                scanStat(l.head.body);
652                aliveEnd |= alive;
653            }
654            if (tree.finalizer != null) {
655                ListBuffer<PendingExit> exits = pendingExits;
656                pendingExits = prevPendingExits;
657                alive = true;
658                scanStat(tree.finalizer);
659                tree.finallyCanCompleteNormally = alive;
660                if (!alive) {
661                    if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
662                        log.warning(Lint.LintCategory.FINALLY,
663                                TreeInfo.diagEndPos(tree.finalizer),
664                                "finally.cannot.complete");
665                    }
666                } else {
667                    while (exits.nonEmpty()) {
668                        pendingExits.append(exits.next());
669                    }
670                    alive = aliveEnd;
671                }
672            } else {
673                alive = aliveEnd;
674                ListBuffer<PendingExit> exits = pendingExits;
675                pendingExits = prevPendingExits;
676                while (exits.nonEmpty()) pendingExits.append(exits.next());
677            }
678        }
679
680        @Override
681        public void visitIf(JCIf tree) {
682            scan(tree.cond);
683            scanStat(tree.thenpart);
684            if (tree.elsepart != null) {
685                boolean aliveAfterThen = alive;
686                alive = true;
687                scanStat(tree.elsepart);
688                alive = alive | aliveAfterThen;
689            } else {
690                alive = true;
691            }
692        }
693
694        public void visitBreak(JCBreak tree) {
695            recordExit(new PendingExit(tree));
696        }
697
698        public void visitContinue(JCContinue tree) {
699            recordExit(new PendingExit(tree));
700        }
701
702        public void visitReturn(JCReturn tree) {
703            scan(tree.expr);
704            recordExit(new PendingExit(tree));
705        }
706
707        public void visitThrow(JCThrow tree) {
708            scan(tree.expr);
709            markDead();
710        }
711
712        public void visitApply(JCMethodInvocation tree) {
713            scan(tree.meth);
714            scan(tree.args);
715        }
716
717        public void visitNewClass(JCNewClass tree) {
718            scan(tree.encl);
719            scan(tree.args);
720            if (tree.def != null) {
721                scan(tree.def);
722            }
723        }
724
725        @Override
726        public void visitLambda(JCLambda tree) {
727            if (tree.type != null &&
728                    tree.type.isErroneous()) {
729                return;
730            }
731
732            ListBuffer<PendingExit> prevPending = pendingExits;
733            boolean prevAlive = alive;
734            try {
735                pendingExits = new ListBuffer<>();
736                alive = true;
737                scanStat(tree.body);
738                tree.canCompleteNormally = alive;
739            }
740            finally {
741                pendingExits = prevPending;
742                alive = prevAlive;
743            }
744        }
745
746        public void visitModuleDef(JCModuleDecl tree) {
747            // Do nothing for modules
748        }
749
750    /**************************************************************************
751     * main method
752     *************************************************************************/
753
754        /** Perform definite assignment/unassignment analysis on a tree.
755         */
756        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
757            analyzeTree(env, env.tree, make);
758        }
759        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
760            try {
761                attrEnv = env;
762                Flow.this.make = make;
763                pendingExits = new ListBuffer<>();
764                alive = true;
765                scan(tree);
766            } finally {
767                pendingExits = null;
768                Flow.this.make = null;
769            }
770        }
771    }
772
773    /**
774     * This pass implements the second step of the dataflow analysis, namely
775     * the exception analysis. This is to ensure that every checked exception that is
776     * thrown is declared or caught. The analyzer uses some info that has been set by
777     * the liveliness analyzer.
778     */
779    class FlowAnalyzer extends BaseAnalyzer<FlowAnalyzer.FlowPendingExit> {
780
781        /** A flag that indicates whether the last statement could
782         *  complete normally.
783         */
784        HashMap<Symbol, List<Type>> preciseRethrowTypes;
785
786        /** The current class being defined.
787         */
788        JCClassDecl classDef;
789
790        /** The list of possibly thrown declarable exceptions.
791         */
792        List<Type> thrown;
793
794        /** The list of exceptions that are either caught or declared to be
795         *  thrown.
796         */
797        List<Type> caught;
798
799        class FlowPendingExit extends BaseAnalyzer.PendingExit {
800
801            Type thrown;
802
803            FlowPendingExit(JCTree tree, Type thrown) {
804                super(tree);
805                this.thrown = thrown;
806            }
807        }
808
809        @Override
810        void markDead() {
811            //do nothing
812        }
813
814        /*-------------------- Exceptions ----------------------*/
815
816        /** Complain that pending exceptions are not caught.
817         */
818        void errorUncaught() {
819            for (FlowPendingExit exit = pendingExits.next();
820                 exit != null;
821                 exit = pendingExits.next()) {
822                if (classDef != null &&
823                    classDef.pos == exit.tree.pos) {
824                    log.error(exit.tree.pos(),
825                            "unreported.exception.default.constructor",
826                            exit.thrown);
827                } else if (exit.tree.hasTag(VARDEF) &&
828                        ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
829                    log.error(exit.tree.pos(),
830                            "unreported.exception.implicit.close",
831                            exit.thrown,
832                            ((JCVariableDecl)exit.tree).sym.name);
833                } else {
834                    log.error(exit.tree.pos(),
835                            "unreported.exception.need.to.catch.or.throw",
836                            exit.thrown);
837                }
838            }
839        }
840
841        /** Record that exception is potentially thrown and check that it
842         *  is caught.
843         */
844        void markThrown(JCTree tree, Type exc) {
845            if (!chk.isUnchecked(tree.pos(), exc)) {
846                if (!chk.isHandled(exc, caught)) {
847                    pendingExits.append(new FlowPendingExit(tree, exc));
848                }
849                thrown = chk.incl(exc, thrown);
850            }
851        }
852
853    /*************************************************************************
854     * Visitor methods for statements and definitions
855     *************************************************************************/
856
857        /* ------------ Visitor methods for various sorts of trees -------------*/
858
859        public void visitClassDef(JCClassDecl tree) {
860            if (tree.sym == null) return;
861
862            JCClassDecl classDefPrev = classDef;
863            List<Type> thrownPrev = thrown;
864            List<Type> caughtPrev = caught;
865            ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
866            Lint lintPrev = lint;
867
868            pendingExits = new ListBuffer<>();
869            if (tree.name != names.empty) {
870                caught = List.nil();
871            }
872            classDef = tree;
873            thrown = List.nil();
874            lint = lint.augment(tree.sym);
875
876            try {
877                // process all the static initializers
878                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
879                    if (!l.head.hasTag(METHODDEF) &&
880                        (TreeInfo.flags(l.head) & STATIC) != 0) {
881                        scan(l.head);
882                        errorUncaught();
883                    }
884                }
885
886                // add intersection of all thrown clauses of initial constructors
887                // to set of caught exceptions, unless class is anonymous.
888                if (tree.name != names.empty) {
889                    boolean firstConstructor = true;
890                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
891                        if (TreeInfo.isInitialConstructor(l.head)) {
892                            List<Type> mthrown =
893                                ((JCMethodDecl) l.head).sym.type.getThrownTypes();
894                            if (firstConstructor) {
895                                caught = mthrown;
896                                firstConstructor = false;
897                            } else {
898                                caught = chk.intersect(mthrown, caught);
899                            }
900                        }
901                    }
902                }
903
904                // process all the instance initializers
905                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
906                    if (!l.head.hasTag(METHODDEF) &&
907                        (TreeInfo.flags(l.head) & STATIC) == 0) {
908                        scan(l.head);
909                        errorUncaught();
910                    }
911                }
912
913                // in an anonymous class, add the set of thrown exceptions to
914                // the throws clause of the synthetic constructor and propagate
915                // outwards.
916                // Changing the throws clause on the fly is okay here because
917                // the anonymous constructor can't be invoked anywhere else,
918                // and its type hasn't been cached.
919                if (tree.name == names.empty) {
920                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
921                        if (TreeInfo.isInitialConstructor(l.head)) {
922                            JCMethodDecl mdef = (JCMethodDecl)l.head;
923                            mdef.thrown = make.Types(thrown);
924                            mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
925                        }
926                    }
927                    thrownPrev = chk.union(thrown, thrownPrev);
928                }
929
930                // process all the methods
931                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
932                    if (l.head.hasTag(METHODDEF)) {
933                        scan(l.head);
934                        errorUncaught();
935                    }
936                }
937
938                thrown = thrownPrev;
939            } finally {
940                pendingExits = pendingExitsPrev;
941                caught = caughtPrev;
942                classDef = classDefPrev;
943                lint = lintPrev;
944            }
945        }
946
947        public void visitMethodDef(JCMethodDecl tree) {
948            if (tree.body == null) return;
949
950            List<Type> caughtPrev = caught;
951            List<Type> mthrown = tree.sym.type.getThrownTypes();
952            Lint lintPrev = lint;
953
954            lint = lint.augment(tree.sym);
955
956            Assert.check(pendingExits.isEmpty());
957
958            try {
959                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
960                    JCVariableDecl def = l.head;
961                    scan(def);
962                }
963                if (TreeInfo.isInitialConstructor(tree))
964                    caught = chk.union(caught, mthrown);
965                else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
966                    caught = mthrown;
967                // else we are in an instance initializer block;
968                // leave caught unchanged.
969
970                scan(tree.body);
971
972                List<FlowPendingExit> exits = pendingExits.toList();
973                pendingExits = new ListBuffer<>();
974                while (exits.nonEmpty()) {
975                    FlowPendingExit exit = exits.head;
976                    exits = exits.tail;
977                    if (exit.thrown == null) {
978                        Assert.check(exit.tree.hasTag(RETURN));
979                    } else {
980                        // uncaught throws will be reported later
981                        pendingExits.append(exit);
982                    }
983                }
984            } finally {
985                caught = caughtPrev;
986                lint = lintPrev;
987            }
988        }
989
990        public void visitVarDef(JCVariableDecl tree) {
991            if (tree.init != null) {
992                Lint lintPrev = lint;
993                lint = lint.augment(tree.sym);
994                try{
995                    scan(tree.init);
996                } finally {
997                    lint = lintPrev;
998                }
999            }
1000        }
1001
1002        public void visitBlock(JCBlock tree) {
1003            scan(tree.stats);
1004        }
1005
1006        public void visitDoLoop(JCDoWhileLoop tree) {
1007            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1008            pendingExits = new ListBuffer<>();
1009            scan(tree.body);
1010            resolveContinues(tree);
1011            scan(tree.cond);
1012            resolveBreaks(tree, prevPendingExits);
1013        }
1014
1015        public void visitWhileLoop(JCWhileLoop tree) {
1016            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1017            pendingExits = new ListBuffer<>();
1018            scan(tree.cond);
1019            scan(tree.body);
1020            resolveContinues(tree);
1021            resolveBreaks(tree, prevPendingExits);
1022        }
1023
1024        public void visitForLoop(JCForLoop tree) {
1025            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1026            scan(tree.init);
1027            pendingExits = new ListBuffer<>();
1028            if (tree.cond != null) {
1029                scan(tree.cond);
1030            }
1031            scan(tree.body);
1032            resolveContinues(tree);
1033            scan(tree.step);
1034            resolveBreaks(tree, prevPendingExits);
1035        }
1036
1037        public void visitForeachLoop(JCEnhancedForLoop tree) {
1038            visitVarDef(tree.var);
1039            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1040            scan(tree.expr);
1041            pendingExits = new ListBuffer<>();
1042            scan(tree.body);
1043            resolveContinues(tree);
1044            resolveBreaks(tree, prevPendingExits);
1045        }
1046
1047        public void visitLabelled(JCLabeledStatement tree) {
1048            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1049            pendingExits = new ListBuffer<>();
1050            scan(tree.body);
1051            resolveBreaks(tree, prevPendingExits);
1052        }
1053
1054        public void visitSwitch(JCSwitch tree) {
1055            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1056            pendingExits = new ListBuffer<>();
1057            scan(tree.selector);
1058            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
1059                JCCase c = l.head;
1060                if (c.pat != null) {
1061                    scan(c.pat);
1062                }
1063                scan(c.stats);
1064            }
1065            resolveBreaks(tree, prevPendingExits);
1066        }
1067
1068        public void visitTry(JCTry tree) {
1069            List<Type> caughtPrev = caught;
1070            List<Type> thrownPrev = thrown;
1071            thrown = List.nil();
1072            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1073                List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1074                        ((JCTypeUnion)l.head.param.vartype).alternatives :
1075                        List.of(l.head.param.vartype);
1076                for (JCExpression ct : subClauses) {
1077                    caught = chk.incl(ct.type, caught);
1078                }
1079            }
1080
1081            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1082            pendingExits = new ListBuffer<>();
1083            for (JCTree resource : tree.resources) {
1084                if (resource instanceof JCVariableDecl) {
1085                    JCVariableDecl vdecl = (JCVariableDecl) resource;
1086                    visitVarDef(vdecl);
1087                } else if (resource instanceof JCExpression) {
1088                    scan((JCExpression) resource);
1089                } else {
1090                    throw new AssertionError(tree);  // parser error
1091                }
1092            }
1093            for (JCTree resource : tree.resources) {
1094                List<Type> closeableSupertypes = resource.type.isCompound() ?
1095                    types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1096                    List.of(resource.type);
1097                for (Type sup : closeableSupertypes) {
1098                    if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1099                        Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1100                                attrEnv,
1101                                sup,
1102                                names.close,
1103                                List.<Type>nil(),
1104                                List.<Type>nil());
1105                        Type mt = types.memberType(resource.type, closeMethod);
1106                        if (closeMethod.kind == MTH) {
1107                            for (Type t : mt.getThrownTypes()) {
1108                                markThrown(resource, t);
1109                            }
1110                        }
1111                    }
1112                }
1113            }
1114            scan(tree.body);
1115            List<Type> thrownInTry = allowImprovedCatchAnalysis ?
1116                chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
1117                thrown;
1118            thrown = thrownPrev;
1119            caught = caughtPrev;
1120
1121            List<Type> caughtInTry = List.nil();
1122            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1123                JCVariableDecl param = l.head.param;
1124                List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1125                        ((JCTypeUnion)l.head.param.vartype).alternatives :
1126                        List.of(l.head.param.vartype);
1127                List<Type> ctypes = List.nil();
1128                List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1129                for (JCExpression ct : subClauses) {
1130                    Type exc = ct.type;
1131                    if (exc != syms.unknownType) {
1132                        ctypes = ctypes.append(exc);
1133                        if (types.isSameType(exc, syms.objectType))
1134                            continue;
1135                        checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1136                        caughtInTry = chk.incl(exc, caughtInTry);
1137                    }
1138                }
1139                scan(param);
1140                preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1141                scan(l.head.body);
1142                preciseRethrowTypes.remove(param.sym);
1143            }
1144            if (tree.finalizer != null) {
1145                List<Type> savedThrown = thrown;
1146                thrown = List.nil();
1147                ListBuffer<FlowPendingExit> exits = pendingExits;
1148                pendingExits = prevPendingExits;
1149                scan(tree.finalizer);
1150                if (!tree.finallyCanCompleteNormally) {
1151                    // discard exits and exceptions from try and finally
1152                    thrown = chk.union(thrown, thrownPrev);
1153                } else {
1154                    thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1155                    thrown = chk.union(thrown, savedThrown);
1156                    // FIX: this doesn't preserve source order of exits in catch
1157                    // versus finally!
1158                    while (exits.nonEmpty()) {
1159                        pendingExits.append(exits.next());
1160                    }
1161                }
1162            } else {
1163                thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1164                ListBuffer<FlowPendingExit> exits = pendingExits;
1165                pendingExits = prevPendingExits;
1166                while (exits.nonEmpty()) pendingExits.append(exits.next());
1167            }
1168        }
1169
1170        @Override
1171        public void visitIf(JCIf tree) {
1172            scan(tree.cond);
1173            scan(tree.thenpart);
1174            if (tree.elsepart != null) {
1175                scan(tree.elsepart);
1176            }
1177        }
1178
1179        void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1180            if (chk.subset(exc, caughtInTry)) {
1181                log.error(pos, "except.already.caught", exc);
1182            } else if (!chk.isUnchecked(pos, exc) &&
1183                    !isExceptionOrThrowable(exc) &&
1184                    !chk.intersects(exc, thrownInTry)) {
1185                log.error(pos, "except.never.thrown.in.try", exc);
1186            } else if (allowImprovedCatchAnalysis) {
1187                List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
1188                // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
1189                // unchecked exception, the result list would not be empty, as the augmented
1190                // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1191                // exception, that would have been covered in the branch above
1192                if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1193                        !isExceptionOrThrowable(exc)) {
1194                    String key = catchableThrownTypes.length() == 1 ?
1195                            "unreachable.catch" :
1196                            "unreachable.catch.1";
1197                    log.warning(pos, key, catchableThrownTypes);
1198                }
1199            }
1200        }
1201        //where
1202            private boolean isExceptionOrThrowable(Type exc) {
1203                return exc.tsym == syms.throwableType.tsym ||
1204                    exc.tsym == syms.exceptionType.tsym;
1205            }
1206
1207        public void visitBreak(JCBreak tree) {
1208            recordExit(new FlowPendingExit(tree, null));
1209        }
1210
1211        public void visitContinue(JCContinue tree) {
1212            recordExit(new FlowPendingExit(tree, null));
1213        }
1214
1215        public void visitReturn(JCReturn tree) {
1216            scan(tree.expr);
1217            recordExit(new FlowPendingExit(tree, null));
1218        }
1219
1220        public void visitThrow(JCThrow tree) {
1221            scan(tree.expr);
1222            Symbol sym = TreeInfo.symbol(tree.expr);
1223            if (sym != null &&
1224                sym.kind == VAR &&
1225                (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1226                preciseRethrowTypes.get(sym) != null &&
1227                allowImprovedRethrowAnalysis) {
1228                for (Type t : preciseRethrowTypes.get(sym)) {
1229                    markThrown(tree, t);
1230                }
1231            }
1232            else {
1233                markThrown(tree, tree.expr.type);
1234            }
1235            markDead();
1236        }
1237
1238        public void visitApply(JCMethodInvocation tree) {
1239            scan(tree.meth);
1240            scan(tree.args);
1241            for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1242                markThrown(tree, l.head);
1243        }
1244
1245        public void visitNewClass(JCNewClass tree) {
1246            scan(tree.encl);
1247            scan(tree.args);
1248           // scan(tree.def);
1249            for (List<Type> l = tree.constructorType.getThrownTypes();
1250                 l.nonEmpty();
1251                 l = l.tail) {
1252                markThrown(tree, l.head);
1253            }
1254            List<Type> caughtPrev = caught;
1255            try {
1256                // If the new class expression defines an anonymous class,
1257                // analysis of the anonymous constructor may encounter thrown
1258                // types which are unsubstituted type variables.
1259                // However, since the constructor's actual thrown types have
1260                // already been marked as thrown, it is safe to simply include
1261                // each of the constructor's formal thrown types in the set of
1262                // 'caught/declared to be thrown' types, for the duration of
1263                // the class def analysis.
1264                if (tree.def != null)
1265                    for (List<Type> l = tree.constructor.type.getThrownTypes();
1266                         l.nonEmpty();
1267                         l = l.tail) {
1268                        caught = chk.incl(l.head, caught);
1269                    }
1270                scan(tree.def);
1271            }
1272            finally {
1273                caught = caughtPrev;
1274            }
1275        }
1276
1277        @Override
1278        public void visitLambda(JCLambda tree) {
1279            if (tree.type != null &&
1280                    tree.type.isErroneous()) {
1281                return;
1282            }
1283            List<Type> prevCaught = caught;
1284            List<Type> prevThrown = thrown;
1285            ListBuffer<FlowPendingExit> prevPending = pendingExits;
1286            try {
1287                pendingExits = new ListBuffer<>();
1288                caught = tree.getDescriptorType(types).getThrownTypes();
1289                thrown = List.nil();
1290                scan(tree.body);
1291                List<FlowPendingExit> exits = pendingExits.toList();
1292                pendingExits = new ListBuffer<>();
1293                while (exits.nonEmpty()) {
1294                    FlowPendingExit exit = exits.head;
1295                    exits = exits.tail;
1296                    if (exit.thrown == null) {
1297                        Assert.check(exit.tree.hasTag(RETURN));
1298                    } else {
1299                        // uncaught throws will be reported later
1300                        pendingExits.append(exit);
1301                    }
1302                }
1303
1304                errorUncaught();
1305            } finally {
1306                pendingExits = prevPending;
1307                caught = prevCaught;
1308                thrown = prevThrown;
1309            }
1310        }
1311
1312        public void visitModuleDef(JCModuleDecl tree) {
1313            // Do nothing for modules
1314        }
1315
1316    /**************************************************************************
1317     * main method
1318     *************************************************************************/
1319
1320        /** Perform definite assignment/unassignment analysis on a tree.
1321         */
1322        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
1323            analyzeTree(env, env.tree, make);
1324        }
1325        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
1326            try {
1327                attrEnv = env;
1328                Flow.this.make = make;
1329                pendingExits = new ListBuffer<>();
1330                preciseRethrowTypes = new HashMap<>();
1331                this.thrown = this.caught = null;
1332                this.classDef = null;
1333                scan(tree);
1334            } finally {
1335                pendingExits = null;
1336                Flow.this.make = null;
1337                this.thrown = this.caught = null;
1338                this.classDef = null;
1339            }
1340        }
1341    }
1342
1343    /**
1344     * Specialized pass that performs inference of thrown types for lambdas.
1345     */
1346    class LambdaFlowAnalyzer extends FlowAnalyzer {
1347        List<Type> inferredThrownTypes;
1348        boolean inLambda;
1349        @Override
1350        public void visitLambda(JCLambda tree) {
1351            if ((tree.type != null &&
1352                    tree.type.isErroneous()) || inLambda) {
1353                return;
1354            }
1355            List<Type> prevCaught = caught;
1356            List<Type> prevThrown = thrown;
1357            ListBuffer<FlowPendingExit> prevPending = pendingExits;
1358            inLambda = true;
1359            try {
1360                pendingExits = new ListBuffer<>();
1361                caught = List.of(syms.throwableType);
1362                thrown = List.nil();
1363                scan(tree.body);
1364                inferredThrownTypes = thrown;
1365            } finally {
1366                pendingExits = prevPending;
1367                caught = prevCaught;
1368                thrown = prevThrown;
1369                inLambda = false;
1370            }
1371        }
1372        @Override
1373        public void visitClassDef(JCClassDecl tree) {
1374            //skip
1375        }
1376    }
1377
1378    /**
1379     * This pass implements (i) definite assignment analysis, which ensures that
1380     * each variable is assigned when used and (ii) definite unassignment analysis,
1381     * which ensures that no final variable is assigned more than once. This visitor
1382     * depends on the results of the liveliness analyzer. This pass is also used to mark
1383     * effectively-final local variables/parameters.
1384     */
1385
1386    public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
1387
1388        /** The set of definitely assigned variables.
1389         */
1390        final Bits inits;
1391
1392        /** The set of definitely unassigned variables.
1393         */
1394        final Bits uninits;
1395
1396        /** The set of variables that are definitely unassigned everywhere
1397         *  in current try block. This variable is maintained lazily; it is
1398         *  updated only when something gets removed from uninits,
1399         *  typically by being assigned in reachable code.  To obtain the
1400         *  correct set of variables which are definitely unassigned
1401         *  anywhere in current try block, intersect uninitsTry and
1402         *  uninits.
1403         */
1404        final Bits uninitsTry;
1405
1406        /** When analyzing a condition, inits and uninits are null.
1407         *  Instead we have:
1408         */
1409        final Bits initsWhenTrue;
1410        final Bits initsWhenFalse;
1411        final Bits uninitsWhenTrue;
1412        final Bits uninitsWhenFalse;
1413
1414        /** A mapping from addresses to variable symbols.
1415         */
1416        protected JCVariableDecl[] vardecls;
1417
1418        /** The current class being defined.
1419         */
1420        JCClassDecl classDef;
1421
1422        /** The first variable sequence number in this class definition.
1423         */
1424        int firstadr;
1425
1426        /** The next available variable sequence number.
1427         */
1428        protected int nextadr;
1429
1430        /** The first variable sequence number in a block that can return.
1431         */
1432        protected int returnadr;
1433
1434        /** The list of unreferenced automatic resources.
1435         */
1436        WriteableScope unrefdResources;
1437
1438        /** Modified when processing a loop body the second time for DU analysis. */
1439        FlowKind flowKind = FlowKind.NORMAL;
1440
1441        /** The starting position of the analyzed tree */
1442        int startPos;
1443
1444        public class AssignPendingExit extends BaseAnalyzer.PendingExit {
1445
1446            final Bits inits;
1447            final Bits uninits;
1448            final Bits exit_inits = new Bits(true);
1449            final Bits exit_uninits = new Bits(true);
1450
1451            public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1452                super(tree);
1453                this.inits = inits;
1454                this.uninits = uninits;
1455                this.exit_inits.assign(inits);
1456                this.exit_uninits.assign(uninits);
1457            }
1458
1459            @Override
1460            public void resolveJump() {
1461                inits.andSet(exit_inits);
1462                uninits.andSet(exit_uninits);
1463            }
1464        }
1465
1466        public AssignAnalyzer() {
1467            this.inits = new Bits();
1468            uninits = new Bits();
1469            uninitsTry = new Bits();
1470            initsWhenTrue = new Bits(true);
1471            initsWhenFalse = new Bits(true);
1472            uninitsWhenTrue = new Bits(true);
1473            uninitsWhenFalse = new Bits(true);
1474        }
1475
1476        private boolean isInitialConstructor = false;
1477
1478        @Override
1479        protected void markDead() {
1480            if (!isInitialConstructor) {
1481                inits.inclRange(returnadr, nextadr);
1482            } else {
1483                for (int address = returnadr; address < nextadr; address++) {
1484                    if (!(isFinalUninitializedStaticField(vardecls[address].sym))) {
1485                        inits.incl(address);
1486                    }
1487                }
1488            }
1489            uninits.inclRange(returnadr, nextadr);
1490        }
1491
1492        /*-------------- Processing variables ----------------------*/
1493
1494        /** Do we need to track init/uninit state of this symbol?
1495         *  I.e. is symbol either a local or a blank final variable?
1496         */
1497        protected boolean trackable(VarSymbol sym) {
1498            return
1499                sym.pos >= startPos &&
1500                ((sym.owner.kind == MTH ||
1501                isFinalUninitializedField(sym)));
1502        }
1503
1504        boolean isFinalUninitializedField(VarSymbol sym) {
1505            return sym.owner.kind == TYP &&
1506                   ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
1507                   classDef.sym.isEnclosedBy((ClassSymbol)sym.owner));
1508        }
1509
1510        boolean isFinalUninitializedStaticField(VarSymbol sym) {
1511            return isFinalUninitializedField(sym) && sym.isStatic();
1512        }
1513
1514        /** Initialize new trackable variable by setting its address field
1515         *  to the next available sequence number and entering it under that
1516         *  index into the vars array.
1517         */
1518        void newVar(JCVariableDecl varDecl) {
1519            VarSymbol sym = varDecl.sym;
1520            vardecls = ArrayUtils.ensureCapacity(vardecls, nextadr);
1521            if ((sym.flags() & FINAL) == 0) {
1522                sym.flags_field |= EFFECTIVELY_FINAL;
1523            }
1524            sym.adr = nextadr;
1525            vardecls[nextadr] = varDecl;
1526            inits.excl(nextadr);
1527            uninits.incl(nextadr);
1528            nextadr++;
1529        }
1530
1531        /** Record an initialization of a trackable variable.
1532         */
1533        void letInit(DiagnosticPosition pos, VarSymbol sym) {
1534            if (sym.adr >= firstadr && trackable(sym)) {
1535                if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
1536                    if (!uninits.isMember(sym.adr)) {
1537                        //assignment targeting an effectively final variable
1538                        //makes the variable lose its status of effectively final
1539                        //if the variable is _not_ definitively unassigned
1540                        sym.flags_field &= ~EFFECTIVELY_FINAL;
1541                    } else {
1542                        uninit(sym);
1543                    }
1544                }
1545                else if ((sym.flags() & FINAL) != 0) {
1546                    if ((sym.flags() & PARAMETER) != 0) {
1547                        if ((sym.flags() & UNION) != 0) { //multi-catch parameter
1548                            log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
1549                        }
1550                        else {
1551                            log.error(pos, "final.parameter.may.not.be.assigned",
1552                                  sym);
1553                        }
1554                    } else if (!uninits.isMember(sym.adr)) {
1555                        log.error(pos, flowKind.errKey, sym);
1556                    } else {
1557                        uninit(sym);
1558                    }
1559                }
1560                inits.incl(sym.adr);
1561            } else if ((sym.flags() & FINAL) != 0) {
1562                log.error(pos, "var.might.already.be.assigned", sym);
1563            }
1564        }
1565        //where
1566            void uninit(VarSymbol sym) {
1567                if (!inits.isMember(sym.adr)) {
1568                    // reachable assignment
1569                    uninits.excl(sym.adr);
1570                    uninitsTry.excl(sym.adr);
1571                } else {
1572                    //log.rawWarning(pos, "unreachable assignment");//DEBUG
1573                    uninits.excl(sym.adr);
1574                }
1575            }
1576
1577        /** If tree is either a simple name or of the form this.name or
1578         *  C.this.name, and tree represents a trackable variable,
1579         *  record an initialization of the variable.
1580         */
1581        void letInit(JCTree tree) {
1582            tree = TreeInfo.skipParens(tree);
1583            if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
1584                Symbol sym = TreeInfo.symbol(tree);
1585                if (sym.kind == VAR) {
1586                    letInit(tree.pos(), (VarSymbol)sym);
1587                }
1588            }
1589        }
1590
1591        /** Check that trackable variable is initialized.
1592         */
1593        void checkInit(DiagnosticPosition pos, VarSymbol sym) {
1594            checkInit(pos, sym, "var.might.not.have.been.initialized");
1595        }
1596
1597        void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
1598            if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
1599                trackable(sym) &&
1600                !inits.isMember(sym.adr)) {
1601                log.error(pos, errkey, sym);
1602                inits.incl(sym.adr);
1603            }
1604        }
1605
1606        /** Utility method to reset several Bits instances.
1607         */
1608        private void resetBits(Bits... bits) {
1609            for (Bits b : bits) {
1610                b.reset();
1611            }
1612        }
1613
1614        /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
1615         */
1616        void split(boolean setToNull) {
1617            initsWhenFalse.assign(inits);
1618            uninitsWhenFalse.assign(uninits);
1619            initsWhenTrue.assign(inits);
1620            uninitsWhenTrue.assign(uninits);
1621            if (setToNull) {
1622                resetBits(inits, uninits);
1623            }
1624        }
1625
1626        /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1627         */
1628        protected void merge() {
1629            inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1630            uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1631        }
1632
1633    /* ************************************************************************
1634     * Visitor methods for statements and definitions
1635     *************************************************************************/
1636
1637        /** Analyze an expression. Make sure to set (un)inits rather than
1638         *  (un)initsWhenTrue(WhenFalse) on exit.
1639         */
1640        void scanExpr(JCTree tree) {
1641            if (tree != null) {
1642                scan(tree);
1643                if (inits.isReset()) {
1644                    merge();
1645                }
1646            }
1647        }
1648
1649        /** Analyze a list of expressions.
1650         */
1651        void scanExprs(List<? extends JCExpression> trees) {
1652            if (trees != null)
1653                for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
1654                    scanExpr(l.head);
1655        }
1656
1657        /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1658         *  rather than (un)inits on exit.
1659         */
1660        void scanCond(JCTree tree) {
1661            if (tree.type.isFalse()) {
1662                if (inits.isReset()) merge();
1663                initsWhenTrue.assign(inits);
1664                initsWhenTrue.inclRange(firstadr, nextadr);
1665                uninitsWhenTrue.assign(uninits);
1666                uninitsWhenTrue.inclRange(firstadr, nextadr);
1667                initsWhenFalse.assign(inits);
1668                uninitsWhenFalse.assign(uninits);
1669            } else if (tree.type.isTrue()) {
1670                if (inits.isReset()) merge();
1671                initsWhenFalse.assign(inits);
1672                initsWhenFalse.inclRange(firstadr, nextadr);
1673                uninitsWhenFalse.assign(uninits);
1674                uninitsWhenFalse.inclRange(firstadr, nextadr);
1675                initsWhenTrue.assign(inits);
1676                uninitsWhenTrue.assign(uninits);
1677            } else {
1678                scan(tree);
1679                if (!inits.isReset())
1680                    split(tree.type != syms.unknownType);
1681            }
1682            if (tree.type != syms.unknownType) {
1683                resetBits(inits, uninits);
1684            }
1685        }
1686
1687        /* ------------ Visitor methods for various sorts of trees -------------*/
1688
1689        public void visitClassDef(JCClassDecl tree) {
1690            if (tree.sym == null) {
1691                return;
1692            }
1693
1694            Lint lintPrev = lint;
1695            lint = lint.augment(tree.sym);
1696            try {
1697                if (tree.sym == null) {
1698                    return;
1699                }
1700
1701                JCClassDecl classDefPrev = classDef;
1702                int firstadrPrev = firstadr;
1703                int nextadrPrev = nextadr;
1704                ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
1705
1706                pendingExits = new ListBuffer<>();
1707                if (tree.name != names.empty) {
1708                    firstadr = nextadr;
1709                }
1710                classDef = tree;
1711                try {
1712                    // define all the static fields
1713                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1714                        if (l.head.hasTag(VARDEF)) {
1715                            JCVariableDecl def = (JCVariableDecl)l.head;
1716                            if ((def.mods.flags & STATIC) != 0) {
1717                                VarSymbol sym = def.sym;
1718                                if (trackable(sym)) {
1719                                    newVar(def);
1720                                }
1721                            }
1722                        }
1723                    }
1724
1725                    // process all the static initializers
1726                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1727                        if (!l.head.hasTag(METHODDEF) &&
1728                            (TreeInfo.flags(l.head) & STATIC) != 0) {
1729                            scan(l.head);
1730                        }
1731                    }
1732
1733                    // define all the instance fields
1734                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1735                        if (l.head.hasTag(VARDEF)) {
1736                            JCVariableDecl def = (JCVariableDecl)l.head;
1737                            if ((def.mods.flags & STATIC) == 0) {
1738                                VarSymbol sym = def.sym;
1739                                if (trackable(sym)) {
1740                                    newVar(def);
1741                                }
1742                            }
1743                        }
1744                    }
1745
1746                    // process all the instance initializers
1747                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1748                        if (!l.head.hasTag(METHODDEF) &&
1749                            (TreeInfo.flags(l.head) & STATIC) == 0) {
1750                            scan(l.head);
1751                        }
1752                    }
1753
1754                    // process all the methods
1755                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1756                        if (l.head.hasTag(METHODDEF)) {
1757                            scan(l.head);
1758                        }
1759                    }
1760                } finally {
1761                    pendingExits = pendingExitsPrev;
1762                    nextadr = nextadrPrev;
1763                    firstadr = firstadrPrev;
1764                    classDef = classDefPrev;
1765                }
1766            } finally {
1767                lint = lintPrev;
1768            }
1769        }
1770
1771        public void visitMethodDef(JCMethodDecl tree) {
1772            if (tree.body == null) {
1773                return;
1774            }
1775
1776            /*  MemberEnter can generate synthetic methods ignore them
1777             */
1778            if ((tree.sym.flags() & SYNTHETIC) != 0) {
1779                return;
1780            }
1781
1782            Lint lintPrev = lint;
1783            lint = lint.augment(tree.sym);
1784            try {
1785                if (tree.body == null) {
1786                    return;
1787                }
1788                /*  Ignore synthetic methods, except for translated lambda methods.
1789                 */
1790                if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
1791                    return;
1792                }
1793
1794                final Bits initsPrev = new Bits(inits);
1795                final Bits uninitsPrev = new Bits(uninits);
1796                int nextadrPrev = nextadr;
1797                int firstadrPrev = firstadr;
1798                int returnadrPrev = returnadr;
1799
1800                Assert.check(pendingExits.isEmpty());
1801                boolean lastInitialConstructor = isInitialConstructor;
1802                try {
1803                    isInitialConstructor = TreeInfo.isInitialConstructor(tree);
1804
1805                    if (!isInitialConstructor) {
1806                        firstadr = nextadr;
1807                    }
1808                    for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1809                        JCVariableDecl def = l.head;
1810                        scan(def);
1811                        Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
1812                        /*  If we are executing the code from Gen, then there can be
1813                         *  synthetic or mandated variables, ignore them.
1814                         */
1815                        initParam(def);
1816                    }
1817                    // else we are in an instance initializer block;
1818                    // leave caught unchanged.
1819                    scan(tree.body);
1820
1821                    if (isInitialConstructor) {
1822                        boolean isSynthesized = (tree.sym.flags() &
1823                                                 GENERATEDCONSTR) != 0;
1824                        for (int i = firstadr; i < nextadr; i++) {
1825                            JCVariableDecl vardecl = vardecls[i];
1826                            VarSymbol var = vardecl.sym;
1827                            if (var.owner == classDef.sym) {
1828                                // choose the diagnostic position based on whether
1829                                // the ctor is default(synthesized) or not
1830                                if (isSynthesized) {
1831                                    checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
1832                                        var, "var.not.initialized.in.default.constructor");
1833                                } else {
1834                                    checkInit(TreeInfo.diagEndPos(tree.body), var);
1835                                }
1836                            }
1837                        }
1838                    }
1839                    List<AssignPendingExit> exits = pendingExits.toList();
1840                    pendingExits = new ListBuffer<>();
1841                    while (exits.nonEmpty()) {
1842                        AssignPendingExit exit = exits.head;
1843                        exits = exits.tail;
1844                        Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1845                        if (isInitialConstructor) {
1846                            inits.assign(exit.exit_inits);
1847                            for (int i = firstadr; i < nextadr; i++) {
1848                                checkInit(exit.tree.pos(), vardecls[i].sym);
1849                            }
1850                        }
1851                    }
1852                } finally {
1853                    inits.assign(initsPrev);
1854                    uninits.assign(uninitsPrev);
1855                    nextadr = nextadrPrev;
1856                    firstadr = firstadrPrev;
1857                    returnadr = returnadrPrev;
1858                    isInitialConstructor = lastInitialConstructor;
1859                }
1860            } finally {
1861                lint = lintPrev;
1862            }
1863        }
1864
1865        protected void initParam(JCVariableDecl def) {
1866            inits.incl(def.sym.adr);
1867            uninits.excl(def.sym.adr);
1868        }
1869
1870        public void visitVarDef(JCVariableDecl tree) {
1871            Lint lintPrev = lint;
1872            lint = lint.augment(tree.sym);
1873            try{
1874                boolean track = trackable(tree.sym);
1875                if (track && tree.sym.owner.kind == MTH) {
1876                    newVar(tree);
1877                }
1878                if (tree.init != null) {
1879                    scanExpr(tree.init);
1880                    if (track) {
1881                        letInit(tree.pos(), tree.sym);
1882                    }
1883                }
1884            } finally {
1885                lint = lintPrev;
1886            }
1887        }
1888
1889        public void visitBlock(JCBlock tree) {
1890            int nextadrPrev = nextadr;
1891            scan(tree.stats);
1892            nextadr = nextadrPrev;
1893        }
1894
1895        public void visitDoLoop(JCDoWhileLoop tree) {
1896            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1897            FlowKind prevFlowKind = flowKind;
1898            flowKind = FlowKind.NORMAL;
1899            final Bits initsSkip = new Bits(true);
1900            final Bits uninitsSkip = new Bits(true);
1901            pendingExits = new ListBuffer<>();
1902            int prevErrors = log.nerrors;
1903            do {
1904                final Bits uninitsEntry = new Bits(uninits);
1905                uninitsEntry.excludeFrom(nextadr);
1906                scan(tree.body);
1907                resolveContinues(tree);
1908                scanCond(tree.cond);
1909                if (!flowKind.isFinal()) {
1910                    initsSkip.assign(initsWhenFalse);
1911                    uninitsSkip.assign(uninitsWhenFalse);
1912                }
1913                if (log.nerrors !=  prevErrors ||
1914                    flowKind.isFinal() ||
1915                    new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
1916                    break;
1917                inits.assign(initsWhenTrue);
1918                uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
1919                flowKind = FlowKind.SPECULATIVE_LOOP;
1920            } while (true);
1921            flowKind = prevFlowKind;
1922            inits.assign(initsSkip);
1923            uninits.assign(uninitsSkip);
1924            resolveBreaks(tree, prevPendingExits);
1925        }
1926
1927        public void visitWhileLoop(JCWhileLoop tree) {
1928            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1929            FlowKind prevFlowKind = flowKind;
1930            flowKind = FlowKind.NORMAL;
1931            final Bits initsSkip = new Bits(true);
1932            final Bits uninitsSkip = new Bits(true);
1933            pendingExits = new ListBuffer<>();
1934            int prevErrors = log.nerrors;
1935            final Bits uninitsEntry = new Bits(uninits);
1936            uninitsEntry.excludeFrom(nextadr);
1937            do {
1938                scanCond(tree.cond);
1939                if (!flowKind.isFinal()) {
1940                    initsSkip.assign(initsWhenFalse) ;
1941                    uninitsSkip.assign(uninitsWhenFalse);
1942                }
1943                inits.assign(initsWhenTrue);
1944                uninits.assign(uninitsWhenTrue);
1945                scan(tree.body);
1946                resolveContinues(tree);
1947                if (log.nerrors != prevErrors ||
1948                    flowKind.isFinal() ||
1949                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
1950                    break;
1951                }
1952                uninits.assign(uninitsEntry.andSet(uninits));
1953                flowKind = FlowKind.SPECULATIVE_LOOP;
1954            } while (true);
1955            flowKind = prevFlowKind;
1956            //a variable is DA/DU after the while statement, if it's DA/DU assuming the
1957            //branch is not taken AND if it's DA/DU before any break statement
1958            inits.assign(initsSkip);
1959            uninits.assign(uninitsSkip);
1960            resolveBreaks(tree, prevPendingExits);
1961        }
1962
1963        public void visitForLoop(JCForLoop tree) {
1964            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1965            FlowKind prevFlowKind = flowKind;
1966            flowKind = FlowKind.NORMAL;
1967            int nextadrPrev = nextadr;
1968            scan(tree.init);
1969            final Bits initsSkip = new Bits(true);
1970            final Bits uninitsSkip = new Bits(true);
1971            pendingExits = new ListBuffer<>();
1972            int prevErrors = log.nerrors;
1973            do {
1974                final Bits uninitsEntry = new Bits(uninits);
1975                uninitsEntry.excludeFrom(nextadr);
1976                if (tree.cond != null) {
1977                    scanCond(tree.cond);
1978                    if (!flowKind.isFinal()) {
1979                        initsSkip.assign(initsWhenFalse);
1980                        uninitsSkip.assign(uninitsWhenFalse);
1981                    }
1982                    inits.assign(initsWhenTrue);
1983                    uninits.assign(uninitsWhenTrue);
1984                } else if (!flowKind.isFinal()) {
1985                    initsSkip.assign(inits);
1986                    initsSkip.inclRange(firstadr, nextadr);
1987                    uninitsSkip.assign(uninits);
1988                    uninitsSkip.inclRange(firstadr, nextadr);
1989                }
1990                scan(tree.body);
1991                resolveContinues(tree);
1992                scan(tree.step);
1993                if (log.nerrors != prevErrors ||
1994                    flowKind.isFinal() ||
1995                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1996                    break;
1997                uninits.assign(uninitsEntry.andSet(uninits));
1998                flowKind = FlowKind.SPECULATIVE_LOOP;
1999            } while (true);
2000            flowKind = prevFlowKind;
2001            //a variable is DA/DU after a for loop, if it's DA/DU assuming the
2002            //branch is not taken AND if it's DA/DU before any break statement
2003            inits.assign(initsSkip);
2004            uninits.assign(uninitsSkip);
2005            resolveBreaks(tree, prevPendingExits);
2006            nextadr = nextadrPrev;
2007        }
2008
2009        public void visitForeachLoop(JCEnhancedForLoop tree) {
2010            visitVarDef(tree.var);
2011
2012            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2013            FlowKind prevFlowKind = flowKind;
2014            flowKind = FlowKind.NORMAL;
2015            int nextadrPrev = nextadr;
2016            scan(tree.expr);
2017            final Bits initsStart = new Bits(inits);
2018            final Bits uninitsStart = new Bits(uninits);
2019
2020            letInit(tree.pos(), tree.var.sym);
2021            pendingExits = new ListBuffer<>();
2022            int prevErrors = log.nerrors;
2023            do {
2024                final Bits uninitsEntry = new Bits(uninits);
2025                uninitsEntry.excludeFrom(nextadr);
2026                scan(tree.body);
2027                resolveContinues(tree);
2028                if (log.nerrors != prevErrors ||
2029                    flowKind.isFinal() ||
2030                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2031                    break;
2032                uninits.assign(uninitsEntry.andSet(uninits));
2033                flowKind = FlowKind.SPECULATIVE_LOOP;
2034            } while (true);
2035            flowKind = prevFlowKind;
2036            inits.assign(initsStart);
2037            uninits.assign(uninitsStart.andSet(uninits));
2038            resolveBreaks(tree, prevPendingExits);
2039            nextadr = nextadrPrev;
2040        }
2041
2042        public void visitLabelled(JCLabeledStatement tree) {
2043            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2044            pendingExits = new ListBuffer<>();
2045            scan(tree.body);
2046            resolveBreaks(tree, prevPendingExits);
2047        }
2048
2049        public void visitSwitch(JCSwitch tree) {
2050            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2051            pendingExits = new ListBuffer<>();
2052            int nextadrPrev = nextadr;
2053            scanExpr(tree.selector);
2054            final Bits initsSwitch = new Bits(inits);
2055            final Bits uninitsSwitch = new Bits(uninits);
2056            boolean hasDefault = false;
2057            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
2058                inits.assign(initsSwitch);
2059                uninits.assign(uninits.andSet(uninitsSwitch));
2060                JCCase c = l.head;
2061                if (c.pat == null) {
2062                    hasDefault = true;
2063                } else {
2064                    scanExpr(c.pat);
2065                }
2066                if (hasDefault) {
2067                    inits.assign(initsSwitch);
2068                    uninits.assign(uninits.andSet(uninitsSwitch));
2069                }
2070                scan(c.stats);
2071                addVars(c.stats, initsSwitch, uninitsSwitch);
2072                if (!hasDefault) {
2073                    inits.assign(initsSwitch);
2074                    uninits.assign(uninits.andSet(uninitsSwitch));
2075                }
2076                // Warn about fall-through if lint switch fallthrough enabled.
2077            }
2078            if (!hasDefault) {
2079                inits.andSet(initsSwitch);
2080            }
2081            resolveBreaks(tree, prevPendingExits);
2082            nextadr = nextadrPrev;
2083        }
2084        // where
2085            /** Add any variables defined in stats to inits and uninits. */
2086            private void addVars(List<JCStatement> stats, final Bits inits,
2087                                        final Bits uninits) {
2088                for (;stats.nonEmpty(); stats = stats.tail) {
2089                    JCTree stat = stats.head;
2090                    if (stat.hasTag(VARDEF)) {
2091                        int adr = ((JCVariableDecl) stat).sym.adr;
2092                        inits.excl(adr);
2093                        uninits.incl(adr);
2094                    }
2095                }
2096            }
2097
2098        public void visitTry(JCTry tree) {
2099            ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2100            final Bits uninitsTryPrev = new Bits(uninitsTry);
2101            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2102            pendingExits = new ListBuffer<>();
2103            final Bits initsTry = new Bits(inits);
2104            uninitsTry.assign(uninits);
2105            for (JCTree resource : tree.resources) {
2106                if (resource instanceof JCVariableDecl) {
2107                    JCVariableDecl vdecl = (JCVariableDecl) resource;
2108                    visitVarDef(vdecl);
2109                    unrefdResources.enter(vdecl.sym);
2110                    resourceVarDecls.append(vdecl);
2111                } else if (resource instanceof JCExpression) {
2112                    scanExpr((JCExpression) resource);
2113                } else {
2114                    throw new AssertionError(tree);  // parser error
2115                }
2116            }
2117            scan(tree.body);
2118            uninitsTry.andSet(uninits);
2119            final Bits initsEnd = new Bits(inits);
2120            final Bits uninitsEnd = new Bits(uninits);
2121            int nextadrCatch = nextadr;
2122
2123            if (!resourceVarDecls.isEmpty() &&
2124                    lint.isEnabled(Lint.LintCategory.TRY)) {
2125                for (JCVariableDecl resVar : resourceVarDecls) {
2126                    if (unrefdResources.includes(resVar.sym)) {
2127                        log.warning(Lint.LintCategory.TRY, resVar.pos(),
2128                                    "try.resource.not.referenced", resVar.sym);
2129                        unrefdResources.remove(resVar.sym);
2130                    }
2131                }
2132            }
2133
2134            /*  The analysis of each catch should be independent.
2135             *  Each one should have the same initial values of inits and
2136             *  uninits.
2137             */
2138            final Bits initsCatchPrev = new Bits(initsTry);
2139            final Bits uninitsCatchPrev = new Bits(uninitsTry);
2140
2141            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2142                JCVariableDecl param = l.head.param;
2143                inits.assign(initsCatchPrev);
2144                uninits.assign(uninitsCatchPrev);
2145                scan(param);
2146                /* If this is a TWR and we are executing the code from Gen,
2147                 * then there can be synthetic variables, ignore them.
2148                 */
2149                initParam(param);
2150                scan(l.head.body);
2151                initsEnd.andSet(inits);
2152                uninitsEnd.andSet(uninits);
2153                nextadr = nextadrCatch;
2154            }
2155            if (tree.finalizer != null) {
2156                inits.assign(initsTry);
2157                uninits.assign(uninitsTry);
2158                ListBuffer<AssignPendingExit> exits = pendingExits;
2159                pendingExits = prevPendingExits;
2160                scan(tree.finalizer);
2161                if (!tree.finallyCanCompleteNormally) {
2162                    // discard exits and exceptions from try and finally
2163                } else {
2164                    uninits.andSet(uninitsEnd);
2165                    // FIX: this doesn't preserve source order of exits in catch
2166                    // versus finally!
2167                    while (exits.nonEmpty()) {
2168                        AssignPendingExit exit = exits.next();
2169                        if (exit.exit_inits != null) {
2170                            exit.exit_inits.orSet(inits);
2171                            exit.exit_uninits.andSet(uninits);
2172                        }
2173                        pendingExits.append(exit);
2174                    }
2175                    inits.orSet(initsEnd);
2176                }
2177            } else {
2178                inits.assign(initsEnd);
2179                uninits.assign(uninitsEnd);
2180                ListBuffer<AssignPendingExit> exits = pendingExits;
2181                pendingExits = prevPendingExits;
2182                while (exits.nonEmpty()) pendingExits.append(exits.next());
2183            }
2184            uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2185        }
2186
2187        public void visitConditional(JCConditional tree) {
2188            scanCond(tree.cond);
2189            final Bits initsBeforeElse = new Bits(initsWhenFalse);
2190            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2191            inits.assign(initsWhenTrue);
2192            uninits.assign(uninitsWhenTrue);
2193            if (tree.truepart.type.hasTag(BOOLEAN) &&
2194                tree.falsepart.type.hasTag(BOOLEAN)) {
2195                // if b and c are boolean valued, then
2196                // v is (un)assigned after a?b:c when true iff
2197                //    v is (un)assigned after b when true and
2198                //    v is (un)assigned after c when true
2199                scanCond(tree.truepart);
2200                final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
2201                final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
2202                final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
2203                final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
2204                inits.assign(initsBeforeElse);
2205                uninits.assign(uninitsBeforeElse);
2206                scanCond(tree.falsepart);
2207                initsWhenTrue.andSet(initsAfterThenWhenTrue);
2208                initsWhenFalse.andSet(initsAfterThenWhenFalse);
2209                uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
2210                uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
2211            } else {
2212                scanExpr(tree.truepart);
2213                final Bits initsAfterThen = new Bits(inits);
2214                final Bits uninitsAfterThen = new Bits(uninits);
2215                inits.assign(initsBeforeElse);
2216                uninits.assign(uninitsBeforeElse);
2217                scanExpr(tree.falsepart);
2218                inits.andSet(initsAfterThen);
2219                uninits.andSet(uninitsAfterThen);
2220            }
2221        }
2222
2223        public void visitIf(JCIf tree) {
2224            scanCond(tree.cond);
2225            final Bits initsBeforeElse = new Bits(initsWhenFalse);
2226            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2227            inits.assign(initsWhenTrue);
2228            uninits.assign(uninitsWhenTrue);
2229            scan(tree.thenpart);
2230            if (tree.elsepart != null) {
2231                final Bits initsAfterThen = new Bits(inits);
2232                final Bits uninitsAfterThen = new Bits(uninits);
2233                inits.assign(initsBeforeElse);
2234                uninits.assign(uninitsBeforeElse);
2235                scan(tree.elsepart);
2236                inits.andSet(initsAfterThen);
2237                uninits.andSet(uninitsAfterThen);
2238            } else {
2239                inits.andSet(initsBeforeElse);
2240                uninits.andSet(uninitsBeforeElse);
2241            }
2242        }
2243
2244        @Override
2245        public void visitBreak(JCBreak tree) {
2246            recordExit(new AssignPendingExit(tree, inits, uninits));
2247        }
2248
2249        @Override
2250        public void visitContinue(JCContinue tree) {
2251            recordExit(new AssignPendingExit(tree, inits, uninits));
2252        }
2253
2254        @Override
2255        public void visitReturn(JCReturn tree) {
2256            scanExpr(tree.expr);
2257            recordExit(new AssignPendingExit(tree, inits, uninits));
2258        }
2259
2260        public void visitThrow(JCThrow tree) {
2261            scanExpr(tree.expr);
2262            markDead();
2263        }
2264
2265        public void visitApply(JCMethodInvocation tree) {
2266            scanExpr(tree.meth);
2267            scanExprs(tree.args);
2268        }
2269
2270        public void visitNewClass(JCNewClass tree) {
2271            scanExpr(tree.encl);
2272            scanExprs(tree.args);
2273            scan(tree.def);
2274        }
2275
2276        @Override
2277        public void visitLambda(JCLambda tree) {
2278            final Bits prevUninits = new Bits(uninits);
2279            final Bits prevInits = new Bits(inits);
2280            int returnadrPrev = returnadr;
2281            int nextadrPrev = nextadr;
2282            ListBuffer<AssignPendingExit> prevPending = pendingExits;
2283            try {
2284                returnadr = nextadr;
2285                pendingExits = new ListBuffer<>();
2286                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2287                    JCVariableDecl def = l.head;
2288                    scan(def);
2289                    inits.incl(def.sym.adr);
2290                    uninits.excl(def.sym.adr);
2291                }
2292                if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
2293                    scanExpr(tree.body);
2294                } else {
2295                    scan(tree.body);
2296                }
2297            }
2298            finally {
2299                returnadr = returnadrPrev;
2300                uninits.assign(prevUninits);
2301                inits.assign(prevInits);
2302                pendingExits = prevPending;
2303                nextadr = nextadrPrev;
2304            }
2305        }
2306
2307        public void visitNewArray(JCNewArray tree) {
2308            scanExprs(tree.dims);
2309            scanExprs(tree.elems);
2310        }
2311
2312        public void visitAssert(JCAssert tree) {
2313            final Bits initsExit = new Bits(inits);
2314            final Bits uninitsExit = new Bits(uninits);
2315            scanCond(tree.cond);
2316            uninitsExit.andSet(uninitsWhenTrue);
2317            if (tree.detail != null) {
2318                inits.assign(initsWhenFalse);
2319                uninits.assign(uninitsWhenFalse);
2320                scanExpr(tree.detail);
2321            }
2322            inits.assign(initsExit);
2323            uninits.assign(uninitsExit);
2324        }
2325
2326        public void visitAssign(JCAssign tree) {
2327            JCTree lhs = TreeInfo.skipParens(tree.lhs);
2328            if (!isIdentOrThisDotIdent(lhs))
2329                scanExpr(lhs);
2330            scanExpr(tree.rhs);
2331            letInit(lhs);
2332        }
2333        private boolean isIdentOrThisDotIdent(JCTree lhs) {
2334            if (lhs.hasTag(IDENT))
2335                return true;
2336            if (!lhs.hasTag(SELECT))
2337                return false;
2338
2339            JCFieldAccess fa = (JCFieldAccess)lhs;
2340            return fa.selected.hasTag(IDENT) &&
2341                   ((JCIdent)fa.selected).name == names._this;
2342        }
2343
2344        // check fields accessed through this.<field> are definitely
2345        // assigned before reading their value
2346        public void visitSelect(JCFieldAccess tree) {
2347            super.visitSelect(tree);
2348            JCTree sel = TreeInfo.skipParens(tree.selected);
2349            if (enforceThisDotInit &&
2350                    sel.hasTag(IDENT) &&
2351                    ((JCIdent)sel).name == names._this &&
2352                    tree.sym.kind == VAR) {
2353                checkInit(tree.pos(), (VarSymbol)tree.sym);
2354            }
2355        }
2356
2357        public void visitAssignop(JCAssignOp tree) {
2358            scanExpr(tree.lhs);
2359            scanExpr(tree.rhs);
2360            letInit(tree.lhs);
2361        }
2362
2363        public void visitUnary(JCUnary tree) {
2364            switch (tree.getTag()) {
2365            case NOT:
2366                scanCond(tree.arg);
2367                final Bits t = new Bits(initsWhenFalse);
2368                initsWhenFalse.assign(initsWhenTrue);
2369                initsWhenTrue.assign(t);
2370                t.assign(uninitsWhenFalse);
2371                uninitsWhenFalse.assign(uninitsWhenTrue);
2372                uninitsWhenTrue.assign(t);
2373                break;
2374            case PREINC: case POSTINC:
2375            case PREDEC: case POSTDEC:
2376                scanExpr(tree.arg);
2377                letInit(tree.arg);
2378                break;
2379            default:
2380                scanExpr(tree.arg);
2381            }
2382        }
2383
2384        public void visitBinary(JCBinary tree) {
2385            switch (tree.getTag()) {
2386            case AND:
2387                scanCond(tree.lhs);
2388                final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2389                final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2390                inits.assign(initsWhenTrue);
2391                uninits.assign(uninitsWhenTrue);
2392                scanCond(tree.rhs);
2393                initsWhenFalse.andSet(initsWhenFalseLeft);
2394                uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2395                break;
2396            case OR:
2397                scanCond(tree.lhs);
2398                final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2399                final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2400                inits.assign(initsWhenFalse);
2401                uninits.assign(uninitsWhenFalse);
2402                scanCond(tree.rhs);
2403                initsWhenTrue.andSet(initsWhenTrueLeft);
2404                uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2405                break;
2406            default:
2407                scanExpr(tree.lhs);
2408                scanExpr(tree.rhs);
2409            }
2410        }
2411
2412        public void visitIdent(JCIdent tree) {
2413            if (tree.sym.kind == VAR) {
2414                checkInit(tree.pos(), (VarSymbol)tree.sym);
2415                referenced(tree.sym);
2416            }
2417        }
2418
2419        void referenced(Symbol sym) {
2420            unrefdResources.remove(sym);
2421        }
2422
2423        public void visitAnnotatedType(JCAnnotatedType tree) {
2424            // annotations don't get scanned
2425            tree.underlyingType.accept(this);
2426        }
2427
2428        public void visitModuleDef(JCModuleDecl tree) {
2429            // Do nothing for modules
2430        }
2431
2432    /**************************************************************************
2433     * main method
2434     *************************************************************************/
2435
2436        /** Perform definite assignment/unassignment analysis on a tree.
2437         */
2438        public void analyzeTree(Env<?> env) {
2439            analyzeTree(env, env.tree);
2440         }
2441
2442        public void analyzeTree(Env<?> env, JCTree tree) {
2443            try {
2444                startPos = tree.pos().getStartPosition();
2445
2446                if (vardecls == null)
2447                    vardecls = new JCVariableDecl[32];
2448                else
2449                    for (int i=0; i<vardecls.length; i++)
2450                        vardecls[i] = null;
2451                firstadr = 0;
2452                nextadr = 0;
2453                pendingExits = new ListBuffer<>();
2454                this.classDef = null;
2455                unrefdResources = WriteableScope.create(env.enclClass.sym);
2456                scan(tree);
2457            } finally {
2458                // note that recursive invocations of this method fail hard
2459                startPos = -1;
2460                resetBits(inits, uninits, uninitsTry, initsWhenTrue,
2461                        initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
2462                if (vardecls != null) {
2463                    for (int i=0; i<vardecls.length; i++)
2464                        vardecls[i] = null;
2465                }
2466                firstadr = 0;
2467                nextadr = 0;
2468                pendingExits = null;
2469                this.classDef = null;
2470                unrefdResources = null;
2471            }
2472        }
2473    }
2474
2475    /**
2476     * This pass implements the last step of the dataflow analysis, namely
2477     * the effectively-final analysis check. This checks that every local variable
2478     * reference from a lambda body/local inner class is either final or effectively final.
2479     * Additional this also checks that every variable that is used as an operand to
2480     * try-with-resources is final or effectively final.
2481     * As effectively final variables are marked as such during DA/DU, this pass must run after
2482     * AssignAnalyzer.
2483     */
2484    class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
2485
2486        JCTree currentTree; //local class or lambda
2487
2488        @Override
2489        void markDead() {
2490            //do nothing
2491        }
2492
2493        @SuppressWarnings("fallthrough")
2494        void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2495            if (currentTree != null &&
2496                    sym.owner.kind == MTH &&
2497                    sym.pos < currentTree.getStartPosition()) {
2498                switch (currentTree.getTag()) {
2499                    case CLASSDEF:
2500                        if (!allowEffectivelyFinalInInnerClasses) {
2501                            if ((sym.flags() & FINAL) == 0) {
2502                                reportInnerClsNeedsFinalError(pos, sym);
2503                            }
2504                            break;
2505                        }
2506                    case LAMBDA:
2507                        if ((sym.flags() & (EFFECTIVELY_FINAL | FINAL)) == 0) {
2508                           reportEffectivelyFinalError(pos, sym);
2509                        }
2510                }
2511            }
2512        }
2513
2514        @SuppressWarnings("fallthrough")
2515        void letInit(JCTree tree) {
2516            tree = TreeInfo.skipParens(tree);
2517            if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
2518                Symbol sym = TreeInfo.symbol(tree);
2519                if (currentTree != null &&
2520                        sym.kind == VAR &&
2521                        sym.owner.kind == MTH &&
2522                        ((VarSymbol)sym).pos < currentTree.getStartPosition()) {
2523                    switch (currentTree.getTag()) {
2524                        case CLASSDEF:
2525                            if (!allowEffectivelyFinalInInnerClasses) {
2526                                reportInnerClsNeedsFinalError(tree, sym);
2527                                break;
2528                            }
2529                        case LAMBDA:
2530                            reportEffectivelyFinalError(tree, sym);
2531                    }
2532                }
2533            }
2534        }
2535
2536        void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
2537            String subKey = currentTree.hasTag(LAMBDA) ?
2538                  "lambda"  : "inner.cls";
2539            log.error(pos, "cant.ref.non.effectively.final.var", sym, diags.fragment(subKey));
2540        }
2541
2542        void reportInnerClsNeedsFinalError(DiagnosticPosition pos, Symbol sym) {
2543            log.error(pos,
2544                    "local.var.accessed.from.icls.needs.final",
2545                    sym);
2546        }
2547
2548    /*************************************************************************
2549     * Visitor methods for statements and definitions
2550     *************************************************************************/
2551
2552        /* ------------ Visitor methods for various sorts of trees -------------*/
2553
2554        public void visitClassDef(JCClassDecl tree) {
2555            JCTree prevTree = currentTree;
2556            try {
2557                currentTree = tree.sym.isLocal() ? tree : null;
2558                super.visitClassDef(tree);
2559            } finally {
2560                currentTree = prevTree;
2561            }
2562        }
2563
2564        @Override
2565        public void visitLambda(JCLambda tree) {
2566            JCTree prevTree = currentTree;
2567            try {
2568                currentTree = tree;
2569                super.visitLambda(tree);
2570            } finally {
2571                currentTree = prevTree;
2572            }
2573        }
2574
2575        @Override
2576        public void visitIdent(JCIdent tree) {
2577            if (tree.sym.kind == VAR) {
2578                checkEffectivelyFinal(tree, (VarSymbol)tree.sym);
2579            }
2580        }
2581
2582        public void visitAssign(JCAssign tree) {
2583            JCTree lhs = TreeInfo.skipParens(tree.lhs);
2584            if (!(lhs instanceof JCIdent)) {
2585                scan(lhs);
2586            }
2587            scan(tree.rhs);
2588            letInit(lhs);
2589        }
2590
2591        public void visitAssignop(JCAssignOp tree) {
2592            scan(tree.lhs);
2593            scan(tree.rhs);
2594            letInit(tree.lhs);
2595        }
2596
2597        public void visitUnary(JCUnary tree) {
2598            switch (tree.getTag()) {
2599                case PREINC: case POSTINC:
2600                case PREDEC: case POSTDEC:
2601                    scan(tree.arg);
2602                    letInit(tree.arg);
2603                    break;
2604                default:
2605                    scan(tree.arg);
2606            }
2607        }
2608
2609        public void visitTry(JCTry tree) {
2610            for (JCTree resource : tree.resources) {
2611                if (!resource.hasTag(VARDEF)) {
2612                    Symbol var = TreeInfo.symbol(resource);
2613                    if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
2614                        log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
2615                    }
2616                }
2617            }
2618            super.visitTry(tree);
2619        }
2620
2621        public void visitModuleDef(JCModuleDecl tree) {
2622            // Do nothing for modules
2623        }
2624
2625    /**************************************************************************
2626     * main method
2627     *************************************************************************/
2628
2629        /** Perform definite assignment/unassignment analysis on a tree.
2630         */
2631        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
2632            analyzeTree(env, env.tree, make);
2633        }
2634        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
2635            try {
2636                attrEnv = env;
2637                Flow.this.make = make;
2638                pendingExits = new ListBuffer<>();
2639                scan(tree);
2640            } finally {
2641                pendingExits = null;
2642                Flow.this.make = null;
2643            }
2644        }
2645    }
2646}
2647