Search in sources :

Example 1 with MarkerNode

use of org.checkerframework.dataflow.cfg.node.MarkerNode in project checker-framework by typetools.

the class CFGTranslationPhaseOne method visitTry.

@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 #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    List<Pair<TypeMirror, Label>> catchLabels = CollectionsPlume.mapList((CatchTree c) -> {
        return Pair.of(TreeUtils.typeOf(c.getParameter().getType()), new Label());
    }, catches);
    // Store return/break/continue labels, just in case we need them for a finally block.
    TryFinallyScopeCell oldReturnTargetL = returnTargetL;
    TryFinallyScopeCell oldBreakTargetL = breakTargetL;
    Map<Name, Label> oldBreakLabels = breakLabels;
    TryFinallyScopeCell oldContinueTargetL = continueTargetL;
    Map<Name, Label> oldContinueLabels = continueLabels;
    Label finallyLabel = null;
    Label exceptionalFinallyLabel = null;
    if (finallyBlock != null) {
        finallyLabel = new Label();
        exceptionalFinallyLabel = new Label();
        tryStack.pushFrame(new TryFinallyFrame(exceptionalFinallyLabel));
        returnTargetL = new TryFinallyScopeCell();
        breakTargetL = new TryFinallyScopeCell();
        breakLabels = new TryFinallyScopeMap();
        continueTargetL = new TryFinallyScopeCell();
        continueLabels = new TryFinallyScopeMap();
    }
    Label doneLabel = new Label();
    tryStack.pushFrame(new TryCatchFrame(types, catchLabels));
    // Must scan the resources *after* we push frame to tryStack. Otherwise we can lose catch
    // blocks.
    // 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);
    }
    extendWithNode(new MarkerNode(tree, "start of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    scan(tree.getBlock(), p);
    extendWithNode(new MarkerNode(tree, "end of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
    tryStack.popFrame();
    int catchIndex = 0;
    for (CatchTree c : catches) {
        addLabelForNextNode(catchLabels.get(catchIndex).second);
        extendWithNode(new MarkerNode(tree, "start of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
        scan(c, p);
        extendWithNode(new MarkerNode(tree, "end of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
        catchIndex++;
        extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
    }
    if (finallyLabel != null) {
        // Reset values before analyzing the finally block!
        tryStack.popFrame();
        {
            // Scan 'finallyBlock' for only 'finallyLabel' (a successful path)
            addLabelForNextNode(finallyLabel);
            extendWithNode(new MarkerNode(tree, "start of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(doneLabel));
        }
        if (hasExceptionalPath(exceptionalFinallyLabel)) {
            // If an exceptional path exists, scan 'finallyBlock' for 'exceptionalFinallyLabel', and
            // scan copied 'finallyBlock' for 'finallyLabel' (a successful path). If there is no
            // successful path, it will be removed in later phase.
            // TODO: Don't we need a separate finally block for each kind of exception?
            addLabelForNextNode(exceptionalFinallyLabel);
            extendWithNode(new MarkerNode(tree, "start of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            NodeWithExceptionsHolder throwing = extendWithNodeWithException(new MarkerNode(tree, "end of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()), throwableType);
            throwing.setTerminatesExecution(true);
        }
        if (returnTargetL.wasAccessed()) {
            addLabelForNextNode(returnTargetL.peekLabel());
            returnTargetL = oldReturnTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(returnTargetL.accessLabel()));
        } else {
            returnTargetL = oldReturnTargetL;
        }
        if (breakTargetL.wasAccessed()) {
            addLabelForNextNode(breakTargetL.peekLabel());
            breakTargetL = oldBreakTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(breakTargetL.accessLabel()));
        } else {
            breakTargetL = oldBreakTargetL;
        }
        Map<Name, Label> accessedBreakLabels = ((TryFinallyScopeMap) breakLabels).getAccessedNames();
        if (!accessedBreakLabels.isEmpty()) {
            breakLabels = oldBreakLabels;
            for (Map.Entry<Name, Label> access : accessedBreakLabels.entrySet()) {
                addLabelForNextNode(access.getValue());
                extendWithNode(new MarkerNode(tree, "start of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                scan(finallyBlock, p);
                extendWithNode(new MarkerNode(tree, "end of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                extendWithExtendedNode(new UnconditionalJump(breakLabels.get(access.getKey())));
            }
        } else {
            breakLabels = oldBreakLabels;
        }
        if (continueTargetL.wasAccessed()) {
            addLabelForNextNode(continueTargetL.peekLabel());
            continueTargetL = oldContinueTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(continueTargetL.accessLabel()));
        } else {
            continueTargetL = oldContinueTargetL;
        }
        Map<Name, Label> accessedContinueLabels = ((TryFinallyScopeMap) continueLabels).getAccessedNames();
        if (!accessedContinueLabels.isEmpty()) {
            continueLabels = oldContinueLabels;
            for (Map.Entry<Name, Label> access : accessedContinueLabels.entrySet()) {
                addLabelForNextNode(access.getValue());
                extendWithNode(new MarkerNode(tree, "start of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                scan(finallyBlock, p);
                extendWithNode(new MarkerNode(tree, "end of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                extendWithExtendedNode(new UnconditionalJump(continueLabels.get(access.getKey())));
            }
        } else {
            continueLabels = oldContinueLabels;
        }
    }
    addLabelForNextNode(doneLabel);
    return null;
}
Also used : CatchTree(com.sun.source.tree.CatchTree) Name(javax.lang.model.element.Name) MarkerNode(org.checkerframework.dataflow.cfg.node.MarkerNode) BlockTree(com.sun.source.tree.BlockTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ForLoopTree(com.sun.source.tree.ForLoopTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) ThrowTree(com.sun.source.tree.ThrowTree) BlockTree(com.sun.source.tree.BlockTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) LabeledStatementTree(com.sun.source.tree.LabeledStatementTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) BreakTree(com.sun.source.tree.BreakTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) WildcardTree(com.sun.source.tree.WildcardTree) UnionTypeTree(com.sun.source.tree.UnionTypeTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) ContinueTree(com.sun.source.tree.ContinueTree) CaseTree(com.sun.source.tree.CaseTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) SwitchTree(com.sun.source.tree.SwitchTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) SynchronizedTree(com.sun.source.tree.SynchronizedTree) AssertTree(com.sun.source.tree.AssertTree) StatementTree(com.sun.source.tree.StatementTree) ModifiersTree(com.sun.source.tree.ModifiersTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) EmptyStatementTree(com.sun.source.tree.EmptyStatementTree) ClassTree(com.sun.source.tree.ClassTree) IfTree(com.sun.source.tree.IfTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) ErroneousTree(com.sun.source.tree.ErroneousTree) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) TryTree(com.sun.source.tree.TryTree) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Pair(org.checkerframework.javacutil.Pair)

Aggregations

AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)1 AnnotationTree (com.sun.source.tree.AnnotationTree)1 ArrayAccessTree (com.sun.source.tree.ArrayAccessTree)1 ArrayTypeTree (com.sun.source.tree.ArrayTypeTree)1 AssertTree (com.sun.source.tree.AssertTree)1 AssignmentTree (com.sun.source.tree.AssignmentTree)1 BinaryTree (com.sun.source.tree.BinaryTree)1 BlockTree (com.sun.source.tree.BlockTree)1 BreakTree (com.sun.source.tree.BreakTree)1 CaseTree (com.sun.source.tree.CaseTree)1 CatchTree (com.sun.source.tree.CatchTree)1 ClassTree (com.sun.source.tree.ClassTree)1 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)1 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)1 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)1 ContinueTree (com.sun.source.tree.ContinueTree)1 DoWhileLoopTree (com.sun.source.tree.DoWhileLoopTree)1 EmptyStatementTree (com.sun.source.tree.EmptyStatementTree)1 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)1 ErroneousTree (com.sun.source.tree.ErroneousTree)1