Flow.java revision 3828:d30434bde0a8
1128710Sru/*
2128710Sru * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3128710Sru * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4128710Sru *
5128710Sru * This code is free software; you can redistribute it and/or modify it
6128710Sru * under the terms of the GNU General Public License version 2 only, as
7128710Sru * published by the Free Software Foundation.  Oracle designates this
8128710Sru * particular file as subject to the "Classpath" exception as provided
9128710Sru * by Oracle in the LICENSE file that accompanied this code.
10128710Sru *
11128710Sru * This code is distributed in the hope that it will be useful, but WITHOUT
12128710Sru * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13128710Sru * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14128710Sru * version 2 for more details (a copy is included in the LICENSE file that
15128710Sru * accompanied this code).
16128710Sru *
1743561Skato * You should have received a copy of the GNU General Public License version
18239064Snyan * 2 along with this work; if not, write to the Free Software Foundation,
19239064Snyan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20128710Sru *
21128710Sru * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22128710Sru * or visit www.oracle.com if you need additional information or have any
23128710Sru * questions.
2443561Skato */
25128710Sru
26128710Sru//todo: one might eliminate uninits.andSets when monotonic
27128710Sru
2843561Skatopackage com.sun.tools.javac.comp;
2943561Skato
3043561Skatoimport java.util.HashMap;
3143561Skato
3258871Skatoimport com.sun.source.tree.LambdaExpressionTree.BodyKind;
33128710Sruimport com.sun.tools.javac.code.*;
34128710Sruimport com.sun.tools.javac.code.Scope.WriteableScope;
35128710Sruimport com.sun.tools.javac.tree.*;
3643561Skatoimport com.sun.tools.javac.util.*;
3743561Skatoimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
3843561Skato
3943561Skatoimport com.sun.tools.javac.code.Symbol.*;
40128710Sruimport com.sun.tools.javac.tree.JCTree.*;
41128710Sru
42128710Sruimport static com.sun.tools.javac.code.Flags.*;
4343561Skatoimport static com.sun.tools.javac.code.Flags.BLOCK;
4443561Skatoimport static com.sun.tools.javac.code.Kinds.Kind.*;
45128710Sruimport static com.sun.tools.javac.code.TypeTag.BOOLEAN;
46128710Sruimport static com.sun.tools.javac.code.TypeTag.VOID;
47128710Sruimport static com.sun.tools.javac.tree.JCTree.Tag.*;
4843561Skato
4943561Skato/** This pass implements dataflow analysis for Java programs though
5043561Skato *  different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that
51128710Sru *  every statement is reachable. Exception analysis (see FlowAnalyzer) ensures that
52128710Sru *  every checked exception that is thrown is declared or caught.  Definite assignment analysis
53128710Sru *  (see AssignAnalyzer) ensures that each variable is assigned when used.  Definite
5443561Skato *  unassignment analysis (see AssignAnalyzer) in ensures that no final variable
5543561Skato *  is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
56128710Sru *  determines that local variables accessed within the scope of an inner class/lambda
57128710Sru *  are either final or effectively-final.
58128710Sru *
5943561Skato *  <p>The JLS has a number of problems in the
60128710Sru *  specification of these flow analysis problems. This implementation
61128710Sru *  attempts to address those issues.
62128710Sru *
6343561Skato *  <p>First, there is no accommodation for a finally clause that cannot
64128710Sru *  complete normally. For liveness analysis, an intervening finally
65128710Sru *  clause can cause a break, continue, or return not to reach its
66128710Sru *  target.  For exception analysis, an intervening finally clause can
6743561Skato *  cause any exception to be "caught".  For DA/DU analysis, the finally
6843561Skato *  clause can prevent a transfer of control from propagating DA/DU
6943561Skato *  state to the target.  In addition, code in the finally clause can
7043561Skato *  affect the DA/DU status of variables.
7143561Skato *
7243561Skato *  <p>For try statements, we introduce the idea of a variable being
7343561Skato *  definitely unassigned "everywhere" in a block.  A variable V is
7443561Skato *  "unassigned everywhere" in a block iff it is unassigned at the
7543561Skato *  beginning of the block and there is no reachable assignment to V
7643561Skato *  in the block.  An assignment V=e is reachable iff V is not DA
7743561Skato *  after e.  Then we can say that V is DU at the beginning of the
7843561Skato *  catch block iff V is DU everywhere in the try block.  Similarly, V
7943561Skato *  is DU at the beginning of the finally block iff V is DU everywhere
8043561Skato *  in the try block and in every catch block.  Specifically, the
8143561Skato *  following bullet is added to 16.2.2
8243561Skato *  <pre>
8343561Skato *      V is <em>unassigned everywhere</em> in a block if it is
8443561Skato *      unassigned before the block and there is no reachable
8543561Skato *      assignment to V within the block.
8643561Skato *  </pre>
8743561Skato *  <p>In 16.2.15, the third bullet (and all of its sub-bullets) for all
8843561Skato *  try blocks is changed to
8943561Skato *  <pre>
9043561Skato *      V is definitely unassigned before a catch block iff V is
9143561Skato *      definitely unassigned everywhere in the try block.
9243561Skato *  </pre>
9343561Skato *  <p>The last bullet (and all of its sub-bullets) for try blocks that
9443561Skato *  have a finally block is changed to
95125780Snyan *  <pre>
9643561Skato *      V is definitely unassigned before the finally block iff
9758871Skato *      V is definitely unassigned everywhere in the try block
9858871Skato *      and everywhere in each catch block of the try statement.
99125780Snyan *  </pre>
10043561Skato *  <p>In addition,
101128710Sru *  <pre>
102128710Sru *      V is definitely assigned at the end of a constructor iff
103128710Sru *      V is definitely assigned after the block that is the body
104125780Snyan *      of the constructor and V is definitely assigned at every
10543561Skato *      return that can return from the constructor.
10658871Skato *  </pre>
10758871Skato *  <p>In addition, each continue statement with the loop as its target
10858871Skato *  is treated as a jump to the end of the loop body, and "intervening"
10943561Skato *  finally clauses are treated as follows: V is DA "due to the
110235264Savg *  continue" iff V is DA before the continue statement or V is DA at
11143561Skato *  the end of any intervening finally block.  V is DU "due to the
11243561Skato *  continue" iff any intervening finally cannot complete normally or V
11343561Skato *  is DU at the end of every intervening finally block.  This "due to
11458871Skato *  the continue" concept is then used in the spec for the loops.
11543561Skato *
11658871Skato *  <p>Similarly, break statements must consider intervening finally
117125780Snyan *  blocks.  For liveness analysis, a break statement for which any
118235264Savg *  intervening finally cannot complete normally is not considered to
11958871Skato *  cause the target statement to be able to complete normally. Then
12058871Skato *  we say V is DA "due to the break" iff V is DA before the break or
121235264Savg *  V is DA at the end of any intervening finally block.  V is DU "due
122235264Savg *  to the break" iff any intervening finally cannot complete normally
12343561Skato *  or V is DU at the break and at the end of every intervening
12443561Skato *  finally block.  (I suspect this latter condition can be
12543561Skato *  simplified.)  This "due to the break" is then used in the spec for
126235264Savg *  all statements that can be "broken".
127235264Savg *
128125780Snyan *  <p>The return statement is treated similarly.  V is DA "due to a
12943561Skato *  return statement" iff V is DA before the return statement or V is
13043561Skato *  DA at the end of any intervening finally block.  Note that we
13158871Skato *  don't have to worry about the return expression because this
13258871Skato *  concept is only used for construcrors.
133125780Snyan *
134235264Savg *  <p>There is no spec in the JLS for when a variable is definitely
135235264Savg *  assigned at the end of a constructor, which is needed for final
136235264Savg *  fields (8.3.1.2).  We implement the rule that V is DA at the end
137235264Savg *  of the constructor iff it is DA and the end of the body of the
138235264Savg *  constructor and V is DA "due to" every return of the constructor.
139235264Savg *
14043561Skato *  <p>Intervening finally blocks similarly affect exception analysis.  An
14143561Skato *  intervening finally that cannot complete normally allows us to ignore
14243561Skato *  an otherwise uncaught exception.
143125780Snyan *
14443561Skato *  <p>To implement the semantics of intervening finally clauses, all
14543561Skato *  nonlocal transfers (break, continue, return, throw, method call that
14658871Skato *  can throw a checked exception, and a constructor invocation that can
14758871Skato *  thrown a checked exception) are recorded in a queue, and removed
148125780Snyan *  from the queue when we complete processing the target of the
149128710Sru *  nonlocal transfer.  This allows us to modify the queue in accordance
150128710Sru *  with the above rules when we encounter a finally clause.  The only
151128710Sru *  exception to this [no pun intended] is that checked exceptions that
15243561Skato *  are known to be caught or declared to be caught in the enclosing
15343561Skato *  method are not recorded in the queue, but instead are recorded in a
15443561Skato *  global variable "{@code Set<Type> thrown}" that records the type of all
15543561Skato *  exceptions that can be thrown.
15643561Skato *
15743561Skato *  <p>Other minor issues the treatment of members of other classes
15843561Skato *  (always considered DA except that within an anonymous class
15943561Skato *  constructor, where DA status from the enclosing scope is
16043561Skato *  preserved), treatment of the case expression (V is DA before the
16143561Skato *  case expression iff V is DA after the switch expression),
16243561Skato *  treatment of variables declared in a switch block (the implied
16343561Skato *  DA/DU status after the switch expression is DU and not DA for
16443561Skato *  variables defined in a switch block), the treatment of boolean ?:
16543561Skato *  expressions (The JLS rules only handle b and c non-boolean; the
16643561Skato *  new rule is that if b and c are boolean valued, then V is
16743561Skato *  (un)assigned after a?b:c when true/false iff V is (un)assigned
16843561Skato *  after b when true/false and V is (un)assigned after c when
16943561Skato *  true/false).
17043561Skato *
17143561Skato *  <p>There is the remaining question of what syntactic forms constitute a
17243561Skato *  reference to a variable.  It is conventional to allow this.x on the
17343561Skato *  left-hand-side to initialize a final instance field named x, yet
17443561Skato *  this.x isn't considered a "use" when appearing on a right-hand-side
17543561Skato *  in most implementations.  Should parentheses affect what is
17643561Skato *  considered a variable reference?  The simplest rule would be to
17758871Skato *  allow unqualified forms only, parentheses optional, and phase out
17843561Skato *  support for assigning to a final field via this.x.
179125780Snyan *
18058871Skato *  <p><b>This is NOT part of any supported API.
181125780Snyan *  If you write code that depends on this, you do so at your own risk.
18243561Skato *  This code and its internal interfaces are subject to change or
18343561Skato *  deletion without notice.</b>
18443561Skato */
185125780Snyanpublic class Flow {
18643561Skato    protected static final Context.Key<Flow> flowKey = new Context.Key<>();
18743561Skato
18858871Skato    private final Names names;
189125780Snyan    private final Log log;
19043561Skato    private final Symtab syms;
191125780Snyan    private final Types types;
19243561Skato    private final Check chk;
19358871Skato    private       TreeMaker make;
19458871Skato    private final Resolve rs;
195125780Snyan    private final JCDiagnostic.Factory diags;
19643561Skato    private Env<AttrContext> attrEnv;
197125780Snyan    private       Lint lint;
19843561Skato    private final boolean allowImprovedRethrowAnalysis;
19943561Skato    private final boolean allowImprovedCatchAnalysis;
20058871Skato    private final boolean allowEffectivelyFinalInInnerClasses;
20158871Skato    private final boolean enforceThisDotInit;
202125780Snyan
203128710Sru    public static Flow instance(Context context) {
204128710Sru        Flow instance = context.get(flowKey);
205128710Sru        if (instance == null)
20643561Skato            instance = new Flow(context);
20743561Skato        return instance;
20843561Skato    }
20943561Skato
21043561Skato    public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
21158871Skato        new AliveAnalyzer().analyzeTree(env, make);
212125780Snyan        new AssignAnalyzer().analyzeTree(env);
21358871Skato        new FlowAnalyzer().analyzeTree(env, make);
21458871Skato        new CaptureAnalyzer().analyzeTree(env, make);
21543561Skato    }
216125780Snyan
21743561Skato    public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
21843561Skato        Log.DiagnosticHandler diagHandler = null;
21943561Skato        //we need to disable diagnostics temporarily; the problem is that if
22043561Skato        //a lambda expression contains e.g. an unreachable statement, an error
22143561Skato        //message will be reported and will cause compilation to skip the flow analyis
22243561Skato        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
223125780Snyan        //related errors, which will allow for more errors to be detected
22443561Skato        if (!speculative) {
22558871Skato            diagHandler = new Log.DiscardDiagnosticHandler(log);
22643561Skato        }
22758871Skato        try {
22843561Skato            new LambdaAliveAnalyzer().analyzeTree(env, that, make);
22958871Skato        } finally {
23043561Skato            if (!speculative) {
23158871Skato                log.popDiagnosticHandler(diagHandler);
23258871Skato            }
233125780Snyan        }
23443561Skato    }
23543561Skato
23643561Skato    public List<Type> analyzeLambdaThrownTypes(final Env<AttrContext> env,
23743561Skato            JCLambda that, TreeMaker make) {
23843561Skato        //we need to disable diagnostics temporarily; the problem is that if
23943561Skato        //a lambda expression contains e.g. an unreachable statement, an error
24043561Skato        //message will be reported and will cause compilation to skip the flow analyis
24143561Skato        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
24243561Skato        //related errors, which will allow for more errors to be detected
24343561Skato        Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
24443561Skato        try {
24543561Skato            new LambdaAssignAnalyzer(env).analyzeTree(env, that);
24643561Skato            LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
24743561Skato            flowAnalyzer.analyzeTree(env, that, make);
24843561Skato            return flowAnalyzer.inferredThrownTypes;
24943561Skato        } finally {
25043561Skato            log.popDiagnosticHandler(diagHandler);
25143561Skato        }
25243561Skato    }
25343561Skato
25443561Skato    /**
25543561Skato     * Definite assignment scan mode
25643561Skato     */
25758871Skato    enum FlowKind {
258125780Snyan        /**
25958871Skato         * This is the normal DA/DU analysis mode
26058871Skato         */
261125780Snyan        NORMAL("var.might.already.be.assigned", false),
26243561Skato        /**
26343561Skato         * This is the speculative DA/DU analysis mode used to speculatively
26461064Snyan         * derive assertions within loop bodies
26543561Skato         */
26643561Skato        SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true);
26743561Skato
26861064Snyan        final String errKey;
26961064Snyan        final boolean isFinal;
27043561Skato
27161064Snyan        FlowKind(String errKey, boolean isFinal) {
27261064Snyan            this.errKey = errKey;
27361064Snyan            this.isFinal = isFinal;
27461064Snyan        }
27561064Snyan
27643561Skato        boolean isFinal() {
27761064Snyan            return isFinal;
27843561Skato        }
27961064Snyan    }
28043561Skato
28161064Snyan    protected Flow(Context context) {
282128710Sru        context.put(flowKey, this);
283128710Sru        names = Names.instance(context);
284128710Sru        log = Log.instance(context);
28543561Skato        syms = Symtab.instance(context);
28643561Skato        types = Types.instance(context);
28743561Skato        chk = Check.instance(context);
28843561Skato        lint = Lint.instance(context);
28943561Skato        rs = Resolve.instance(context);
29043561Skato        diags = JCDiagnostic.Factory.instance(context);
29143561Skato        Source source = Source.instance(context);
29243561Skato        allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
29343561Skato        allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
29443561Skato        allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
29543561Skato        enforceThisDotInit = source.enforceThisDotInit();
29643561Skato    }
29743561Skato
29843561Skato    /**
29943561Skato     * Base visitor class for all visitors implementing dataflow analysis logic.
30043561Skato     * This class define the shared logic for handling jumps (break/continue statements).
30143561Skato     */
30243561Skato    static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
30343561Skato
30443561Skato        enum JumpKind {
30543561Skato            BREAK(JCTree.Tag.BREAK) {
30643561Skato                @Override
307128710Sru                JCTree getTarget(JCTree tree) {
308128710Sru                    return ((JCBreak)tree).target;
309128710Sru                }
31043561Skato            },
31143561Skato            CONTINUE(JCTree.Tag.CONTINUE) {
31243561Skato                @Override
31343561Skato                JCTree getTarget(JCTree tree) {
31443561Skato                    return ((JCContinue)tree).target;
315128710Sru                }
316128710Sru            };
317128710Sru
31843561Skato            final JCTree.Tag treeTag;
31943561Skato
32043561Skato            private JumpKind(Tag treeTag) {
32143561Skato                this.treeTag = treeTag;
32243561Skato            }
32343561Skato
32443561Skato            abstract JCTree getTarget(JCTree tree);
32543561Skato        }
32643561Skato
32743561Skato        /** The currently pending exits that go from current inner blocks
32843561Skato         *  to an enclosing block, in source order.
32943561Skato         */
33043561Skato        ListBuffer<P> pendingExits;
33143561Skato
33243561Skato        /** A pending exit.  These are the statements return, break, and
33343561Skato         *  continue.  In addition, exception-throwing expressions or
33443561Skato         *  statements are put here when not known to be caught.  This
33543561Skato         *  will typically result in an error unless it is within a
33643561Skato         *  try-finally whose finally block cannot complete normally.
33743561Skato         */
33843561Skato        static class PendingExit {
33943561Skato            JCTree tree;
34043561Skato
34143561Skato            PendingExit(JCTree tree) {
34243561Skato                this.tree = tree;
34343561Skato            }
34443561Skato
34543561Skato            void resolveJump() {
34643561Skato                //do nothing
34743561Skato            }
34843561Skato        }
34943561Skato
35043561Skato        abstract void markDead();
35143561Skato
35243561Skato        /** Record an outward transfer of control. */
35343561Skato        void recordExit(P pe) {
35443561Skato            pendingExits.append(pe);
35543561Skato            markDead();
35643561Skato        }
35743561Skato
35843561Skato        /** Resolve all jumps of this statement. */
35943561Skato        private boolean resolveJump(JCTree tree,
36043561Skato                        ListBuffer<P> oldPendingExits,
36143561Skato                        JumpKind jk) {
36243561Skato            boolean resolved = false;
363128710Sru            List<P> exits = pendingExits.toList();
364128710Sru            pendingExits = oldPendingExits;
365128710Sru            for (; exits.nonEmpty(); exits = exits.tail) {
36643561Skato                P exit = exits.head;
36743561Skato                if (exit.tree.hasTag(jk.treeTag) &&
36843561Skato                        jk.getTarget(exit.tree) == tree) {
36943561Skato                    exit.resolveJump();
37043561Skato                    resolved = true;
37143561Skato                } else {
37243561Skato                    pendingExits.append(exit);
37343561Skato                }
37443561Skato            }
37543561Skato            return resolved;
37643561Skato        }
37743561Skato
37843561Skato        /** Resolve all continues of this statement. */
37943561Skato        boolean resolveContinues(JCTree tree) {
38043561Skato            return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
38143561Skato        }
38243561Skato
38343561Skato        /** Resolve all breaks of this statement. */
38443561Skato        boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
38543561Skato            return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
386128710Sru        }
387128710Sru
388128710Sru        @Override
38943561Skato        public void scan(JCTree tree) {
39043561Skato            if (tree != null && (
39143561Skato                    tree.type == null ||
39243561Skato                    tree.type != Type.stuckType)) {
39343561Skato                super.scan(tree);
39443561Skato            }
39543561Skato        }
39643561Skato
397128710Sru        public void visitPackageDef(JCPackageDecl tree) {
398128710Sru            // Do nothing for PackageDecl
399128710Sru        }
40052148Sbrian    }
40143561Skato
40243561Skato    /**
403125780Snyan     * This pass implements the first step of the dataflow analysis, namely
40443561Skato     * the liveness analysis check. This checks that every statement is reachable.
40543561Skato     * The output of this analysis pass are used by other analyzers. This analyzer
40643561Skato     * sets the 'finallyCanCompleteNormally' field in the JCTry class.
40743561Skato     */
40843561Skato    class AliveAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
40943561Skato
41043561Skato        /** A flag that indicates whether the last statement could
41143561Skato         *  complete normally.
41243561Skato         */
41343561Skato        private boolean alive;
41443561Skato
41543561Skato        @Override
41643561Skato        void markDead() {
41743561Skato            alive = false;
41843561Skato        }
41943561Skato
42043561Skato    /*************************************************************************
42143561Skato     * Visitor methods for statements and definitions
42243561Skato     *************************************************************************/
42343561Skato
42443561Skato        /** Analyze a definition.
42543561Skato         */
426125780Snyan        void scanDef(JCTree tree) {
427128710Sru            scanStat(tree);
428128710Sru            if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
429128710Sru                log.error(tree.pos(),
43043561Skato                          "initializer.must.be.able.to.complete.normally");
431            }
432        }
433
434        /** Analyze a statement. Check that statement is reachable.
435         */
436        void scanStat(JCTree tree) {
437            if (!alive && tree != null) {
438                log.error(tree.pos(), "unreachable.stmt");
439                if (!tree.hasTag(SKIP)) alive = true;
440            }
441            scan(tree);
442        }
443
444        /** Analyze list of statements.
445         */
446        void scanStats(List<? extends JCStatement> trees) {
447            if (trees != null)
448                for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
449                    scanStat(l.head);
450        }
451
452        /* ------------ Visitor methods for various sorts of trees -------------*/
453
454        public void visitClassDef(JCClassDecl tree) {
455            if (tree.sym == null) return;
456            boolean alivePrev = alive;
457            ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
458            Lint lintPrev = lint;
459
460            pendingExits = new ListBuffer<>();
461            lint = lint.augment(tree.sym);
462
463            try {
464                // process all the static initializers
465                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
466                    if (!l.head.hasTag(METHODDEF) &&
467                        (TreeInfo.flags(l.head) & STATIC) != 0) {
468                        scanDef(l.head);
469                    }
470                }
471
472                // process all the instance initializers
473                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
474                    if (!l.head.hasTag(METHODDEF) &&
475                        (TreeInfo.flags(l.head) & STATIC) == 0) {
476                        scanDef(l.head);
477                    }
478                }
479
480                // process all the methods
481                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
482                    if (l.head.hasTag(METHODDEF)) {
483                        scan(l.head);
484                    }
485                }
486            } finally {
487                pendingExits = pendingExitsPrev;
488                alive = alivePrev;
489                lint = lintPrev;
490            }
491        }
492
493        public void visitMethodDef(JCMethodDecl tree) {
494            if (tree.body == null) return;
495            Lint lintPrev = lint;
496
497            lint = lint.augment(tree.sym);
498
499            Assert.check(pendingExits.isEmpty());
500
501            try {
502                alive = true;
503                scanStat(tree.body);
504
505                if (alive && !tree.sym.type.getReturnType().hasTag(VOID))
506                    log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
507
508                List<PendingExit> exits = pendingExits.toList();
509                pendingExits = new ListBuffer<>();
510                while (exits.nonEmpty()) {
511                    PendingExit exit = exits.head;
512                    exits = exits.tail;
513                    Assert.check(exit.tree.hasTag(RETURN));
514                }
515            } finally {
516                lint = lintPrev;
517            }
518        }
519
520        public void visitVarDef(JCVariableDecl tree) {
521            if (tree.init != null) {
522                Lint lintPrev = lint;
523                lint = lint.augment(tree.sym);
524                try{
525                    scan(tree.init);
526                } finally {
527                    lint = lintPrev;
528                }
529            }
530        }
531
532        public void visitBlock(JCBlock tree) {
533            scanStats(tree.stats);
534        }
535
536        public void visitDoLoop(JCDoWhileLoop tree) {
537            ListBuffer<PendingExit> prevPendingExits = pendingExits;
538            pendingExits = new ListBuffer<>();
539            scanStat(tree.body);
540            alive |= resolveContinues(tree);
541            scan(tree.cond);
542            alive = alive && !tree.cond.type.isTrue();
543            alive |= resolveBreaks(tree, prevPendingExits);
544        }
545
546        public void visitWhileLoop(JCWhileLoop tree) {
547            ListBuffer<PendingExit> prevPendingExits = pendingExits;
548            pendingExits = new ListBuffer<>();
549            scan(tree.cond);
550            alive = !tree.cond.type.isFalse();
551            scanStat(tree.body);
552            alive |= resolveContinues(tree);
553            alive = resolveBreaks(tree, prevPendingExits) ||
554                !tree.cond.type.isTrue();
555        }
556
557        public void visitForLoop(JCForLoop tree) {
558            ListBuffer<PendingExit> prevPendingExits = pendingExits;
559            scanStats(tree.init);
560            pendingExits = new ListBuffer<>();
561            if (tree.cond != null) {
562                scan(tree.cond);
563                alive = !tree.cond.type.isFalse();
564            } else {
565                alive = true;
566            }
567            scanStat(tree.body);
568            alive |= resolveContinues(tree);
569            scan(tree.step);
570            alive = resolveBreaks(tree, prevPendingExits) ||
571                tree.cond != null && !tree.cond.type.isTrue();
572        }
573
574        public void visitForeachLoop(JCEnhancedForLoop tree) {
575            visitVarDef(tree.var);
576            ListBuffer<PendingExit> prevPendingExits = pendingExits;
577            scan(tree.expr);
578            pendingExits = new ListBuffer<>();
579            scanStat(tree.body);
580            alive |= resolveContinues(tree);
581            resolveBreaks(tree, prevPendingExits);
582            alive = true;
583        }
584
585        public void visitLabelled(JCLabeledStatement tree) {
586            ListBuffer<PendingExit> prevPendingExits = pendingExits;
587            pendingExits = new ListBuffer<>();
588            scanStat(tree.body);
589            alive |= resolveBreaks(tree, prevPendingExits);
590        }
591
592        public void visitSwitch(JCSwitch tree) {
593            ListBuffer<PendingExit> prevPendingExits = pendingExits;
594            pendingExits = new ListBuffer<>();
595            scan(tree.selector);
596            boolean hasDefault = false;
597            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
598                alive = true;
599                JCCase c = l.head;
600                if (c.pat == null)
601                    hasDefault = true;
602                else
603                    scan(c.pat);
604                scanStats(c.stats);
605                // Warn about fall-through if lint switch fallthrough enabled.
606                if (alive &&
607                    lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
608                    c.stats.nonEmpty() && l.tail.nonEmpty())
609                    log.warning(Lint.LintCategory.FALLTHROUGH,
610                                l.tail.head.pos(),
611                                "possible.fall-through.into.case");
612            }
613            if (!hasDefault) {
614                alive = true;
615            }
616            alive |= resolveBreaks(tree, prevPendingExits);
617        }
618
619        public void visitTry(JCTry tree) {
620            ListBuffer<PendingExit> prevPendingExits = pendingExits;
621            pendingExits = new ListBuffer<>();
622            for (JCTree resource : tree.resources) {
623                if (resource instanceof JCVariableDecl) {
624                    JCVariableDecl vdecl = (JCVariableDecl) resource;
625                    visitVarDef(vdecl);
626                } else if (resource instanceof JCExpression) {
627                    scan((JCExpression) resource);
628                } else {
629                    throw new AssertionError(tree);  // parser error
630                }
631            }
632
633            scanStat(tree.body);
634            boolean aliveEnd = alive;
635
636            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
637                alive = true;
638                JCVariableDecl param = l.head.param;
639                scan(param);
640                scanStat(l.head.body);
641                aliveEnd |= alive;
642            }
643            if (tree.finalizer != null) {
644                ListBuffer<PendingExit> exits = pendingExits;
645                pendingExits = prevPendingExits;
646                alive = true;
647                scanStat(tree.finalizer);
648                tree.finallyCanCompleteNormally = alive;
649                if (!alive) {
650                    if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
651                        log.warning(Lint.LintCategory.FINALLY,
652                                TreeInfo.diagEndPos(tree.finalizer),
653                                "finally.cannot.complete");
654                    }
655                } else {
656                    while (exits.nonEmpty()) {
657                        pendingExits.append(exits.next());
658                    }
659                    alive = aliveEnd;
660                }
661            } else {
662                alive = aliveEnd;
663                ListBuffer<PendingExit> exits = pendingExits;
664                pendingExits = prevPendingExits;
665                while (exits.nonEmpty()) pendingExits.append(exits.next());
666            }
667        }
668
669        @Override
670        public void visitIf(JCIf tree) {
671            scan(tree.cond);
672            scanStat(tree.thenpart);
673            if (tree.elsepart != null) {
674                boolean aliveAfterThen = alive;
675                alive = true;
676                scanStat(tree.elsepart);
677                alive = alive | aliveAfterThen;
678            } else {
679                alive = true;
680            }
681        }
682
683        public void visitBreak(JCBreak tree) {
684            recordExit(new PendingExit(tree));
685        }
686
687        public void visitContinue(JCContinue tree) {
688            recordExit(new PendingExit(tree));
689        }
690
691        public void visitReturn(JCReturn tree) {
692            scan(tree.expr);
693            recordExit(new PendingExit(tree));
694        }
695
696        public void visitThrow(JCThrow tree) {
697            scan(tree.expr);
698            markDead();
699        }
700
701        public void visitApply(JCMethodInvocation tree) {
702            scan(tree.meth);
703            scan(tree.args);
704        }
705
706        public void visitNewClass(JCNewClass tree) {
707            scan(tree.encl);
708            scan(tree.args);
709            if (tree.def != null) {
710                scan(tree.def);
711            }
712        }
713
714        @Override
715        public void visitLambda(JCLambda tree) {
716            if (tree.type != null &&
717                    tree.type.isErroneous()) {
718                return;
719            }
720
721            ListBuffer<PendingExit> prevPending = pendingExits;
722            boolean prevAlive = alive;
723            try {
724                pendingExits = new ListBuffer<>();
725                alive = true;
726                scanStat(tree.body);
727                tree.canCompleteNormally = alive;
728            }
729            finally {
730                pendingExits = prevPending;
731                alive = prevAlive;
732            }
733        }
734
735        public void visitModuleDef(JCModuleDecl tree) {
736            // Do nothing for modules
737        }
738
739    /**************************************************************************
740     * main method
741     *************************************************************************/
742
743        /** Perform definite assignment/unassignment analysis on a tree.
744         */
745        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
746            analyzeTree(env, env.tree, make);
747        }
748        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
749            try {
750                attrEnv = env;
751                Flow.this.make = make;
752                pendingExits = new ListBuffer<>();
753                alive = true;
754                scan(tree);
755            } finally {
756                pendingExits = null;
757                Flow.this.make = null;
758            }
759        }
760    }
761
762    /**
763     * This pass implements the second step of the dataflow analysis, namely
764     * the exception analysis. This is to ensure that every checked exception that is
765     * thrown is declared or caught. The analyzer uses some info that has been set by
766     * the liveliness analyzer.
767     */
768    class FlowAnalyzer extends BaseAnalyzer<FlowAnalyzer.FlowPendingExit> {
769
770        /** A flag that indicates whether the last statement could
771         *  complete normally.
772         */
773        HashMap<Symbol, List<Type>> preciseRethrowTypes;
774
775        /** The current class being defined.
776         */
777        JCClassDecl classDef;
778
779        /** The list of possibly thrown declarable exceptions.
780         */
781        List<Type> thrown;
782
783        /** The list of exceptions that are either caught or declared to be
784         *  thrown.
785         */
786        List<Type> caught;
787
788        class FlowPendingExit extends BaseAnalyzer.PendingExit {
789
790            Type thrown;
791
792            FlowPendingExit(JCTree tree, Type thrown) {
793                super(tree);
794                this.thrown = thrown;
795            }
796        }
797
798        @Override
799        void markDead() {
800            //do nothing
801        }
802
803        /*-------------------- Exceptions ----------------------*/
804
805        /** Complain that pending exceptions are not caught.
806         */
807        void errorUncaught() {
808            for (FlowPendingExit exit = pendingExits.next();
809                 exit != null;
810                 exit = pendingExits.next()) {
811                if (classDef != null &&
812                    classDef.pos == exit.tree.pos) {
813                    log.error(exit.tree.pos(),
814                            "unreported.exception.default.constructor",
815                            exit.thrown);
816                } else if (exit.tree.hasTag(VARDEF) &&
817                        ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
818                    log.error(exit.tree.pos(),
819                            "unreported.exception.implicit.close",
820                            exit.thrown,
821                            ((JCVariableDecl)exit.tree).sym.name);
822                } else {
823                    log.error(exit.tree.pos(),
824                            "unreported.exception.need.to.catch.or.throw",
825                            exit.thrown);
826                }
827            }
828        }
829
830        /** Record that exception is potentially thrown and check that it
831         *  is caught.
832         */
833        void markThrown(JCTree tree, Type exc) {
834            if (!chk.isUnchecked(tree.pos(), exc)) {
835                if (!chk.isHandled(exc, caught)) {
836                    pendingExits.append(new FlowPendingExit(tree, exc));
837                }
838                thrown = chk.incl(exc, thrown);
839            }
840        }
841
842    /*************************************************************************
843     * Visitor methods for statements and definitions
844     *************************************************************************/
845
846        /* ------------ Visitor methods for various sorts of trees -------------*/
847
848        public void visitClassDef(JCClassDecl tree) {
849            if (tree.sym == null) return;
850
851            JCClassDecl classDefPrev = classDef;
852            List<Type> thrownPrev = thrown;
853            List<Type> caughtPrev = caught;
854            ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
855            Lint lintPrev = lint;
856            boolean anonymousClass = tree.name == names.empty;
857            pendingExits = new ListBuffer<>();
858            if (!anonymousClass) {
859                caught = List.nil();
860            }
861            classDef = tree;
862            thrown = List.nil();
863            lint = lint.augment(tree.sym);
864
865            try {
866                // process all the static initializers
867                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
868                    if (!l.head.hasTag(METHODDEF) &&
869                        (TreeInfo.flags(l.head) & STATIC) != 0) {
870                        scan(l.head);
871                        errorUncaught();
872                    }
873                }
874
875                // add intersection of all thrown clauses of initial constructors
876                // to set of caught exceptions, unless class is anonymous.
877                if (!anonymousClass) {
878                    boolean firstConstructor = true;
879                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
880                        if (TreeInfo.isInitialConstructor(l.head)) {
881                            List<Type> mthrown =
882                                ((JCMethodDecl) l.head).sym.type.getThrownTypes();
883                            if (firstConstructor) {
884                                caught = mthrown;
885                                firstConstructor = false;
886                            } else {
887                                caught = chk.intersect(mthrown, caught);
888                            }
889                        }
890                    }
891                }
892
893                // process all the instance initializers
894                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
895                    if (!l.head.hasTag(METHODDEF) &&
896                        (TreeInfo.flags(l.head) & STATIC) == 0) {
897                        scan(l.head);
898                        errorUncaught();
899                    }
900                }
901
902                // in an anonymous class, add the set of thrown exceptions to
903                // the throws clause of the synthetic constructor and propagate
904                // outwards.
905                // Changing the throws clause on the fly is okay here because
906                // the anonymous constructor can't be invoked anywhere else,
907                // and its type hasn't been cached.
908                if (anonymousClass) {
909                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
910                        if (TreeInfo.isConstructor(l.head)) {
911                            JCMethodDecl mdef = (JCMethodDecl)l.head;
912                            scan(mdef);
913                            mdef.thrown = make.Types(thrown);
914                            mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
915                        }
916                    }
917                    thrownPrev = chk.union(thrown, thrownPrev);
918                }
919
920                // process all the methods
921                for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
922                    if (anonymousClass && TreeInfo.isConstructor(l.head))
923                        continue; // there can never be an uncaught exception.
924                    if (l.head.hasTag(METHODDEF)) {
925                        scan(l.head);
926                        errorUncaught();
927                    }
928                }
929
930                thrown = thrownPrev;
931            } finally {
932                pendingExits = pendingExitsPrev;
933                caught = caughtPrev;
934                classDef = classDefPrev;
935                lint = lintPrev;
936            }
937        }
938
939        public void visitMethodDef(JCMethodDecl tree) {
940            if (tree.body == null) return;
941
942            List<Type> caughtPrev = caught;
943            List<Type> mthrown = tree.sym.type.getThrownTypes();
944            Lint lintPrev = lint;
945
946            lint = lint.augment(tree.sym);
947
948            Assert.check(pendingExits.isEmpty());
949
950            try {
951                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
952                    JCVariableDecl def = l.head;
953                    scan(def);
954                }
955                if (TreeInfo.isInitialConstructor(tree))
956                    caught = chk.union(caught, mthrown);
957                else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
958                    caught = mthrown;
959                // else we are in an instance initializer block;
960                // leave caught unchanged.
961
962                scan(tree.body);
963
964                List<FlowPendingExit> exits = pendingExits.toList();
965                pendingExits = new ListBuffer<>();
966                while (exits.nonEmpty()) {
967                    FlowPendingExit exit = exits.head;
968                    exits = exits.tail;
969                    if (exit.thrown == null) {
970                        Assert.check(exit.tree.hasTag(RETURN));
971                    } else {
972                        // uncaught throws will be reported later
973                        pendingExits.append(exit);
974                    }
975                }
976            } finally {
977                caught = caughtPrev;
978                lint = lintPrev;
979            }
980        }
981
982        public void visitVarDef(JCVariableDecl tree) {
983            if (tree.init != null) {
984                Lint lintPrev = lint;
985                lint = lint.augment(tree.sym);
986                try{
987                    scan(tree.init);
988                } finally {
989                    lint = lintPrev;
990                }
991            }
992        }
993
994        public void visitBlock(JCBlock tree) {
995            scan(tree.stats);
996        }
997
998        public void visitDoLoop(JCDoWhileLoop tree) {
999            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1000            pendingExits = new ListBuffer<>();
1001            scan(tree.body);
1002            resolveContinues(tree);
1003            scan(tree.cond);
1004            resolveBreaks(tree, prevPendingExits);
1005        }
1006
1007        public void visitWhileLoop(JCWhileLoop tree) {
1008            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1009            pendingExits = new ListBuffer<>();
1010            scan(tree.cond);
1011            scan(tree.body);
1012            resolveContinues(tree);
1013            resolveBreaks(tree, prevPendingExits);
1014        }
1015
1016        public void visitForLoop(JCForLoop tree) {
1017            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1018            scan(tree.init);
1019            pendingExits = new ListBuffer<>();
1020            if (tree.cond != null) {
1021                scan(tree.cond);
1022            }
1023            scan(tree.body);
1024            resolveContinues(tree);
1025            scan(tree.step);
1026            resolveBreaks(tree, prevPendingExits);
1027        }
1028
1029        public void visitForeachLoop(JCEnhancedForLoop tree) {
1030            visitVarDef(tree.var);
1031            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1032            scan(tree.expr);
1033            pendingExits = new ListBuffer<>();
1034            scan(tree.body);
1035            resolveContinues(tree);
1036            resolveBreaks(tree, prevPendingExits);
1037        }
1038
1039        public void visitLabelled(JCLabeledStatement tree) {
1040            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1041            pendingExits = new ListBuffer<>();
1042            scan(tree.body);
1043            resolveBreaks(tree, prevPendingExits);
1044        }
1045
1046        public void visitSwitch(JCSwitch tree) {
1047            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1048            pendingExits = new ListBuffer<>();
1049            scan(tree.selector);
1050            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
1051                JCCase c = l.head;
1052                if (c.pat != null) {
1053                    scan(c.pat);
1054                }
1055                scan(c.stats);
1056            }
1057            resolveBreaks(tree, prevPendingExits);
1058        }
1059
1060        public void visitTry(JCTry tree) {
1061            List<Type> caughtPrev = caught;
1062            List<Type> thrownPrev = thrown;
1063            thrown = List.nil();
1064            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1065                List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1066                        ((JCTypeUnion)l.head.param.vartype).alternatives :
1067                        List.of(l.head.param.vartype);
1068                for (JCExpression ct : subClauses) {
1069                    caught = chk.incl(ct.type, caught);
1070                }
1071            }
1072
1073            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
1074            pendingExits = new ListBuffer<>();
1075            for (JCTree resource : tree.resources) {
1076                if (resource instanceof JCVariableDecl) {
1077                    JCVariableDecl vdecl = (JCVariableDecl) resource;
1078                    visitVarDef(vdecl);
1079                } else if (resource instanceof JCExpression) {
1080                    scan((JCExpression) resource);
1081                } else {
1082                    throw new AssertionError(tree);  // parser error
1083                }
1084            }
1085            for (JCTree resource : tree.resources) {
1086                List<Type> closeableSupertypes = resource.type.isCompound() ?
1087                    types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1088                    List.of(resource.type);
1089                for (Type sup : closeableSupertypes) {
1090                    if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1091                        Symbol closeMethod = rs.resolveQualifiedMethod(tree,
1092                                attrEnv,
1093                                types.skipTypeVars(sup, false),
1094                                names.close,
1095                                List.nil(),
1096                                List.nil());
1097                        Type mt = types.memberType(resource.type, closeMethod);
1098                        if (closeMethod.kind == MTH) {
1099                            for (Type t : mt.getThrownTypes()) {
1100                                markThrown(resource, t);
1101                            }
1102                        }
1103                    }
1104                }
1105            }
1106            scan(tree.body);
1107            List<Type> thrownInTry = allowImprovedCatchAnalysis ?
1108                chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
1109                thrown;
1110            thrown = thrownPrev;
1111            caught = caughtPrev;
1112
1113            List<Type> caughtInTry = List.nil();
1114            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1115                JCVariableDecl param = l.head.param;
1116                List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1117                        ((JCTypeUnion)l.head.param.vartype).alternatives :
1118                        List.of(l.head.param.vartype);
1119                List<Type> ctypes = List.nil();
1120                List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1121                for (JCExpression ct : subClauses) {
1122                    Type exc = ct.type;
1123                    if (exc != syms.unknownType) {
1124                        ctypes = ctypes.append(exc);
1125                        if (types.isSameType(exc, syms.objectType))
1126                            continue;
1127                        checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
1128                        caughtInTry = chk.incl(exc, caughtInTry);
1129                    }
1130                }
1131                scan(param);
1132                preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
1133                scan(l.head.body);
1134                preciseRethrowTypes.remove(param.sym);
1135            }
1136            if (tree.finalizer != null) {
1137                List<Type> savedThrown = thrown;
1138                thrown = List.nil();
1139                ListBuffer<FlowPendingExit> exits = pendingExits;
1140                pendingExits = prevPendingExits;
1141                scan(tree.finalizer);
1142                if (!tree.finallyCanCompleteNormally) {
1143                    // discard exits and exceptions from try and finally
1144                    thrown = chk.union(thrown, thrownPrev);
1145                } else {
1146                    thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1147                    thrown = chk.union(thrown, savedThrown);
1148                    // FIX: this doesn't preserve source order of exits in catch
1149                    // versus finally!
1150                    while (exits.nonEmpty()) {
1151                        pendingExits.append(exits.next());
1152                    }
1153                }
1154            } else {
1155                thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1156                ListBuffer<FlowPendingExit> exits = pendingExits;
1157                pendingExits = prevPendingExits;
1158                while (exits.nonEmpty()) pendingExits.append(exits.next());
1159            }
1160        }
1161
1162        @Override
1163        public void visitIf(JCIf tree) {
1164            scan(tree.cond);
1165            scan(tree.thenpart);
1166            if (tree.elsepart != null) {
1167                scan(tree.elsepart);
1168            }
1169        }
1170
1171        void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
1172            if (chk.subset(exc, caughtInTry)) {
1173                log.error(pos, "except.already.caught", exc);
1174            } else if (!chk.isUnchecked(pos, exc) &&
1175                    !isExceptionOrThrowable(exc) &&
1176                    !chk.intersects(exc, thrownInTry)) {
1177                log.error(pos, "except.never.thrown.in.try", exc);
1178            } else if (allowImprovedCatchAnalysis) {
1179                List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
1180                // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
1181                // unchecked exception, the result list would not be empty, as the augmented
1182                // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
1183                // exception, that would have been covered in the branch above
1184                if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() &&
1185                        !isExceptionOrThrowable(exc)) {
1186                    String key = catchableThrownTypes.length() == 1 ?
1187                            "unreachable.catch" :
1188                            "unreachable.catch.1";
1189                    log.warning(pos, key, catchableThrownTypes);
1190                }
1191            }
1192        }
1193        //where
1194            private boolean isExceptionOrThrowable(Type exc) {
1195                return exc.tsym == syms.throwableType.tsym ||
1196                    exc.tsym == syms.exceptionType.tsym;
1197            }
1198
1199        public void visitBreak(JCBreak tree) {
1200            recordExit(new FlowPendingExit(tree, null));
1201        }
1202
1203        public void visitContinue(JCContinue tree) {
1204            recordExit(new FlowPendingExit(tree, null));
1205        }
1206
1207        public void visitReturn(JCReturn tree) {
1208            scan(tree.expr);
1209            recordExit(new FlowPendingExit(tree, null));
1210        }
1211
1212        public void visitThrow(JCThrow tree) {
1213            scan(tree.expr);
1214            Symbol sym = TreeInfo.symbol(tree.expr);
1215            if (sym != null &&
1216                sym.kind == VAR &&
1217                (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
1218                preciseRethrowTypes.get(sym) != null &&
1219                allowImprovedRethrowAnalysis) {
1220                for (Type t : preciseRethrowTypes.get(sym)) {
1221                    markThrown(tree, t);
1222                }
1223            }
1224            else {
1225                markThrown(tree, tree.expr.type);
1226            }
1227            markDead();
1228        }
1229
1230        public void visitApply(JCMethodInvocation tree) {
1231            scan(tree.meth);
1232            scan(tree.args);
1233            for (List<Type> l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail)
1234                markThrown(tree, l.head);
1235        }
1236
1237        public void visitNewClass(JCNewClass tree) {
1238            scan(tree.encl);
1239            scan(tree.args);
1240           // scan(tree.def);
1241            for (List<Type> l = tree.constructorType.getThrownTypes();
1242                 l.nonEmpty();
1243                 l = l.tail) {
1244                markThrown(tree, l.head);
1245            }
1246            List<Type> caughtPrev = caught;
1247            try {
1248                // If the new class expression defines an anonymous class,
1249                // analysis of the anonymous constructor may encounter thrown
1250                // types which are unsubstituted type variables.
1251                // However, since the constructor's actual thrown types have
1252                // already been marked as thrown, it is safe to simply include
1253                // each of the constructor's formal thrown types in the set of
1254                // 'caught/declared to be thrown' types, for the duration of
1255                // the class def analysis.
1256                if (tree.def != null)
1257                    for (List<Type> l = tree.constructor.type.getThrownTypes();
1258                         l.nonEmpty();
1259                         l = l.tail) {
1260                        caught = chk.incl(l.head, caught);
1261                    }
1262                scan(tree.def);
1263            }
1264            finally {
1265                caught = caughtPrev;
1266            }
1267        }
1268
1269        @Override
1270        public void visitLambda(JCLambda tree) {
1271            if (tree.type != null &&
1272                    tree.type.isErroneous()) {
1273                return;
1274            }
1275            List<Type> prevCaught = caught;
1276            List<Type> prevThrown = thrown;
1277            ListBuffer<FlowPendingExit> prevPending = pendingExits;
1278            try {
1279                pendingExits = new ListBuffer<>();
1280                caught = tree.getDescriptorType(types).getThrownTypes();
1281                thrown = List.nil();
1282                scan(tree.body);
1283                List<FlowPendingExit> exits = pendingExits.toList();
1284                pendingExits = new ListBuffer<>();
1285                while (exits.nonEmpty()) {
1286                    FlowPendingExit exit = exits.head;
1287                    exits = exits.tail;
1288                    if (exit.thrown == null) {
1289                        Assert.check(exit.tree.hasTag(RETURN));
1290                    } else {
1291                        // uncaught throws will be reported later
1292                        pendingExits.append(exit);
1293                    }
1294                }
1295
1296                errorUncaught();
1297            } finally {
1298                pendingExits = prevPending;
1299                caught = prevCaught;
1300                thrown = prevThrown;
1301            }
1302        }
1303
1304        public void visitModuleDef(JCModuleDecl tree) {
1305            // Do nothing for modules
1306        }
1307
1308    /**************************************************************************
1309     * main method
1310     *************************************************************************/
1311
1312        /** Perform definite assignment/unassignment analysis on a tree.
1313         */
1314        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
1315            analyzeTree(env, env.tree, make);
1316        }
1317        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
1318            try {
1319                attrEnv = env;
1320                Flow.this.make = make;
1321                pendingExits = new ListBuffer<>();
1322                preciseRethrowTypes = new HashMap<>();
1323                this.thrown = this.caught = null;
1324                this.classDef = null;
1325                scan(tree);
1326            } finally {
1327                pendingExits = null;
1328                Flow.this.make = null;
1329                this.thrown = this.caught = null;
1330                this.classDef = null;
1331            }
1332        }
1333    }
1334
1335    /**
1336     * Specialized pass that performs reachability analysis on a lambda
1337     */
1338    class LambdaAliveAnalyzer extends AliveAnalyzer {
1339
1340        boolean inLambda;
1341
1342        @Override
1343        public void visitReturn(JCReturn tree) {
1344            //ignore lambda return expression (which might not even be attributed)
1345            recordExit(new PendingExit(tree));
1346        }
1347
1348        @Override
1349        public void visitLambda(JCLambda tree) {
1350            if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) {
1351                return;
1352            }
1353            inLambda = true;
1354            try {
1355                super.visitLambda(tree);
1356            } finally {
1357                inLambda = false;
1358            }
1359        }
1360
1361        @Override
1362        public void visitClassDef(JCClassDecl tree) {
1363            //skip
1364        }
1365    }
1366
1367    /**
1368     * Specialized pass that performs DA/DU on a lambda
1369     */
1370    class LambdaAssignAnalyzer extends AssignAnalyzer {
1371        WriteableScope enclosedSymbols;
1372        boolean inLambda;
1373
1374        LambdaAssignAnalyzer(Env<AttrContext> env) {
1375            enclosedSymbols = WriteableScope.create(env.enclClass.sym);
1376        }
1377
1378        @Override
1379        public void visitLambda(JCLambda tree) {
1380            if (inLambda) {
1381                return;
1382            }
1383            inLambda = true;
1384            try {
1385                super.visitLambda(tree);
1386            } finally {
1387                inLambda = false;
1388            }
1389        }
1390
1391        @Override
1392        public void visitVarDef(JCVariableDecl tree) {
1393            enclosedSymbols.enter(tree.sym);
1394            super.visitVarDef(tree);
1395        }
1396        @Override
1397        protected boolean trackable(VarSymbol sym) {
1398            return enclosedSymbols.includes(sym) &&
1399                   sym.owner.kind == MTH;
1400        }
1401
1402        @Override
1403        public void visitClassDef(JCClassDecl tree) {
1404            //skip
1405        }
1406    }
1407
1408    /**
1409     * Specialized pass that performs inference of thrown types for lambdas.
1410     */
1411    class LambdaFlowAnalyzer extends FlowAnalyzer {
1412        List<Type> inferredThrownTypes;
1413        boolean inLambda;
1414        @Override
1415        public void visitLambda(JCLambda tree) {
1416            if ((tree.type != null &&
1417                    tree.type.isErroneous()) || inLambda) {
1418                return;
1419            }
1420            List<Type> prevCaught = caught;
1421            List<Type> prevThrown = thrown;
1422            ListBuffer<FlowPendingExit> prevPending = pendingExits;
1423            inLambda = true;
1424            try {
1425                pendingExits = new ListBuffer<>();
1426                caught = List.of(syms.throwableType);
1427                thrown = List.nil();
1428                scan(tree.body);
1429                inferredThrownTypes = thrown;
1430            } finally {
1431                pendingExits = prevPending;
1432                caught = prevCaught;
1433                thrown = prevThrown;
1434                inLambda = false;
1435            }
1436        }
1437        @Override
1438        public void visitClassDef(JCClassDecl tree) {
1439            //skip
1440        }
1441    }
1442
1443    /**
1444     * This pass implements (i) definite assignment analysis, which ensures that
1445     * each variable is assigned when used and (ii) definite unassignment analysis,
1446     * which ensures that no final variable is assigned more than once. This visitor
1447     * depends on the results of the liveliness analyzer. This pass is also used to mark
1448     * effectively-final local variables/parameters.
1449     */
1450
1451    public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
1452
1453        /** The set of definitely assigned variables.
1454         */
1455        final Bits inits;
1456
1457        /** The set of definitely unassigned variables.
1458         */
1459        final Bits uninits;
1460
1461        /** The set of variables that are definitely unassigned everywhere
1462         *  in current try block. This variable is maintained lazily; it is
1463         *  updated only when something gets removed from uninits,
1464         *  typically by being assigned in reachable code.  To obtain the
1465         *  correct set of variables which are definitely unassigned
1466         *  anywhere in current try block, intersect uninitsTry and
1467         *  uninits.
1468         */
1469        final Bits uninitsTry;
1470
1471        /** When analyzing a condition, inits and uninits are null.
1472         *  Instead we have:
1473         */
1474        final Bits initsWhenTrue;
1475        final Bits initsWhenFalse;
1476        final Bits uninitsWhenTrue;
1477        final Bits uninitsWhenFalse;
1478
1479        /** A mapping from addresses to variable symbols.
1480         */
1481        protected JCVariableDecl[] vardecls;
1482
1483        /** The current class being defined.
1484         */
1485        JCClassDecl classDef;
1486
1487        /** The first variable sequence number in this class definition.
1488         */
1489        int firstadr;
1490
1491        /** The next available variable sequence number.
1492         */
1493        protected int nextadr;
1494
1495        /** The first variable sequence number in a block that can return.
1496         */
1497        protected int returnadr;
1498
1499        /** The list of unreferenced automatic resources.
1500         */
1501        WriteableScope unrefdResources;
1502
1503        /** Modified when processing a loop body the second time for DU analysis. */
1504        FlowKind flowKind = FlowKind.NORMAL;
1505
1506        /** The starting position of the analyzed tree */
1507        int startPos;
1508
1509        public class AssignPendingExit extends BaseAnalyzer.PendingExit {
1510
1511            final Bits inits;
1512            final Bits uninits;
1513            final Bits exit_inits = new Bits(true);
1514            final Bits exit_uninits = new Bits(true);
1515
1516            public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1517                super(tree);
1518                this.inits = inits;
1519                this.uninits = uninits;
1520                this.exit_inits.assign(inits);
1521                this.exit_uninits.assign(uninits);
1522            }
1523
1524            @Override
1525            public void resolveJump() {
1526                inits.andSet(exit_inits);
1527                uninits.andSet(exit_uninits);
1528            }
1529        }
1530
1531        public AssignAnalyzer() {
1532            this.inits = new Bits();
1533            uninits = new Bits();
1534            uninitsTry = new Bits();
1535            initsWhenTrue = new Bits(true);
1536            initsWhenFalse = new Bits(true);
1537            uninitsWhenTrue = new Bits(true);
1538            uninitsWhenFalse = new Bits(true);
1539        }
1540
1541        private boolean isInitialConstructor = false;
1542
1543        @Override
1544        protected void markDead() {
1545            if (!isInitialConstructor) {
1546                inits.inclRange(returnadr, nextadr);
1547            } else {
1548                for (int address = returnadr; address < nextadr; address++) {
1549                    if (!(isFinalUninitializedStaticField(vardecls[address].sym))) {
1550                        inits.incl(address);
1551                    }
1552                }
1553            }
1554            uninits.inclRange(returnadr, nextadr);
1555        }
1556
1557        /*-------------- Processing variables ----------------------*/
1558
1559        /** Do we need to track init/uninit state of this symbol?
1560         *  I.e. is symbol either a local or a blank final variable?
1561         */
1562        protected boolean trackable(VarSymbol sym) {
1563            return
1564                sym.pos >= startPos &&
1565                ((sym.owner.kind == MTH ||
1566                isFinalUninitializedField(sym)));
1567        }
1568
1569        boolean isFinalUninitializedField(VarSymbol sym) {
1570            return sym.owner.kind == TYP &&
1571                   ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
1572                   classDef.sym.isEnclosedBy((ClassSymbol)sym.owner));
1573        }
1574
1575        boolean isFinalUninitializedStaticField(VarSymbol sym) {
1576            return isFinalUninitializedField(sym) && sym.isStatic();
1577        }
1578
1579        /** Initialize new trackable variable by setting its address field
1580         *  to the next available sequence number and entering it under that
1581         *  index into the vars array.
1582         */
1583        void newVar(JCVariableDecl varDecl) {
1584            VarSymbol sym = varDecl.sym;
1585            vardecls = ArrayUtils.ensureCapacity(vardecls, nextadr);
1586            if ((sym.flags() & FINAL) == 0) {
1587                sym.flags_field |= EFFECTIVELY_FINAL;
1588            }
1589            sym.adr = nextadr;
1590            vardecls[nextadr] = varDecl;
1591            inits.excl(nextadr);
1592            uninits.incl(nextadr);
1593            nextadr++;
1594        }
1595
1596        /** Record an initialization of a trackable variable.
1597         */
1598        void letInit(DiagnosticPosition pos, VarSymbol sym) {
1599            if (sym.adr >= firstadr && trackable(sym)) {
1600                if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
1601                    if (!uninits.isMember(sym.adr)) {
1602                        //assignment targeting an effectively final variable
1603                        //makes the variable lose its status of effectively final
1604                        //if the variable is _not_ definitively unassigned
1605                        sym.flags_field &= ~EFFECTIVELY_FINAL;
1606                    } else {
1607                        uninit(sym);
1608                    }
1609                }
1610                else if ((sym.flags() & FINAL) != 0) {
1611                    if ((sym.flags() & PARAMETER) != 0) {
1612                        if ((sym.flags() & UNION) != 0) { //multi-catch parameter
1613                            log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
1614                        }
1615                        else {
1616                            log.error(pos, "final.parameter.may.not.be.assigned",
1617                                  sym);
1618                        }
1619                    } else if (!uninits.isMember(sym.adr)) {
1620                        log.error(pos, flowKind.errKey, sym);
1621                    } else {
1622                        uninit(sym);
1623                    }
1624                }
1625                inits.incl(sym.adr);
1626            } else if ((sym.flags() & FINAL) != 0) {
1627                log.error(pos, "var.might.already.be.assigned", sym);
1628            }
1629        }
1630        //where
1631            void uninit(VarSymbol sym) {
1632                if (!inits.isMember(sym.adr)) {
1633                    // reachable assignment
1634                    uninits.excl(sym.adr);
1635                    uninitsTry.excl(sym.adr);
1636                } else {
1637                    //log.rawWarning(pos, "unreachable assignment");//DEBUG
1638                    uninits.excl(sym.adr);
1639                }
1640            }
1641
1642        /** If tree is either a simple name or of the form this.name or
1643         *  C.this.name, and tree represents a trackable variable,
1644         *  record an initialization of the variable.
1645         */
1646        void letInit(JCTree tree) {
1647            tree = TreeInfo.skipParens(tree);
1648            if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
1649                Symbol sym = TreeInfo.symbol(tree);
1650                if (sym.kind == VAR) {
1651                    letInit(tree.pos(), (VarSymbol)sym);
1652                }
1653            }
1654        }
1655
1656        /** Check that trackable variable is initialized.
1657         */
1658        void checkInit(DiagnosticPosition pos, VarSymbol sym) {
1659            checkInit(pos, sym, "var.might.not.have.been.initialized");
1660        }
1661
1662        void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
1663            if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
1664                trackable(sym) &&
1665                !inits.isMember(sym.adr)) {
1666                log.error(pos, errkey, sym);
1667                inits.incl(sym.adr);
1668            }
1669        }
1670
1671        /** Utility method to reset several Bits instances.
1672         */
1673        private void resetBits(Bits... bits) {
1674            for (Bits b : bits) {
1675                b.reset();
1676            }
1677        }
1678
1679        /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
1680         */
1681        void split(boolean setToNull) {
1682            initsWhenFalse.assign(inits);
1683            uninitsWhenFalse.assign(uninits);
1684            initsWhenTrue.assign(inits);
1685            uninitsWhenTrue.assign(uninits);
1686            if (setToNull) {
1687                resetBits(inits, uninits);
1688            }
1689        }
1690
1691        /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1692         */
1693        protected void merge() {
1694            inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1695            uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1696        }
1697
1698    /* ************************************************************************
1699     * Visitor methods for statements and definitions
1700     *************************************************************************/
1701
1702        /** Analyze an expression. Make sure to set (un)inits rather than
1703         *  (un)initsWhenTrue(WhenFalse) on exit.
1704         */
1705        void scanExpr(JCTree tree) {
1706            if (tree != null) {
1707                scan(tree);
1708                if (inits.isReset()) {
1709                    merge();
1710                }
1711            }
1712        }
1713
1714        /** Analyze a list of expressions.
1715         */
1716        void scanExprs(List<? extends JCExpression> trees) {
1717            if (trees != null)
1718                for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
1719                    scanExpr(l.head);
1720        }
1721
1722        /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1723         *  rather than (un)inits on exit.
1724         */
1725        void scanCond(JCTree tree) {
1726            if (tree.type.isFalse()) {
1727                if (inits.isReset()) merge();
1728                initsWhenTrue.assign(inits);
1729                initsWhenTrue.inclRange(firstadr, nextadr);
1730                uninitsWhenTrue.assign(uninits);
1731                uninitsWhenTrue.inclRange(firstadr, nextadr);
1732                initsWhenFalse.assign(inits);
1733                uninitsWhenFalse.assign(uninits);
1734            } else if (tree.type.isTrue()) {
1735                if (inits.isReset()) merge();
1736                initsWhenFalse.assign(inits);
1737                initsWhenFalse.inclRange(firstadr, nextadr);
1738                uninitsWhenFalse.assign(uninits);
1739                uninitsWhenFalse.inclRange(firstadr, nextadr);
1740                initsWhenTrue.assign(inits);
1741                uninitsWhenTrue.assign(uninits);
1742            } else {
1743                scan(tree);
1744                if (!inits.isReset())
1745                    split(tree.type != syms.unknownType);
1746            }
1747            if (tree.type != syms.unknownType) {
1748                resetBits(inits, uninits);
1749            }
1750        }
1751
1752        /* ------------ Visitor methods for various sorts of trees -------------*/
1753
1754        public void visitClassDef(JCClassDecl tree) {
1755            if (tree.sym == null) {
1756                return;
1757            }
1758
1759            Lint lintPrev = lint;
1760            lint = lint.augment(tree.sym);
1761            try {
1762                if (tree.sym == null) {
1763                    return;
1764                }
1765
1766                JCClassDecl classDefPrev = classDef;
1767                int firstadrPrev = firstadr;
1768                int nextadrPrev = nextadr;
1769                ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
1770
1771                pendingExits = new ListBuffer<>();
1772                if (tree.name != names.empty) {
1773                    firstadr = nextadr;
1774                }
1775                classDef = tree;
1776                try {
1777                    // define all the static fields
1778                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1779                        if (l.head.hasTag(VARDEF)) {
1780                            JCVariableDecl def = (JCVariableDecl)l.head;
1781                            if ((def.mods.flags & STATIC) != 0) {
1782                                VarSymbol sym = def.sym;
1783                                if (trackable(sym)) {
1784                                    newVar(def);
1785                                }
1786                            }
1787                        }
1788                    }
1789
1790                    // process all the static initializers
1791                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1792                        if (!l.head.hasTag(METHODDEF) &&
1793                            (TreeInfo.flags(l.head) & STATIC) != 0) {
1794                            scan(l.head);
1795                        }
1796                    }
1797
1798                    // define all the instance fields
1799                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1800                        if (l.head.hasTag(VARDEF)) {
1801                            JCVariableDecl def = (JCVariableDecl)l.head;
1802                            if ((def.mods.flags & STATIC) == 0) {
1803                                VarSymbol sym = def.sym;
1804                                if (trackable(sym)) {
1805                                    newVar(def);
1806                                }
1807                            }
1808                        }
1809                    }
1810
1811                    // process all the instance initializers
1812                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1813                        if (!l.head.hasTag(METHODDEF) &&
1814                            (TreeInfo.flags(l.head) & STATIC) == 0) {
1815                            scan(l.head);
1816                        }
1817                    }
1818
1819                    // process all the methods
1820                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
1821                        if (l.head.hasTag(METHODDEF)) {
1822                            scan(l.head);
1823                        }
1824                    }
1825                } finally {
1826                    pendingExits = pendingExitsPrev;
1827                    nextadr = nextadrPrev;
1828                    firstadr = firstadrPrev;
1829                    classDef = classDefPrev;
1830                }
1831            } finally {
1832                lint = lintPrev;
1833            }
1834        }
1835
1836        public void visitMethodDef(JCMethodDecl tree) {
1837            if (tree.body == null) {
1838                return;
1839            }
1840
1841            /*  MemberEnter can generate synthetic methods ignore them
1842             */
1843            if ((tree.sym.flags() & SYNTHETIC) != 0) {
1844                return;
1845            }
1846
1847            Lint lintPrev = lint;
1848            lint = lint.augment(tree.sym);
1849            try {
1850                if (tree.body == null) {
1851                    return;
1852                }
1853                /*  Ignore synthetic methods, except for translated lambda methods.
1854                 */
1855                if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
1856                    return;
1857                }
1858
1859                final Bits initsPrev = new Bits(inits);
1860                final Bits uninitsPrev = new Bits(uninits);
1861                int nextadrPrev = nextadr;
1862                int firstadrPrev = firstadr;
1863                int returnadrPrev = returnadr;
1864
1865                Assert.check(pendingExits.isEmpty());
1866                boolean lastInitialConstructor = isInitialConstructor;
1867                try {
1868                    isInitialConstructor = TreeInfo.isInitialConstructor(tree);
1869
1870                    if (!isInitialConstructor) {
1871                        firstadr = nextadr;
1872                    }
1873                    for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
1874                        JCVariableDecl def = l.head;
1875                        scan(def);
1876                        Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
1877                        /*  If we are executing the code from Gen, then there can be
1878                         *  synthetic or mandated variables, ignore them.
1879                         */
1880                        initParam(def);
1881                    }
1882                    // else we are in an instance initializer block;
1883                    // leave caught unchanged.
1884                    scan(tree.body);
1885
1886                    if (isInitialConstructor) {
1887                        boolean isSynthesized = (tree.sym.flags() &
1888                                                 GENERATEDCONSTR) != 0;
1889                        for (int i = firstadr; i < nextadr; i++) {
1890                            JCVariableDecl vardecl = vardecls[i];
1891                            VarSymbol var = vardecl.sym;
1892                            if (var.owner == classDef.sym) {
1893                                // choose the diagnostic position based on whether
1894                                // the ctor is default(synthesized) or not
1895                                if (isSynthesized) {
1896                                    checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
1897                                        var, "var.not.initialized.in.default.constructor");
1898                                } else {
1899                                    checkInit(TreeInfo.diagEndPos(tree.body), var);
1900                                }
1901                            }
1902                        }
1903                    }
1904                    List<AssignPendingExit> exits = pendingExits.toList();
1905                    pendingExits = new ListBuffer<>();
1906                    while (exits.nonEmpty()) {
1907                        AssignPendingExit exit = exits.head;
1908                        exits = exits.tail;
1909                        Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1910                        if (isInitialConstructor) {
1911                            inits.assign(exit.exit_inits);
1912                            for (int i = firstadr; i < nextadr; i++) {
1913                                checkInit(exit.tree.pos(), vardecls[i].sym);
1914                            }
1915                        }
1916                    }
1917                } finally {
1918                    inits.assign(initsPrev);
1919                    uninits.assign(uninitsPrev);
1920                    nextadr = nextadrPrev;
1921                    firstadr = firstadrPrev;
1922                    returnadr = returnadrPrev;
1923                    isInitialConstructor = lastInitialConstructor;
1924                }
1925            } finally {
1926                lint = lintPrev;
1927            }
1928        }
1929
1930        protected void initParam(JCVariableDecl def) {
1931            inits.incl(def.sym.adr);
1932            uninits.excl(def.sym.adr);
1933        }
1934
1935        public void visitVarDef(JCVariableDecl tree) {
1936            Lint lintPrev = lint;
1937            lint = lint.augment(tree.sym);
1938            try{
1939                boolean track = trackable(tree.sym);
1940                if (track && tree.sym.owner.kind == MTH) {
1941                    newVar(tree);
1942                }
1943                if (tree.init != null) {
1944                    scanExpr(tree.init);
1945                    if (track) {
1946                        letInit(tree.pos(), tree.sym);
1947                    }
1948                }
1949            } finally {
1950                lint = lintPrev;
1951            }
1952        }
1953
1954        public void visitBlock(JCBlock tree) {
1955            int nextadrPrev = nextadr;
1956            scan(tree.stats);
1957            nextadr = nextadrPrev;
1958        }
1959
1960        public void visitDoLoop(JCDoWhileLoop tree) {
1961            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1962            FlowKind prevFlowKind = flowKind;
1963            flowKind = FlowKind.NORMAL;
1964            final Bits initsSkip = new Bits(true);
1965            final Bits uninitsSkip = new Bits(true);
1966            pendingExits = new ListBuffer<>();
1967            int prevErrors = log.nerrors;
1968            do {
1969                final Bits uninitsEntry = new Bits(uninits);
1970                uninitsEntry.excludeFrom(nextadr);
1971                scan(tree.body);
1972                resolveContinues(tree);
1973                scanCond(tree.cond);
1974                if (!flowKind.isFinal()) {
1975                    initsSkip.assign(initsWhenFalse);
1976                    uninitsSkip.assign(uninitsWhenFalse);
1977                }
1978                if (log.nerrors !=  prevErrors ||
1979                    flowKind.isFinal() ||
1980                    new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
1981                    break;
1982                inits.assign(initsWhenTrue);
1983                uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
1984                flowKind = FlowKind.SPECULATIVE_LOOP;
1985            } while (true);
1986            flowKind = prevFlowKind;
1987            inits.assign(initsSkip);
1988            uninits.assign(uninitsSkip);
1989            resolveBreaks(tree, prevPendingExits);
1990        }
1991
1992        public void visitWhileLoop(JCWhileLoop tree) {
1993            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1994            FlowKind prevFlowKind = flowKind;
1995            flowKind = FlowKind.NORMAL;
1996            final Bits initsSkip = new Bits(true);
1997            final Bits uninitsSkip = new Bits(true);
1998            pendingExits = new ListBuffer<>();
1999            int prevErrors = log.nerrors;
2000            final Bits uninitsEntry = new Bits(uninits);
2001            uninitsEntry.excludeFrom(nextadr);
2002            do {
2003                scanCond(tree.cond);
2004                if (!flowKind.isFinal()) {
2005                    initsSkip.assign(initsWhenFalse) ;
2006                    uninitsSkip.assign(uninitsWhenFalse);
2007                }
2008                inits.assign(initsWhenTrue);
2009                uninits.assign(uninitsWhenTrue);
2010                scan(tree.body);
2011                resolveContinues(tree);
2012                if (log.nerrors != prevErrors ||
2013                    flowKind.isFinal() ||
2014                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
2015                    break;
2016                }
2017                uninits.assign(uninitsEntry.andSet(uninits));
2018                flowKind = FlowKind.SPECULATIVE_LOOP;
2019            } while (true);
2020            flowKind = prevFlowKind;
2021            //a variable is DA/DU after the while statement, if it's DA/DU assuming the
2022            //branch is not taken AND if it's DA/DU before any break statement
2023            inits.assign(initsSkip);
2024            uninits.assign(uninitsSkip);
2025            resolveBreaks(tree, prevPendingExits);
2026        }
2027
2028        public void visitForLoop(JCForLoop tree) {
2029            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2030            FlowKind prevFlowKind = flowKind;
2031            flowKind = FlowKind.NORMAL;
2032            int nextadrPrev = nextadr;
2033            scan(tree.init);
2034            final Bits initsSkip = new Bits(true);
2035            final Bits uninitsSkip = new Bits(true);
2036            pendingExits = new ListBuffer<>();
2037            int prevErrors = log.nerrors;
2038            do {
2039                final Bits uninitsEntry = new Bits(uninits);
2040                uninitsEntry.excludeFrom(nextadr);
2041                if (tree.cond != null) {
2042                    scanCond(tree.cond);
2043                    if (!flowKind.isFinal()) {
2044                        initsSkip.assign(initsWhenFalse);
2045                        uninitsSkip.assign(uninitsWhenFalse);
2046                    }
2047                    inits.assign(initsWhenTrue);
2048                    uninits.assign(uninitsWhenTrue);
2049                } else if (!flowKind.isFinal()) {
2050                    initsSkip.assign(inits);
2051                    initsSkip.inclRange(firstadr, nextadr);
2052                    uninitsSkip.assign(uninits);
2053                    uninitsSkip.inclRange(firstadr, nextadr);
2054                }
2055                scan(tree.body);
2056                resolveContinues(tree);
2057                scan(tree.step);
2058                if (log.nerrors != prevErrors ||
2059                    flowKind.isFinal() ||
2060                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2061                    break;
2062                uninits.assign(uninitsEntry.andSet(uninits));
2063                flowKind = FlowKind.SPECULATIVE_LOOP;
2064            } while (true);
2065            flowKind = prevFlowKind;
2066            //a variable is DA/DU after a for loop, if it's DA/DU assuming the
2067            //branch is not taken AND if it's DA/DU before any break statement
2068            inits.assign(initsSkip);
2069            uninits.assign(uninitsSkip);
2070            resolveBreaks(tree, prevPendingExits);
2071            nextadr = nextadrPrev;
2072        }
2073
2074        public void visitForeachLoop(JCEnhancedForLoop tree) {
2075            visitVarDef(tree.var);
2076
2077            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2078            FlowKind prevFlowKind = flowKind;
2079            flowKind = FlowKind.NORMAL;
2080            int nextadrPrev = nextadr;
2081            scan(tree.expr);
2082            final Bits initsStart = new Bits(inits);
2083            final Bits uninitsStart = new Bits(uninits);
2084
2085            letInit(tree.pos(), tree.var.sym);
2086            pendingExits = new ListBuffer<>();
2087            int prevErrors = log.nerrors;
2088            do {
2089                final Bits uninitsEntry = new Bits(uninits);
2090                uninitsEntry.excludeFrom(nextadr);
2091                scan(tree.body);
2092                resolveContinues(tree);
2093                if (log.nerrors != prevErrors ||
2094                    flowKind.isFinal() ||
2095                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
2096                    break;
2097                uninits.assign(uninitsEntry.andSet(uninits));
2098                flowKind = FlowKind.SPECULATIVE_LOOP;
2099            } while (true);
2100            flowKind = prevFlowKind;
2101            inits.assign(initsStart);
2102            uninits.assign(uninitsStart.andSet(uninits));
2103            resolveBreaks(tree, prevPendingExits);
2104            nextadr = nextadrPrev;
2105        }
2106
2107        public void visitLabelled(JCLabeledStatement tree) {
2108            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2109            pendingExits = new ListBuffer<>();
2110            scan(tree.body);
2111            resolveBreaks(tree, prevPendingExits);
2112        }
2113
2114        public void visitSwitch(JCSwitch tree) {
2115            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2116            pendingExits = new ListBuffer<>();
2117            int nextadrPrev = nextadr;
2118            scanExpr(tree.selector);
2119            final Bits initsSwitch = new Bits(inits);
2120            final Bits uninitsSwitch = new Bits(uninits);
2121            boolean hasDefault = false;
2122            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
2123                inits.assign(initsSwitch);
2124                uninits.assign(uninits.andSet(uninitsSwitch));
2125                JCCase c = l.head;
2126                if (c.pat == null) {
2127                    hasDefault = true;
2128                } else {
2129                    scanExpr(c.pat);
2130                }
2131                if (hasDefault) {
2132                    inits.assign(initsSwitch);
2133                    uninits.assign(uninits.andSet(uninitsSwitch));
2134                }
2135                scan(c.stats);
2136                addVars(c.stats, initsSwitch, uninitsSwitch);
2137                if (!hasDefault) {
2138                    inits.assign(initsSwitch);
2139                    uninits.assign(uninits.andSet(uninitsSwitch));
2140                }
2141                // Warn about fall-through if lint switch fallthrough enabled.
2142            }
2143            if (!hasDefault) {
2144                inits.andSet(initsSwitch);
2145            }
2146            resolveBreaks(tree, prevPendingExits);
2147            nextadr = nextadrPrev;
2148        }
2149        // where
2150            /** Add any variables defined in stats to inits and uninits. */
2151            private void addVars(List<JCStatement> stats, final Bits inits,
2152                                        final Bits uninits) {
2153                for (;stats.nonEmpty(); stats = stats.tail) {
2154                    JCTree stat = stats.head;
2155                    if (stat.hasTag(VARDEF)) {
2156                        int adr = ((JCVariableDecl) stat).sym.adr;
2157                        inits.excl(adr);
2158                        uninits.incl(adr);
2159                    }
2160                }
2161            }
2162
2163        public void visitTry(JCTry tree) {
2164            ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
2165            final Bits uninitsTryPrev = new Bits(uninitsTry);
2166            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
2167            pendingExits = new ListBuffer<>();
2168            final Bits initsTry = new Bits(inits);
2169            uninitsTry.assign(uninits);
2170            for (JCTree resource : tree.resources) {
2171                if (resource instanceof JCVariableDecl) {
2172                    JCVariableDecl vdecl = (JCVariableDecl) resource;
2173                    visitVarDef(vdecl);
2174                    unrefdResources.enter(vdecl.sym);
2175                    resourceVarDecls.append(vdecl);
2176                } else if (resource instanceof JCExpression) {
2177                    scanExpr((JCExpression) resource);
2178                } else {
2179                    throw new AssertionError(tree);  // parser error
2180                }
2181            }
2182            scan(tree.body);
2183            uninitsTry.andSet(uninits);
2184            final Bits initsEnd = new Bits(inits);
2185            final Bits uninitsEnd = new Bits(uninits);
2186            int nextadrCatch = nextadr;
2187
2188            if (!resourceVarDecls.isEmpty() &&
2189                    lint.isEnabled(Lint.LintCategory.TRY)) {
2190                for (JCVariableDecl resVar : resourceVarDecls) {
2191                    if (unrefdResources.includes(resVar.sym)) {
2192                        log.warning(Lint.LintCategory.TRY, resVar.pos(),
2193                                    "try.resource.not.referenced", resVar.sym);
2194                        unrefdResources.remove(resVar.sym);
2195                    }
2196                }
2197            }
2198
2199            /*  The analysis of each catch should be independent.
2200             *  Each one should have the same initial values of inits and
2201             *  uninits.
2202             */
2203            final Bits initsCatchPrev = new Bits(initsTry);
2204            final Bits uninitsCatchPrev = new Bits(uninitsTry);
2205
2206            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
2207                JCVariableDecl param = l.head.param;
2208                inits.assign(initsCatchPrev);
2209                uninits.assign(uninitsCatchPrev);
2210                scan(param);
2211                /* If this is a TWR and we are executing the code from Gen,
2212                 * then there can be synthetic variables, ignore them.
2213                 */
2214                initParam(param);
2215                scan(l.head.body);
2216                initsEnd.andSet(inits);
2217                uninitsEnd.andSet(uninits);
2218                nextadr = nextadrCatch;
2219            }
2220            if (tree.finalizer != null) {
2221                inits.assign(initsTry);
2222                uninits.assign(uninitsTry);
2223                ListBuffer<AssignPendingExit> exits = pendingExits;
2224                pendingExits = prevPendingExits;
2225                scan(tree.finalizer);
2226                if (!tree.finallyCanCompleteNormally) {
2227                    // discard exits and exceptions from try and finally
2228                } else {
2229                    uninits.andSet(uninitsEnd);
2230                    // FIX: this doesn't preserve source order of exits in catch
2231                    // versus finally!
2232                    while (exits.nonEmpty()) {
2233                        AssignPendingExit exit = exits.next();
2234                        if (exit.exit_inits != null) {
2235                            exit.exit_inits.orSet(inits);
2236                            exit.exit_uninits.andSet(uninits);
2237                        }
2238                        pendingExits.append(exit);
2239                    }
2240                    inits.orSet(initsEnd);
2241                }
2242            } else {
2243                inits.assign(initsEnd);
2244                uninits.assign(uninitsEnd);
2245                ListBuffer<AssignPendingExit> exits = pendingExits;
2246                pendingExits = prevPendingExits;
2247                while (exits.nonEmpty()) pendingExits.append(exits.next());
2248            }
2249            uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
2250        }
2251
2252        public void visitConditional(JCConditional tree) {
2253            scanCond(tree.cond);
2254            final Bits initsBeforeElse = new Bits(initsWhenFalse);
2255            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2256            inits.assign(initsWhenTrue);
2257            uninits.assign(uninitsWhenTrue);
2258            if (tree.truepart.type.hasTag(BOOLEAN) &&
2259                tree.falsepart.type.hasTag(BOOLEAN)) {
2260                // if b and c are boolean valued, then
2261                // v is (un)assigned after a?b:c when true iff
2262                //    v is (un)assigned after b when true and
2263                //    v is (un)assigned after c when true
2264                scanCond(tree.truepart);
2265                final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
2266                final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
2267                final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
2268                final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
2269                inits.assign(initsBeforeElse);
2270                uninits.assign(uninitsBeforeElse);
2271                scanCond(tree.falsepart);
2272                initsWhenTrue.andSet(initsAfterThenWhenTrue);
2273                initsWhenFalse.andSet(initsAfterThenWhenFalse);
2274                uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
2275                uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
2276            } else {
2277                scanExpr(tree.truepart);
2278                final Bits initsAfterThen = new Bits(inits);
2279                final Bits uninitsAfterThen = new Bits(uninits);
2280                inits.assign(initsBeforeElse);
2281                uninits.assign(uninitsBeforeElse);
2282                scanExpr(tree.falsepart);
2283                inits.andSet(initsAfterThen);
2284                uninits.andSet(uninitsAfterThen);
2285            }
2286        }
2287
2288        public void visitIf(JCIf tree) {
2289            scanCond(tree.cond);
2290            final Bits initsBeforeElse = new Bits(initsWhenFalse);
2291            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2292            inits.assign(initsWhenTrue);
2293            uninits.assign(uninitsWhenTrue);
2294            scan(tree.thenpart);
2295            if (tree.elsepart != null) {
2296                final Bits initsAfterThen = new Bits(inits);
2297                final Bits uninitsAfterThen = new Bits(uninits);
2298                inits.assign(initsBeforeElse);
2299                uninits.assign(uninitsBeforeElse);
2300                scan(tree.elsepart);
2301                inits.andSet(initsAfterThen);
2302                uninits.andSet(uninitsAfterThen);
2303            } else {
2304                inits.andSet(initsBeforeElse);
2305                uninits.andSet(uninitsBeforeElse);
2306            }
2307        }
2308
2309        @Override
2310        public void visitBreak(JCBreak tree) {
2311            recordExit(new AssignPendingExit(tree, inits, uninits));
2312        }
2313
2314        @Override
2315        public void visitContinue(JCContinue tree) {
2316            recordExit(new AssignPendingExit(tree, inits, uninits));
2317        }
2318
2319        @Override
2320        public void visitReturn(JCReturn tree) {
2321            scanExpr(tree.expr);
2322            recordExit(new AssignPendingExit(tree, inits, uninits));
2323        }
2324
2325        public void visitThrow(JCThrow tree) {
2326            scanExpr(tree.expr);
2327            markDead();
2328        }
2329
2330        public void visitApply(JCMethodInvocation tree) {
2331            scanExpr(tree.meth);
2332            scanExprs(tree.args);
2333        }
2334
2335        public void visitNewClass(JCNewClass tree) {
2336            scanExpr(tree.encl);
2337            scanExprs(tree.args);
2338            scan(tree.def);
2339        }
2340
2341        @Override
2342        public void visitLambda(JCLambda tree) {
2343            final Bits prevUninits = new Bits(uninits);
2344            final Bits prevInits = new Bits(inits);
2345            int returnadrPrev = returnadr;
2346            int nextadrPrev = nextadr;
2347            ListBuffer<AssignPendingExit> prevPending = pendingExits;
2348            try {
2349                returnadr = nextadr;
2350                pendingExits = new ListBuffer<>();
2351                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
2352                    JCVariableDecl def = l.head;
2353                    scan(def);
2354                    inits.incl(def.sym.adr);
2355                    uninits.excl(def.sym.adr);
2356                }
2357                if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
2358                    scanExpr(tree.body);
2359                } else {
2360                    scan(tree.body);
2361                }
2362            }
2363            finally {
2364                returnadr = returnadrPrev;
2365                uninits.assign(prevUninits);
2366                inits.assign(prevInits);
2367                pendingExits = prevPending;
2368                nextadr = nextadrPrev;
2369            }
2370        }
2371
2372        public void visitNewArray(JCNewArray tree) {
2373            scanExprs(tree.dims);
2374            scanExprs(tree.elems);
2375        }
2376
2377        public void visitAssert(JCAssert tree) {
2378            final Bits initsExit = new Bits(inits);
2379            final Bits uninitsExit = new Bits(uninits);
2380            scanCond(tree.cond);
2381            uninitsExit.andSet(uninitsWhenTrue);
2382            if (tree.detail != null) {
2383                inits.assign(initsWhenFalse);
2384                uninits.assign(uninitsWhenFalse);
2385                scanExpr(tree.detail);
2386            }
2387            inits.assign(initsExit);
2388            uninits.assign(uninitsExit);
2389        }
2390
2391        public void visitAssign(JCAssign tree) {
2392            JCTree lhs = TreeInfo.skipParens(tree.lhs);
2393            if (!isIdentOrThisDotIdent(lhs))
2394                scanExpr(lhs);
2395            scanExpr(tree.rhs);
2396            letInit(lhs);
2397        }
2398        private boolean isIdentOrThisDotIdent(JCTree lhs) {
2399            if (lhs.hasTag(IDENT))
2400                return true;
2401            if (!lhs.hasTag(SELECT))
2402                return false;
2403
2404            JCFieldAccess fa = (JCFieldAccess)lhs;
2405            return fa.selected.hasTag(IDENT) &&
2406                   ((JCIdent)fa.selected).name == names._this;
2407        }
2408
2409        // check fields accessed through this.<field> are definitely
2410        // assigned before reading their value
2411        public void visitSelect(JCFieldAccess tree) {
2412            super.visitSelect(tree);
2413            JCTree sel = TreeInfo.skipParens(tree.selected);
2414            if (enforceThisDotInit &&
2415                    sel.hasTag(IDENT) &&
2416                    ((JCIdent)sel).name == names._this &&
2417                    tree.sym.kind == VAR) {
2418                checkInit(tree.pos(), (VarSymbol)tree.sym);
2419            }
2420        }
2421
2422        public void visitAssignop(JCAssignOp tree) {
2423            scanExpr(tree.lhs);
2424            scanExpr(tree.rhs);
2425            letInit(tree.lhs);
2426        }
2427
2428        public void visitUnary(JCUnary tree) {
2429            switch (tree.getTag()) {
2430            case NOT:
2431                scanCond(tree.arg);
2432                final Bits t = new Bits(initsWhenFalse);
2433                initsWhenFalse.assign(initsWhenTrue);
2434                initsWhenTrue.assign(t);
2435                t.assign(uninitsWhenFalse);
2436                uninitsWhenFalse.assign(uninitsWhenTrue);
2437                uninitsWhenTrue.assign(t);
2438                break;
2439            case PREINC: case POSTINC:
2440            case PREDEC: case POSTDEC:
2441                scanExpr(tree.arg);
2442                letInit(tree.arg);
2443                break;
2444            default:
2445                scanExpr(tree.arg);
2446            }
2447        }
2448
2449        public void visitBinary(JCBinary tree) {
2450            switch (tree.getTag()) {
2451            case AND:
2452                scanCond(tree.lhs);
2453                final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2454                final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2455                inits.assign(initsWhenTrue);
2456                uninits.assign(uninitsWhenTrue);
2457                scanCond(tree.rhs);
2458                initsWhenFalse.andSet(initsWhenFalseLeft);
2459                uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2460                break;
2461            case OR:
2462                scanCond(tree.lhs);
2463                final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2464                final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2465                inits.assign(initsWhenFalse);
2466                uninits.assign(uninitsWhenFalse);
2467                scanCond(tree.rhs);
2468                initsWhenTrue.andSet(initsWhenTrueLeft);
2469                uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2470                break;
2471            default:
2472                scanExpr(tree.lhs);
2473                scanExpr(tree.rhs);
2474            }
2475        }
2476
2477        public void visitIdent(JCIdent tree) {
2478            if (tree.sym.kind == VAR) {
2479                checkInit(tree.pos(), (VarSymbol)tree.sym);
2480                referenced(tree.sym);
2481            }
2482        }
2483
2484        void referenced(Symbol sym) {
2485            unrefdResources.remove(sym);
2486        }
2487
2488        public void visitAnnotatedType(JCAnnotatedType tree) {
2489            // annotations don't get scanned
2490            tree.underlyingType.accept(this);
2491        }
2492
2493        public void visitModuleDef(JCModuleDecl tree) {
2494            // Do nothing for modules
2495        }
2496
2497    /**************************************************************************
2498     * main method
2499     *************************************************************************/
2500
2501        /** Perform definite assignment/unassignment analysis on a tree.
2502         */
2503        public void analyzeTree(Env<?> env) {
2504            analyzeTree(env, env.tree);
2505         }
2506
2507        public void analyzeTree(Env<?> env, JCTree tree) {
2508            try {
2509                startPos = tree.pos().getStartPosition();
2510
2511                if (vardecls == null)
2512                    vardecls = new JCVariableDecl[32];
2513                else
2514                    for (int i=0; i<vardecls.length; i++)
2515                        vardecls[i] = null;
2516                firstadr = 0;
2517                nextadr = 0;
2518                pendingExits = new ListBuffer<>();
2519                this.classDef = null;
2520                unrefdResources = WriteableScope.create(env.enclClass.sym);
2521                scan(tree);
2522            } finally {
2523                // note that recursive invocations of this method fail hard
2524                startPos = -1;
2525                resetBits(inits, uninits, uninitsTry, initsWhenTrue,
2526                        initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
2527                if (vardecls != null) {
2528                    for (int i=0; i<vardecls.length; i++)
2529                        vardecls[i] = null;
2530                }
2531                firstadr = 0;
2532                nextadr = 0;
2533                pendingExits = null;
2534                this.classDef = null;
2535                unrefdResources = null;
2536            }
2537        }
2538    }
2539
2540    /**
2541     * This pass implements the last step of the dataflow analysis, namely
2542     * the effectively-final analysis check. This checks that every local variable
2543     * reference from a lambda body/local inner class is either final or effectively final.
2544     * Additional this also checks that every variable that is used as an operand to
2545     * try-with-resources is final or effectively final.
2546     * As effectively final variables are marked as such during DA/DU, this pass must run after
2547     * AssignAnalyzer.
2548     */
2549    class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
2550
2551        JCTree currentTree; //local class or lambda
2552
2553        @Override
2554        void markDead() {
2555            //do nothing
2556        }
2557
2558        @SuppressWarnings("fallthrough")
2559        void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
2560            if (currentTree != null &&
2561                    sym.owner.kind == MTH &&
2562                    sym.pos < currentTree.getStartPosition()) {
2563                switch (currentTree.getTag()) {
2564                    case CLASSDEF:
2565                        if (!allowEffectivelyFinalInInnerClasses) {
2566                            if ((sym.flags() & FINAL) == 0) {
2567                                reportInnerClsNeedsFinalError(pos, sym);
2568                            }
2569                            break;
2570                        }
2571                    case LAMBDA:
2572                        if ((sym.flags() & (EFFECTIVELY_FINAL | FINAL)) == 0) {
2573                           reportEffectivelyFinalError(pos, sym);
2574                        }
2575                }
2576            }
2577        }
2578
2579        @SuppressWarnings("fallthrough")
2580        void letInit(JCTree tree) {
2581            tree = TreeInfo.skipParens(tree);
2582            if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
2583                Symbol sym = TreeInfo.symbol(tree);
2584                if (currentTree != null &&
2585                        sym.kind == VAR &&
2586                        sym.owner.kind == MTH &&
2587                        ((VarSymbol)sym).pos < currentTree.getStartPosition()) {
2588                    switch (currentTree.getTag()) {
2589                        case CLASSDEF:
2590                            if (!allowEffectivelyFinalInInnerClasses) {
2591                                reportInnerClsNeedsFinalError(tree, sym);
2592                                break;
2593                            }
2594                        case LAMBDA:
2595                            reportEffectivelyFinalError(tree, sym);
2596                    }
2597                }
2598            }
2599        }
2600
2601        void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
2602            String subKey = currentTree.hasTag(LAMBDA) ?
2603                  "lambda"  : "inner.cls";
2604            log.error(pos, "cant.ref.non.effectively.final.var", sym, diags.fragment(subKey));
2605        }
2606
2607        void reportInnerClsNeedsFinalError(DiagnosticPosition pos, Symbol sym) {
2608            log.error(pos,
2609                    "local.var.accessed.from.icls.needs.final",
2610                    sym);
2611        }
2612
2613    /*************************************************************************
2614     * Visitor methods for statements and definitions
2615     *************************************************************************/
2616
2617        /* ------------ Visitor methods for various sorts of trees -------------*/
2618
2619        public void visitClassDef(JCClassDecl tree) {
2620            JCTree prevTree = currentTree;
2621            try {
2622                currentTree = tree.sym.isLocal() ? tree : null;
2623                super.visitClassDef(tree);
2624            } finally {
2625                currentTree = prevTree;
2626            }
2627        }
2628
2629        @Override
2630        public void visitLambda(JCLambda tree) {
2631            JCTree prevTree = currentTree;
2632            try {
2633                currentTree = tree;
2634                super.visitLambda(tree);
2635            } finally {
2636                currentTree = prevTree;
2637            }
2638        }
2639
2640        @Override
2641        public void visitIdent(JCIdent tree) {
2642            if (tree.sym.kind == VAR) {
2643                checkEffectivelyFinal(tree, (VarSymbol)tree.sym);
2644            }
2645        }
2646
2647        public void visitAssign(JCAssign tree) {
2648            JCTree lhs = TreeInfo.skipParens(tree.lhs);
2649            if (!(lhs instanceof JCIdent)) {
2650                scan(lhs);
2651            }
2652            scan(tree.rhs);
2653            letInit(lhs);
2654        }
2655
2656        public void visitAssignop(JCAssignOp tree) {
2657            scan(tree.lhs);
2658            scan(tree.rhs);
2659            letInit(tree.lhs);
2660        }
2661
2662        public void visitUnary(JCUnary tree) {
2663            switch (tree.getTag()) {
2664                case PREINC: case POSTINC:
2665                case PREDEC: case POSTDEC:
2666                    scan(tree.arg);
2667                    letInit(tree.arg);
2668                    break;
2669                default:
2670                    scan(tree.arg);
2671            }
2672        }
2673
2674        public void visitTry(JCTry tree) {
2675            for (JCTree resource : tree.resources) {
2676                if (!resource.hasTag(VARDEF)) {
2677                    Symbol var = TreeInfo.symbol(resource);
2678                    if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
2679                        log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
2680                    }
2681                }
2682            }
2683            super.visitTry(tree);
2684        }
2685
2686        public void visitModuleDef(JCModuleDecl tree) {
2687            // Do nothing for modules
2688        }
2689
2690    /**************************************************************************
2691     * main method
2692     *************************************************************************/
2693
2694        /** Perform definite assignment/unassignment analysis on a tree.
2695         */
2696        public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
2697            analyzeTree(env, env.tree, make);
2698        }
2699        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
2700            try {
2701                attrEnv = env;
2702                Flow.this.make = make;
2703                pendingExits = new ListBuffer<>();
2704                scan(tree);
2705            } finally {
2706                pendingExits = null;
2707                Flow.this.make = null;
2708            }
2709        }
2710    }
2711}
2712