Search in sources :

Example 11 with BinaryTree

use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.

the class SignednessVisitor method isMaskedShift.

/**
 * Determines if a right shift operation, {@code >>} or {@code >>>}, is masked with a masking
 * operation of the form {@code shiftExpr & maskLit} or {@code shiftExpr | maskLit} such that
 * the mask renders the shift signedness ({@code >>} vs {@code >>>}) irrelevent by destroying
 * the bits duplicated into the shift result. For example, the following pairs of right shifts
 * on {@code byte b} both produce the same results under any input, because of their masks:
 *
 * <p>{@code (b >> 4) & 0x0F == (b >>> 4) & 0x0F;}
 *
 * <p>{@code (b >> 4) | 0xF0 == (b >>> 4) | 0xF0;}
 *
 * @param shiftExpr a right shift expression: {@code expr1 >> expr2} or {@code expr1 >>> expr2}
 * @return true iff the right shift is masked such that a signed or unsigned right shift has the
 *     same effect
 */
private boolean isMaskedShift(BinaryTree shiftExpr) {
    // enclosing is the operation or statement that immediately contains shiftExpr
    Tree enclosing;
    // enclosingChild is the top node in the chain of nodes from shiftExpr to parent
    Tree enclosingChild;
    {
        TreePath parentPath = visitorState.getPath().getParentPath();
        enclosing = parentPath.getLeaf();
        enclosingChild = enclosing;
        // Strip away all parentheses from the shift operation
        while (enclosing.getKind() == Kind.PARENTHESIZED) {
            parentPath = parentPath.getParentPath();
            enclosingChild = enclosing;
            enclosing = parentPath.getLeaf();
        }
    }
    if (!isMask(enclosing)) {
        return false;
    }
    BinaryTree maskExpr = (BinaryTree) enclosing;
    ExpressionTree shiftAmountExpr = shiftExpr.getRightOperand();
    // Determine which child of maskExpr leads to shiftExpr. The other one is the mask.
    ExpressionTree mask = maskExpr.getRightOperand() == enclosingChild ? maskExpr.getLeftOperand() : maskExpr.getRightOperand();
    // Strip away the parentheses from the mask if any exist
    mask = TreeUtils.skipParens(mask);
    if (!isLiteral(shiftAmountExpr) || !isLiteral(mask)) {
        return false;
    }
    LiteralTree shiftLit = (LiteralTree) shiftAmountExpr;
    LiteralTree maskLit = (LiteralTree) mask;
    return maskIgnoresMSB(maskExpr.getKind(), shiftLit, maskLit);
}
Also used : TreePath(com.sun.source.util.TreePath) BinaryTree(com.sun.source.tree.BinaryTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BinaryTree(com.sun.source.tree.BinaryTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) TypeCastTree(com.sun.source.tree.TypeCastTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) LiteralTree(com.sun.source.tree.LiteralTree)

Example 12 with BinaryTree

use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.

the class SignednessVisitor method visitBinary.

/**
 * Enforces the following rules on binary operations involving Unsigned and Signed types:
 *
 * <ul>
 *   <li>Do not allow any Unsigned types or PolySigned types in {@literal {/, %}} operations.
 *   <li>Do not allow signed right shift {@literal {>>}} on an Unsigned type or a PolySigned type.
 *   <li>Do not allow unsigned right shift {@literal {>>>}} on a Signed type or a PolySigned type.
 *   <li>Allow any left shift {@literal {<<}}.
 *   <li>Do not allow non-equality comparisons {@literal {<, <=, >, >=}} on Unsigned types or
 *       PolySigned types.
 *   <li>Do not allow the mixing of Signed and Unsigned types.
 * </ul>
 */
@Override
public Void visitBinary(BinaryTree node, Void p) {
    // Used in diagnostic messages.
    ExpressionTree leftOp = node.getLeftOperand();
    ExpressionTree rightOp = node.getRightOperand();
    Pair<AnnotatedTypeMirror, AnnotatedTypeMirror> argTypes = atypeFactory.binaryTreeArgTypes(node);
    AnnotatedTypeMirror leftOpType = argTypes.first;
    AnnotatedTypeMirror rightOpType = argTypes.second;
    Tree.Kind kind = node.getKind();
    switch(kind) {
        case DIVIDE:
        case REMAINDER:
            if (hasUnsignedAnnotation(leftOpType)) {
                checker.reportError(leftOp, "operation.unsignedlhs", kind, leftOpType, rightOpType);
            } else if (hasUnsignedAnnotation(rightOpType)) {
                checker.reportError(rightOp, "operation.unsignedrhs", kind, leftOpType, rightOpType);
            }
            break;
        case RIGHT_SHIFT:
            if (hasUnsignedAnnotation(leftOpType) && !atypeFactory.isMaskedShiftEitherSignedness(node, getCurrentPath()) && !atypeFactory.isCastedShiftEitherSignedness(node, getCurrentPath())) {
                checker.reportError(leftOp, "shift.signed", kind, leftOpType, rightOpType);
            }
            break;
        case UNSIGNED_RIGHT_SHIFT:
            if (hasSignedAnnotation(leftOpType) && !atypeFactory.isMaskedShiftEitherSignedness(node, getCurrentPath()) && !atypeFactory.isCastedShiftEitherSignedness(node, getCurrentPath())) {
                checker.reportError(leftOp, "shift.unsigned", kind, leftOpType, rightOpType);
            }
            break;
        case LEFT_SHIFT:
            break;
        case GREATER_THAN:
        case GREATER_THAN_EQUAL:
        case LESS_THAN:
        case LESS_THAN_EQUAL:
            if (hasUnsignedAnnotation(leftOpType)) {
                checker.reportError(leftOp, "comparison.unsignedlhs", leftOpType, rightOpType);
            } else if (hasUnsignedAnnotation(rightOpType)) {
                checker.reportError(rightOp, "comparison.unsignedrhs", leftOpType, rightOpType);
            }
            break;
        case EQUAL_TO:
        case NOT_EQUAL_TO:
            if (leftOpType.hasAnnotation(Unsigned.class) && rightOpType.hasAnnotation(Signed.class)) {
                checker.reportError(node, "comparison.mixed.unsignedlhs", leftOpType, rightOpType);
            } else if (leftOpType.hasAnnotation(Signed.class) && rightOpType.hasAnnotation(Unsigned.class)) {
                checker.reportError(node, "comparison.mixed.unsignedrhs", leftOpType, rightOpType);
            }
            break;
        case PLUS:
            if (TreeUtils.isStringConcatenation(node)) {
                AnnotationMirror leftAnno = leftOpType.getEffectiveAnnotations().iterator().next();
                AnnotationMirror rightAnno = rightOpType.getEffectiveAnnotations().iterator().next();
                if (leftOpType.getKind() != TypeKind.CHAR && !TypesUtils.isDeclaredOfName(leftOpType.getUnderlyingType(), "java.lang.Character") && !atypeFactory.getQualifierHierarchy().isSubtype(leftAnno, atypeFactory.SIGNED)) {
                    checker.reportError(leftOp, "unsigned.concat");
                } else if (rightOpType.getKind() != TypeKind.CHAR && !TypesUtils.isDeclaredOfName(rightOpType.getUnderlyingType(), "java.lang.Character") && !atypeFactory.getQualifierHierarchy().isSubtype(rightAnno, atypeFactory.SIGNED)) {
                    checker.reportError(rightOp, "unsigned.concat");
                }
                break;
            }
        // fall through
        default:
            if (leftOpType.hasAnnotation(Unsigned.class) && rightOpType.hasAnnotation(Signed.class)) {
                checker.reportError(node, "operation.mixed.unsignedlhs", kind, leftOpType, rightOpType);
            } else if (leftOpType.hasAnnotation(Signed.class) && rightOpType.hasAnnotation(Unsigned.class)) {
                checker.reportError(node, "operation.mixed.unsignedrhs", kind, leftOpType, rightOpType);
            }
            break;
    }
    return super.visitBinary(node, p);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) Unsigned(org.checkerframework.checker.signedness.qual.Unsigned) Signed(org.checkerframework.checker.signedness.qual.Signed) PolySigned(org.checkerframework.checker.signedness.qual.PolySigned) ExpressionTree(com.sun.source.tree.ExpressionTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BinaryTree(com.sun.source.tree.BinaryTree) Tree(com.sun.source.tree.Tree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 13 with BinaryTree

use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.

the class CFGTranslationPhaseOne method visitBinary.

@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 = TreeUtils.typeOf(tree);
                TypeMirror leftType = TreeUtils.typeOf(leftTree);
                TypeMirror rightType = TreeUtils.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.isIntegralPrimitive(exprType)) {
                        r = new IntegerDivisionNode(tree, left, right);
                        extendWithNodeWithException(r, arithmeticExceptionType);
                    } else {
                        r = new FloatingDivisionNode(tree, left, right);
                    }
                } else {
                    assert kind == Tree.Kind.REMAINDER;
                    if (TypesUtils.isIntegralPrimitive(exprType)) {
                        r = new IntegerRemainderNode(tree, left, right);
                        extendWithNodeWithException(r, arithmeticExceptionType);
                    } else {
                        r = new FloatingRemainderNode(tree, left, right);
                    }
                }
                break;
            }
        case MINUS:
        case PLUS:
            {
                // see JLS 15.18
                // TypeMirror exprType = InternalUtils.typeOf(tree);
                TypeMirror leftType = TreeUtils.typeOf(leftTree);
                TypeMirror rightType = TreeUtils.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);
                    // set conversion.
                    if (kind == Tree.Kind.PLUS) {
                        r = new NumericalAdditionNode(tree, left, right);
                    } else {
                        assert kind == Tree.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 == Tree.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 = TreeUtils.typeOf(leftTree);
                if (TypesUtils.isBoxedPrimitive(leftType)) {
                    leftType = types.unboxedType(leftType);
                }
                TypeMirror rightType = TreeUtils.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 == Tree.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 = TreeUtils.typeOf(leftTree);
                TypeMirror rightType = TreeUtils.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 == Tree.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(FlowRule.ELSE_TO_ELSE);
                } else {
                    cjump = new ConditionalJump(shortCircuitL, rightStartL);
                    cjump.setTrueFlowRule(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:
            throw new BugInCF("unexpected binary tree: " + kind);
    }
    assert r != null : "unexpected binary tree";
    extendWithNode(r);
    return r;
}
Also used : IntegerRemainderNode(org.checkerframework.dataflow.cfg.node.IntegerRemainderNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) 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) BitwiseOrNode(org.checkerframework.dataflow.cfg.node.BitwiseOrNode) NumericalMultiplicationNode(org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode) IntegerDivisionNode(org.checkerframework.dataflow.cfg.node.IntegerDivisionNode) LessThanNode(org.checkerframework.dataflow.cfg.node.LessThanNode) BitwiseXorNode(org.checkerframework.dataflow.cfg.node.BitwiseXorNode) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode) ConditionalAndNode(org.checkerframework.dataflow.cfg.node.ConditionalAndNode) TypeMirror(javax.lang.model.type.TypeMirror) BitwiseAndNode(org.checkerframework.dataflow.cfg.node.BitwiseAndNode) 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) LessThanOrEqualNode(org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode) UnsignedRightShiftNode(org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode) FloatingRemainderNode(org.checkerframework.dataflow.cfg.node.FloatingRemainderNode) NotEqualNode(org.checkerframework.dataflow.cfg.node.NotEqualNode) ConditionalOrNode(org.checkerframework.dataflow.cfg.node.ConditionalOrNode) StringConcatenateNode(org.checkerframework.dataflow.cfg.node.StringConcatenateNode) GreaterThanOrEqualNode(org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode) FloatingDivisionNode(org.checkerframework.dataflow.cfg.node.FloatingDivisionNode) SignedRightShiftNode(org.checkerframework.dataflow.cfg.node.SignedRightShiftNode) GreaterThanNode(org.checkerframework.dataflow.cfg.node.GreaterThanNode) LeftShiftNode(org.checkerframework.dataflow.cfg.node.LeftShiftNode) BugInCF(org.checkerframework.javacutil.BugInCF) EqualToNode(org.checkerframework.dataflow.cfg.node.EqualToNode) Kind(com.sun.source.tree.Tree.Kind)

Example 14 with BinaryTree

use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.

the class CFGTranslationPhaseOne method createIncrementOrDecrementAssign.

/**
 * Create assignment node which represent increment or decrement.
 *
 * @param target tree for assignment node. If it's null, corresponding assignment tree will be
 *     generated.
 * @param expr expression node to be incremented or decremented
 * @param isIncrement true when it's increment
 * @return assignment node for corresponding increment or decrement
 */
private AssignmentNode createIncrementOrDecrementAssign(Tree target, Node expr, boolean isIncrement) {
    ExpressionTree exprTree = (ExpressionTree) expr.getTree();
    TypeMirror exprType = expr.getType();
    TypeMirror oneType = types.getPrimitiveType(TypeKind.INT);
    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, isIncrement ? Tree.Kind.PLUS : Tree.Kind.MINUS, exprTree, oneTree);
    handleArtificialTree(operTree);
    Node operNode;
    if (isIncrement) {
        operNode = new NumericalAdditionNode(operTree, exprRHS, one);
    } else {
        operNode = new NumericalSubtractionNode(operTree, exprRHS, one);
    }
    operNode.setInSource(false);
    extendWithNode(operNode);
    Node narrowed = narrowAndBox(operNode, exprType);
    if (target == null) {
        target = treeBuilder.buildAssignment(exprTree, (ExpressionTree) narrowed.getTree());
        handleArtificialTree(target);
    }
    AssignmentNode assignNode = new AssignmentNode(target, expr, narrowed);
    assignNode.setInSource(false);
    extendWithNode(assignNode);
    return assignNode;
}
Also used : AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) TypeMirror(javax.lang.model.type.TypeMirror) 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) BinaryTree(com.sun.source.tree.BinaryTree) 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) LiteralTree(com.sun.source.tree.LiteralTree) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode)

Example 15 with BinaryTree

use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.

the class JavaExpression method fromTree.

/**
 * Converts a javac {@link ExpressionTree} to a CF JavaExpression. The result might contain {@link
 * Unknown}.
 *
 * <p>We ignore operations such as widening and narrowing when computing the JavaExpression.
 *
 * @param tree a javac tree
 * @return a JavaExpression for the given javac tree
 */
public static JavaExpression fromTree(ExpressionTree tree) {
    JavaExpression result;
    switch(tree.getKind()) {
        case ARRAY_ACCESS:
            ArrayAccessTree a = (ArrayAccessTree) tree;
            JavaExpression arrayAccessExpression = fromTree(a.getExpression());
            JavaExpression index = fromTree(a.getIndex());
            result = new ArrayAccess(TreeUtils.typeOf(a), arrayAccessExpression, index);
            break;
        case BOOLEAN_LITERAL:
        case CHAR_LITERAL:
        case DOUBLE_LITERAL:
        case FLOAT_LITERAL:
        case INT_LITERAL:
        case LONG_LITERAL:
        case NULL_LITERAL:
        case STRING_LITERAL:
            LiteralTree vn = (LiteralTree) tree;
            result = new ValueLiteral(TreeUtils.typeOf(tree), vn.getValue());
            break;
        case NEW_ARRAY:
            NewArrayTree newArrayTree = (NewArrayTree) tree;
            List<@Nullable JavaExpression> dimensions;
            if (newArrayTree.getDimensions() == null) {
                dimensions = Collections.emptyList();
            } else {
                dimensions = new ArrayList<>(newArrayTree.getDimensions().size());
                for (ExpressionTree dimension : newArrayTree.getDimensions()) {
                    dimensions.add(fromTree(dimension));
                }
            }
            List<JavaExpression> initializers;
            if (newArrayTree.getInitializers() == null) {
                initializers = Collections.emptyList();
            } else {
                initializers = new ArrayList<>(newArrayTree.getInitializers().size());
                for (ExpressionTree initializer : newArrayTree.getInitializers()) {
                    initializers.add(fromTree(initializer));
                }
            }
            result = new ArrayCreation(TreeUtils.typeOf(tree), dimensions, initializers);
            break;
        case METHOD_INVOCATION:
            MethodInvocationTree mn = (MethodInvocationTree) tree;
            assert TreeUtils.isUseOfElement(mn) : "@AssumeAssertion(nullness): tree kind";
            ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn);
            // Note that the method might be nondeterministic.
            List<JavaExpression> parameters = CollectionsPlume.mapList(JavaExpression::fromTree, mn.getArguments());
            JavaExpression methodReceiver;
            if (ElementUtils.isStatic(invokedMethod)) {
                @SuppressWarnings(// enclosingTypeElement(ExecutableElement): @NonNull
                "nullness:assignment") @NonNull TypeElement methodType = ElementUtils.enclosingTypeElement(invokedMethod);
                methodReceiver = new ClassName(methodType.asType());
            } else {
                methodReceiver = getReceiver(mn);
            }
            TypeMirror resultType = TreeUtils.typeOf(mn);
            result = new MethodCall(resultType, invokedMethod, methodReceiver, parameters);
            break;
        case MEMBER_SELECT:
            result = fromMemberSelect((MemberSelectTree) tree);
            break;
        case IDENTIFIER:
            IdentifierTree identifierTree = (IdentifierTree) tree;
            TypeMirror typeOfId = TreeUtils.typeOf(identifierTree);
            Name identifierName = identifierTree.getName();
            if (identifierName.contentEquals("this") || identifierName.contentEquals("super")) {
                result = new ThisReference(typeOfId);
                break;
            }
            assert TreeUtils.isUseOfElement(identifierTree) : "@AssumeAssertion(nullness): tree kind";
            Element ele = TreeUtils.elementFromUse(identifierTree);
            if (ElementUtils.isTypeElement(ele)) {
                result = new ClassName(ele.asType());
                break;
            }
            result = fromVariableElement(typeOfId, ele);
            break;
        case UNARY_PLUS:
            return fromTree(((UnaryTree) tree).getExpression());
        case BITWISE_COMPLEMENT:
        case LOGICAL_COMPLEMENT:
        case POSTFIX_DECREMENT:
        case POSTFIX_INCREMENT:
        case PREFIX_DECREMENT:
        case PREFIX_INCREMENT:
        case UNARY_MINUS:
            JavaExpression operand = fromTree(((UnaryTree) tree).getExpression());
            return new UnaryOperation(TreeUtils.typeOf(tree), tree.getKind(), operand);
        case CONDITIONAL_AND:
        case CONDITIONAL_OR:
        case DIVIDE:
        case EQUAL_TO:
        case GREATER_THAN:
        case GREATER_THAN_EQUAL:
        case LEFT_SHIFT:
        case LESS_THAN:
        case LESS_THAN_EQUAL:
        case MINUS:
        case MULTIPLY:
        case NOT_EQUAL_TO:
        case OR:
        case PLUS:
        case REMAINDER:
        case RIGHT_SHIFT:
        case UNSIGNED_RIGHT_SHIFT:
        case XOR:
            BinaryTree binaryTree = (BinaryTree) tree;
            JavaExpression left = fromTree(binaryTree.getLeftOperand());
            JavaExpression right = fromTree(binaryTree.getRightOperand());
            return new BinaryOperation(TreeUtils.typeOf(tree), tree.getKind(), left, right);
        default:
            result = null;
    }
    if (result == null) {
        result = new Unknown(tree);
    }
    return result;
}
Also used : ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) ExecutableElement(javax.lang.model.element.ExecutableElement) MemberSelectTree(com.sun.source.tree.MemberSelectTree) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) BinaryTree(com.sun.source.tree.BinaryTree) IdentifierTree(com.sun.source.tree.IdentifierTree) LiteralTree(com.sun.source.tree.LiteralTree) Name(javax.lang.model.element.Name) TypeMirror(javax.lang.model.type.TypeMirror) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) NonNull(org.checkerframework.checker.nullness.qual.NonNull) ExpressionTree(com.sun.source.tree.ExpressionTree) TypeElement(javax.lang.model.element.TypeElement) NewArrayTree(com.sun.source.tree.NewArrayTree)

Aggregations

BinaryTree (com.sun.source.tree.BinaryTree)30 ExpressionTree (com.sun.source.tree.ExpressionTree)26 Tree (com.sun.source.tree.Tree)17 LiteralTree (com.sun.source.tree.LiteralTree)15 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)13 IdentifierTree (com.sun.source.tree.IdentifierTree)11 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)11 MemberSelectTree (com.sun.source.tree.MemberSelectTree)10 ClassTree (com.sun.source.tree.ClassTree)9 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)9 TypeCastTree (com.sun.source.tree.TypeCastTree)9 MethodTree (com.sun.source.tree.MethodTree)8 PrimitiveTypeTree (com.sun.source.tree.PrimitiveTypeTree)8 VariableTree (com.sun.source.tree.VariableTree)8 AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)6 BlockTree (com.sun.source.tree.BlockTree)6 ReturnTree (com.sun.source.tree.ReturnTree)6 StatementTree (com.sun.source.tree.StatementTree)6 TypeMirror (javax.lang.model.type.TypeMirror)6 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)5