Search in sources :

Example 1 with MethodCall

use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.

the class JavaExpressionOptimizer method visitMethodCall.

@Override
protected JavaExpression visitMethodCall(MethodCall methodCallExpr, Void unused) {
    JavaExpression optReceiver = convert(methodCallExpr.getReceiver());
    List<JavaExpression> optArguments = convert(methodCallExpr.getArguments());
    // Length of string literal: convert it to an integer literal.
    if (methodCallExpr.getElement().getSimpleName().contentEquals("length") && optReceiver instanceof ValueLiteral) {
        Object value = ((ValueLiteral) optReceiver).getValue();
        if (value instanceof String) {
            return new ValueLiteral(factory.types.getPrimitiveType(TypeKind.INT), ((String) value).length());
        }
    }
    return new MethodCall(methodCallExpr.getType(), methodCallExpr.getElement(), optReceiver, optArguments);
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) ValueLiteral(org.checkerframework.dataflow.expression.ValueLiteral) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 2 with MethodCall

use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.

the class UpperBoundTransfer method refineNeqSequenceLength.

/**
 * If lengthAccess node is an sequence length field or method access (optionally with a constant
 * offset subtracted) and the other node is less than or equal to that sequence length (minus the
 * offset), then refine the other node's type to less than the sequence length (minus the offset).
 * This is case 12.
 */
private void refineNeqSequenceLength(Node lengthAccess, Node otherNode, AnnotationMirror otherNodeAnno, CFStore store) {
    // If lengthAccess is "receiver.length - c" where c is an integer constant,
    // then lengthOffset is "c".
    int lengthOffset = 0;
    if (lengthAccess instanceof NumericalSubtractionNode) {
        NumericalSubtractionNode subtraction = (NumericalSubtractionNode) lengthAccess;
        Node offsetNode = subtraction.getRightOperand();
        Long offsetValue = ValueCheckerUtils.getExactValue(offsetNode.getTree(), atypeFactory.getValueAnnotatedTypeFactory());
        if (offsetValue != null && offsetValue > Integer.MIN_VALUE && offsetValue <= Integer.MAX_VALUE) {
            lengthOffset = offsetValue.intValue();
            lengthAccess = subtraction.getLeftOperand();
        } else {
            // Subtraction of non-constant expressions is not supported
            return;
        }
    }
    JavaExpression receiver = null;
    if (NodeUtils.isArrayLengthFieldAccess(lengthAccess)) {
        FieldAccess fa = (FieldAccess) JavaExpression.fromNodeFieldAccess((FieldAccessNode) lengthAccess);
        receiver = fa.getReceiver();
    } else if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(lengthAccess)) {
        JavaExpression ma = JavaExpression.fromNode(lengthAccess);
        if (ma instanceof MethodCall) {
            receiver = ((MethodCall) ma).getReceiver();
        }
    }
    if (receiver != null && !receiver.containsUnknown()) {
        UBQualifier otherQualifier = UBQualifier.createUBQualifier(otherNodeAnno, (UpperBoundChecker) atypeFactory.getChecker());
        String sequence = receiver.toString();
        // Check if otherNode + c - 1 < receiver.length
        if (otherQualifier.hasSequenceWithOffset(sequence, lengthOffset - 1)) {
            // Add otherNode + c < receiver.length
            UBQualifier newQualifier = UBQualifier.createUBQualifier(sequence, Integer.toString(lengthOffset));
            otherQualifier = otherQualifier.glb(newQualifier);
            for (Node internal : splitAssignments(otherNode)) {
                JavaExpression leftJe = JavaExpression.fromNode(internal);
                store.insertValue(leftJe, atypeFactory.convertUBQualifierToAnnotation(otherQualifier));
            }
        }
    }
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) NumericalMultiplicationNode(org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) CaseNode(org.checkerframework.dataflow.cfg.node.CaseNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) IntegerLiteralNode(org.checkerframework.dataflow.cfg.node.IntegerLiteralNode) Node(org.checkerframework.dataflow.cfg.node.Node) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) MethodCall(org.checkerframework.dataflow.expression.MethodCall) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode)

Example 3 with MethodCall

use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.

the class UpperBoundTransfer method visitMethodInvocation.

/**
 * If n is a String.length() method invocation, then the type of s.length() is the glb
 * of @LTEqLengthOf("s") and the value of s.length() in the store. This is case 20.
 */
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
    if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(n)) {
        JavaExpression stringLength = JavaExpression.fromNode(n);
        if (stringLength instanceof MethodCall) {
            JavaExpression receiverJe = ((MethodCall) stringLength).getReceiver();
            Tree receiverTree = n.getTarget().getReceiver().getTree();
            // receiverTree is null when the receiver is implicit "this".
            if (receiverTree != null) {
                TransferResult<CFValue, CFStore> result = visitLengthAccess(n, in, receiverJe, receiverTree);
                if (result != null) {
                    return result;
                }
            }
        }
    }
    return super.visitMethodInvocation(n, in);
}
Also used : CFValue(org.checkerframework.framework.flow.CFValue) CFStore(org.checkerframework.framework.flow.CFStore) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) Tree(com.sun.source.tree.Tree) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 4 with MethodCall

use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.

the class LockStore method insertLockPossiblyHeld.

/*
   * Insert an annotation exactly, without regard to whether an annotation was already present.
   * This is only done for @LockPossiblyHeld. This is not sound for other type qualifiers.
   */
public void insertLockPossiblyHeld(JavaExpression je) {
    if (je.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (je instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) je;
        CFValue current = localVariableValues.get(localVar);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            localVariableValues.put(localVar, value);
        }
    } else if (je instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) je;
        CFValue current = fieldValues.get(fieldAcc);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            fieldValues.put(fieldAcc, value);
        }
    } else if (je instanceof MethodCall) {
        MethodCall method = (MethodCall) je;
        CFValue current = methodValues.get(method);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            methodValues.put(method, value);
        }
    } else if (je instanceof ArrayAccess) {
        ArrayAccess arrayAccess = (ArrayAccess) je;
        CFValue current = arrayValues.get(arrayAccess);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            arrayValues.put(arrayAccess, value);
        }
    } else if (je instanceof ThisReference) {
        thisValue = changeLockAnnoToTop(je, thisValue);
    } else if (je instanceof ClassName) {
        ClassName className = (ClassName) je;
        CFValue current = classValues.get(className);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            classValues.put(className, value);
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : CFValue(org.checkerframework.framework.flow.CFValue) ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 5 with MethodCall

use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.

the class CFAbstractStore method computeNewValueAndInsert.

/**
 * Inserts the result of applying {@code merger} to {@code value} and the previous value for
 * {@code expr}.
 *
 * @param expr the JavaExpression
 * @param value the value of the JavaExpression
 * @param merger the function used to merge {@code value} and the previous value of {@code expr}
 * @param permitNondeterministic if false, does nothing if {@code expr} is nondeterministic; if
 *     true, permits nondeterministic expressions to be placed in the store
 */
protected void computeNewValueAndInsert(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) {
    if (!shouldInsert(expr, value, permitNondeterministic)) {
        return;
    }
    if (expr instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) expr;
        V oldValue = localVariableValues.get(localVar);
        V newValue = merger.apply(oldValue, value);
        if (newValue != null) {
            localVariableValues.put(localVar, newValue);
        }
    } else if (expr instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) expr;
        // Only store information about final fields (where the receiver is
        // also fixed) if concurrent semantics are enabled.
        boolean isMonotonic = isMonotonicUpdate(fieldAcc, value);
        if (sequentialSemantics || isMonotonic || fieldAcc.isUnassignableByOtherCode()) {
            V oldValue = fieldValues.get(fieldAcc);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                fieldValues.put(fieldAcc, newValue);
            }
        }
    } else if (expr instanceof MethodCall) {
        MethodCall method = (MethodCall) expr;
        // Don't store any information if concurrent semantics are enabled.
        if (sequentialSemantics) {
            V oldValue = methodValues.get(method);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                methodValues.put(method, newValue);
            }
        }
    } else if (expr instanceof ArrayAccess) {
        ArrayAccess arrayAccess = (ArrayAccess) expr;
        if (sequentialSemantics) {
            V oldValue = arrayValues.get(arrayAccess);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                arrayValues.put(arrayAccess, newValue);
            }
        }
    } else if (expr instanceof ThisReference) {
        ThisReference thisRef = (ThisReference) expr;
        if (sequentialSemantics || thisRef.isUnassignableByOtherCode()) {
            V oldValue = thisValue;
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                thisValue = newValue;
            }
        }
    } else if (expr instanceof ClassName) {
        ClassName className = (ClassName) expr;
        if (sequentialSemantics || className.isUnassignableByOtherCode()) {
            V oldValue = classValues.get(className);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                classValues.put(className, newValue);
            }
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Aggregations

MethodCall (org.checkerframework.dataflow.expression.MethodCall)11 FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)9 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)6 ClassName (org.checkerframework.dataflow.expression.ClassName)6 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)6 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 ThisReference (org.checkerframework.dataflow.expression.ThisReference)3 CFValue (org.checkerframework.framework.flow.CFValue)3 Tree (com.sun.source.tree.Tree)1 ArrayCreationNode (org.checkerframework.dataflow.cfg.node.ArrayCreationNode)1 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)1 CaseNode (org.checkerframework.dataflow.cfg.node.CaseNode)1 FieldAccessNode (org.checkerframework.dataflow.cfg.node.FieldAccessNode)1 IntegerLiteralNode (org.checkerframework.dataflow.cfg.node.IntegerLiteralNode)1 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)1 Node (org.checkerframework.dataflow.cfg.node.Node)1 NumericalAdditionNode (org.checkerframework.dataflow.cfg.node.NumericalAdditionNode)1 NumericalMultiplicationNode (org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode)1