package org.checkerframework.dataflow.cfg;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/

import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.AssertTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.BreakTree;
import com.sun.source.tree.CaseTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.ContinueTree;
import com.sun.source.tree.DoWhileLoopTree;
import com.sun.source.tree.EmptyStatementTree;
import com.sun.source.tree.EnhancedForLoopTree;
import com.sun.source.tree.ErroneousTree;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.ForLoopTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.IfTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.LabeledStatementTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.SwitchTree;
import com.sun.source.tree.SynchronizedTree;
import com.sun.source.tree.ThrowTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TryTree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.UnionTypeTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.tree.WildcardTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.ReferenceType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.CFGBuilder.ExtendedNode.ExtendedNodeType;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod;
import org.checkerframework.dataflow.cfg.block.Block;
import org.checkerframework.dataflow.cfg.block.Block.BlockType;
import org.checkerframework.dataflow.cfg.block.BlockImpl;
import org.checkerframework.dataflow.cfg.block.ConditionalBlockImpl;
import org.checkerframework.dataflow.cfg.block.ExceptionBlockImpl;
import org.checkerframework.dataflow.cfg.block.RegularBlockImpl;
import org.checkerframework.dataflow.cfg.block.SingleSuccessorBlockImpl;
import org.checkerframework.dataflow.cfg.block.SpecialBlock.SpecialBlockType;
import org.checkerframework.dataflow.cfg.block.SpecialBlockImpl;
import org.checkerframework.dataflow.cfg.node.ArrayAccessNode;
import org.checkerframework.dataflow.cfg.node.ArrayCreationNode;
import org.checkerframework.dataflow.cfg.node.ArrayTypeNode;
import org.checkerframework.dataflow.cfg.node.AssertionErrorNode;
import org.checkerframework.dataflow.cfg.node.AssignmentNode;
import org.checkerframework.dataflow.cfg.node.BitwiseAndNode;
import org.checkerframework.dataflow.cfg.node.BitwiseComplementNode;
import org.checkerframework.dataflow.cfg.node.BitwiseOrNode;
import org.checkerframework.dataflow.cfg.node.BitwiseXorNode;
import org.checkerframework.dataflow.cfg.node.BooleanLiteralNode;
import org.checkerframework.dataflow.cfg.node.CaseNode;
import org.checkerframework.dataflow.cfg.node.CharacterLiteralNode;
import org.checkerframework.dataflow.cfg.node.ClassNameNode;
import org.checkerframework.dataflow.cfg.node.ConditionalAndNode;
import org.checkerframework.dataflow.cfg.node.ConditionalNotNode;
import org.checkerframework.dataflow.cfg.node.ConditionalOrNode;
import org.checkerframework.dataflow.cfg.node.DoubleLiteralNode;
import org.checkerframework.dataflow.cfg.node.EqualToNode;
import org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.dataflow.cfg.node.FloatLiteralNode;
import org.checkerframework.dataflow.cfg.node.FloatingDivisionNode;
import org.checkerframework.dataflow.cfg.node.FloatingRemainderNode;
import org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode;
import org.checkerframework.dataflow.cfg.node.GreaterThanNode;
import org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode;
import org.checkerframework.dataflow.cfg.node.ImplicitThisLiteralNode;
import org.checkerframework.dataflow.cfg.node.InstanceOfNode;
import org.checkerframework.dataflow.cfg.node.IntegerDivisionNode;
import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode;
import org.checkerframework.dataflow.cfg.node.IntegerRemainderNode;
import org.checkerframework.dataflow.cfg.node.LeftShiftNode;
import org.checkerframework.dataflow.cfg.node.LessThanNode;
import org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.LongLiteralNode;
import org.checkerframework.dataflow.cfg.node.MarkerNode;
import org.checkerframework.dataflow.cfg.node.MethodAccessNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.NarrowingConversionNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.NotEqualNode;
import org.checkerframework.dataflow.cfg.node.NullChkNode;
import org.checkerframework.dataflow.cfg.node.NullLiteralNode;
import org.checkerframework.dataflow.cfg.node.NumericalAdditionNode;
import org.checkerframework.dataflow.cfg.node.NumericalMinusNode;
import org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode;
import org.checkerframework.dataflow.cfg.node.NumericalPlusNode;
import org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode;
import org.checkerframework.dataflow.cfg.node.ObjectCreationNode;
import org.checkerframework.dataflow.cfg.node.PackageNameNode;
import org.checkerframework.dataflow.cfg.node.ParameterizedTypeNode;
import org.checkerframework.dataflow.cfg.node.PrimitiveTypeNode;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.dataflow.cfg.node.SignedRightShiftNode;
import org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode;
import org.checkerframework.dataflow.cfg.node.StringConcatenateNode;
import org.checkerframework.dataflow.cfg.node.StringConversionNode;
import org.checkerframework.dataflow.cfg.node.StringLiteralNode;
import org.checkerframework.dataflow.cfg.node.SuperNode;
import org.checkerframework.dataflow.cfg.node.SynchronizedNode;
import org.checkerframework.dataflow.cfg.node.TernaryExpressionNode;
import org.checkerframework.dataflow.cfg.node.ThisLiteralNode;
import org.checkerframework.dataflow.cfg.node.ThrowNode;
import org.checkerframework.dataflow.cfg.node.TypeCastNode;
import org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode;
import org.checkerframework.dataflow.cfg.node.ValueLiteralNode;
import org.checkerframework.dataflow.cfg.node.VariableDeclarationNode;
import org.checkerframework.dataflow.cfg.node.WideningConversionNode;
import org.checkerframework.dataflow.qual.TerminatesExecution;
import org.checkerframework.dataflow.util.MostlySingleton;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BasicAnnotationProvider;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.checkerframework.javacutil.trees.TreeBuilder;

/**
 * Builds the control flow graph of some Java code (either a method, or an arbitrary statement).
 *
 * <p>The translation of the AST to the CFG is split into three phases:
 *
 * <ol>
 *   <li><em>Phase one.</em> In the first phase, the AST is translated into a sequence of {@link
 *       org.checkerframework.dataflow.cfg.CFGBuilder.ExtendedNode}s. An extended node can either be
 *       a {@link Node}, or one of several meta elements such as a conditional or unconditional jump
 *       or a node with additional information about exceptions. Some of the extended nodes contain
 *       labels (e.g., for the jump target), and phase one additionally creates a mapping from
 *       labels to extended nodes. Finally, the list of leaders is computed: A leader is an extended
 *       node which will give rise to a basic block in phase two.
 *   <li><em>Phase two.</em> In this phase, the sequence of extended nodes is translated to a graph
 *       of control flow blocks that contain nodes. The meta elements from phase one are translated
 *       into the correct edges.
 *   <li><em>Phase three.</em> The control flow graph generated in phase two can contain degenerate
 *       basic blocks such as empty regular basic blocks or conditional basic blocks that have the
 *       same block as both 'then' and 'else' successor. This phase removes these cases while
 *       preserving the control flow structure.
 * </ol>
 *
 * @author Stefan Heule
 */
public class CFGBuilder {

    /** Can assertions be assumed to be disabled? */
    protected final boolean assumeAssertionsDisabled;

    /** Can assertions be assumed to be enabled? */
    protected final boolean assumeAssertionsEnabled;

    public CFGBuilder(boolean assumeAssertionsEnabled, boolean assumeAssertionsDisabled) {
        assert !(assumeAssertionsDisabled && assumeAssertionsEnabled);
        this.assumeAssertionsEnabled = assumeAssertionsEnabled;
        this.assumeAssertionsDisabled = assumeAssertionsDisabled;
    }

    /**
     * Class declarations that have been encountered when building the control-flow graph for a
     * method.
     */
    protected final List<ClassTree> declaredClasses = new LinkedList<>();

    public List<ClassTree> getDeclaredClasses() {
        return declaredClasses;
    }

    /**
     * Lambdas encountered when building the control-flow graph for a method, variable initializer,
     * or initializer.
     */
    protected final List<LambdaExpressionTree> declaredLambdas = new LinkedList<>();

    public List<LambdaExpressionTree> getDeclaredLambdas() {
        return declaredLambdas;
    }

    /** Build the control flow graph of some code. */
    public static ControlFlowGraph build(
            CompilationUnitTree root,
            ProcessingEnvironment env,
            UnderlyingAST underlyingAST,
            boolean assumeAssertionsEnabled,
            boolean assumeAssertionsDisabled) {
        return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled)
                .run(root, env, underlyingAST);
    }

    /**
     * Build the control flow graph of some code (method, initializer block, ...). bodyPath is the
     * TreePath to the body of that code.
     */
    public static ControlFlowGraph build(
            TreePath bodyPath,
            ProcessingEnvironment env,
            UnderlyingAST underlyingAST,
            boolean assumeAssertionsEnabled,
            boolean assumeAssertionsDisabled) {
        return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled)
                .run(bodyPath, env, underlyingAST);
    }

    /** Build the control flow graph of a method. */
    public static ControlFlowGraph build(
            CompilationUnitTree root,
            ProcessingEnvironment env,
            MethodTree tree,
            ClassTree classTree,
            boolean assumeAssertionsEnabled,
            boolean assumeAssertionsDisabled) {
        return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled)
                .run(root, env, tree, classTree);
    }

    /** Build the control flow graph of some code. */
    public static ControlFlowGraph build(
            CompilationUnitTree root, ProcessingEnvironment env, UnderlyingAST underlyingAST) {
        return new CFGBuilder(false, false).run(root, env, underlyingAST);
    }

    /** Build the control flow graph of a method. */
    public static ControlFlowGraph build(
            CompilationUnitTree root,
            ProcessingEnvironment env,
            MethodTree tree,
            ClassTree classTree) {
        return new CFGBuilder(false, false).run(root, env, tree, classTree);
    }

    /** Build the control flow graph of some code. */
    public ControlFlowGraph run(
            CompilationUnitTree root, ProcessingEnvironment env, UnderlyingAST underlyingAST) {
        declaredClasses.clear();
        declaredLambdas.clear();

        TreeBuilder builder = new TreeBuilder(env);
        AnnotationProvider annotationProvider = new BasicAnnotationProvider();
        PhaseOneResult phase1result =
                new CFGTranslationPhaseOne()
                        .process(
                                root,
                                env,
                                underlyingAST,
                                exceptionalExitLabel,
                                builder,
                                annotationProvider);
        ControlFlowGraph phase2result = new CFGTranslationPhaseTwo().process(phase1result);
        ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result);
        return phase3result;
    }

    /**
     * Build the control flow graph of some code (method, initializer block, ...). bodyPath is the
     * TreePath to the body of that code.
     */
    public ControlFlowGraph run(
            TreePath bodyPath, ProcessingEnvironment env, UnderlyingAST underlyingAST) {
        declaredClasses.clear();
        TreeBuilder builder = new TreeBuilder(env);
        AnnotationProvider annotationProvider = new BasicAnnotationProvider();
        PhaseOneResult phase1result =
                new CFGTranslationPhaseOne()
                        .process(
                                bodyPath,
                                env,
                                underlyingAST,
                                exceptionalExitLabel,
                                builder,
                                annotationProvider);
        ControlFlowGraph phase2result = new CFGTranslationPhaseTwo().process(phase1result);
        ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result);
        return phase3result;
    }

    /** Build the control flow graph of a method. */
    public ControlFlowGraph run(
            CompilationUnitTree root,
            ProcessingEnvironment env,
            MethodTree tree,
            ClassTree classTree) {
        UnderlyingAST underlyingAST = new CFGMethod(tree, classTree);
        return run(root, env, underlyingAST);
    }

    /* --------------------------------------------------------- */
    /* Extended Node Types and Labels */
    /* --------------------------------------------------------- */

    /** Special label to identify the exceptional exit. */
    protected final Label exceptionalExitLabel = new Label();

    /** Special label to identify the regular exit. */
    protected final Label regularExitLabel = new Label();

    /**
     * An extended node can be one of several things (depending on its {@code type}):
     *
     * <ul>
     *   <li><em>NODE</em>. An extended node of this type is just a wrapper for a {@link Node} (that
     *       cannot throw exceptions).
     *   <li><em>EXCEPTION_NODE</em>. A wrapper for a {@link Node} which can throw exceptions. It
     *       contains a label for every possible exception type the node might throw.
     *   <li><em>UNCONDITIONAL_JUMP</em>. An unconditional jump to a label.
     *   <li><em>TWO_TARGET_CONDITIONAL_JUMP</em>. A conditional jump with two targets for both the
     *       'then' and 'else' branch.
     * </ul>
     */
    protected abstract static class ExtendedNode {

        /** The basic block this extended node belongs to (as determined in phase two). */
        protected BlockImpl block;

        /** Type of this node. */
        protected ExtendedNodeType type;

        /** Does this node terminate the execution? (e.g., "System.exit()") */
        protected boolean terminatesExecution = false;

        public ExtendedNode(ExtendedNodeType type) {
            this.type = type;
        }

        /** Extended node types (description see above). */
        public enum ExtendedNodeType {
            NODE,
            EXCEPTION_NODE,
            UNCONDITIONAL_JUMP,
            CONDITIONAL_JUMP
        }

        public ExtendedNodeType getType() {
            return type;
        }

        public boolean getTerminatesExecution() {
            return terminatesExecution;
        }

        public void setTerminatesExecution(boolean terminatesExecution) {
            this.terminatesExecution = terminatesExecution;
        }

        /**
         * @return the node contained in this extended node (only applicable if the type is {@code
         *     NODE} or {@code EXCEPTION_NODE}).
         */
        public Node getNode() {
            assert false;
            return null;
        }

        /**
         * @return the label associated with this extended node (only applicable if type is {@link
         *     ExtendedNodeType#CONDITIONAL_JUMP} or {@link ExtendedNodeType#UNCONDITIONAL_JUMP}).
         */
        public Label getLabel() {
            assert false;
            return null;
        }

        public BlockImpl getBlock() {
            return block;
        }

        public void setBlock(BlockImpl b) {
            this.block = b;
        }

        @Override
        public String toString() {
            return "ExtendedNode(" + type + ")";
        }
    }

    /** An extended node of type {@code NODE}. */
    protected static class NodeHolder extends ExtendedNode {

        protected Node node;

        public NodeHolder(Node node) {
            super(ExtendedNodeType.NODE);
            this.node = node;
        }

        @Override
        public Node getNode() {
            return node;
        }

        @Override
        public String toString() {
            return "NodeHolder(" + node + ")";
        }
    }

    /** An extended node of type {@code EXCEPTION_NODE}. */
    protected static class NodeWithExceptionsHolder extends ExtendedNode {

        protected Node node;
        /**
         * Map from exception type to labels of successors that may be reached as a result of that
         * exception.
         */
        protected Map<TypeMirror, Set<Label>> exceptions;

        public NodeWithExceptionsHolder(Node node, Map<TypeMirror, Set<Label>> exceptions) {
            super(ExtendedNodeType.EXCEPTION_NODE);
            this.node = node;
            this.exceptions = exceptions;
        }

        public Map<TypeMirror, Set<Label>> getExceptions() {
            return exceptions;
        }

        @Override
        public Node getNode() {
            return node;
        }

        @Override
        public String toString() {
            return "NodeWithExceptionsHolder(" + node + ")";
        }
    }

    /**
     * An extended node of type {@link ExtendedNodeType#CONDITIONAL_JUMP}.
     *
     * <p><em>Important:</em> In the list of extended nodes, there should not be any labels that
     * point to a conditional jump. Furthermore, the node directly ahead of any conditional jump has
     * to be a {@link NodeWithExceptionsHolder} or {@link NodeHolder}, and the node held by that
     * extended node is required to be of boolean type.
     */
    protected static class ConditionalJump extends ExtendedNode {

        protected Label trueSucc;
        protected Label falseSucc;

        protected Store.FlowRule trueFlowRule;
        protected Store.FlowRule falseFlowRule;

        public ConditionalJump(Label trueSucc, Label falseSucc) {
            super(ExtendedNodeType.CONDITIONAL_JUMP);
            this.trueSucc = trueSucc;
            this.falseSucc = falseSucc;
        }

        public Label getThenLabel() {
            return trueSucc;
        }

        public Label getElseLabel() {
            return falseSucc;
        }

        public Store.FlowRule getTrueFlowRule() {
            return trueFlowRule;
        }

        public Store.FlowRule getFalseFlowRule() {
            return falseFlowRule;
        }

        public void setTrueFlowRule(Store.FlowRule rule) {
            trueFlowRule = rule;
        }

        public void setFalseFlowRule(Store.FlowRule rule) {
            falseFlowRule = rule;
        }

        @Override
        public String toString() {
            return "TwoTargetConditionalJump(" + getThenLabel() + "," + getElseLabel() + ")";
        }
    }

    /** An extended node of type {@link ExtendedNodeType#UNCONDITIONAL_JUMP}. */
    protected static class UnconditionalJump extends ExtendedNode {

        protected Label jumpTarget;

        public UnconditionalJump(Label jumpTarget) {
            super(ExtendedNodeType.UNCONDITIONAL_JUMP);
            this.jumpTarget = jumpTarget;
        }

        @Override
        public Label getLabel() {
            return jumpTarget;
        }

        @Override
        public String toString() {
            return "JumpMarker(" + getLabel() + ")";
        }
    }

    /**
     * A label is used to refer to other extended nodes using a mapping from labels to extended
     * nodes. Labels get their names either from labeled statements in the source code or from
     * internally generated unique names.
     */
    protected static class Label {
        private static int uid = 0;

        protected String name;

        public Label(String name) {
            this.name = name;
        }

        public Label() {
            this.name = uniqueName();
        }

        @Override
        public String toString() {
            return name;
        }

        /**
         * Return a new unique label name that cannot be confused with a Java source code label.
         *
         * @return a new unique label name
         */
        private static String uniqueName() {
            return "%L" + uid++;
        }
    }

    /**
     * A TryFrame takes a thrown exception type and maps it to a set of possible control-flow
     * successors.
     */
    protected static interface TryFrame {
        /**
         * Given a type of thrown exception, add the set of possible control flow successor {@link
         * Label}s to the argument set. Return true if the exception is known to be caught by one of
         * those labels and false if it may propagate still further.
         */
        public boolean possibleLabels(TypeMirror thrown, Set<Label> labels);
    }

    /**
     * A TryCatchFrame contains an ordered list of catch labels that apply to exceptions with
     * specific types.
     */
    protected static class TryCatchFrame implements TryFrame {
        protected Types types;

        /** An ordered list of pairs because catch blocks are ordered. */
        protected List<Pair<TypeMirror, Label>> catchLabels;

        public TryCatchFrame(Types types, List<Pair<TypeMirror, Label>> catchLabels) {
            this.types = types;
            this.catchLabels = catchLabels;
        }

        /**
         * Given a type of thrown exception, add the set of possible control flow successor {@link
         * Label}s to the argument set. Return true if the exception is known to be caught by one of
         * those labels and false if it may propagate still further.
         */
        @Override
        public boolean possibleLabels(TypeMirror thrown, Set<Label> labels) {
            // A conservative approach would be to say that every catch block
            // might execute for any thrown exception, but we try to do better.
            //
            // We rely on several assumptions that seem to hold as of Java 7.
            // 1) An exception parameter in a catch block must be either
            //    a declared type or a union composed of declared types,
            //    all of which are subtypes of Throwable.
            // 2) A thrown type must either be a declared type or a variable
            //    that extends a declared type, which is a subtype of Throwable.
            //
            // Under those assumptions, if the thrown type (or its bound) is
            // a subtype of the caught type (or one of its alternatives), then
            // the catch block must apply and none of the later ones can apply.
            // Otherwise, if the thrown type (or its bound) is a supertype
            // of the caught type (or one of its alternatives), then the catch
            // block may apply, but so may later ones.
            // Otherwise, the thrown type and the caught type are unrelated
            // declared types, so they do not overlap on any non-null value.

            while (!(thrown instanceof DeclaredType)) {
                assert thrown instanceof TypeVariable
                        : "thrown type must be a variable or a declared type";
                thrown = ((TypeVariable) thrown).getUpperBound();
            }
            DeclaredType declaredThrown = (DeclaredType) thrown;
            assert thrown != null : "thrown type must be bounded by a declared type";

            for (Pair<TypeMirror, Label> pair : catchLabels) {
                TypeMirror caught = pair.first;
                boolean canApply = false;

                if (caught instanceof DeclaredType) {
                    DeclaredType declaredCaught = (DeclaredType) caught;
                    if (types.isSubtype(declaredThrown, declaredCaught)) {
                        // No later catch blocks can apply.
                        labels.add(pair.second);
                        return true;
                    } else if (types.isSubtype(declaredCaught, declaredThrown)) {
                        canApply = true;
                    }
                } else {
                    assert caught instanceof UnionType
                            : "caught type must be a union or a declared type";
                    UnionType caughtUnion = (UnionType) caught;
                    for (TypeMirror alternative : caughtUnion.getAlternatives()) {
                        assert alternative instanceof DeclaredType
                                : "alternatives of an caught union type must be declared types";
                        DeclaredType declaredAlt = (DeclaredType) alternative;
                        if (types.isSubtype(declaredThrown, declaredAlt)) {
                            // No later catch blocks can apply.
                            labels.add(pair.second);
                            return true;
                        } else if (types.isSubtype(declaredAlt, declaredThrown)) {
                            canApply = true;
                        }
                    }
                }

                if (canApply) {
                    labels.add(pair.second);
                }
            }

            return false;
        }
    }

    /** A TryFinallyFrame applies to exceptions of any type */
    protected static class TryFinallyFrame implements TryFrame {
        protected Label finallyLabel;

        public TryFinallyFrame(Label finallyLabel) {
            this.finallyLabel = finallyLabel;
        }

        @Override
        public boolean possibleLabels(TypeMirror thrown, Set<Label> labels) {
            labels.add(finallyLabel);
            return true;
        }
    }

    /**
     * An exception stack represents the set of all try-catch blocks in effect at a given point in a
     * program. It maps an exception type to a set of Labels and it maps a block exit (via return or
     * fall-through) to a single Label.
     */
    protected static class TryStack {
        protected Label exitLabel;
        protected LinkedList<TryFrame> frames;

        public TryStack(Label exitLabel) {
            this.exitLabel = exitLabel;
            this.frames = new LinkedList<>();
        }

        public void pushFrame(TryFrame frame) {
            frames.addFirst(frame);
        }

        public void popFrame() {
            frames.removeFirst();
        }

        /**
         * Returns the set of possible {@link Label}s where control may transfer when an exception
         * of the given type is thrown.
         */
        public Set<Label> possibleLabels(TypeMirror thrown) {
            // Work up from the innermost frame until the exception is known to
            // be caught.
            Set<Label> labels = new MostlySingleton<>();
            for (TryFrame frame : frames) {
                if (frame.possibleLabels(thrown, labels)) {
                    return labels;
                }
            }
            labels.add(exitLabel);
            return labels;
        }
    }

    /* --------------------------------------------------------- */
    /* Phase Three */
    /* --------------------------------------------------------- */

    /**
     * Class that performs phase three of the translation process. In particular, the following
     * degenerate cases of basic blocks are removed:
     *
     * <ol>
     *   <li>Empty regular basic blocks: These blocks will be removed and their predecessors linked
     *       directly to the successor.
     *   <li>Conditional basic blocks that have the same basic block as the 'then' and 'else'
     *       successor: The conditional basic block will be removed in this case.
     *   <li>Two consecutive, non-empty, regular basic blocks where the second block has exactly one
     *       predecessor (namely the other of the two blocks): In this case, the two blocks are
     *       merged.
     *   <li>Some basic blocks might not be reachable from the entryBlock. These basic blocks are
     *       removed, and the list of predecessors (in the doubly-linked structure of basic blocks)
     *       are adapted correctly.
     * </ol>
     *
     * Eliminating the second type of degenerate cases might introduce cases of the third problem.
     * These are also removed.
     */
    public static class CFGTranslationPhaseThree {

        /**
         * A simple wrapper object that holds a basic block and allows to set one of its successors.
         */
        protected interface PredecessorHolder {
            void setSuccessor(BlockImpl b);

            BlockImpl getBlock();
        }

        /**
         * Perform phase three on the control flow graph {@code cfg}.
         *
         * @param cfg the control flow graph. Ownership is transfered to this method and the caller
         *     is not allowed to read or modify {@code cfg} after the call to {@code process} any
         *     more.
         * @return the resulting control flow graph
         */
        public static ControlFlowGraph process(ControlFlowGraph cfg) {
            Set<Block> worklist = cfg.getAllBlocks();
            Set<Block> dontVisit = new HashSet<>();

            // note: this method has to be careful when relinking basic blocks
            // to not forget to adjust the predecessors, too

            // fix predecessor lists by removing any unreachable predecessors
            for (Block c : worklist) {
                BlockImpl cur = (BlockImpl) c;
                for (BlockImpl pred : new HashSet<>(cur.getPredecessors())) {
                    if (!worklist.contains(pred)) {
                        cur.removePredecessor(pred);
                    }
                }
            }

            // remove empty blocks
            for (Block cur : worklist) {
                if (dontVisit.contains(cur)) {
                    continue;
                }

                if (cur.getType() == BlockType.REGULAR_BLOCK) {
                    RegularBlockImpl b = (RegularBlockImpl) cur;
                    if (b.isEmpty()) {
                        Set<RegularBlockImpl> empty = new HashSet<>();
                        Set<PredecessorHolder> predecessors = new HashSet<>();
                        BlockImpl succ = computeNeighborhoodOfEmptyBlock(b, empty, predecessors);
                        for (RegularBlockImpl e : empty) {
                            succ.removePredecessor(e);
                            dontVisit.add(e);
                        }
                        for (PredecessorHolder p : predecessors) {
                            BlockImpl block = p.getBlock();
                            dontVisit.add(block);
                            succ.removePredecessor(block);
                            p.setSuccessor(succ);
                        }
                    }
                }
            }

            // remove useless conditional blocks
            worklist = cfg.getAllBlocks();
            for (Block c : worklist) {
                BlockImpl cur = (BlockImpl) c;

                if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
                    ConditionalBlockImpl cb = (ConditionalBlockImpl) cur;
                    assert cb.getPredecessors().size() == 1;
                    if (cb.getThenSuccessor() == cb.getElseSuccessor()) {
                        BlockImpl pred = cb.getPredecessors().iterator().next();
                        PredecessorHolder predecessorHolder = getPredecessorHolder(pred, cb);
                        BlockImpl succ = (BlockImpl) cb.getThenSuccessor();
                        succ.removePredecessor(cb);
                        predecessorHolder.setSuccessor(succ);
                    }
                }
            }

            // merge consecutive basic blocks if possible
            worklist = cfg.getAllBlocks();
            for (Block cur : worklist) {
                if (cur.getType() == BlockType.REGULAR_BLOCK) {
                    RegularBlockImpl b = (RegularBlockImpl) cur;
                    Block succ = b.getRegularSuccessor();
                    if (succ.getType() == BlockType.REGULAR_BLOCK) {
                        RegularBlockImpl rs = (RegularBlockImpl) succ;
                        if (rs.getPredecessors().size() == 1) {
                            b.setSuccessor(rs.getRegularSuccessor());
                            b.addNodes(rs.getContents());
                            rs.getRegularSuccessor().removePredecessor(rs);
                        }
                    }
                }
            }

            return cfg;
        }

        /**
         * Compute the set of empty regular basic blocks {@code empty}, starting at {@code start}
         * and going both forward and backwards. Furthermore, compute the predecessors of these
         * empty blocks ({@code predecessors} ), and their single successor (return value).
         *
         * @param start the starting point of the search (an empty, regular basic block)
         * @param empty an empty set to be filled by this method with all empty basic blocks found
         *     (including {@code start}).
         * @param predecessors an empty set to be filled by this method with all predecessors
         * @return the single successor of the set of the empty basic blocks
         */
        protected static BlockImpl computeNeighborhoodOfEmptyBlock(
                RegularBlockImpl start,
                Set<RegularBlockImpl> empty,
                Set<PredecessorHolder> predecessors) {

            // get empty neighborhood that come before 'start'
            computeNeighborhoodOfEmptyBlockBackwards(start, empty, predecessors);

            // go forward
            BlockImpl succ = (BlockImpl) start.getSuccessor();
            while (succ.getType() == BlockType.REGULAR_BLOCK) {
                RegularBlockImpl cur = (RegularBlockImpl) succ;
                if (cur.isEmpty()) {
                    computeNeighborhoodOfEmptyBlockBackwards(cur, empty, predecessors);
                    assert empty.contains(cur) : "cur ought to be in empty";
                    succ = (BlockImpl) cur.getSuccessor();
                    if (succ == cur) {
                        // An infinite loop, making exit block unreachable
                        break;
                    }
                } else {
                    break;
                }
            }
            return succ;
        }

        /**
         * Compute the set of empty regular basic blocks {@code empty}, starting at {@code start}
         * and looking only backwards in the control flow graph. Furthermore, compute the
         * predecessors of these empty blocks ( {@code predecessors}).
         *
         * @param start the starting point of the search (an empty, regular basic block)
         * @param empty a set to be filled by this method with all empty basic blocks found
         *     (including {@code start}).
         * @param predecessors a set to be filled by this method with all predecessors
         */
        protected static void computeNeighborhoodOfEmptyBlockBackwards(
                RegularBlockImpl start,
                Set<RegularBlockImpl> empty,
                Set<PredecessorHolder> predecessors) {

            RegularBlockImpl cur = start;
            empty.add(cur);
            for (final BlockImpl pred : cur.getPredecessors()) {
                switch (pred.getType()) {
                    case SPECIAL_BLOCK:
                        // add pred correctly to predecessor list
                        predecessors.add(getPredecessorHolder(pred, cur));
                        break;
                    case CONDITIONAL_BLOCK:
                        // add pred correctly to predecessor list
                        predecessors.add(getPredecessorHolder(pred, cur));
                        break;
                    case EXCEPTION_BLOCK:
                        // add pred correctly to predecessor list
                        predecessors.add(getPredecessorHolder(pred, cur));
                        break;
                    case REGULAR_BLOCK:
                        RegularBlockImpl r = (RegularBlockImpl) pred;
                        if (r.isEmpty()) {
                            // recursively look backwards
                            if (!empty.contains(r)) {
                                computeNeighborhoodOfEmptyBlockBackwards(r, empty, predecessors);
                            }
                        } else {
                            // add pred correctly to predecessor list
                            predecessors.add(getPredecessorHolder(pred, cur));
                        }
                        break;
                }
            }
        }

        /**
         * Return a predecessor holder that can be used to set the successor of {@code pred} in the
         * place where previously the edge pointed to {@code cur}. Additionally, the predecessor
         * holder also takes care of unlinking (i.e., removing the {@code pred} from {@code cur's}
         * predecessors).
         */
        protected static PredecessorHolder getPredecessorHolder(
                final BlockImpl pred, final BlockImpl cur) {
            switch (pred.getType()) {
                case SPECIAL_BLOCK:
                    SingleSuccessorBlockImpl s = (SingleSuccessorBlockImpl) pred;
                    return singleSuccessorHolder(s, cur);
                case CONDITIONAL_BLOCK:
                    // add pred correctly to predecessor list
                    final ConditionalBlockImpl c = (ConditionalBlockImpl) pred;
                    if (c.getThenSuccessor() == cur) {
                        return new PredecessorHolder() {
                            @Override
                            public void setSuccessor(BlockImpl b) {
                                c.setThenSuccessor(b);
                                cur.removePredecessor(pred);
                            }

                            @Override
                            public BlockImpl getBlock() {
                                return c;
                            }
                        };
                    } else {
                        assert c.getElseSuccessor() == cur;
                        return new PredecessorHolder() {
                            @Override
                            public void setSuccessor(BlockImpl b) {
                                c.setElseSuccessor(b);
                                cur.removePredecessor(pred);
                            }

                            @Override
                            public BlockImpl getBlock() {
                                return c;
                            }
                        };
                    }
                case EXCEPTION_BLOCK:
                    // add pred correctly to predecessor list
                    final ExceptionBlockImpl e = (ExceptionBlockImpl) pred;
                    if (e.getSuccessor() == cur) {
                        return singleSuccessorHolder(e, cur);
                    } else {
                        Set<Entry<TypeMirror, Set<Block>>> entrySet =
                                e.getExceptionalSuccessors().entrySet();
                        for (final Entry<TypeMirror, Set<Block>> entry : entrySet) {
                            if (entry.getValue().contains(cur)) {
                                return new PredecessorHolder() {
                                    @Override
                                    public void setSuccessor(BlockImpl b) {
                                        e.addExceptionalSuccessor(b, entry.getKey());
                                        cur.removePredecessor(pred);
                                    }

                                    @Override
                                    public BlockImpl getBlock() {
                                        return e;
                                    }
                                };
                            }
                        }
                    }
                    assert false;
                    break;
                case REGULAR_BLOCK:
                    RegularBlockImpl r = (RegularBlockImpl) pred;
                    return singleSuccessorHolder(r, cur);
            }
            return null;
        }

        /**
         * @return a {@link PredecessorHolder} that sets the successor of a single successor block
         *     {@code s}.
         */
        protected static PredecessorHolder singleSuccessorHolder(
                final SingleSuccessorBlockImpl s, final BlockImpl old) {
            return new PredecessorHolder() {
                @Override
                public void setSuccessor(BlockImpl b) {
                    s.setSuccessor(b);
                    old.removePredecessor(s);
                }

                @Override
                public BlockImpl getBlock() {
                    return s;
                }
            };
        }
    }

    /* --------------------------------------------------------- */
    /* Phase Two */
    /* --------------------------------------------------------- */

    /** Tuple class with up to three members. */
    protected static class Tuple<A, B, C> {
        public A a;
        public B b;
        public C c;

        public Tuple(A a, B b) {
            this.a = a;
            this.b = b;
        }

        public Tuple(A a, B b, C c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }

    /** Class that performs phase two of the translation process. */
    public class CFGTranslationPhaseTwo {

        public CFGTranslationPhaseTwo() {}

        /**
         * Perform phase two of the translation.
         *
         * @param in the result of phase one
         * @return a control flow graph that might still contain degenerate basic block (such as
         *     empty regular basic blocks or conditional blocks with the same block as 'then' and
         *     'else' sucessor)
         */
        public ControlFlowGraph process(PhaseOneResult in) {

            Map<Label, Integer> bindings = in.bindings;
            ArrayList<ExtendedNode> nodeList = in.nodeList;
            Set<Integer> leaders = in.leaders;

            assert in.nodeList.size() > 0;

            // exit blocks
            SpecialBlockImpl regularExitBlock = new SpecialBlockImpl(SpecialBlockType.EXIT);
            SpecialBlockImpl exceptionalExitBlock =
                    new SpecialBlockImpl(SpecialBlockType.EXCEPTIONAL_EXIT);

            // record missing edges that will be added later
            Set<Tuple<? extends SingleSuccessorBlockImpl, Integer, ?>> missingEdges =
                    new MostlySingleton<>();

            // missing exceptional edges
            Set<Tuple<ExceptionBlockImpl, Integer, TypeMirror>> missingExceptionalEdges =
                    new HashSet<>();

            // create start block
            SpecialBlockImpl startBlock = new SpecialBlockImpl(SpecialBlockType.ENTRY);
            missingEdges.add(new Tuple<>(startBlock, 0));

            // loop through all 'leaders' (while dynamically detecting the
            // leaders)
            RegularBlockImpl block = new RegularBlockImpl();
            int i = 0;
            for (ExtendedNode node : nodeList) {
                switch (node.getType()) {
                    case NODE:
                        if (leaders.contains(i)) {
                            RegularBlockImpl b = new RegularBlockImpl();
                            block.setSuccessor(b);
                            block = b;
                        }
                        block.addNode(node.getNode());
                        node.setBlock(block);

                        // does this node end the execution (modeled as an edge to
                        // the exceptional exit block)
                        boolean terminatesExecution = node.getTerminatesExecution();
                        if (terminatesExecution) {
                            block.setSuccessor(exceptionalExitBlock);
                            block = new RegularBlockImpl();
                        }
                        break;
                    case CONDITIONAL_JUMP:
                        {
                            ConditionalJump cj = (ConditionalJump) node;
                            // Exception nodes may fall through to conditional jumps,
                            // so we set the block which is required for the insertion
                            // of missing edges.
                            node.setBlock(block);
                            assert block != null;
                            final ConditionalBlockImpl cb = new ConditionalBlockImpl();
                            if (cj.getTrueFlowRule() != null) {
                                cb.setThenFlowRule(cj.getTrueFlowRule());
                            }
                            if (cj.getFalseFlowRule() != null) {
                                cb.setElseFlowRule(cj.getFalseFlowRule());
                            }
                            block.setSuccessor(cb);
                            block = new RegularBlockImpl();
                            // use two anonymous SingleSuccessorBlockImpl that set the
                            // 'then' and 'else' successor of the conditional block
                            final Label thenLabel = cj.getThenLabel();
                            final Label elseLabel = cj.getElseLabel();
                            missingEdges.add(
                                    new Tuple<>(
                                            new SingleSuccessorBlockImpl() {
                                                @Override
                                                public void setSuccessor(BlockImpl successor) {
                                                    cb.setThenSuccessor(successor);
                                                }
                                            },
                                            bindings.get(thenLabel)));
                            missingEdges.add(
                                    new Tuple<>(
                                            new SingleSuccessorBlockImpl() {
                                                @Override
                                                public void setSuccessor(BlockImpl successor) {
                                                    cb.setElseSuccessor(successor);
                                                }
                                            },
                                            bindings.get(elseLabel)));
                            break;
                        }
                    case UNCONDITIONAL_JUMP:
                        if (leaders.contains(i)) {
                            RegularBlockImpl b = new RegularBlockImpl();
                            block.setSuccessor(b);
                            block = b;
                        }
                        node.setBlock(block);
                        if (node.getLabel() == regularExitLabel) {
                            block.setSuccessor(regularExitBlock);
                        } else if (node.getLabel() == exceptionalExitLabel) {
                            block.setSuccessor(exceptionalExitBlock);
                        } else {
                            missingEdges.add(new Tuple<>(block, bindings.get(node.getLabel())));
                        }
                        block = new RegularBlockImpl();
                        break;
                    case EXCEPTION_NODE:
                        NodeWithExceptionsHolder en = (NodeWithExceptionsHolder) node;
                        // create new exception block and link with previous block
                        ExceptionBlockImpl e = new ExceptionBlockImpl();
                        Node nn = en.getNode();
                        e.setNode(nn);
                        node.setBlock(e);
                        block.setSuccessor(e);
                        block = new RegularBlockImpl();

                        // ensure linking between e and next block (normal edge)
                        // Note: do not link to the next block for throw statements
                        // (these throw exceptions for sure)
                        if (!node.getTerminatesExecution()) {
                            missingEdges.add(new Tuple<>(e, i + 1));
                        }

                        // exceptional edges
                        for (Entry<TypeMirror, Set<Label>> entry : en.getExceptions().entrySet()) {
                            TypeMirror cause = entry.getKey();
                            for (Label label : entry.getValue()) {
                                Integer target = bindings.get(label);
                                missingExceptionalEdges.add(
                                        new Tuple<ExceptionBlockImpl, Integer, TypeMirror>(
                                                e, target, cause));
                            }
                        }
                        break;
                }
                i++;
            }

            // add missing edges
            for (Tuple<? extends SingleSuccessorBlockImpl, Integer, ?> p : missingEdges) {
                Integer index = p.b;
                ExtendedNode extendedNode = nodeList.get(index);
                BlockImpl target = extendedNode.getBlock();
                SingleSuccessorBlockImpl source = p.a;
                source.setSuccessor(target);
            }

            // add missing exceptional edges
            for (Tuple<ExceptionBlockImpl, Integer, ?> p : missingExceptionalEdges) {
                Integer index = p.b;
                TypeMirror cause = (TypeMirror) p.c;
                ExceptionBlockImpl source = p.a;
                if (index == null) {
                    // edge to exceptional exit
                    source.addExceptionalSuccessor(exceptionalExitBlock, cause);
                } else {
                    // edge to specific target
                    ExtendedNode extendedNode = nodeList.get(index);
                    BlockImpl target = extendedNode.getBlock();
                    source.addExceptionalSuccessor(target, cause);
                }
            }

            return new ControlFlowGraph(
                    startBlock,
                    regularExitBlock,
                    exceptionalExitBlock,
                    in.underlyingAST,
                    in.treeLookupMap,
                    in.convertedTreeLookupMap,
                    in.returnNodes);
        }
    }

    /* --------------------------------------------------------- */
    /* Phase One */
    /* --------------------------------------------------------- */

    /**
     * A wrapper object to pass around the result of phase one. For a documentation of the fields
     * see {@link CFGTranslationPhaseOne}.
     */
    protected static class PhaseOneResult {

        private final IdentityHashMap<Tree, Node> treeLookupMap;
        private final IdentityHashMap<Tree, Node> convertedTreeLookupMap;
        private final UnderlyingAST underlyingAST;
        private final Map<Label, Integer> bindings;
        private final ArrayList<ExtendedNode> nodeList;
        private final Set<Integer> leaders;
        private final List<ReturnNode> returnNodes;

        public PhaseOneResult(
                UnderlyingAST underlyingAST,
                IdentityHashMap<Tree, Node> treeLookupMap,
                IdentityHashMap<Tree, Node> convertedTreeLookupMap,
                ArrayList<ExtendedNode> nodeList,
                Map<Label, Integer> bindings,
                Set<Integer> leaders,
                List<ReturnNode> returnNodes) {
            this.underlyingAST = underlyingAST;
            this.treeLookupMap = treeLookupMap;
            this.convertedTreeLookupMap = convertedTreeLookupMap;
            this.nodeList = nodeList;
            this.bindings = bindings;
            this.leaders = leaders;
            this.returnNodes = returnNodes;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (ExtendedNode n : nodeList) {
                sb.append(nodeToString(n));
                sb.append("\n");
            }
            return sb.toString();
        }

        protected String nodeToString(ExtendedNode n) {
            if (n.getType() == ExtendedNodeType.CONDITIONAL_JUMP) {
                ConditionalJump t = (ConditionalJump) n;
                return "TwoTargetConditionalJump("
                        + resolveLabel(t.getThenLabel())
                        + ","
                        + resolveLabel(t.getElseLabel())
                        + ")";
            } else if (n.getType() == ExtendedNodeType.UNCONDITIONAL_JUMP) {
                return "UnconditionalJump(" + resolveLabel(n.getLabel()) + ")";
            } else {
                return n.toString();
            }
        }

        private String resolveLabel(Label label) {
            Integer index = bindings.get(label);
            if (index == null) {
                return "null";
            }
            return nodeToString(nodeList.get(index));
        }
    }

    /**
     * Class that performs phase one of the translation process. It generates the following
     * information:
     *
     * <ul>
     *   <li>A sequence of extended nodes.
     *   <li>A set of bindings from {@link Label}s to positions in the node sequence.
     *   <li>A set of leader nodes that give rise to basic blocks in phase two.
     *   <li>A lookup map that gives the mapping from AST tree nodes to {@link Node}s.
     * </ul>
     *
     * <p>The return type of this scanner is {@link Node}. For expressions, the corresponding node
     * is returned to allow linking between different nodes.
     *
     * <p>However, for statements there is usually no single {@link Node} that is created, and thus
     * no node is returned (rather, null is returned).
     *
     * <p>Every {@code visit*} method is assumed to add at least one extended node to the list of
     * nodes (which might only be a jump).
     */
    public class CFGTranslationPhaseOne extends TreePathScanner<Node, Void> {

        public CFGTranslationPhaseOne() {}

        /** Annotation processing environment and its associated type and tree utilities. */
        protected ProcessingEnvironment env;

        protected Elements elements;
        protected Types types;
        protected Trees trees;
        protected TreeBuilder treeBuilder;
        protected AnnotationProvider annotationProvider;

        /**
         * Current {@link Label} to which a break statement with no label should jump, or null if
         * there is no valid destination.
         */
        protected /*@Nullable*/ Label breakTargetL;

        /**
         * Map from AST label Names to CFG {@link Label}s for breaks. Each labeled statement creates
         * two CFG {@link Label}s, one for break and one for continue.
         */
        protected Map<Name, Label> breakLabels;

        /**
         * Current {@link Label} to which a continue statement with no label should jump, or null if
         * there is no valid destination.
         */
        protected /*@Nullable*/ Label continueTargetL;

        /**
         * Map from AST label Names to CFG {@link Label}s for continues. Each labeled statement
         * creates two CFG {@link Label}s, one for break and one for continue.
         */
        protected Map<Name, Label> continueLabels;

        /**
         * Maps from AST {@link Tree}s to {@link Node}s. Every Tree that produces a value will have
         * at least one corresponding Node. Trees that undergo conversions, such as boxing or
         * unboxing, can map to two distinct Nodes. The Node for the pre-conversion value is stored
         * in the treeLookupMap, while the Node for the post-conversion value is stored in the
         * convertedTreeLookupMap.
         */
        protected IdentityHashMap<Tree, Node> treeLookupMap;

        /** Map from AST {@link Tree}s to post-conversion {@link Node}s. */
        protected IdentityHashMap<Tree, Node> convertedTreeLookupMap;

        /** The list of extended nodes. */
        protected ArrayList<ExtendedNode> nodeList;

        /** The bindings of labels to positions (i.e., indices) in the {@code nodeList}. */
        protected Map<Label, Integer> bindings;

        /** The set of leaders (represented as indices into {@code nodeList}). */
        protected Set<Integer> leaders;

        /**
         * All return nodes (if any) encountered. Only includes return statements that actually
         * return something
         */
        private List<ReturnNode> returnNodes;

        /** Nested scopes of try-catch blocks in force at the current program point. */
        private TryStack tryStack;

        /**
         * Performs the actual work of phase one.
         *
         * @param bodyPath path to the body of the underlying AST's method
         * @param env annotation processing environment containing type utilities
         * @param underlyingAST the AST for which the CFG is to be built
         * @param exceptionalExitLabel the label for exceptional exits from the CFG
         * @param treeBuilder builder for new AST nodes
         * @param annotationProvider extracts annotations from AST nodes
         * @return the result of phase one
         */
        public PhaseOneResult process(
                TreePath bodyPath,
                ProcessingEnvironment env,
                UnderlyingAST underlyingAST,
                Label exceptionalExitLabel,
                TreeBuilder treeBuilder,
                AnnotationProvider annotationProvider) {
            this.env = env;
            this.tryStack = new TryStack(exceptionalExitLabel);
            this.treeBuilder = treeBuilder;
            this.annotationProvider = annotationProvider;
            elements = env.getElementUtils();
            types = env.getTypeUtils();

            // initialize lists and maps
            treeLookupMap = new IdentityHashMap<>();
            convertedTreeLookupMap = new IdentityHashMap<>();
            nodeList = new ArrayList<>();
            bindings = new HashMap<>();
            leaders = new HashSet<>();
            breakLabels = new HashMap<>();
            continueLabels = new HashMap<>();
            returnNodes = new ArrayList<>();

            // traverse AST of the method body
            scan(bodyPath, null);

            // add marker to indicate that the next block will be the exit block
            // Note: if there is a return statement earlier in the method (which
            // is always the case for non-void methods), then this is not
            // strictly necessary. However, it is also not a problem, as it will
            // just generate a degenerated control graph case that will be
            // removed in a later phase.
            nodeList.add(new UnconditionalJump(regularExitLabel));

            return new PhaseOneResult(
                    underlyingAST,
                    treeLookupMap,
                    convertedTreeLookupMap,
                    nodeList,
                    bindings,
                    leaders,
                    returnNodes);
        }

        public PhaseOneResult process(
                CompilationUnitTree root,
                ProcessingEnvironment env,
                UnderlyingAST underlyingAST,
                Label exceptionalExitLabel,
                TreeBuilder treeBuilder,
                AnnotationProvider annotationProvider) {
            trees = Trees.instance(env);
            TreePath bodyPath = trees.getPath(root, underlyingAST.getCode());
            return process(
                    bodyPath,
                    env,
                    underlyingAST,
                    exceptionalExitLabel,
                    treeBuilder,
                    annotationProvider);
        }

        /**
         * Perform any actions required when CFG translation creates a new Tree that is not part of
         * the original AST.
         *
         * @param tree the newly created Tree
         */
        public void handleArtificialTree(Tree tree) {}

        /* --------------------------------------------------------- */
        /* Nodes and Labels Management */
        /* --------------------------------------------------------- */

        /**
         * Add a node to the lookup map if it not already present.
         *
         * @param node the node to add to the lookup map
         */
        protected void addToLookupMap(Node node) {
            Tree tree = node.getTree();
            if (tree == null) {
                return;
            }
            if (!treeLookupMap.containsKey(tree)) {
                treeLookupMap.put(tree, node);
            }

            Tree enclosingParens = parenMapping.get(tree);
            while (enclosingParens != null) {
                treeLookupMap.put(enclosingParens, node);
                enclosingParens = parenMapping.get(enclosingParens);
            }
        }

        /**
         * Add a node in the post-conversion lookup map. The node should refer to a Tree and that
         * Tree should already be in the pre-conversion lookup map. This method is used to update
         * the Tree-Node mapping with conversion nodes.
         *
         * @param node the node to add to the lookup map
         */
        protected void addToConvertedLookupMap(Node node) {
            Tree tree = node.getTree();
            addToConvertedLookupMap(tree, node);
        }

        /**
         * Add a node in the post-conversion lookup map. The tree argument should already be in the
         * pre-conversion lookup map. This method is used to update the Tree-Node mapping with
         * conversion nodes.
         *
         * @param tree the tree used as a key in the map
         * @param node the node to add to the lookup map
         */
        protected void addToConvertedLookupMap(Tree tree, Node node) {
            assert tree != null;
            assert treeLookupMap.containsKey(tree);
            convertedTreeLookupMap.put(tree, node);
        }

        /**
         * Extend the list of extended nodes with a node.
         *
         * @param node the node to add
         * @return the same node (for convenience)
         */
        protected <T extends Node> T extendWithNode(T node) {
            addToLookupMap(node);
            extendWithExtendedNode(new NodeHolder(node));
            return node;
        }

        /**
         * Extend the list of extended nodes with a node, where {@code node} might throw the
         * exception {@code cause}.
         *
         * @param node the node to add
         * @param cause an exception that the node might throw
         * @return the node holder
         */
        protected NodeWithExceptionsHolder extendWithNodeWithException(
                Node node, TypeMirror cause) {
            addToLookupMap(node);
            return extendWithNodeWithExceptions(node, Collections.singleton(cause));
        }

        /**
         * Extend the list of extended nodes with a node, where {@code node} might throw any of the
         * exception in {@code causes}.
         *
         * @param node the node to add
         * @param causes set of exceptions that the node might throw
         * @return the node holder
         */
        protected NodeWithExceptionsHolder extendWithNodeWithExceptions(
                Node node, Set<TypeMirror> causes) {
            addToLookupMap(node);
            Map<TypeMirror, Set<Label>> exceptions = new HashMap<>();
            for (TypeMirror cause : causes) {
                exceptions.put(cause, tryStack.possibleLabels(cause));
            }
            NodeWithExceptionsHolder exNode = new NodeWithExceptionsHolder(node, exceptions);
            extendWithExtendedNode(exNode);
            return exNode;
        }

        /**
         * Insert {@code node} after {@code pred} in the list of extended nodes, or append to the
         * list if {@code pred} is not present.
         *
         * @param node the node to add
         * @param pred the desired predecessor of node
         * @return the node holder
         */
        protected <T extends Node> T insertNodeAfter(T node, Node pred) {
            addToLookupMap(node);
            insertExtendedNodeAfter(new NodeHolder(node), pred);
            return node;
        }

        /**
         * Insert a {@code node} that might throw the exception {@code cause} after {@code pred} in
         * the list of extended nodes, or append to the list if {@code pred} is not present.
         *
         * @param node the node to add
         * @param causes set of exceptions that the node might throw
         * @param pred the desired predecessor of node
         * @return the node holder
         */
        protected NodeWithExceptionsHolder insertNodeWithExceptionsAfter(
                Node node, Set<TypeMirror> causes, Node pred) {
            addToLookupMap(node);
            Map<TypeMirror, Set<Label>> exceptions = new HashMap<>();
            for (TypeMirror cause : causes) {
                exceptions.put(cause, tryStack.possibleLabels(cause));
            }
            NodeWithExceptionsHolder exNode = new NodeWithExceptionsHolder(node, exceptions);
            insertExtendedNodeAfter(exNode, pred);
            return exNode;
        }

        /**
         * Extend the list of extended nodes with an extended node.
         *
         * @param n the extended node
         */
        protected void extendWithExtendedNode(ExtendedNode n) {
            nodeList.add(n);
        }

        /**
         * Insert {@code n} after the node {@code pred} in the list of extended nodes, or append
         * {@code n} if {@code pred} is not present.
         *
         * @param n the extended node
         * @param pred the desired predecessor
         */
        protected void insertExtendedNodeAfter(ExtendedNode n, Node pred) {
            int index = -1;
            for (int i = 0; i < nodeList.size(); i++) {
                ExtendedNode inList = nodeList.get(i);
                if (inList instanceof NodeHolder || inList instanceof NodeWithExceptionsHolder) {
                    if (inList.getNode() == pred) {
                        index = i;
                        break;
                    }
                }
            }
            if (index != -1) {
                nodeList.add(index + 1, n);
                // update bindings
                for (Entry<Label, Integer> e : bindings.entrySet()) {
                    if (e.getValue() >= index + 1) {
                        bindings.put(e.getKey(), e.getValue() + 1);
                    }
                }
                // update leaders
                Set<Integer> newLeaders = new HashSet<>();
                for (Integer l : leaders) {
                    if (l >= index + 1) {
                        newLeaders.add(l + 1);
                    } else {
                        newLeaders.add(l);
                    }
                }
                leaders = newLeaders;
            } else {
                nodeList.add(n);
            }
        }

        /**
         * Add the label {@code l} to the extended node that will be placed next in the sequence.
         */
        protected void addLabelForNextNode(Label l) {
            leaders.add(nodeList.size());
            bindings.put(l, nodeList.size());
        }

        /* --------------------------------------------------------- */
        /* Utility Methods */
        /* --------------------------------------------------------- */

        protected long uid = 0;

        protected String uniqueName(String prefix) {
            return prefix + "#num" + uid++;
        }

        /**
         * If the input node is an unboxed primitive type, insert a call to the appropriate valueOf
         * method, otherwise leave it alone.
         *
         * @param node in input node
         * @return a Node representing the boxed version of the input, which may simply be the input
         *     node
         */
        protected Node box(Node node) {
            // For boxing conversion, see JLS 5.1.7
            if (TypesUtils.isPrimitive(node.getType())) {
                PrimitiveType primitive = types.getPrimitiveType(node.getType().getKind());
                TypeMirror boxedType = types.getDeclaredType(types.boxedClass(primitive));

                TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();
                IdentifierTree classTree = treeBuilder.buildClassUse(boxedElement);
                handleArtificialTree(classTree);
                ClassNameNode className = new ClassNameNode(classTree);
                className.setInSource(false);
                insertNodeAfter(className, node);

                MemberSelectTree valueOfSelect = treeBuilder.buildValueOfMethodAccess(classTree);
                handleArtificialTree(valueOfSelect);
                MethodAccessNode valueOfAccess = new MethodAccessNode(valueOfSelect, className);
                valueOfAccess.setInSource(false);
                insertNodeAfter(valueOfAccess, className);

                MethodInvocationTree valueOfCall =
                        treeBuilder.buildMethodInvocation(
                                valueOfSelect, (ExpressionTree) node.getTree());
                handleArtificialTree(valueOfCall);
                Node boxed =
                        new MethodInvocationNode(
                                valueOfCall,
                                valueOfAccess,
                                Collections.singletonList(node),
                                getCurrentPath());
                boxed.setInSource(false);
                // Add Throwable to account for unchecked exceptions
                TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable");
                addToConvertedLookupMap(node.getTree(), boxed);
                insertNodeWithExceptionsAfter(
                        boxed, Collections.singleton(throwableElement.asType()), valueOfAccess);
                return boxed;
            } else {
                return node;
            }
        }

        /**
         * If the input node is a boxed type, unbox it, otherwise leave it alone.
         *
         * @param node in input node
         * @return a Node representing the unboxed version of the input, which may simply be the
         *     input node
         */
        protected Node unbox(Node node) {
            if (TypesUtils.isBoxedPrimitive(node.getType())) {

                MemberSelectTree primValueSelect =
                        treeBuilder.buildPrimValueMethodAccess(node.getTree());
                handleArtificialTree(primValueSelect);
                MethodAccessNode primValueAccess = new MethodAccessNode(primValueSelect, node);
                primValueAccess.setInSource(false);
                // Method access may throw NullPointerException
                TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException");
                insertNodeWithExceptionsAfter(
                        primValueAccess, Collections.singleton(npeElement.asType()), node);

                MethodInvocationTree primValueCall =
                        treeBuilder.buildMethodInvocation(primValueSelect);
                handleArtificialTree(primValueCall);
                Node unboxed =
                        new MethodInvocationNode(
                                primValueCall,
                                primValueAccess,
                                Collections.<Node>emptyList(),
                                getCurrentPath());
                unboxed.setInSource(false);

                // Add Throwable to account for unchecked exceptions
                TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable");
                addToConvertedLookupMap(node.getTree(), unboxed);
                insertNodeWithExceptionsAfter(
                        unboxed, Collections.singleton(throwableElement.asType()), primValueAccess);
                return unboxed;
            } else {
                return node;
            }
        }

        private TreeInfo getTreeInfo(Tree tree) {
            final TypeMirror type = InternalUtils.typeOf(tree);
            final boolean boxed = TypesUtils.isBoxedPrimitive(type);
            final TypeMirror unboxedType = boxed ? types.unboxedType(type) : type;

            final boolean bool = TypesUtils.isBooleanType(type);
            final boolean numeric = TypesUtils.isNumeric(unboxedType);

            return new TreeInfo() {
                @Override
                public boolean isNumeric() {
                    return numeric;
                }

                @Override
                public boolean isBoxed() {
                    return boxed;
                }

                @Override
                public boolean isBoolean() {
                    return bool;
                }

                @Override
                public TypeMirror unboxedType() {
                    return unboxedType;
                }
            };
        }

        /** @return the unboxed tree if necessary, as described in JLS 5.1.8 */
        private Node unboxAsNeeded(Node node, boolean boxed) {
            return boxed ? unbox(node) : node;
        }

        /**
         * Convert the input node to String type, if it isn't already.
         *
         * @param node an input node
         * @return a Node with the value promoted to String, which may be the input node
         */
        protected Node stringConversion(Node node) {
            // For string conversion, see JLS 5.1.11
            TypeElement stringElement = elements.getTypeElement("java.lang.String");
            if (!TypesUtils.isString(node.getType())) {
                Node converted =
                        new StringConversionNode(node.getTree(), node, stringElement.asType());
                addToConvertedLookupMap(converted);
                insertNodeAfter(converted, node);
                return converted;
            } else {
                return node;
            }
        }

        /**
         * Perform unary numeric promotion on the input node.
         *
         * @param node a node producing a value of numeric primitive or boxed type
         * @return a Node with the value promoted to the int, long float or double, which may be the
         *     input node
         */
        protected Node unaryNumericPromotion(Node node) {
            // For unary numeric promotion, see JLS 5.6.1
            node = unbox(node);

            switch (node.getType().getKind()) {
                case BYTE:
                case CHAR:
                case SHORT:
                    {
                        TypeMirror intType = types.getPrimitiveType(TypeKind.INT);
                        Node widened = new WideningConversionNode(node.getTree(), node, intType);
                        addToConvertedLookupMap(widened);
                        insertNodeAfter(widened, node);
                        return widened;
                    }
                default:
                    // Nothing to do.
                    break;
            }

            return node;
        }

        /**
         * Returns true if the argument type is a numeric primitive or a boxed numeric primitive and
         * false otherwise.
         */
        protected boolean isNumericOrBoxed(TypeMirror type) {
            if (TypesUtils.isBoxedPrimitive(type)) {
                type = types.unboxedType(type);
            }
            return TypesUtils.isNumeric(type);
        }

        /**
         * Compute the type to which two numeric types must be promoted before performing a binary
         * numeric operation on them. The input types must both be numeric and the output type is
         * primitive.
         *
         * @param left the type of the left operand
         * @param right the type of the right operand
         * @return a TypeMirror representing the binary numeric promoted type
         */
        protected TypeMirror binaryPromotedType(TypeMirror left, TypeMirror right) {
            if (TypesUtils.isBoxedPrimitive(left)) {
                left = types.unboxedType(left);
            }
            if (TypesUtils.isBoxedPrimitive(right)) {
                right = types.unboxedType(right);
            }
            TypeKind promotedTypeKind = TypesUtils.widenedNumericType(left, right);
            return types.getPrimitiveType(promotedTypeKind);
        }

        /**
         * Perform binary numeric promotion on the input node to make it match the expression type.
         *
         * @param node a node producing a value of numeric primitive or boxed type
         * @param exprType the type to promote the value to
         * @return a Node with the value promoted to the exprType, which may be the input node
         */
        protected Node binaryNumericPromotion(Node node, TypeMirror exprType) {
            // For binary numeric promotion, see JLS 5.6.2
            node = unbox(node);

            if (!types.isSameType(node.getType(), exprType)) {
                Node widened = new WideningConversionNode(node.getTree(), node, exprType);
                addToConvertedLookupMap(widened);
                insertNodeAfter(widened, node);
                return widened;
            } else {
                return node;
            }
        }

        /**
         * Perform widening primitive conversion on the input node to make it match the destination
         * type.
         *
         * @param node a node producing a value of numeric primitive type
         * @param destType the type to widen the value to
         * @return a Node with the value widened to the exprType, which may be the input node
         */
        protected Node widen(Node node, TypeMirror destType) {
            // For widening conversion, see JLS 5.1.2
            assert TypesUtils.isPrimitive(node.getType()) && TypesUtils.isPrimitive(destType)
                    : "widening must be applied to primitive types";
            if (types.isSubtype(node.getType(), destType)
                    && !types.isSameType(node.getType(), destType)) {
                Node widened = new WideningConversionNode(node.getTree(), node, destType);
                addToConvertedLookupMap(widened);
                insertNodeAfter(widened, node);
                return widened;
            } else {
                return node;
            }
        }

        /**
         * Perform narrowing conversion on the input node to make it match the destination type.
         *
         * @param node a node producing a value of numeric primitive type
         * @param destType the type to narrow the value to
         * @return a Node with the value narrowed to the exprType, which may be the input node
         */
        protected Node narrow(Node node, TypeMirror destType) {
            // For narrowing conversion, see JLS 5.1.3
            assert TypesUtils.isPrimitive(node.getType()) && TypesUtils.isPrimitive(destType)
                    : "narrowing must be applied to primitive types";
            if (types.isSubtype(destType, node.getType())
                    && !types.isSameType(destType, node.getType())) {
                Node narrowed = new NarrowingConversionNode(node.getTree(), node, destType);
                addToConvertedLookupMap(narrowed);
                insertNodeAfter(narrowed, node);
                return narrowed;
            } else {
                return node;
            }
        }

        /**
         * Perform narrowing conversion and optionally boxing conversion on the input node to make
         * it match the destination type.
         *
         * @param node a node producing a value of numeric primitive type
         * @param destType the type to narrow the value to (possibly boxed)
         * @return a Node with the value narrowed and boxed to the destType, which may be the input
         *     node
         */
        protected Node narrowAndBox(Node node, TypeMirror destType) {
            if (TypesUtils.isBoxedPrimitive(destType)) {
                return box(narrow(node, types.unboxedType(destType)));
            } else {
                return narrow(node, destType);
            }
        }

        /**
         * Return whether a conversion from the type of the node to varType requires narrowing.
         *
         * @param varType the type of a variable (or general LHS) to be converted to
         * @param node a node whose value is being converted
         * @return whether this conversion requires narrowing to succeed
         */
        protected boolean conversionRequiresNarrowing(TypeMirror varType, Node node) {
            // Narrowing is restricted to cases where the left hand side
            // is byte, char, short or Byte, Char, Short and the right
            // hand side is a constant.
            TypeMirror unboxedVarType =
                    TypesUtils.isBoxedPrimitive(varType) ? types.unboxedType(varType) : varType;
            TypeKind unboxedVarKind = unboxedVarType.getKind();
            boolean isLeftNarrowableTo =
                    unboxedVarKind == TypeKind.BYTE
                            || unboxedVarKind == TypeKind.SHORT
                            || unboxedVarKind == TypeKind.CHAR;
            boolean isRightConstant = node instanceof ValueLiteralNode;
            return isLeftNarrowableTo && isRightConstant;
        }

        /**
         * Assignment conversion and method invocation conversion are almost identical, except that
         * assignment conversion allows narrowing. We factor out the common logic here.
         *
         * @param node a Node producing a value
         * @param varType the type of a variable
         * @param contextAllowsNarrowing whether to allow narrowing (for assignment conversion) or
         *     not (for method invocation conversion)
         * @return a Node with the value converted to the type of the variable, which may be the
         *     input node itself
         */
        protected Node commonConvert(
                Node node, TypeMirror varType, boolean contextAllowsNarrowing) {
            // For assignment conversion, see JLS 5.2
            // For method invocation conversion, see JLS 5.3

            // Check for identical types or "identity conversion"
            TypeMirror nodeType = node.getType();
            boolean isSameType = types.isSameType(nodeType, varType);
            if (isSameType) {
                return node;
            }

            boolean isRightNumeric = TypesUtils.isNumeric(nodeType);
            boolean isRightPrimitive = TypesUtils.isPrimitive(nodeType);
            boolean isRightBoxed = TypesUtils.isBoxedPrimitive(nodeType);
            boolean isRightReference = nodeType instanceof ReferenceType;
            boolean isLeftNumeric = TypesUtils.isNumeric(varType);
            boolean isLeftPrimitive = TypesUtils.isPrimitive(varType);
            // boolean isLeftBoxed = TypesUtils.isBoxedPrimitive(varType);
            boolean isLeftReference = varType instanceof ReferenceType;
            boolean isSubtype = types.isSubtype(nodeType, varType);

            if (isRightNumeric && isLeftNumeric && isSubtype) {
                node = widen(node, varType);
                nodeType = node.getType();
            } else if (isRightReference && isLeftReference && isSubtype) {
                // widening reference conversion is a no-op, but if it
                // applies, then later conversions do not.
            } else if (isRightPrimitive && isLeftReference) {
                if (contextAllowsNarrowing && conversionRequiresNarrowing(varType, node)) {
                    node = narrowAndBox(node, varType);
                    nodeType = node.getType();
                } else {
                    node = box(node);
                    nodeType = node.getType();
                }
            } else if (isRightBoxed && isLeftPrimitive) {
                node = unbox(node);
                nodeType = node.getType();

                if (types.isSubtype(nodeType, varType) && !types.isSameType(nodeType, varType)) {
                    node = widen(node, varType);
                    nodeType = node.getType();
                }
            } else if (isRightPrimitive && isLeftPrimitive) {
                if (contextAllowsNarrowing && conversionRequiresNarrowing(varType, node)) {
                    node = narrow(node, varType);
                    nodeType = node.getType();
                }
            }

            // TODO: if checkers need to know about null references of
            // a particular type, add logic for them here.

            return node;
        }

        /**
         * Perform assignment conversion so that it can be assigned to a variable of the given type.
         *
         * @param node a Node producing a value
         * @param varType the type of a variable
         * @return a Node with the value converted to the type of the variable, which may be the
         *     input node itself
         */
        protected Node assignConvert(Node node, TypeMirror varType) {
            return commonConvert(node, varType, true);
        }

        /**
         * Perform method invocation conversion so that the node can be passed as a formal parameter
         * of the given type.
         *
         * @param node a Node producing a value
         * @param formalType the type of a formal parameter
         * @return a Node with the value converted to the type of the formal, which may be the input
         *     node itself
         */
        protected Node methodInvocationConvert(Node node, TypeMirror formalType) {
            return commonConvert(node, formalType, false);
        }

        /**
         * Given a method element and as list of argument expressions, return a list of {@link
         * Node}s representing the arguments converted for a call of the method. This method applies
         * to both method invocations and constructor calls.
         *
         * @param method an ExecutableElement representing a method to be called
         * @param actualExprs a List of argument expressions to a call
         * @return a List of {@link Node}s representing arguments after conversions required by a
         *     call to this method
         */
        protected List<Node> convertCallArguments(
                ExecutableElement method, List<? extends ExpressionTree> actualExprs) {
            // NOTE: It is important to convert one method argument before
            // generating CFG nodes for the next argument, since label binding
            // expects nodes to be generated in execution order.  Therefore,
            // this method first determines which conversions need to be applied
            // and then iterates over the actual arguments.
            List<? extends VariableElement> formals = method.getParameters();

            ArrayList<Node> convertedNodes = new ArrayList<Node>();

            int numFormals = formals.size();
            int numActuals = actualExprs.size();
            if (method.isVarArgs()) {
                // Create a new array argument if the actuals outnumber
                // the formals, or if the last actual is not assignable
                // to the last formal.
                int lastArgIndex = numFormals - 1;
                TypeMirror lastParamType = formals.get(lastArgIndex).asType();
                List<Node> dimensions = new ArrayList<>();
                List<Node> initializers = new ArrayList<>();

                if (numActuals == numFormals - 1) {
                    // Apply method invocation conversion to all actual
                    // arguments, then create and append an empty array
                    for (int i = 0; i < numActuals; i++) {
                        Node actualVal = scan(actualExprs.get(i), null);
                        convertedNodes.add(
                                methodInvocationConvert(actualVal, formals.get(i).asType()));
                    }

                    Node lastArgument =
                            new ArrayCreationNode(null, lastParamType, dimensions, initializers);
                    extendWithNode(lastArgument);

                    convertedNodes.add(lastArgument);
                } else {
                    TypeMirror actualType = InternalUtils.typeOf(actualExprs.get(lastArgIndex));
                    if (numActuals == numFormals && types.isAssignable(actualType, lastParamType)) {
                        // Normal call with no array creation, apply method
                        // invocation conversion to all arguments.
                        for (int i = 0; i < numActuals; i++) {
                            Node actualVal = scan(actualExprs.get(i), null);
                            convertedNodes.add(
                                    methodInvocationConvert(actualVal, formals.get(i).asType()));
                        }
                    } else {
                        assert lastParamType instanceof ArrayType
                                : "variable argument formal must be an array";
                        // Apply method invocation conversion to lastArgIndex
                        // arguments and use the remaining ones to initialize
                        // an array.
                        for (int i = 0; i < lastArgIndex; i++) {
                            Node actualVal = scan(actualExprs.get(i), null);
                            convertedNodes.add(
                                    methodInvocationConvert(actualVal, formals.get(i).asType()));
                        }

                        TypeMirror elemType = ((ArrayType) lastParamType).getComponentType();
                        for (int i = lastArgIndex; i < numActuals; i++) {
                            Node actualVal = scan(actualExprs.get(i), null);
                            initializers.add(assignConvert(actualVal, elemType));
                        }

                        Node lastArgument =
                                new ArrayCreationNode(
                                        null, lastParamType, dimensions, initializers);
                        extendWithNode(lastArgument);
                        convertedNodes.add(lastArgument);
                    }
                }
            } else {
                for (int i = 0; i < numActuals; i++) {
                    Node actualVal = scan(actualExprs.get(i), null);
                    convertedNodes.add(methodInvocationConvert(actualVal, formals.get(i).asType()));
                }
            }

            return convertedNodes;
        }

        /**
         * Convert an operand of a conditional expression to the type of the whole expression.
         *
         * @param node a node occurring as the second or third operand of a conditional expression
         * @param destType the type to promote the value to
         * @return a Node with the value promoted to the destType, which may be the input node
         */
        protected Node conditionalExprPromotion(Node node, TypeMirror destType) {
            // For rules on converting operands of conditional expressions,
            // JLS 15.25
            TypeMirror nodeType = node.getType();

            // If the operand is already the same type as the whole
            // expression, then do nothing.
            if (types.isSameType(nodeType, destType)) {
                return node;
            }

            // If the operand is a primitive and the whole expression is
            // boxed, then apply boxing.
            if (TypesUtils.isPrimitive(nodeType) && TypesUtils.isBoxedPrimitive(destType)) {
                return box(node);
            }

            // If the operand is byte or Byte and the whole expression is
            // short, then convert to short.
            boolean isBoxedPrimitive = TypesUtils.isBoxedPrimitive(nodeType);
            TypeMirror unboxedNodeType = isBoxedPrimitive ? types.unboxedType(nodeType) : nodeType;
            TypeMirror unboxedDestType =
                    TypesUtils.isBoxedPrimitive(destType) ? types.unboxedType(destType) : destType;
            if (TypesUtils.isNumeric(unboxedNodeType) && TypesUtils.isNumeric(unboxedDestType)) {
                if (unboxedNodeType.getKind() == TypeKind.BYTE
                        && destType.getKind() == TypeKind.SHORT) {
                    if (isBoxedPrimitive) {
                        node = unbox(node);
                    }
                    return widen(node, destType);
                }

                // If the operand is Byte, Short or Character and the whole expression
                // is the unboxed version of it, then apply unboxing.
                TypeKind destKind = destType.getKind();
                if (destKind == TypeKind.BYTE
                        || destKind == TypeKind.CHAR
                        || destKind == TypeKind.SHORT) {
                    if (isBoxedPrimitive) {
                        return unbox(node);
                    } else if (nodeType.getKind() == TypeKind.INT) {
                        return narrow(node, destType);
                    }
                }

                return binaryNumericPromotion(node, destType);
            }

            // For the final case in JLS 15.25, apply boxing but not lub.
            if (TypesUtils.isPrimitive(nodeType)
                    && (destType.getKind() == TypeKind.DECLARED
                            || destType.getKind() == TypeKind.UNION
                            || destType.getKind() == TypeKind.INTERSECTION)) {
                return box(node);
            }

            return node;
        }

        /**
         * Returns the label {@link Name} of the leaf in the argument path, or null if the leaf is
         * not a labeled statement.
         */
        protected /*@Nullable*/ Name getLabel(TreePath path) {
            if (path.getParentPath() != null) {
                Tree parent = path.getParentPath().getLeaf();
                if (parent.getKind() == Tree.Kind.LABELED_STATEMENT) {
                    return ((LabeledStatementTree) parent).getLabel();
                }
            }
            return null;
        }

        /* --------------------------------------------------------- */
        /* Visitor Methods */
        /* --------------------------------------------------------- */

        @Override
        public Node visitAnnotatedType(AnnotatedTypeTree tree, Void p) {
            return scan(tree.getUnderlyingType(), p);
        }

        @Override
        public Node visitAnnotation(AnnotationTree tree, Void p) {
            assert false : "AnnotationTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public MethodInvocationNode visitMethodInvocation(MethodInvocationTree tree, Void p) {

            // see JLS 15.12.4

            // First, compute the receiver, if any (15.12.4.1)
            // Second, evaluate the actual arguments, left to right and
            // possibly some arguments are stored into an array for variable
            // arguments calls (15.12.4.2)
            // Third, test the receiver, if any, for nullness (15.12.4.4)
            // Fourth, convert the arguments to the type of the formal
            // parameters (15.12.4.5)
            // Fifth, if the method is synchronized, lock the receiving
            // object or class (15.12.4.5)
            ExecutableElement method = TreeUtils.elementFromUse(tree);
            if (method == null) {
                // The method wasn't found, e.g. because of a compilation error.
                return null;
            }

            // TODO? Variable wasn't used.
            // boolean isBooleanMethod = TypesUtils.isBooleanType(method.getReturnType());

            ExpressionTree methodSelect = tree.getMethodSelect();
            assert TreeUtils.isMethodAccess(methodSelect)
                    : "Expected a method access, but got: " + methodSelect;

            List<? extends ExpressionTree> actualExprs = tree.getArguments();

            // Look up method to invoke and possibly throw NullPointerException
            Node receiver = getReceiver(methodSelect, TreeUtils.enclosingClass(getCurrentPath()));

            MethodAccessNode target = new MethodAccessNode(methodSelect, receiver);

            ExecutableElement element = TreeUtils.elementFromUse(tree);
            if (ElementUtils.isStatic(element) || receiver instanceof ThisLiteralNode) {
                // No NullPointerException can be thrown, use normal node
                extendWithNode(target);
            } else {
                TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException");
                extendWithNodeWithException(target, npeElement.asType());
            }

            List<Node> arguments = new ArrayList<>();

            // Don't convert arguments for enum super calls.  The AST contains
            // no actual arguments, while the method element expects two arguments,
            // leading to an exception in convertCallArguments.  Since no actual
            // arguments are present in the AST that is being checked, it shouldn't
            // cause any harm to omit the conversions.
            // See also BaseTypeVisitor.visitMethodInvocation and
            // QualifierPolymorphism.annotate
            if (!TreeUtils.isEnumSuper(tree)) {
                arguments = convertCallArguments(method, actualExprs);
            }

            // TODO: lock the receiver for synchronized methods

            MethodInvocationNode node =
                    new MethodInvocationNode(tree, target, arguments, getCurrentPath());

            Set<TypeMirror> thrownSet = new HashSet<>();
            // Add exceptions explicitly mentioned in the throws clause.
            List<? extends TypeMirror> thrownTypes = element.getThrownTypes();
            thrownSet.addAll(thrownTypes);
            // Add Throwable to account for unchecked exceptions
            TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable");
            thrownSet.add(throwableElement.asType());

            ExtendedNode extendedNode = extendWithNodeWithExceptions(node, thrownSet);

            /* Check for the TerminatesExecution annotation. */
            Element methodElement = InternalUtils.symbol(tree);
            boolean terminatesExecution =
                    annotationProvider.getDeclAnnotation(methodElement, TerminatesExecution.class)
                            != null;
            if (terminatesExecution) {
                extendedNode.setTerminatesExecution(true);
            }

            return node;
        }

        @Override
        public Node visitAssert(AssertTree tree, Void p) {

            // see JLS 14.10

            // If assertions are enabled, then we can just translate the
            // assertion.
            if (assumeAssertionsEnabled || assumeAssertionsEnabledFor(tree)) {
                translateAssertWithAssertionsEnabled(tree);
                return null;
            }

            // If assertions are disabled, then nothing is executed.
            if (assumeAssertionsDisabled) {
                return null;
            }

            // Otherwise, we don't know if assertions are enabled, so we use a
            // variable "ea" and case-split on it. One branch does execute the
            // assertion, while the other assumes assertions are disabled.
            VariableTree ea = getAssertionsEnabledVariable();

            // all necessary labels
            Label assertionEnabled = new Label();
            Label assertionDisabled = new Label();

            extendWithNode(new LocalVariableNode(ea));
            extendWithExtendedNode(new ConditionalJump(assertionEnabled, assertionDisabled));

            // 'then' branch (i.e. check the assertion)
            addLabelForNextNode(assertionEnabled);

            translateAssertWithAssertionsEnabled(tree);

            // 'else' branch
            addLabelForNextNode(assertionDisabled);

            return null;
        }

        /**
         * Should assertions be assumed to be executed for a given {@link AssertTree}? False by
         * default.
         */
        protected boolean assumeAssertionsEnabledFor(AssertTree tree) {
            return false;
        }

        /** The {@link VariableTree} that indicates whether assertions are enabled or not. */
        protected VariableTree ea = null;

        /**
         * Get a synthetic {@link VariableTree} that indicates whether assertions are enabled or
         * not.
         */
        protected VariableTree getAssertionsEnabledVariable() {
            if (ea == null) {
                String name = uniqueName("assertionsEnabled");
                MethodTree enclosingMethod = TreeUtils.enclosingMethod(getCurrentPath());
                Element owner;
                if (enclosingMethod != null) {
                    owner = TreeUtils.elementFromDeclaration(enclosingMethod);
                } else {
                    ClassTree enclosingClass = TreeUtils.enclosingClass(getCurrentPath());
                    owner = TreeUtils.elementFromDeclaration(enclosingClass);
                }
                ExpressionTree initializer = null;
                ea =
                        treeBuilder.buildVariableDecl(
                                types.getPrimitiveType(TypeKind.BOOLEAN), name, owner, initializer);
            }
            return ea;
        }

        /**
         * Translates an assertion statement to the correct CFG nodes. The translation assumes that
         * assertions are enabled.
         */
        protected void translateAssertWithAssertionsEnabled(AssertTree tree) {

            // all necessary labels
            Label assertEnd = new Label();
            Label elseEntry = new Label();

            // basic block for the condition
            Node condition = unbox(scan(tree.getCondition(), null));
            ConditionalJump cjump = new ConditionalJump(assertEnd, elseEntry);
            extendWithExtendedNode(cjump);

            // else branch
            Node detail = null;
            addLabelForNextNode(elseEntry);
            if (tree.getDetail() != null) {
                detail = scan(tree.getDetail(), null);
            }
            TypeElement assertException = elements.getTypeElement("java.lang.AssertionError");
            AssertionErrorNode assertNode =
                    new AssertionErrorNode(tree, condition, detail, assertException.asType());
            extendWithNode(assertNode);
            NodeWithExceptionsHolder exNode =
                    extendWithNodeWithException(
                            new ThrowNode(null, assertNode, env.getTypeUtils()),
                            assertException.asType());
            exNode.setTerminatesExecution(true);

            // then branch (nothing happens)
            addLabelForNextNode(assertEnd);
        }

        @Override
        public Node visitAssignment(AssignmentTree tree, Void p) {

            // see JLS 15.26.1

            AssignmentNode assignmentNode;
            ExpressionTree variable = tree.getVariable();
            TypeMirror varType = InternalUtils.typeOf(variable);

            // case 1: field access
            if (TreeUtils.isFieldAccess(variable)) {
                // visit receiver
                Node receiver = getReceiver(variable, TreeUtils.enclosingClass(getCurrentPath()));

                // visit expression
                Node expression = scan(tree.getExpression(), p);
                expression = assignConvert(expression, varType);

                // visit field access (throws null-pointer exception)
                FieldAccessNode target = new FieldAccessNode(variable, receiver);
                target.setLValue();

                Element element = TreeUtils.elementFromUse(variable);
                if (ElementUtils.isStatic(element) || receiver instanceof ThisLiteralNode) {
                    // No NullPointerException can be thrown, use normal node
                    extendWithNode(target);
                } else {
                    TypeElement npeElement =
                            elements.getTypeElement("java.lang.NullPointerException");
                    extendWithNodeWithException(target, npeElement.asType());
                }

                // add assignment node
                assignmentNode = new AssignmentNode(tree, target, expression);
                extendWithNode(assignmentNode);
            }

            // case 2: other cases
            else {
                Node target = scan(variable, p);
                target.setLValue();

                assignmentNode = translateAssignment(tree, target, tree.getExpression());
            }

            return assignmentNode;
        }

        /** Translate an assignment. */
        protected AssignmentNode translateAssignment(Tree tree, Node target, ExpressionTree rhs) {
            Node expression = scan(rhs, null);
            return translateAssignment(tree, target, expression);
        }

        /** Translate an assignment where the RHS has already been scanned. */
        protected AssignmentNode translateAssignment(Tree tree, Node target, Node expression) {
            assert tree instanceof AssignmentTree || tree instanceof VariableTree;
            target.setLValue();
            expression = assignConvert(expression, target.getType());
            AssignmentNode assignmentNode = new AssignmentNode(tree, target, expression);
            extendWithNode(assignmentNode);
            return assignmentNode;
        }

        /**
         * Note 1: Requires {@code tree} to be a field or method access tree.
         *
         * <p>Note 2: Visits the receiver and adds all necessary blocks to the CFG.
         *
         * @param tree the field access tree containing the receiver
         * @param classTree the ClassTree enclosing the field access
         * @return the receiver of the field access
         */
        private Node getReceiver(ExpressionTree tree, ClassTree classTree) {
            assert TreeUtils.isFieldAccess(tree) || TreeUtils.isMethodAccess(tree);
            if (tree.getKind().equals(Tree.Kind.MEMBER_SELECT)) {
                MemberSelectTree mtree = (MemberSelectTree) tree;
                return scan(mtree.getExpression(), null);
            } else {
                Element ele = TreeUtils.elementFromUse(tree);
                TypeElement declaringClass = ElementUtils.enclosingClass(ele);
                TypeMirror type = ElementUtils.getType(declaringClass);
                if (ElementUtils.isStatic(ele)) {
                    Node node = new ClassNameNode(type, declaringClass);
                    extendWithNode(node);
                    return node;
                } else {
                    Node node = new ImplicitThisLiteralNode(type);
                    extendWithNode(node);
                    return node;
                }
            }
        }

        /**
         * Map an operation with assignment to the corresponding operation without assignment.
         *
         * @param kind a Tree.Kind representing an operation with assignment
         * @return the Tree.Kind for the same operation without assignment
         */
        protected Tree.Kind withoutAssignment(Tree.Kind kind) {
            switch (kind) {
                case DIVIDE_ASSIGNMENT:
                    return Tree.Kind.DIVIDE;
                case MULTIPLY_ASSIGNMENT:
                    return Tree.Kind.MULTIPLY;
                case REMAINDER_ASSIGNMENT:
                    return Tree.Kind.REMAINDER;
                case MINUS_ASSIGNMENT:
                    return Tree.Kind.MINUS;
                case PLUS_ASSIGNMENT:
                    return Tree.Kind.PLUS;
                case LEFT_SHIFT_ASSIGNMENT:
                    return Tree.Kind.LEFT_SHIFT;
                case RIGHT_SHIFT_ASSIGNMENT:
                    return Tree.Kind.RIGHT_SHIFT;
                case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
                    return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
                case AND_ASSIGNMENT:
                    return Tree.Kind.AND;
                case OR_ASSIGNMENT:
                    return Tree.Kind.OR;
                case XOR_ASSIGNMENT:
                    return Tree.Kind.XOR;
                default:
                    return Tree.Kind.ERRONEOUS;
            }
        }

        @Override
        public Node visitCompoundAssignment(CompoundAssignmentTree tree, Void p) {
            // According the JLS 15.26.2, E1 op= E2 is equivalent to
            // E1 = (T) ((E1) op (E2)), where T is the type of E1,
            // except that E1 is evaluated only once.
            //

            Tree.Kind kind = tree.getKind();
            switch (kind) {
                case DIVIDE_ASSIGNMENT:
                case MULTIPLY_ASSIGNMENT:
                case REMAINDER_ASSIGNMENT:
                    {
                        // see JLS 15.17 and 15.26.2
                        Node targetLHS = scan(tree.getVariable(), p);
                        Node value = scan(tree.getExpression(), p);

                        TypeMirror exprType = InternalUtils.typeOf(tree);
                        TypeMirror leftType = InternalUtils.typeOf(tree.getVariable());
                        TypeMirror rightType = InternalUtils.typeOf(tree.getExpression());
                        TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                        Node targetRHS = binaryNumericPromotion(targetLHS, promotedType);
                        value = binaryNumericPromotion(value, promotedType);

                        BinaryTree operTree =
                                treeBuilder.buildBinary(
                                        promotedType,
                                        withoutAssignment(kind),
                                        tree.getVariable(),
                                        tree.getExpression());
                        handleArtificialTree(operTree);
                        Node operNode;
                        if (kind == Tree.Kind.MULTIPLY_ASSIGNMENT) {
                            operNode = new NumericalMultiplicationNode(operTree, targetRHS, value);
                        } else if (kind == Tree.Kind.DIVIDE_ASSIGNMENT) {
                            if (TypesUtils.isIntegral(exprType)) {
                                operNode = new IntegerDivisionNode(operTree, targetRHS, value);
                            } else {
                                operNode = new FloatingDivisionNode(operTree, targetRHS, value);
                            }
                        } else {
                            assert kind == Kind.REMAINDER_ASSIGNMENT;
                            if (TypesUtils.isIntegral(exprType)) {
                                operNode = new IntegerRemainderNode(operTree, targetRHS, value);
                            } else {
                                operNode = new FloatingRemainderNode(operTree, targetRHS, value);
                            }
                        }
                        extendWithNode(operNode);

                        TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
                        handleArtificialTree(castTree);
                        TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType);
                        castNode.setInSource(false);
                        extendWithNode(castNode);

                        AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
                        extendWithNode(assignNode);
                        return assignNode;
                    }

                case MINUS_ASSIGNMENT:
                case PLUS_ASSIGNMENT:
                    {
                        // see JLS 15.18 and 15.26.2

                        Node targetLHS = scan(tree.getVariable(), p);
                        Node value = scan(tree.getExpression(), p);

                        TypeMirror leftType = InternalUtils.typeOf(tree.getVariable());
                        TypeMirror rightType = InternalUtils.typeOf(tree.getExpression());

                        if (TypesUtils.isString(leftType) || TypesUtils.isString(rightType)) {
                            assert (kind == Tree.Kind.PLUS_ASSIGNMENT);
                            Node targetRHS = stringConversion(targetLHS);
                            value = stringConversion(value);
                            Node r = new StringConcatenateAssignmentNode(tree, targetRHS, value);
                            extendWithNode(r);
                            return r;
                        } else {
                            TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                            Node targetRHS = binaryNumericPromotion(targetLHS, promotedType);
                            value = binaryNumericPromotion(value, promotedType);

                            BinaryTree operTree =
                                    treeBuilder.buildBinary(
                                            promotedType,
                                            withoutAssignment(kind),
                                            tree.getVariable(),
                                            tree.getExpression());
                            handleArtificialTree(operTree);
                            Node operNode;
                            if (kind == Tree.Kind.PLUS_ASSIGNMENT) {
                                operNode = new NumericalAdditionNode(operTree, targetRHS, value);
                            } else {
                                assert kind == Kind.MINUS_ASSIGNMENT;
                                operNode = new NumericalSubtractionNode(operTree, targetRHS, value);
                            }
                            extendWithNode(operNode);

                            TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
                            handleArtificialTree(castTree);
                            TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType);
                            castNode.setInSource(false);
                            extendWithNode(castNode);

                            // Map the compound assignment tree to an assignment node, which
                            // will have the correct type.
                            AssignmentNode assignNode =
                                    new AssignmentNode(tree, targetLHS, castNode);
                            extendWithNode(assignNode);
                            return assignNode;
                        }
                    }

                case LEFT_SHIFT_ASSIGNMENT:
                case RIGHT_SHIFT_ASSIGNMENT:
                case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
                    {
                        // see JLS 15.19 and 15.26.2
                        Node targetLHS = scan(tree.getVariable(), p);
                        Node value = scan(tree.getExpression(), p);

                        TypeMirror leftType = InternalUtils.typeOf(tree.getVariable());

                        Node targetRHS = unaryNumericPromotion(targetLHS);
                        value = unaryNumericPromotion(value);

                        BinaryTree operTree =
                                treeBuilder.buildBinary(
                                        leftType,
                                        withoutAssignment(kind),
                                        tree.getVariable(),
                                        tree.getExpression());
                        handleArtificialTree(operTree);
                        Node operNode;
                        if (kind == Tree.Kind.LEFT_SHIFT_ASSIGNMENT) {
                            operNode = new LeftShiftNode(operTree, targetRHS, value);
                        } else if (kind == Tree.Kind.RIGHT_SHIFT_ASSIGNMENT) {
                            operNode = new SignedRightShiftNode(operTree, targetRHS, value);
                        } else {
                            assert kind == Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
                            operNode = new UnsignedRightShiftNode(operTree, targetRHS, value);
                        }
                        extendWithNode(operNode);

                        TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
                        handleArtificialTree(castTree);
                        TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType);
                        castNode.setInSource(false);
                        extendWithNode(castNode);

                        AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
                        extendWithNode(assignNode);
                        return assignNode;
                    }

                case AND_ASSIGNMENT:
                case OR_ASSIGNMENT:
                case XOR_ASSIGNMENT:
                    // see JLS 15.22
                    Node targetLHS = scan(tree.getVariable(), p);
                    Node value = scan(tree.getExpression(), p);

                    TypeMirror leftType = InternalUtils.typeOf(tree.getVariable());
                    TypeMirror rightType = InternalUtils.typeOf(tree.getExpression());

                    Node targetRHS = null;
                    if (isNumericOrBoxed(leftType) && isNumericOrBoxed(rightType)) {
                        TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                        targetRHS = binaryNumericPromotion(targetLHS, promotedType);
                        value = binaryNumericPromotion(value, promotedType);
                    } else if (TypesUtils.isBooleanType(leftType)
                            && TypesUtils.isBooleanType(rightType)) {
                        targetRHS = unbox(targetLHS);
                        value = unbox(value);
                    } else {
                        assert false
                                : "Both argument to logical operation must be numeric or boolean";
                    }

                    BinaryTree operTree =
                            treeBuilder.buildBinary(
                                    leftType,
                                    withoutAssignment(kind),
                                    tree.getVariable(),
                                    tree.getExpression());
                    handleArtificialTree(operTree);
                    Node operNode;
                    if (kind == Tree.Kind.AND_ASSIGNMENT) {
                        operNode = new BitwiseAndNode(operTree, targetRHS, value);
                    } else if (kind == Tree.Kind.OR_ASSIGNMENT) {
                        operNode = new BitwiseOrNode(operTree, targetRHS, value);
                    } else {
                        assert kind == Kind.XOR_ASSIGNMENT;
                        operNode = new BitwiseXorNode(operTree, targetRHS, value);
                    }
                    extendWithNode(operNode);

                    TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
                    handleArtificialTree(castTree);
                    TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType);
                    castNode.setInSource(false);
                    extendWithNode(castNode);

                    AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
                    extendWithNode(assignNode);
                    return assignNode;
                default:
                    assert false : "unexpected compound assignment type";
                    break;
            }
            assert false : "unexpected compound assignment type";
            return null;
        }

        @Override
        public Node visitBinary(BinaryTree tree, Void p) {
            // Note that for binary operations it is important to perform any required
            // promotion on the left operand before generating any Nodes for the right
            // operand, because labels must be inserted AFTER ALL preceding Nodes and
            // BEFORE ALL following Nodes.
            Node r = null;
            Tree leftTree = tree.getLeftOperand();
            Tree rightTree = tree.getRightOperand();

            Tree.Kind kind = tree.getKind();
            switch (kind) {
                case DIVIDE:
                case MULTIPLY:
                case REMAINDER:
                    {
                        // see JLS 15.17

                        TypeMirror exprType = InternalUtils.typeOf(tree);
                        TypeMirror leftType = InternalUtils.typeOf(leftTree);
                        TypeMirror rightType = InternalUtils.typeOf(rightTree);
                        TypeMirror promotedType = binaryPromotedType(leftType, rightType);

                        Node left = binaryNumericPromotion(scan(leftTree, p), promotedType);
                        Node right = binaryNumericPromotion(scan(rightTree, p), promotedType);

                        if (kind == Tree.Kind.MULTIPLY) {
                            r = new NumericalMultiplicationNode(tree, left, right);
                        } else if (kind == Tree.Kind.DIVIDE) {
                            if (TypesUtils.isIntegral(exprType)) {
                                r = new IntegerDivisionNode(tree, left, right);
                            } else {
                                r = new FloatingDivisionNode(tree, left, right);
                            }
                        } else {
                            assert kind == Kind.REMAINDER;
                            if (TypesUtils.isIntegral(exprType)) {
                                r = new IntegerRemainderNode(tree, left, right);
                            } else {
                                r = new FloatingRemainderNode(tree, left, right);
                            }
                        }
                        break;
                    }

                case MINUS:
                case PLUS:
                    {
                        // see JLS 15.18

                        // TypeMirror exprType = InternalUtils.typeOf(tree);
                        TypeMirror leftType = InternalUtils.typeOf(leftTree);
                        TypeMirror rightType = InternalUtils.typeOf(rightTree);

                        if (TypesUtils.isString(leftType) || TypesUtils.isString(rightType)) {
                            assert (kind == Tree.Kind.PLUS);
                            Node left = stringConversion(scan(leftTree, p));
                            Node right = stringConversion(scan(rightTree, p));
                            r = new StringConcatenateNode(tree, left, right);
                        } else {
                            TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                            Node left = binaryNumericPromotion(scan(leftTree, p), promotedType);
                            Node right = binaryNumericPromotion(scan(rightTree, p), promotedType);

                            // TODO: Decide whether to deal with floating-point value
                            // set conversion.
                            if (kind == Tree.Kind.PLUS) {
                                r = new NumericalAdditionNode(tree, left, right);
                            } else {
                                assert kind == Kind.MINUS;
                                r = new NumericalSubtractionNode(tree, left, right);
                            }
                        }
                        break;
                    }

                case LEFT_SHIFT:
                case RIGHT_SHIFT:
                case UNSIGNED_RIGHT_SHIFT:
                    {
                        // see JLS 15.19

                        Node left = unaryNumericPromotion(scan(leftTree, p));
                        Node right = unaryNumericPromotion(scan(rightTree, p));

                        if (kind == Tree.Kind.LEFT_SHIFT) {
                            r = new LeftShiftNode(tree, left, right);
                        } else if (kind == Tree.Kind.RIGHT_SHIFT) {
                            r = new SignedRightShiftNode(tree, left, right);
                        } else {
                            assert kind == Kind.UNSIGNED_RIGHT_SHIFT;
                            r = new UnsignedRightShiftNode(tree, left, right);
                        }
                        break;
                    }

                case GREATER_THAN:
                case GREATER_THAN_EQUAL:
                case LESS_THAN:
                case LESS_THAN_EQUAL:
                    {
                        // see JLS 15.20.1
                        TypeMirror leftType = InternalUtils.typeOf(leftTree);
                        if (TypesUtils.isBoxedPrimitive(leftType)) {
                            leftType = types.unboxedType(leftType);
                        }

                        TypeMirror rightType = InternalUtils.typeOf(rightTree);
                        if (TypesUtils.isBoxedPrimitive(rightType)) {
                            rightType = types.unboxedType(rightType);
                        }

                        TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                        Node left = binaryNumericPromotion(scan(leftTree, p), promotedType);
                        Node right = binaryNumericPromotion(scan(rightTree, p), promotedType);

                        Node node;
                        if (kind == Tree.Kind.GREATER_THAN) {
                            node = new GreaterThanNode(tree, left, right);
                        } else if (kind == Tree.Kind.GREATER_THAN_EQUAL) {
                            node = new GreaterThanOrEqualNode(tree, left, right);
                        } else if (kind == Tree.Kind.LESS_THAN) {
                            node = new LessThanNode(tree, left, right);
                        } else {
                            assert kind == Tree.Kind.LESS_THAN_EQUAL;
                            node = new LessThanOrEqualNode(tree, left, right);
                        }

                        extendWithNode(node);

                        return node;
                    }

                case EQUAL_TO:
                case NOT_EQUAL_TO:
                    {
                        // see JLS 15.21
                        TreeInfo leftInfo = getTreeInfo(leftTree);
                        TreeInfo rightInfo = getTreeInfo(rightTree);
                        Node left = scan(leftTree, p);
                        Node right = scan(rightTree, p);

                        if (leftInfo.isNumeric()
                                && rightInfo.isNumeric()
                                && !(leftInfo.isBoxed() && rightInfo.isBoxed())) {
                            // JLS 15.21.1 numerical equality
                            TypeMirror promotedType =
                                    binaryPromotedType(
                                            leftInfo.unboxedType(), rightInfo.unboxedType());
                            left = binaryNumericPromotion(left, promotedType);
                            right = binaryNumericPromotion(right, promotedType);
                        } else if (leftInfo.isBoolean()
                                && rightInfo.isBoolean()
                                && !(leftInfo.isBoxed() && rightInfo.isBoxed())) {
                            // JSL 15.21.2 boolean equality
                            left = unboxAsNeeded(left, leftInfo.isBoxed());
                            right = unboxAsNeeded(right, rightInfo.isBoxed());
                        }

                        Node node;
                        if (kind == Tree.Kind.EQUAL_TO) {
                            node = new EqualToNode(tree, left, right);
                        } else {
                            assert kind == Kind.NOT_EQUAL_TO;
                            node = new NotEqualNode(tree, left, right);
                        }
                        extendWithNode(node);

                        return node;
                    }

                case AND:
                case OR:
                case XOR:
                    {
                        // see JLS 15.22
                        TypeMirror leftType = InternalUtils.typeOf(leftTree);
                        TypeMirror rightType = InternalUtils.typeOf(rightTree);
                        boolean isBooleanOp =
                                TypesUtils.isBooleanType(leftType)
                                        && TypesUtils.isBooleanType(rightType);

                        Node left;
                        Node right;

                        if (isBooleanOp) {
                            left = unbox(scan(leftTree, p));
                            right = unbox(scan(rightTree, p));
                        } else if (isNumericOrBoxed(leftType) && isNumericOrBoxed(rightType)) {
                            TypeMirror promotedType = binaryPromotedType(leftType, rightType);
                            left = binaryNumericPromotion(scan(leftTree, p), promotedType);
                            right = binaryNumericPromotion(scan(rightTree, p), promotedType);
                        } else {
                            left = unbox(scan(leftTree, p));
                            right = unbox(scan(rightTree, p));
                        }

                        Node node;
                        if (kind == Tree.Kind.AND) {
                            node = new BitwiseAndNode(tree, left, right);
                        } else if (kind == Tree.Kind.OR) {
                            node = new BitwiseOrNode(tree, left, right);
                        } else {
                            assert kind == Kind.XOR;
                            node = new BitwiseXorNode(tree, left, right);
                        }

                        extendWithNode(node);

                        return node;
                    }

                case CONDITIONAL_AND:
                case CONDITIONAL_OR:
                    {
                        // see JLS 15.23 and 15.24

                        // all necessary labels
                        Label rightStartL = new Label();
                        Label shortCircuitL = new Label();

                        // left-hand side
                        Node left = scan(leftTree, p);

                        ConditionalJump cjump;
                        if (kind == Tree.Kind.CONDITIONAL_AND) {
                            cjump = new ConditionalJump(rightStartL, shortCircuitL);
                            cjump.setFalseFlowRule(Store.FlowRule.ELSE_TO_ELSE);
                        } else {
                            cjump = new ConditionalJump(shortCircuitL, rightStartL);
                            cjump.setTrueFlowRule(Store.FlowRule.THEN_TO_THEN);
                        }
                        extendWithExtendedNode(cjump);

                        // right-hand side
                        addLabelForNextNode(rightStartL);
                        Node right = scan(rightTree, p);

                        // conditional expression itself
                        addLabelForNextNode(shortCircuitL);
                        Node node;
                        if (kind == Tree.Kind.CONDITIONAL_AND) {
                            node = new ConditionalAndNode(tree, left, right);
                        } else {
                            node = new ConditionalOrNode(tree, left, right);
                        }
                        extendWithNode(node);
                        return node;
                    }
                default:
                    assert false : "unexpected binary tree: " + kind;
                    break;
            }
            assert r != null : "unexpected binary tree";
            return extendWithNode(r);
        }

        @Override
        public Node visitBlock(BlockTree tree, Void p) {
            for (StatementTree n : tree.getStatements()) {
                scan(n, null);
            }
            return null;
        }

        @Override
        public Node visitBreak(BreakTree tree, Void p) {
            Name label = tree.getLabel();
            if (label == null) {
                assert breakTargetL != null : "no target for break statement";

                extendWithExtendedNode(new UnconditionalJump(breakTargetL));
            } else {
                assert breakLabels.containsKey(label);

                extendWithExtendedNode(new UnconditionalJump(breakLabels.get(label)));
            }

            return null;
        }

        @Override
        public Node visitSwitch(SwitchTree tree, Void p) {
            SwitchBuilder builder = new SwitchBuilder(tree, p);
            builder.build();
            return null;
        }

        private class SwitchBuilder {
            private final SwitchTree switchTree;
            private final Label[] caseBodyLabels;
            private final Void p;
            private Node switchExpr;

            private SwitchBuilder(SwitchTree tree, Void p) {
                this.switchTree = tree;
                this.caseBodyLabels = new Label[switchTree.getCases().size() + 1];
                this.p = p;
            }

            public void build() {
                Label oldBreakTargetL = breakTargetL;
                breakTargetL = new Label();
                int cases = caseBodyLabels.length - 1;
                for (int i = 0; i < cases; ++i) {
                    caseBodyLabels[i] = new Label();
                }
                caseBodyLabels[cases] = breakTargetL;

                switchExpr = unbox(scan(switchTree.getExpression(), p));
                extendWithNode(
                        new MarkerNode(
                                switchTree, "start of switch statement", env.getTypeUtils()));

                Integer defaultIndex = null;
                for (int i = 0; i < cases; ++i) {
                    CaseTree caseTree = switchTree.getCases().get(i);
                    if (caseTree.getExpression() == null) {
                        defaultIndex = i;
                    } else {
                        buildCase(caseTree, i);
                    }
                }
                if (defaultIndex != null) {
                    // the checks of all cases must happen before the default case,
                    // therefore we build the default case last.
                    // fallthrough is still handled correctly with the caseBodyLabels.
                    buildCase(switchTree.getCases().get(defaultIndex), defaultIndex);
                }

                addLabelForNextNode(breakTargetL);
                breakTargetL = oldBreakTargetL;
            }

            private void buildCase(CaseTree tree, int index) {
                final Label thisBodyL = caseBodyLabels[index];
                final Label nextBodyL = caseBodyLabels[index + 1];
                final Label nextCaseL = new Label();

                ExpressionTree exprTree = tree.getExpression();
                if (exprTree != null) {
                    Node expr = scan(exprTree, p);
                    CaseNode test = new CaseNode(tree, switchExpr, expr, env.getTypeUtils());
                    extendWithNode(test);
                    extendWithExtendedNode(new ConditionalJump(thisBodyL, nextCaseL));
                }
                addLabelForNextNode(thisBodyL);
                for (StatementTree stmt : tree.getStatements()) {
                    scan(stmt, p);
                }
                extendWithExtendedNode(new UnconditionalJump(nextBodyL));
                addLabelForNextNode(nextCaseL);
            }
        }

        @Override
        public Node visitCase(CaseTree tree, Void p) {
            throw new AssertionError("case visitor is implemented in SwitchBuilder");
        }

        @Override
        public Node visitCatch(CatchTree tree, Void p) {
            scan(tree.getParameter(), p);
            scan(tree.getBlock(), p);
            return null;
        }

        @Override
        public Node visitClass(ClassTree tree, Void p) {
            declaredClasses.add(tree);
            return null;
        }

        @Override
        public Node visitConditionalExpression(ConditionalExpressionTree tree, Void p) {
            // see JLS 15.25
            TypeMirror exprType = InternalUtils.typeOf(tree);

            Label trueStart = new Label();
            Label falseStart = new Label();
            Label merge = new Label();

            Node condition = unbox(scan(tree.getCondition(), p));
            ConditionalJump cjump = new ConditionalJump(trueStart, falseStart);
            extendWithExtendedNode(cjump);

            addLabelForNextNode(trueStart);
            Node trueExpr = scan(tree.getTrueExpression(), p);
            trueExpr = conditionalExprPromotion(trueExpr, exprType);
            extendWithExtendedNode(new UnconditionalJump(merge));

            addLabelForNextNode(falseStart);
            Node falseExpr = scan(tree.getFalseExpression(), p);
            falseExpr = conditionalExprPromotion(falseExpr, exprType);

            addLabelForNextNode(merge);
            Node node = new TernaryExpressionNode(tree, condition, trueExpr, falseExpr);
            extendWithNode(node);

            return node;
        }

        @Override
        public Node visitContinue(ContinueTree tree, Void p) {
            Name label = tree.getLabel();
            if (label == null) {
                assert continueTargetL != null : "no target for continue statement";

                extendWithExtendedNode(new UnconditionalJump(continueTargetL));
            } else {
                assert continueLabels.containsKey(label);

                extendWithExtendedNode(new UnconditionalJump(continueLabels.get(label)));
            }

            return null;
        }

        @Override
        public Node visitDoWhileLoop(DoWhileLoopTree tree, Void p) {
            Name parentLabel = getLabel(getCurrentPath());

            Label loopEntry = new Label();
            Label loopExit = new Label();

            // If the loop is a labeled statement, then its continue
            // target is identical for continues with no label and
            // continues with the loop's label.
            Label conditionStart;
            if (parentLabel != null) {
                conditionStart = continueLabels.get(parentLabel);
            } else {
                conditionStart = new Label();
            }

            Label oldBreakTargetL = breakTargetL;
            breakTargetL = loopExit;

            Label oldContinueTargetL = continueTargetL;
            continueTargetL = conditionStart;

            // Loop body
            addLabelForNextNode(loopEntry);
            if (tree.getStatement() != null) {
                scan(tree.getStatement(), p);
            }

            // Condition
            addLabelForNextNode(conditionStart);
            if (tree.getCondition() != null) {
                unbox(scan(tree.getCondition(), p));
                ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit);
                extendWithExtendedNode(cjump);
            }

            // Loop exit
            addLabelForNextNode(loopExit);

            breakTargetL = oldBreakTargetL;
            continueTargetL = oldContinueTargetL;

            return null;
        }

        @Override
        public Node visitErroneous(ErroneousTree tree, Void p) {
            assert false : "ErroneousTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitExpressionStatement(ExpressionStatementTree tree, Void p) {
            return scan(tree.getExpression(), p);
        }

        @Override
        public Node visitEnhancedForLoop(EnhancedForLoopTree tree, Void p) {
            // see JLS 14.14.2
            Name parentLabel = getLabel(getCurrentPath());

            Label conditionStart = new Label();
            Label loopEntry = new Label();
            Label loopExit = new Label();

            // If the loop is a labeled statement, then its continue
            // target is identical for continues with no label and
            // continues with the loop's label.
            Label updateStart;
            if (parentLabel != null) {
                updateStart = continueLabels.get(parentLabel);
            } else {
                updateStart = new Label();
            }

            Label oldBreakTargetL = breakTargetL;
            breakTargetL = loopExit;

            Label oldContinueTargetL = continueTargetL;
            continueTargetL = updateStart;

            // Distinguish loops over Iterables from loops over arrays.

            TypeElement iterableElement = elements.getTypeElement("java.lang.Iterable");
            TypeMirror iterableType = types.erasure(iterableElement.asType());

            VariableTree variable = tree.getVariable();
            VariableElement variableElement = TreeUtils.elementFromDeclaration(variable);
            ExpressionTree expression = tree.getExpression();
            StatementTree statement = tree.getStatement();

            TypeMirror exprType = InternalUtils.typeOf(expression);

            if (types.isSubtype(exprType, iterableType)) {
                // Take the upper bound of a type variable or wildcard
                exprType = TypesUtils.upperBound(exprType);

                assert (exprType instanceof DeclaredType) : "an Iterable must be a DeclaredType";
                DeclaredType declaredExprType = (DeclaredType) exprType;
                declaredExprType.getTypeArguments();

                MemberSelectTree iteratorSelect = treeBuilder.buildIteratorMethodAccess(expression);
                handleArtificialTree(iteratorSelect);

                MethodInvocationTree iteratorCall =
                        treeBuilder.buildMethodInvocation(iteratorSelect);
                handleArtificialTree(iteratorCall);

                VariableTree iteratorVariable =
                        createEnhancedForLoopIteratorVariable(iteratorCall, variableElement);
                handleArtificialTree(iteratorVariable);

                VariableDeclarationNode iteratorVariableDecl =
                        new VariableDeclarationNode(iteratorVariable);
                iteratorVariableDecl.setInSource(false);

                extendWithNode(iteratorVariableDecl);

                Node expressionNode = scan(expression, p);

                MethodAccessNode iteratorAccessNode =
                        new MethodAccessNode(iteratorSelect, expressionNode);
                iteratorAccessNode.setInSource(false);
                extendWithNode(iteratorAccessNode);
                MethodInvocationNode iteratorCallNode =
                        new MethodInvocationNode(
                                iteratorCall,
                                iteratorAccessNode,
                                Collections.<Node>emptyList(),
                                getCurrentPath());
                iteratorCallNode.setInSource(false);
                extendWithNode(iteratorCallNode);

                translateAssignment(
                        iteratorVariable,
                        new LocalVariableNode(iteratorVariable),
                        iteratorCallNode);

                // Test the loop ending condition
                addLabelForNextNode(conditionStart);
                IdentifierTree iteratorUse1 = treeBuilder.buildVariableUse(iteratorVariable);
                handleArtificialTree(iteratorUse1);

                LocalVariableNode iteratorReceiverNode = new LocalVariableNode(iteratorUse1);
                iteratorReceiverNode.setInSource(false);
                extendWithNode(iteratorReceiverNode);

                MemberSelectTree hasNextSelect = treeBuilder.buildHasNextMethodAccess(iteratorUse1);
                handleArtificialTree(hasNextSelect);

                MethodAccessNode hasNextAccessNode =
                        new MethodAccessNode(hasNextSelect, iteratorReceiverNode);
                hasNextAccessNode.setInSource(false);
                extendWithNode(hasNextAccessNode);

                MethodInvocationTree hasNextCall = treeBuilder.buildMethodInvocation(hasNextSelect);
                handleArtificialTree(hasNextCall);

                MethodInvocationNode hasNextCallNode =
                        new MethodInvocationNode(
                                hasNextCall,
                                hasNextAccessNode,
                                Collections.<Node>emptyList(),
                                getCurrentPath());
                hasNextCallNode.setInSource(false);
                extendWithNode(hasNextCallNode);
                extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit));

                // Loop body, starting with declaration of the loop iteration variable
                addLabelForNextNode(loopEntry);
                extendWithNode(new VariableDeclarationNode(variable));

                IdentifierTree iteratorUse2 = treeBuilder.buildVariableUse(iteratorVariable);
                handleArtificialTree(iteratorUse2);

                LocalVariableNode iteratorReceiverNode2 = new LocalVariableNode(iteratorUse2);
                iteratorReceiverNode2.setInSource(false);
                extendWithNode(iteratorReceiverNode2);

                MemberSelectTree nextSelect = treeBuilder.buildNextMethodAccess(iteratorUse2);
                handleArtificialTree(nextSelect);

                MethodAccessNode nextAccessNode =
                        new MethodAccessNode(nextSelect, iteratorReceiverNode2);
                nextAccessNode.setInSource(false);
                extendWithNode(nextAccessNode);

                MethodInvocationTree nextCall = treeBuilder.buildMethodInvocation(nextSelect);
                handleArtificialTree(nextCall);

                MethodInvocationNode nextCallNode =
                        new MethodInvocationNode(
                                nextCall,
                                nextAccessNode,
                                Collections.<Node>emptyList(),
                                getCurrentPath());
                nextCallNode.setInSource(false);
                extendWithNode(nextCallNode);

                translateAssignment(variable, new LocalVariableNode(variable), nextCall);

                if (statement != null) {
                    scan(statement, p);
                }

                // Loop back edge
                addLabelForNextNode(updateStart);
                extendWithExtendedNode(new UnconditionalJump(conditionStart));

            } else {
                // TODO: Shift any labels after the initialization of the
                // temporary array variable.

                VariableTree arrayVariable =
                        createEnhancedForLoopArrayVariable(expression, variableElement);
                handleArtificialTree(arrayVariable);

                VariableDeclarationNode arrayVariableNode =
                        new VariableDeclarationNode(arrayVariable);
                arrayVariableNode.setInSource(false);
                extendWithNode(arrayVariableNode);
                Node expressionNode = scan(expression, p);

                translateAssignment(
                        arrayVariable, new LocalVariableNode(arrayVariable), expressionNode);

                // Declare and initialize the loop index variable
                TypeMirror intType = types.getPrimitiveType(TypeKind.INT);

                LiteralTree zero = treeBuilder.buildLiteral(Integer.valueOf(0));
                handleArtificialTree(zero);

                VariableTree indexVariable =
                        treeBuilder.buildVariableDecl(
                                intType,
                                uniqueName("index"),
                                variableElement.getEnclosingElement(),
                                zero);
                handleArtificialTree(indexVariable);
                VariableDeclarationNode indexVariableNode =
                        new VariableDeclarationNode(indexVariable);
                indexVariableNode.setInSource(false);
                extendWithNode(indexVariableNode);
                IntegerLiteralNode zeroNode = extendWithNode(new IntegerLiteralNode(zero));

                translateAssignment(indexVariable, new LocalVariableNode(indexVariable), zeroNode);

                // Compare index to array length
                addLabelForNextNode(conditionStart);
                IdentifierTree indexUse1 = treeBuilder.buildVariableUse(indexVariable);
                handleArtificialTree(indexUse1);
                LocalVariableNode indexNode1 = new LocalVariableNode(indexUse1);
                indexNode1.setInSource(false);
                extendWithNode(indexNode1);

                IdentifierTree arrayUse1 = treeBuilder.buildVariableUse(arrayVariable);
                handleArtificialTree(arrayUse1);
                LocalVariableNode arrayNode1 = extendWithNode(new LocalVariableNode(arrayUse1));

                MemberSelectTree lengthSelect = treeBuilder.buildArrayLengthAccess(arrayUse1);
                handleArtificialTree(lengthSelect);
                FieldAccessNode lengthAccessNode = new FieldAccessNode(lengthSelect, arrayNode1);
                lengthAccessNode.setInSource(false);
                extendWithNode(lengthAccessNode);

                BinaryTree lessThan = treeBuilder.buildLessThan(indexUse1, lengthSelect);
                handleArtificialTree(lessThan);

                LessThanNode lessThanNode =
                        new LessThanNode(lessThan, indexNode1, lengthAccessNode);
                lessThanNode.setInSource(false);
                extendWithNode(lessThanNode);
                extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit));

                // Loop body, starting with declaration of the loop iteration variable
                addLabelForNextNode(loopEntry);
                extendWithNode(new VariableDeclarationNode(variable));

                IdentifierTree arrayUse2 = treeBuilder.buildVariableUse(arrayVariable);
                handleArtificialTree(arrayUse2);
                LocalVariableNode arrayNode2 = new LocalVariableNode(arrayUse2);
                arrayNode2.setInSource(false);
                extendWithNode(arrayNode2);

                IdentifierTree indexUse2 = treeBuilder.buildVariableUse(indexVariable);
                handleArtificialTree(indexUse2);
                LocalVariableNode indexNode2 = new LocalVariableNode(indexUse2);
                indexNode2.setInSource(false);
                extendWithNode(indexNode2);

                ArrayAccessTree arrayAccess = treeBuilder.buildArrayAccess(arrayUse2, indexUse2);
                handleArtificialTree(arrayAccess);
                ArrayAccessNode arrayAccessNode =
                        new ArrayAccessNode(arrayAccess, arrayNode2, indexNode2);
                arrayAccessNode.setInSource(false);
                extendWithNode(arrayAccessNode);
                translateAssignment(variable, new LocalVariableNode(variable), arrayAccessNode);

                if (statement != null) {
                    scan(statement, p);
                }

                // Loop back edge
                addLabelForNextNode(updateStart);

                IdentifierTree indexUse3 = treeBuilder.buildVariableUse(indexVariable);
                handleArtificialTree(indexUse3);
                LocalVariableNode indexNode3 = new LocalVariableNode(indexUse3);
                indexNode3.setInSource(false);
                extendWithNode(indexNode3);

                LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1));
                handleArtificialTree(oneTree);
                Node one = new IntegerLiteralNode(oneTree);
                one.setInSource(false);
                extendWithNode(one);

                BinaryTree addOneTree =
                        treeBuilder.buildBinary(intType, Tree.Kind.PLUS, indexUse3, oneTree);
                handleArtificialTree(addOneTree);
                Node addOneNode = new NumericalAdditionNode(addOneTree, indexNode3, one);
                addOneNode.setInSource(false);
                extendWithNode(addOneNode);

                AssignmentTree assignTree = treeBuilder.buildAssignment(indexUse3, addOneTree);
                handleArtificialTree(assignTree);
                Node assignNode = new AssignmentNode(assignTree, indexNode3, addOneNode);
                assignNode.setInSource(false);
                extendWithNode(assignNode);

                extendWithExtendedNode(new UnconditionalJump(conditionStart));
            }

            // Loop exit
            addLabelForNextNode(loopExit);

            breakTargetL = oldBreakTargetL;
            continueTargetL = oldContinueTargetL;

            return null;
        }

        protected VariableTree createEnhancedForLoopIteratorVariable(
                MethodInvocationTree iteratorCall, VariableElement variableElement) {
            TypeMirror iteratorType = InternalUtils.typeOf(iteratorCall);

            // Declare and initialize a new, unique iterator variable
            VariableTree iteratorVariable =
                    treeBuilder.buildVariableDecl(
                            iteratorType, // annotatedIteratorTypeTree,
                            uniqueName("iter"),
                            variableElement.getEnclosingElement(),
                            iteratorCall);
            return iteratorVariable;
        }

        protected VariableTree createEnhancedForLoopArrayVariable(
                ExpressionTree expression, VariableElement variableElement) {
            TypeMirror arrayType = InternalUtils.typeOf(expression);

            // Declare and initialize a temporary array variable
            VariableTree arrayVariable =
                    treeBuilder.buildVariableDecl(
                            arrayType,
                            uniqueName("array"),
                            variableElement.getEnclosingElement(),
                            expression);
            return arrayVariable;
        }

        @Override
        public Node visitForLoop(ForLoopTree tree, Void p) {
            Name parentLabel = getLabel(getCurrentPath());

            Label conditionStart = new Label();
            Label loopEntry = new Label();
            Label loopExit = new Label();

            // If the loop is a labeled statement, then its continue
            // target is identical for continues with no label and
            // continues with the loop's label.
            Label updateStart;
            if (parentLabel != null) {
                updateStart = continueLabels.get(parentLabel);
            } else {
                updateStart = new Label();
            }

            Label oldBreakTargetL = breakTargetL;
            breakTargetL = loopExit;

            Label oldContinueTargetL = continueTargetL;
            continueTargetL = updateStart;

            // Initializer
            for (StatementTree init : tree.getInitializer()) {
                scan(init, p);
            }

            // Condition
            addLabelForNextNode(conditionStart);
            if (tree.getCondition() != null) {
                unbox(scan(tree.getCondition(), p));
                ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit);
                extendWithExtendedNode(cjump);
            }

            // Loop body
            addLabelForNextNode(loopEntry);
            if (tree.getStatement() != null) {
                scan(tree.getStatement(), p);
            }

            // Update
            addLabelForNextNode(updateStart);
            for (ExpressionStatementTree update : tree.getUpdate()) {
                scan(update, p);
            }

            extendWithExtendedNode(new UnconditionalJump(conditionStart));

            // Loop exit
            addLabelForNextNode(loopExit);

            breakTargetL = oldBreakTargetL;
            continueTargetL = oldContinueTargetL;

            return null;
        }

        @Override
        public Node visitIdentifier(IdentifierTree tree, Void p) {
            Node node;
            if (TreeUtils.isFieldAccess(tree)) {
                Node receiver = getReceiver(tree, TreeUtils.enclosingClass(getCurrentPath()));
                node = new FieldAccessNode(tree, receiver);
            } else {
                Element element = TreeUtils.elementFromUse(tree);
                switch (element.getKind()) {
                    case ANNOTATION_TYPE:
                    case CLASS:
                    case ENUM:
                    case INTERFACE:
                    case TYPE_PARAMETER:
                        node = new ClassNameNode(tree);
                        break;
                    case FIELD:
                        // Note that "this"/"super" is a field, but not a field access.
                        if (element.getSimpleName().contentEquals("this")) {
                            node = new ExplicitThisLiteralNode(tree);
                        } else {
                            node = new SuperNode(tree);
                        }
                        break;
                    case EXCEPTION_PARAMETER:
                    case LOCAL_VARIABLE:
                    case RESOURCE_VARIABLE:
                    case PARAMETER:
                        node = new LocalVariableNode(tree);
                        break;
                    case PACKAGE:
                        node = new PackageNameNode(tree);
                        break;
                    default:
                        throw new IllegalArgumentException(
                                "unexpected element kind : " + element.getKind());
                }
            }
            extendWithNode(node);
            return node;
        }

        @Override
        public Node visitIf(IfTree tree, Void p) {
            // all necessary labels
            Label thenEntry = new Label();
            Label elseEntry = new Label();
            Label endIf = new Label();

            // basic block for the condition
            unbox(scan(tree.getCondition(), p));

            ConditionalJump cjump = new ConditionalJump(thenEntry, elseEntry);
            extendWithExtendedNode(cjump);

            // then branch
            addLabelForNextNode(thenEntry);
            StatementTree thenStatement = tree.getThenStatement();
            scan(thenStatement, p);
            extendWithExtendedNode(new UnconditionalJump(endIf));

            // else branch
            addLabelForNextNode(elseEntry);
            StatementTree elseStatement = tree.getElseStatement();
            if (elseStatement != null) {
                scan(elseStatement, p);
            }

            // label the end of the if statement
            addLabelForNextNode(endIf);

            return null;
        }

        @Override
        public Node visitImport(ImportTree tree, Void p) {
            assert false : "ImportTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitArrayAccess(ArrayAccessTree tree, Void p) {
            Node array = scan(tree.getExpression(), p);
            Node index = unaryNumericPromotion(scan(tree.getIndex(), p));
            return extendWithNode(new ArrayAccessNode(tree, array, index));
        }

        @Override
        public Node visitLabeledStatement(LabeledStatementTree tree, Void p) {
            // This method can set the break target after generating all Nodes
            // in the contained statement, but it can't set the continue target,
            // which may be in the middle of a sequence of nodes. Labeled loops
            // must look up and use the continue Labels.
            Name labelName = tree.getLabel();

            Label breakL = new Label(labelName + "_break");
            Label continueL = new Label(labelName + "_continue");

            breakLabels.put(labelName, breakL);
            continueLabels.put(labelName, continueL);

            scan(tree.getStatement(), p);

            addLabelForNextNode(breakL);

            breakLabels.remove(labelName);
            continueLabels.remove(labelName);

            return null;
        }

        @Override
        public Node visitLiteral(LiteralTree tree, Void p) {
            Node r = null;
            switch (tree.getKind()) {
                case BOOLEAN_LITERAL:
                    r = new BooleanLiteralNode(tree);
                    break;
                case CHAR_LITERAL:
                    r = new CharacterLiteralNode(tree);
                    break;
                case DOUBLE_LITERAL:
                    r = new DoubleLiteralNode(tree);
                    break;
                case FLOAT_LITERAL:
                    r = new FloatLiteralNode(tree);
                    break;
                case INT_LITERAL:
                    r = new IntegerLiteralNode(tree);
                    break;
                case LONG_LITERAL:
                    r = new LongLiteralNode(tree);
                    break;
                case NULL_LITERAL:
                    r = new NullLiteralNode(tree);
                    break;
                case STRING_LITERAL:
                    r = new StringLiteralNode(tree);
                    break;
                default:
                    assert false : "unexpected literal tree";
                    break;
            }
            assert r != null : "unexpected literal tree";
            Node result = extendWithNode(r);
            return result;
        }

        @Override
        public Node visitMethod(MethodTree tree, Void p) {
            assert false : "MethodTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitModifiers(ModifiersTree tree, Void p) {
            assert false : "ModifiersTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitNewArray(NewArrayTree tree, Void p) {
            // see JLS 15.10

            ArrayType type = (ArrayType) InternalUtils.typeOf(tree);
            TypeMirror elemType = type.getComponentType();

            List<? extends ExpressionTree> dimensions = tree.getDimensions();
            List<? extends ExpressionTree> initializers = tree.getInitializers();

            List<Node> dimensionNodes = new ArrayList<Node>();
            if (dimensions != null) {
                for (ExpressionTree dim : dimensions) {
                    dimensionNodes.add(unaryNumericPromotion(scan(dim, p)));
                }
            }

            List<Node> initializerNodes = new ArrayList<Node>();
            if (initializers != null) {
                for (ExpressionTree init : initializers) {
                    initializerNodes.add(assignConvert(scan(init, p), elemType));
                }
            }

            Node node = new ArrayCreationNode(tree, type, dimensionNodes, initializerNodes);
            return extendWithNode(node);
        }

        @Override
        public Node visitNewClass(NewClassTree tree, Void p) {
            // see JLS 15.9

            Tree enclosingExpr = tree.getEnclosingExpression();
            if (enclosingExpr != null) {
                scan(enclosingExpr, p);
            }

            // We ignore any class body because its methods should
            // be visited separately.
            // TODO: For anonymous classes we want to propagate the current store
            // to the anonymous class.
            // See Issues 266, 811.

            // Convert constructor arguments
            ExecutableElement constructor = TreeUtils.elementFromUse(tree);

            List<? extends ExpressionTree> actualExprs = tree.getArguments();

            List<Node> arguments = convertCallArguments(constructor, actualExprs);

            // TODO: for anonymous classes, don't use the identifier alone.
            // See Issue 890.
            Node constructorNode = scan(tree.getIdentifier(), p);

            Node node = new ObjectCreationNode(tree, constructorNode, arguments);

            Set<TypeMirror> thrownSet = new HashSet<>();
            // Add exceptions explicitly mentioned in the throws clause.
            List<? extends TypeMirror> thrownTypes = constructor.getThrownTypes();
            thrownSet.addAll(thrownTypes);
            // Add Throwable to account for unchecked exceptions
            TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable");
            thrownSet.add(throwableElement.asType());

            extendWithNodeWithExceptions(node, thrownSet);

            return node;
        }

        /**
         * Maps a {@code Tree} its directly enclosing {@code ParenthesizedTree} if one exists.
         *
         * <p>This map is used by {@link CFGTranslationPhaseOne#addToLookupMap(Node)} to associate a
         * {@code ParenthesizedTree} with the dataflow {@code Node} that was used during inference.
         * This map is necessary because dataflow does not create a {@code Node} for a {@code
         * ParenthesizedTree.}
         */
        private final Map<Tree, ParenthesizedTree> parenMapping = new HashMap<>();

        @Override
        public Node visitParenthesized(ParenthesizedTree tree, Void p) {
            parenMapping.put(tree.getExpression(), tree);
            return scan(tree.getExpression(), p);
        }

        @Override
        public Node visitReturn(ReturnTree tree, Void p) {
            ExpressionTree ret = tree.getExpression();
            // TODO: also have a return-node if nothing is returned
            ReturnNode result = null;
            if (ret != null) {
                Node node = scan(ret, p);
                Tree enclosing =
                        TreeUtils.enclosingOfKind(
                                getCurrentPath(),
                                new HashSet<Kind>(
                                        Arrays.asList(Kind.METHOD, Kind.LAMBDA_EXPRESSION)));
                if (enclosing.getKind() == Kind.LAMBDA_EXPRESSION) {
                    LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclosing;
                    TreePath lambdaTreePath =
                            TreePath.getPath(getCurrentPath().getCompilationUnit(), lambdaTree);
                    Context ctx = ((JavacProcessingEnvironment) env).getContext();
                    Element overriddenElement =
                            com.sun.tools.javac.code.Types.instance(ctx)
                                    .findDescriptorSymbol(
                                            ((Type) trees.getTypeMirror(lambdaTreePath)).tsym);

                    result =
                            new ReturnNode(
                                    tree,
                                    node,
                                    env.getTypeUtils(),
                                    lambdaTree,
                                    (MethodSymbol) overriddenElement);
                } else {
                    result = new ReturnNode(tree, node, env.getTypeUtils(), (MethodTree) enclosing);
                }
                returnNodes.add(result);
                extendWithNode(result);
            }
            extendWithExtendedNode(new UnconditionalJump(regularExitLabel));
            // TODO: return statements should also flow to an enclosing finally block
            return result;
        }

        @Override
        public Node visitMemberSelect(MemberSelectTree tree, Void p) {
            Node expr = scan(tree.getExpression(), p);
            if (!TreeUtils.isFieldAccess(tree)) {
                // Could be a selector of a class or package
                Node result = null;
                Element element = TreeUtils.elementFromUse(tree);
                switch (element.getKind()) {
                    case ANNOTATION_TYPE:
                    case CLASS:
                    case ENUM:
                    case INTERFACE:
                        result = extendWithNode(new ClassNameNode(tree, expr));
                        break;
                    case PACKAGE:
                        result = extendWithNode(new PackageNameNode(tree, (PackageNameNode) expr));
                        break;
                    default:
                        assert false : "Unexpected element kind: " + element.getKind();
                        return null;
                }
                return result;
            }

            Node node = new FieldAccessNode(tree, expr);

            Element element = TreeUtils.elementFromUse(tree);
            if (ElementUtils.isStatic(element)
                    || expr instanceof ImplicitThisLiteralNode
                    || expr instanceof ExplicitThisLiteralNode) {
                // No NullPointerException can be thrown, use normal node
                extendWithNode(node);
            } else {
                TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException");
                extendWithNodeWithException(node, npeElement.asType());
            }

            return node;
        }

        @Override
        public Node visitEmptyStatement(EmptyStatementTree tree, Void p) {
            return null;
        }

        @Override
        public Node visitSynchronized(SynchronizedTree tree, Void p) {
            // see JLS 14.19

            Node synchronizedExpr = scan(tree.getExpression(), p);
            SynchronizedNode synchronizedStartNode =
                    new SynchronizedNode(tree, synchronizedExpr, true, env.getTypeUtils());
            extendWithNode(synchronizedStartNode);
            scan(tree.getBlock(), p);
            SynchronizedNode synchronizedEndNode =
                    new SynchronizedNode(tree, synchronizedExpr, false, env.getTypeUtils());
            extendWithNode(synchronizedEndNode);

            return null;
        }

        @Override
        public Node visitThrow(ThrowTree tree, Void p) {
            Node expression = scan(tree.getExpression(), p);
            TypeMirror exception = expression.getType();
            ThrowNode throwsNode = new ThrowNode(tree, expression, env.getTypeUtils());
            NodeWithExceptionsHolder exNode = extendWithNodeWithException(throwsNode, exception);
            exNode.setTerminatesExecution(true);
            return throwsNode;
        }

        @Override
        public Node visitCompilationUnit(CompilationUnitTree tree, Void p) {
            assert false : "CompilationUnitTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitTry(TryTree tree, Void p) {
            List<? extends CatchTree> catches = tree.getCatches();
            BlockTree finallyBlock = tree.getFinallyBlock();

            extendWithNode(new MarkerNode(tree, "start of try statement", env.getTypeUtils()));

            // TODO: Should we handle try-with-resources blocks by also generating code
            // for automatically closing the resources?
            List<? extends Tree> resources = tree.getResources();
            for (Tree resource : resources) {
                scan(resource, p);
            }

            List<Pair<TypeMirror, Label>> catchLabels = new ArrayList<>();
            for (CatchTree c : catches) {
                TypeMirror type = InternalUtils.typeOf(c.getParameter().getType());
                assert type != null : "exception parameters must have a type";
                catchLabels.add(Pair.of(type, new Label()));
            }

            Label finallyLabel = null;
            if (finallyBlock != null) {
                finallyLabel = new Label();
                tryStack.pushFrame(new TryFinallyFrame(finallyLabel));
            }

            Label doneLabel = new Label();

            tryStack.pushFrame(new TryCatchFrame(types, catchLabels));

            scan(tree.getBlock(), p);
            extendWithExtendedNode(new UnconditionalJump(firstNonNull(finallyLabel, doneLabel)));

            tryStack.popFrame();

            int catchIndex = 0;
            for (CatchTree c : catches) {
                addLabelForNextNode(catchLabels.get(catchIndex).second);
                scan(c, p);
                catchIndex++;
                extendWithExtendedNode(
                        new UnconditionalJump(firstNonNull(finallyLabel, doneLabel)));
            }

            if (finallyLabel != null) {
                tryStack.popFrame();
                addLabelForNextNode(finallyLabel);
                scan(finallyBlock, p);

                TypeMirror throwableType = elements.getTypeElement("java.lang.Throwable").asType();
                extendWithNodeWithException(
                        new MarkerNode(tree, "end of finally block", env.getTypeUtils()),
                        throwableType);
            }

            addLabelForNextNode(doneLabel);

            return null;
        }

        @Override
        public Node visitParameterizedType(ParameterizedTypeTree tree, Void p) {
            return extendWithNode(new ParameterizedTypeNode(tree));
        }

        @Override
        public Node visitUnionType(UnionTypeTree tree, Void p) {
            assert false : "UnionTypeTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitArrayType(ArrayTypeTree tree, Void p) {
            return extendWithNode(new ArrayTypeNode(tree));
        }

        @Override
        public Node visitTypeCast(TypeCastTree tree, Void p) {
            final Node operand = scan(tree.getExpression(), p);
            final TypeMirror type = InternalUtils.typeOf(tree.getType());
            final Node node = new TypeCastNode(tree, operand, type);
            final TypeElement cceElement = elements.getTypeElement("java.lang.ClassCastException");

            extendWithNodeWithException(node, cceElement.asType());
            return node;
        }

        @Override
        public Node visitPrimitiveType(PrimitiveTypeTree tree, Void p) {
            return extendWithNode(new PrimitiveTypeNode(tree));
        }

        @Override
        public Node visitTypeParameter(TypeParameterTree tree, Void p) {
            assert false : "TypeParameterTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitInstanceOf(InstanceOfTree tree, Void p) {
            Node operand = scan(tree.getExpression(), p);
            TypeMirror refType = InternalUtils.typeOf(tree.getType());
            InstanceOfNode node = new InstanceOfNode(tree, operand, refType, types);
            extendWithNode(node);
            return node;
        }

        @Override
        public Node visitUnary(UnaryTree tree, Void p) {
            Node result = null;
            Tree.Kind kind = tree.getKind();
            switch (kind) {
                case BITWISE_COMPLEMENT:
                case UNARY_MINUS:
                case UNARY_PLUS:
                    {
                        // see JLS 15.14 and 15.15
                        Node expr = scan(tree.getExpression(), p);
                        expr = unaryNumericPromotion(expr);

                        // TypeMirror exprType = InternalUtils.typeOf(tree);

                        switch (kind) {
                            case BITWISE_COMPLEMENT:
                                result = extendWithNode(new BitwiseComplementNode(tree, expr));
                                break;
                            case UNARY_MINUS:
                                result = extendWithNode(new NumericalMinusNode(tree, expr));
                                break;
                            case UNARY_PLUS:
                                result = extendWithNode(new NumericalPlusNode(tree, expr));
                                break;
                            default:
                                assert false;
                                break;
                        }
                        break;
                    }

                case LOGICAL_COMPLEMENT:
                    {
                        // see JLS 15.15.6
                        Node expr = scan(tree.getExpression(), p);
                        result = extendWithNode(new ConditionalNotNode(tree, unbox(expr)));
                        break;
                    }

                case POSTFIX_DECREMENT:
                case POSTFIX_INCREMENT:
                    {
                        ExpressionTree exprTree = tree.getExpression();
                        TypeMirror exprType = InternalUtils.typeOf(exprTree);
                        TypeMirror oneType = types.getPrimitiveType(TypeKind.INT);
                        Node expr = scan(exprTree, p);

                        TypeMirror promotedType = binaryPromotedType(exprType, oneType);

                        LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1));
                        handleArtificialTree(oneTree);

                        Node exprRHS = binaryNumericPromotion(expr, promotedType);
                        Node one = new IntegerLiteralNode(oneTree);
                        one.setInSource(false);
                        extendWithNode(one);
                        one = binaryNumericPromotion(one, promotedType);

                        BinaryTree operTree =
                                treeBuilder.buildBinary(
                                        promotedType,
                                        (kind == Tree.Kind.POSTFIX_INCREMENT
                                                ? Tree.Kind.PLUS
                                                : Tree.Kind.MINUS),
                                        exprTree,
                                        oneTree);
                        handleArtificialTree(operTree);
                        Node operNode;
                        if (kind == Tree.Kind.POSTFIX_INCREMENT) {
                            operNode = new NumericalAdditionNode(operTree, exprRHS, one);
                        } else {
                            assert kind == Tree.Kind.POSTFIX_DECREMENT;
                            operNode = new NumericalSubtractionNode(operTree, exprRHS, one);
                        }
                        extendWithNode(operNode);

                        Node narrowed = narrowAndBox(operNode, exprType);
                        // TODO: By using the assignment as the result of the expression, we
                        // act like a pre-increment/decrement.  Fix this by saving the initial
                        // value of the expression in a temporary.
                        AssignmentNode assignNode = new AssignmentNode(tree, expr, narrowed);
                        extendWithNode(assignNode);
                        result = assignNode;
                        break;
                    }
                case PREFIX_DECREMENT:
                case PREFIX_INCREMENT:
                    {
                        ExpressionTree exprTree = tree.getExpression();
                        TypeMirror exprType = InternalUtils.typeOf(exprTree);
                        TypeMirror oneType = types.getPrimitiveType(TypeKind.INT);
                        Node expr = scan(exprTree, p);

                        TypeMirror promotedType = binaryPromotedType(exprType, oneType);

                        LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1));
                        handleArtificialTree(oneTree);

                        Node exprRHS = binaryNumericPromotion(expr, promotedType);
                        Node one = new IntegerLiteralNode(oneTree);
                        one.setInSource(false);
                        extendWithNode(one);
                        one = binaryNumericPromotion(one, promotedType);

                        BinaryTree operTree =
                                treeBuilder.buildBinary(
                                        promotedType,
                                        (kind == Tree.Kind.PREFIX_INCREMENT
                                                ? Tree.Kind.PLUS
                                                : Tree.Kind.MINUS),
                                        exprTree,
                                        oneTree);
                        handleArtificialTree(operTree);
                        Node operNode;
                        if (kind == Tree.Kind.PREFIX_INCREMENT) {
                            operNode = new NumericalAdditionNode(operTree, exprRHS, one);
                        } else {
                            assert kind == Tree.Kind.PREFIX_DECREMENT;
                            operNode = new NumericalSubtractionNode(operTree, exprRHS, one);
                        }
                        extendWithNode(operNode);

                        Node narrowed = narrowAndBox(operNode, exprType);
                        AssignmentNode assignNode = new AssignmentNode(tree, expr, narrowed);
                        extendWithNode(assignNode);
                        result = assignNode;
                        break;
                    }

                case OTHER:
                default:
                    // special node NLLCHK
                    if (tree.toString().startsWith("<*nullchk*>")) {
                        Node expr = scan(tree.getExpression(), p);
                        result = extendWithNode(new NullChkNode(tree, expr));
                        break;
                    }

                    assert false : "Unknown kind (" + kind + ") of unary expression: " + tree;
            }

            return result;
        }

        @Override
        public Node visitVariable(VariableTree tree, Void p) {

            // see JLS 14.4

            boolean isField =
                    getCurrentPath().getParentPath() != null
                            && getCurrentPath().getParentPath().getLeaf().getKind() == Kind.CLASS;
            Node node = null;

            ClassTree enclosingClass = TreeUtils.enclosingClass(getCurrentPath());
            TypeElement classElem = TreeUtils.elementFromDeclaration(enclosingClass);
            Node receiver = new ImplicitThisLiteralNode(classElem.asType());

            if (isField) {
                ExpressionTree initializer = tree.getInitializer();
                assert initializer != null;
                node =
                        translateAssignment(
                                tree,
                                new FieldAccessNode(
                                        tree, TreeUtils.elementFromDeclaration(tree), receiver),
                                initializer);
            } else {
                // local variable definition
                VariableDeclarationNode decl = new VariableDeclarationNode(tree);
                extendWithNode(decl);

                // initializer

                ExpressionTree initializer = tree.getInitializer();
                if (initializer != null) {
                    node =
                            translateAssignment(
                                    tree, new LocalVariableNode(tree, receiver), initializer);
                }
            }

            return node;
        }

        @Override
        public Node visitWhileLoop(WhileLoopTree tree, Void p) {
            Name parentLabel = getLabel(getCurrentPath());

            Label loopEntry = new Label();
            Label loopExit = new Label();

            // If the loop is a labeled statement, then its continue
            // target is identical for continues with no label and
            // continues with the loop's label.
            Label conditionStart;
            if (parentLabel != null) {
                conditionStart = continueLabels.get(parentLabel);
            } else {
                conditionStart = new Label();
            }

            Label oldBreakTargetL = breakTargetL;
            breakTargetL = loopExit;

            Label oldContinueTargetL = continueTargetL;
            continueTargetL = conditionStart;

            // Condition
            addLabelForNextNode(conditionStart);
            if (tree.getCondition() != null) {
                unbox(scan(tree.getCondition(), p));
                ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit);
                extendWithExtendedNode(cjump);
            }

            // Loop body
            addLabelForNextNode(loopEntry);
            if (tree.getStatement() != null) {
                scan(tree.getStatement(), p);
            }
            extendWithExtendedNode(new UnconditionalJump(conditionStart));

            // Loop exit
            addLabelForNextNode(loopExit);

            breakTargetL = oldBreakTargetL;
            continueTargetL = oldContinueTargetL;

            return null;
        }

        @Override
        public Node visitLambdaExpression(LambdaExpressionTree tree, Void p) {
            declaredLambdas.add(tree);
            Node node = new FunctionalInterfaceNode(tree);
            extendWithNode(node);
            return node;
        }

        @Override
        public Node visitMemberReference(MemberReferenceTree tree, Void p) {
            Tree enclosingExpr = tree.getQualifierExpression();
            if (enclosingExpr != null) {
                scan(enclosingExpr, p);
            }

            Node node = new FunctionalInterfaceNode(tree);
            extendWithNode(node);

            return node;
        }

        @Override
        public Node visitWildcard(WildcardTree tree, Void p) {
            assert false : "WildcardTree is unexpected in AST to CFG translation";
            return null;
        }

        @Override
        public Node visitOther(Tree tree, Void p) {
            assert false : "Unknown AST element encountered in AST to CFG translation.";
            return null;
        }
    }

    /** A tuple with 4 named elements. */
    private interface TreeInfo {
        boolean isBoxed();

        boolean isNumeric();

        boolean isBoolean();

        TypeMirror unboxedType();
    }

    private static <A> A firstNonNull(A first, A second) {
        if (first != null) {
            return first;
        } else if (second != null) {
            return second;
        } else {
            throw new NullPointerException();
        }
    }

    /* --------------------------------------------------------- */
    /* Utility routines for debugging CFG building */
    /* --------------------------------------------------------- */

    /**
     * Print a set of {@link Block}s and the edges between them. This is useful for examining the
     * results of phase two.
     */
    protected static void printBlocks(Set<Block> blocks) {
        for (Block b : blocks) {
            System.out.print(b.hashCode() + ": " + b);
            switch (b.getType()) {
                case REGULAR_BLOCK:
                case SPECIAL_BLOCK:
                    {
                        Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor();
                        System.out.println(" -> " + (succ != null ? succ.hashCode() : "||"));
                        break;
                    }
                case EXCEPTION_BLOCK:
                    {
                        Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor();
                        System.out.print(" -> " + (succ != null ? succ.hashCode() : "||") + " {");
                        for (Map.Entry<TypeMirror, Set<Block>> entry :
                                ((ExceptionBlockImpl) b).getExceptionalSuccessors().entrySet()) {
                            System.out.print(entry.getKey() + " : " + entry.getValue() + ", ");
                        }
                        System.out.println("}");
                        break;
                    }
                case CONDITIONAL_BLOCK:
                    {
                        Block tSucc = ((ConditionalBlockImpl) b).getThenSuccessor();
                        Block eSucc = ((ConditionalBlockImpl) b).getElseSuccessor();
                        System.out.println(
                                " -> T "
                                        + (tSucc != null ? tSucc.hashCode() : "||")
                                        + " F "
                                        + (eSucc != null ? eSucc.hashCode() : "||"));
                        break;
                    }
            }
        }
    }
}
