Search in sources :

Example 1 with ArrayAccessNode

use of org.checkerframework.dataflow.cfg.node.ArrayAccessNode in project bazel by bazelbuild.

the class FlowExpressions method internalReprOf.

/**
     * We ignore operations such as widening and
     * narrowing when computing the internal representation.
     *
     * @return The internal representation (as {@link Receiver}) of any
     *         {@link Node}. Might contain {@link Unknown}.
     */
public static Receiver internalReprOf(AnnotationProvider provider, Node receiverNode, boolean allowNonDeterminitic) {
    Receiver receiver = null;
    if (receiverNode instanceof FieldAccessNode) {
        FieldAccessNode fan = (FieldAccessNode) receiverNode;
        if (fan.getFieldName().equals("this")) {
            // For some reason, "className.this" is considered a field access.
            // We right this wrong here.
            receiver = new ThisReference(fan.getReceiver().getType());
        } else {
            receiver = internalReprOfFieldAccess(provider, fan);
        }
    } else if (receiverNode instanceof ExplicitThisLiteralNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof ThisLiteralNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof SuperNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof LocalVariableNode) {
        LocalVariableNode lv = (LocalVariableNode) receiverNode;
        receiver = new LocalVariable(lv);
    } else if (receiverNode instanceof ArrayAccessNode) {
        ArrayAccessNode a = (ArrayAccessNode) receiverNode;
        receiver = internalReprOfArrayAccess(provider, a);
    } else if (receiverNode instanceof StringConversionNode) {
        // ignore string conversion
        return internalReprOf(provider, ((StringConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof WideningConversionNode) {
        // ignore widening
        return internalReprOf(provider, ((WideningConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof NarrowingConversionNode) {
        // ignore narrowing
        return internalReprOf(provider, ((NarrowingConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof ClassNameNode) {
        ClassNameNode cn = (ClassNameNode) receiverNode;
        receiver = new ClassName(cn.getType());
    } else if (receiverNode instanceof ValueLiteralNode) {
        ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
        receiver = new ValueLiteral(vn.getType(), vn);
    } else if (receiverNode instanceof MethodInvocationNode) {
        MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
        ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn.getTree());
        // check if this represents a boxing operation of a constant, in which
        // case we treat the method call as deterministic, because there is no way
        // to behave differently in two executions where two constants are being used.
        boolean considerDeterministic = false;
        if (invokedMethod.toString().equals("valueOf(long)") && mn.getTarget().getReceiver().toString().equals("Long")) {
            Node arg = mn.getArgument(0);
            if (arg instanceof ValueLiteralNode) {
                considerDeterministic = true;
            }
        }
        if (PurityUtils.isDeterministic(provider, invokedMethod) || allowNonDeterminitic || considerDeterministic) {
            List<Receiver> parameters = new ArrayList<>();
            for (Node p : mn.getArguments()) {
                parameters.add(internalReprOf(provider, p));
            }
            Receiver methodReceiver;
            if (ElementUtils.isStatic(invokedMethod)) {
                methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
            } else {
                methodReceiver = internalReprOf(provider, mn.getTarget().getReceiver());
            }
            receiver = new PureMethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
        }
    }
    if (receiver == null) {
        receiver = new Unknown(receiverNode.getType());
    }
    return receiver;
}
Also used : MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ExecutableElement(javax.lang.model.element.ExecutableElement) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) Node(org.checkerframework.dataflow.cfg.node.Node) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with ArrayAccessNode

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

the class CFGTranslationPhaseOne method visitArrayAccess.

@Override
public Node visitArrayAccess(ArrayAccessTree tree, Void p) {
    Node array = scan(tree.getExpression(), p);
    Node index = unaryNumericPromotion(scan(tree.getIndex(), p));
    Node arrayAccess = new ArrayAccessNode(tree, array, index);
    extendWithNode(arrayAccess);
    extendWithNodeWithException(arrayAccess, arrayIndexOutOfBoundsExceptionType);
    extendWithNodeWithException(arrayAccess, nullPointerExceptionType);
    return arrayAccess;
}
Also used : NumericalMultiplicationNode(org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) UnsignedRightShiftNode(org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode) LeftShiftNode(org.checkerframework.dataflow.cfg.node.LeftShiftNode) PrimitiveTypeNode(org.checkerframework.dataflow.cfg.node.PrimitiveTypeNode) FloatLiteralNode(org.checkerframework.dataflow.cfg.node.FloatLiteralNode) LessThanNode(org.checkerframework.dataflow.cfg.node.LessThanNode) BitwiseOrNode(org.checkerframework.dataflow.cfg.node.BitwiseOrNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) EqualToNode(org.checkerframework.dataflow.cfg.node.EqualToNode) NumericalPlusNode(org.checkerframework.dataflow.cfg.node.NumericalPlusNode) ConditionalAndNode(org.checkerframework.dataflow.cfg.node.ConditionalAndNode) VariableDeclarationNode(org.checkerframework.dataflow.cfg.node.VariableDeclarationNode) ClassDeclarationNode(org.checkerframework.dataflow.cfg.node.ClassDeclarationNode) IntegerDivisionNode(org.checkerframework.dataflow.cfg.node.IntegerDivisionNode) AssertionErrorNode(org.checkerframework.dataflow.cfg.node.AssertionErrorNode) InstanceOfNode(org.checkerframework.dataflow.cfg.node.InstanceOfNode) BooleanLiteralNode(org.checkerframework.dataflow.cfg.node.BooleanLiteralNode) ThisNode(org.checkerframework.dataflow.cfg.node.ThisNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) NullLiteralNode(org.checkerframework.dataflow.cfg.node.NullLiteralNode) ArrayTypeNode(org.checkerframework.dataflow.cfg.node.ArrayTypeNode) LambdaResultExpressionNode(org.checkerframework.dataflow.cfg.node.LambdaResultExpressionNode) IntegerRemainderNode(org.checkerframework.dataflow.cfg.node.IntegerRemainderNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ConditionalOrNode(org.checkerframework.dataflow.cfg.node.ConditionalOrNode) NotEqualNode(org.checkerframework.dataflow.cfg.node.NotEqualNode) BitwiseXorNode(org.checkerframework.dataflow.cfg.node.BitwiseXorNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ExplicitThisNode(org.checkerframework.dataflow.cfg.node.ExplicitThisNode) StringConcatenateNode(org.checkerframework.dataflow.cfg.node.StringConcatenateNode) NullChkNode(org.checkerframework.dataflow.cfg.node.NullChkNode) CharacterLiteralNode(org.checkerframework.dataflow.cfg.node.CharacterLiteralNode) FloatingDivisionNode(org.checkerframework.dataflow.cfg.node.FloatingDivisionNode) FunctionalInterfaceNode(org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) MethodAccessNode(org.checkerframework.dataflow.cfg.node.MethodAccessNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) LongLiteralNode(org.checkerframework.dataflow.cfg.node.LongLiteralNode) MarkerNode(org.checkerframework.dataflow.cfg.node.MarkerNode) ImplicitThisNode(org.checkerframework.dataflow.cfg.node.ImplicitThisNode) FloatingRemainderNode(org.checkerframework.dataflow.cfg.node.FloatingRemainderNode) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) PackageNameNode(org.checkerframework.dataflow.cfg.node.PackageNameNode) DoubleLiteralNode(org.checkerframework.dataflow.cfg.node.DoubleLiteralNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) IntegerLiteralNode(org.checkerframework.dataflow.cfg.node.IntegerLiteralNode) SignedRightShiftNode(org.checkerframework.dataflow.cfg.node.SignedRightShiftNode) ThrowNode(org.checkerframework.dataflow.cfg.node.ThrowNode) GreaterThanOrEqualNode(org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode) StringLiteralNode(org.checkerframework.dataflow.cfg.node.StringLiteralNode) TernaryExpressionNode(org.checkerframework.dataflow.cfg.node.TernaryExpressionNode) BitwiseAndNode(org.checkerframework.dataflow.cfg.node.BitwiseAndNode) ParameterizedTypeNode(org.checkerframework.dataflow.cfg.node.ParameterizedTypeNode) CaseNode(org.checkerframework.dataflow.cfg.node.CaseNode) SwitchExpressionNode(org.checkerframework.dataflow.cfg.node.SwitchExpressionNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode) BitwiseComplementNode(org.checkerframework.dataflow.cfg.node.BitwiseComplementNode) ConditionalNotNode(org.checkerframework.dataflow.cfg.node.ConditionalNotNode) NumericalMinusNode(org.checkerframework.dataflow.cfg.node.NumericalMinusNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) GreaterThanNode(org.checkerframework.dataflow.cfg.node.GreaterThanNode) LessThanOrEqualNode(org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode) SynchronizedNode(org.checkerframework.dataflow.cfg.node.SynchronizedNode) Node(org.checkerframework.dataflow.cfg.node.Node) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode)

Example 3 with ArrayAccessNode

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

the class CFGTranslationPhaseOne method visitEnhancedForLoop.

@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();
    }
    TryFinallyScopeCell oldBreakTargetL = breakTargetL;
    breakTargetL = new TryFinallyScopeCell(loopExit);
    TryFinallyScopeCell oldContinueTargetL = continueTargetL;
    continueTargetL = new TryFinallyScopeCell(updateStart);
    // Distinguish loops over Iterables from loops over arrays.
    VariableTree variable = tree.getVariable();
    VariableElement variableElement = TreeUtils.elementFromDeclaration(variable);
    ExpressionTree expression = tree.getExpression();
    StatementTree statement = tree.getStatement();
    TypeMirror exprType = TreeUtils.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.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.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.emptyList(), getCurrentPath());
        // If the type of iteratorVariable is a capture, its type tree may be missing annotations, so
        // save the expression in the node so that the full type can be found later.
        nextCallNode.setIterableExpression(expression);
        nextCallNode.setInSource(false);
        extendWithNode(nextCallNode);
        AssignmentNode assignNode = translateAssignment(variable, new LocalVariableNode(variable), nextCall);
        // translateAssignment() scans variable and creates new nodes, so set the expression
        // there, too.
        ((MethodInvocationNode) assignNode.getExpression()).setIterableExpression(expression);
        assert 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 = new IntegerLiteralNode(zero);
        extendWithNode(zeroNode);
        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 = new LocalVariableNode(arrayUse1);
        extendWithNode(arrayNode1);
        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.setArrayExpression(expression);
        arrayAccessNode.setInSource(false);
        extendWithNode(arrayAccessNode);
        AssignmentNode arrayAccessAssignNode = translateAssignment(variable, new LocalVariableNode(variable), arrayAccessNode);
        extendWithNodeWithException(arrayAccessNode, nullPointerExceptionType);
        // translateAssignment() scans variable and creates new nodes, so set the expression
        // there, too.
        Node arrayAccessAssignNodeExpr = arrayAccessAssignNode.getExpression();
        if (arrayAccessAssignNodeExpr instanceof ArrayAccessNode) {
            ((ArrayAccessNode) arrayAccessAssignNodeExpr).setArrayExpression(expression);
        } else if (arrayAccessAssignNodeExpr instanceof MethodInvocationNode) {
            // If the array component type is a primitive, there may be a boxing or unboxing
            // conversion. Treat that as an iterator.
            MethodInvocationNode boxingNode = (MethodInvocationNode) arrayAccessAssignNodeExpr;
            boxingNode.setIterableExpression(expression);
        }
        assert 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;
}
Also used : ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) MemberSelectTree(com.sun.source.tree.MemberSelectTree) NumericalMultiplicationNode(org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) UnsignedRightShiftNode(org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode) LeftShiftNode(org.checkerframework.dataflow.cfg.node.LeftShiftNode) PrimitiveTypeNode(org.checkerframework.dataflow.cfg.node.PrimitiveTypeNode) FloatLiteralNode(org.checkerframework.dataflow.cfg.node.FloatLiteralNode) LessThanNode(org.checkerframework.dataflow.cfg.node.LessThanNode) BitwiseOrNode(org.checkerframework.dataflow.cfg.node.BitwiseOrNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) EqualToNode(org.checkerframework.dataflow.cfg.node.EqualToNode) NumericalPlusNode(org.checkerframework.dataflow.cfg.node.NumericalPlusNode) ConditionalAndNode(org.checkerframework.dataflow.cfg.node.ConditionalAndNode) VariableDeclarationNode(org.checkerframework.dataflow.cfg.node.VariableDeclarationNode) ClassDeclarationNode(org.checkerframework.dataflow.cfg.node.ClassDeclarationNode) IntegerDivisionNode(org.checkerframework.dataflow.cfg.node.IntegerDivisionNode) AssertionErrorNode(org.checkerframework.dataflow.cfg.node.AssertionErrorNode) InstanceOfNode(org.checkerframework.dataflow.cfg.node.InstanceOfNode) BooleanLiteralNode(org.checkerframework.dataflow.cfg.node.BooleanLiteralNode) ThisNode(org.checkerframework.dataflow.cfg.node.ThisNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) NullLiteralNode(org.checkerframework.dataflow.cfg.node.NullLiteralNode) ArrayTypeNode(org.checkerframework.dataflow.cfg.node.ArrayTypeNode) LambdaResultExpressionNode(org.checkerframework.dataflow.cfg.node.LambdaResultExpressionNode) IntegerRemainderNode(org.checkerframework.dataflow.cfg.node.IntegerRemainderNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ConditionalOrNode(org.checkerframework.dataflow.cfg.node.ConditionalOrNode) NotEqualNode(org.checkerframework.dataflow.cfg.node.NotEqualNode) BitwiseXorNode(org.checkerframework.dataflow.cfg.node.BitwiseXorNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ExplicitThisNode(org.checkerframework.dataflow.cfg.node.ExplicitThisNode) StringConcatenateNode(org.checkerframework.dataflow.cfg.node.StringConcatenateNode) NullChkNode(org.checkerframework.dataflow.cfg.node.NullChkNode) CharacterLiteralNode(org.checkerframework.dataflow.cfg.node.CharacterLiteralNode) FloatingDivisionNode(org.checkerframework.dataflow.cfg.node.FloatingDivisionNode) FunctionalInterfaceNode(org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) MethodAccessNode(org.checkerframework.dataflow.cfg.node.MethodAccessNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) LongLiteralNode(org.checkerframework.dataflow.cfg.node.LongLiteralNode) MarkerNode(org.checkerframework.dataflow.cfg.node.MarkerNode) ImplicitThisNode(org.checkerframework.dataflow.cfg.node.ImplicitThisNode) FloatingRemainderNode(org.checkerframework.dataflow.cfg.node.FloatingRemainderNode) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) PackageNameNode(org.checkerframework.dataflow.cfg.node.PackageNameNode) DoubleLiteralNode(org.checkerframework.dataflow.cfg.node.DoubleLiteralNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) IntegerLiteralNode(org.checkerframework.dataflow.cfg.node.IntegerLiteralNode) SignedRightShiftNode(org.checkerframework.dataflow.cfg.node.SignedRightShiftNode) ThrowNode(org.checkerframework.dataflow.cfg.node.ThrowNode) GreaterThanOrEqualNode(org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode) StringLiteralNode(org.checkerframework.dataflow.cfg.node.StringLiteralNode) TernaryExpressionNode(org.checkerframework.dataflow.cfg.node.TernaryExpressionNode) BitwiseAndNode(org.checkerframework.dataflow.cfg.node.BitwiseAndNode) ParameterizedTypeNode(org.checkerframework.dataflow.cfg.node.ParameterizedTypeNode) CaseNode(org.checkerframework.dataflow.cfg.node.CaseNode) SwitchExpressionNode(org.checkerframework.dataflow.cfg.node.SwitchExpressionNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode) BitwiseComplementNode(org.checkerframework.dataflow.cfg.node.BitwiseComplementNode) ConditionalNotNode(org.checkerframework.dataflow.cfg.node.ConditionalNotNode) NumericalMinusNode(org.checkerframework.dataflow.cfg.node.NumericalMinusNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) GreaterThanNode(org.checkerframework.dataflow.cfg.node.GreaterThanNode) LessThanOrEqualNode(org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode) SynchronizedNode(org.checkerframework.dataflow.cfg.node.SynchronizedNode) Node(org.checkerframework.dataflow.cfg.node.Node) VariableTree(com.sun.source.tree.VariableTree) BinaryTree(com.sun.source.tree.BinaryTree) IdentifierTree(com.sun.source.tree.IdentifierTree) VariableElement(javax.lang.model.element.VariableElement) LessThanNode(org.checkerframework.dataflow.cfg.node.LessThanNode) LiteralTree(com.sun.source.tree.LiteralTree) Name(javax.lang.model.element.Name) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) LabeledStatementTree(com.sun.source.tree.LabeledStatementTree) StatementTree(com.sun.source.tree.StatementTree) EmptyStatementTree(com.sun.source.tree.EmptyStatementTree) TypeMirror(javax.lang.model.type.TypeMirror) VariableDeclarationNode(org.checkerframework.dataflow.cfg.node.VariableDeclarationNode) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) IntegerLiteralNode(org.checkerframework.dataflow.cfg.node.IntegerLiteralNode) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) AssignmentTree(com.sun.source.tree.AssignmentTree) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) MethodAccessNode(org.checkerframework.dataflow.cfg.node.MethodAccessNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) DeclaredType(javax.lang.model.type.DeclaredType)

Example 4 with ArrayAccessNode

use of org.checkerframework.dataflow.cfg.node.ArrayAccessNode in project error-prone by google.

the class NullnessPropagationTransfer method visitAssignment.

@Override
Nullness visitAssignment(AssignmentNode node, SubNodeValues inputs, LocalVariableUpdates updates) {
    Nullness value = inputs.valueOfSubNode(node.getExpression());
    Node target = node.getTarget();
    if (target instanceof LocalVariableNode) {
        updates.set((LocalVariableNode) target, value);
    }
    if (target instanceof ArrayAccessNode) {
        setNonnullIfLocalVariable(updates, ((ArrayAccessNode) target).getArray());
    }
    if (target instanceof FieldAccessNode) {
        FieldAccessNode fieldAccess = (FieldAccessNode) target;
        ClassAndField targetField = tryGetFieldSymbol(target.getTree());
        setReceiverNonnull(updates, fieldAccess.getReceiver(), targetField);
    }
    /*
     * We propagate the value of the target to the value of the assignment expressions as a whole.
     * We do this regardless of whether the target is a local variable. For example:
     *
     * String s = object.field = "foo"; // Now |s| is non-null.
     *
     * It's not clear to me that this is technically correct, but it works in practice with the
     * bytecode generated by both javac and ecj.
     *
     * http://stackoverflow.com/q/12850676/28465
     */
    return value;
}
Also used : TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) EqualToNode(org.checkerframework.dataflow.cfg.node.EqualToNode) VariableDeclarationNode(org.checkerframework.dataflow.cfg.node.VariableDeclarationNode) InstanceOfNode(org.checkerframework.dataflow.cfg.node.InstanceOfNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) NotEqualNode(org.checkerframework.dataflow.cfg.node.NotEqualNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) FunctionalInterfaceNode(org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode) Node(org.checkerframework.dataflow.cfg.node.Node) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode)

Example 5 with ArrayAccessNode

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

the class FlowExpressions method internalReprOf.

/**
 * We ignore operations such as widening and narrowing when computing the internal
 * representation.
 *
 * @return the internal representation (as {@link Receiver}) of any {@link Node}. Might contain
 *     {@link Unknown}.
 */
public static Receiver internalReprOf(AnnotationProvider provider, Node receiverNode, boolean allowNonDeterministic) {
    Receiver receiver = null;
    if (receiverNode instanceof FieldAccessNode) {
        FieldAccessNode fan = (FieldAccessNode) receiverNode;
        if (fan.getFieldName().equals("this")) {
            // For some reason, "className.this" is considered a field access.
            // We right this wrong here.
            receiver = new ThisReference(fan.getReceiver().getType());
        } else if (fan.getFieldName().equals("class")) {
            // "className.class" is considered a field access. This makes sense,
            // since .class is similar to a field access which is the equivalent
            // of a call to getClass(). However for the purposes of dataflow
            // analysis, and value stores, this is the equivalent of a ClassNameNode.
            receiver = new ClassName(fan.getReceiver().getType());
        } else {
            receiver = internalReprOfFieldAccess(provider, fan);
        }
    } else if (receiverNode instanceof ExplicitThisLiteralNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof ThisLiteralNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof SuperNode) {
        receiver = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof LocalVariableNode) {
        LocalVariableNode lv = (LocalVariableNode) receiverNode;
        receiver = new LocalVariable(lv);
    } else if (receiverNode instanceof ArrayAccessNode) {
        ArrayAccessNode a = (ArrayAccessNode) receiverNode;
        receiver = internalReprOfArrayAccess(provider, a);
    } else if (receiverNode instanceof StringConversionNode) {
        // ignore string conversion
        return internalReprOf(provider, ((StringConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof WideningConversionNode) {
        // ignore widening
        return internalReprOf(provider, ((WideningConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof NarrowingConversionNode) {
        // ignore narrowing
        return internalReprOf(provider, ((NarrowingConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof ClassNameNode) {
        ClassNameNode cn = (ClassNameNode) receiverNode;
        receiver = new ClassName(cn.getType());
    } else if (receiverNode instanceof ValueLiteralNode) {
        ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
        receiver = new ValueLiteral(vn.getType(), vn);
    } else if (receiverNode instanceof ArrayCreationNode) {
        ArrayCreationNode an = (ArrayCreationNode) receiverNode;
        List<Receiver> dimensions = new ArrayList<>();
        for (Node dimension : an.getDimensions()) {
            dimensions.add(internalReprOf(provider, dimension, allowNonDeterministic));
        }
        List<Receiver> initializers = new ArrayList<>();
        for (Node initializer : an.getInitializers()) {
            initializers.add(internalReprOf(provider, initializer, allowNonDeterministic));
        }
        receiver = new ArrayCreation(an.getType(), dimensions, initializers);
    } else if (receiverNode instanceof MethodInvocationNode) {
        MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
        ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn.getTree());
        // check if this represents a boxing operation of a constant, in which
        // case we treat the method call as deterministic, because there is no way
        // to behave differently in two executions where two constants are being used.
        boolean considerDeterministic = false;
        if (isLongValueOf(mn, invokedMethod)) {
            Node arg = mn.getArgument(0);
            if (arg instanceof ValueLiteralNode) {
                considerDeterministic = true;
            }
        }
        if (PurityUtils.isDeterministic(provider, invokedMethod) || allowNonDeterministic || considerDeterministic) {
            List<Receiver> parameters = new ArrayList<>();
            for (Node p : mn.getArguments()) {
                parameters.add(internalReprOf(provider, p));
            }
            Receiver methodReceiver;
            if (ElementUtils.isStatic(invokedMethod)) {
                methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
            } else {
                methodReceiver = internalReprOf(provider, mn.getTarget().getReceiver());
            }
            receiver = new MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
        }
    }
    if (receiver == null) {
        receiver = new Unknown(receiverNode.getType());
    }
    return receiver;
}
Also used : ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) ArrayList(java.util.ArrayList) List(java.util.List) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode)

Aggregations

ArrayAccessNode (org.checkerframework.dataflow.cfg.node.ArrayAccessNode)7 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)7 FieldAccessNode (org.checkerframework.dataflow.cfg.node.FieldAccessNode)6 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)6 ArrayCreationNode (org.checkerframework.dataflow.cfg.node.ArrayCreationNode)5 ClassNameNode (org.checkerframework.dataflow.cfg.node.ClassNameNode)5 NarrowingConversionNode (org.checkerframework.dataflow.cfg.node.NarrowingConversionNode)5 Node (org.checkerframework.dataflow.cfg.node.Node)5 StringConversionNode (org.checkerframework.dataflow.cfg.node.StringConversionNode)5 SuperNode (org.checkerframework.dataflow.cfg.node.SuperNode)5 ValueLiteralNode (org.checkerframework.dataflow.cfg.node.ValueLiteralNode)5 WideningConversionNode (org.checkerframework.dataflow.cfg.node.WideningConversionNode)5 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)3 EqualToNode (org.checkerframework.dataflow.cfg.node.EqualToNode)3 ExplicitThisNode (org.checkerframework.dataflow.cfg.node.ExplicitThisNode)3 FunctionalInterfaceNode (org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode)3 InstanceOfNode (org.checkerframework.dataflow.cfg.node.InstanceOfNode)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2