Search in sources :

Example 6 with FieldAccess

use of org.checkerframework.dataflow.expression.FieldAccess 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 7 with FieldAccess

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

the class LessThanAnnotatedTypeFactory method getMinValueFromString.

/**
 * Returns the minimum value of {@code expression} at {@code tree}.
 *
 * @param expression the expression whose minimum value to retrieve
 * @param tree where to determine the value
 * @param path the path to {@code tree}
 * @return the minimum value of {@code expression} at {@code tree}
 */
private long getMinValueFromString(String expression, Tree tree, TreePath path) {
    ValueAnnotatedTypeFactory valueAtypeFactory = getValueAnnotatedTypeFactory();
    JavaExpression expressionJe;
    try {
        expressionJe = valueAtypeFactory.parseJavaExpressionString(expression, path);
    } catch (JavaExpressionParseException e) {
        return Long.MIN_VALUE;
    }
    AnnotationMirror intRange = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, IntRange.class);
    if (intRange != null) {
        return valueAtypeFactory.getRange(intRange).from;
    }
    AnnotationMirror intValue = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, IntVal.class);
    if (intValue != null) {
        List<Long> possibleValues = valueAtypeFactory.getIntValues(intValue);
        return Collections.min(possibleValues);
    }
    if (expressionJe instanceof FieldAccess) {
        FieldAccess fieldAccess = ((FieldAccess) expressionJe);
        if (fieldAccess.getReceiver().getType().getKind() == TypeKind.ARRAY) {
            // array.length might not be in the store, so check for the length of the array.
            AnnotationMirror arrayRange = valueAtypeFactory.getAnnotationFromJavaExpression(fieldAccess.getReceiver(), tree, ArrayLenRange.class);
            if (arrayRange != null) {
                return valueAtypeFactory.getRange(arrayRange).from;
            }
            AnnotationMirror arrayLen = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, ArrayLen.class);
            if (arrayLen != null) {
                List<Integer> possibleValues = valueAtypeFactory.getArrayLength(arrayLen);
                return Collections.min(possibleValues);
            }
            // Even arrays that we know nothing about must have at least zero length.
            return 0;
        }
    }
    return Long.MIN_VALUE;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ValueAnnotatedTypeFactory(org.checkerframework.common.value.ValueAnnotatedTypeFactory)

Example 8 with FieldAccess

use of org.checkerframework.dataflow.expression.FieldAccess 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)

Example 9 with FieldAccess

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

the class CFAbstractStore method removeConflicting.

/**
 * Remove any information in this store that might not be true any more after {@code fieldAccess}
 * has been assigned a new value (with the abstract value {@code val}). This includes the
 * following steps (assume that {@code fieldAccess} is of the form <em>a.f</em> for some
 * <em>a</em>.
 *
 * <ol>
 *   <li value="1">Update the abstract value of other field accesses <em>b.g</em> where the field
 *       is equal (that is, <em>f=g</em>), and the receiver <em>b</em> might alias the receiver of
 *       {@code fieldAccess}, <em>a</em>. This update will raise the abstract value for such field
 *       accesses to at least {@code val} (or the old value, if that was less precise). However,
 *       this is only necessary if the field <em>g</em> is not final.
 *   <li value="2">Remove any abstract values for field accesses <em>b.g</em> where {@code
 *       fieldAccess} might alias any expression in the receiver <em>b</em>.
 *   <li value="3">Remove any information about method calls.
 *   <li value="4">Remove any abstract values an array access <em>b[i]</em> where {@code
 *       fieldAccess} might alias any expression in the receiver <em>a</em> or index <em>i</em>.
 * </ol>
 *
 * @param val the abstract value of the value assigned to {@code n} (or {@code null} if the
 *     abstract value is not known).
 */
protected void removeConflicting(FieldAccess fieldAccess, @Nullable V val) {
    final Iterator<Map.Entry<FieldAccess, V>> fieldValuesIterator = fieldValues.entrySet().iterator();
    while (fieldValuesIterator.hasNext()) {
        Map.Entry<FieldAccess, V> entry = fieldValuesIterator.next();
        FieldAccess otherFieldAccess = entry.getKey();
        V otherVal = entry.getValue();
        // case 2:
        if (otherFieldAccess.getReceiver().containsModifiableAliasOf(this, fieldAccess)) {
            // remove information completely
            fieldValuesIterator.remove();
        } else // case 1:
        if (fieldAccess.getField().equals(otherFieldAccess.getField())) {
            if (canAlias(fieldAccess.getReceiver(), otherFieldAccess.getReceiver())) {
                if (!otherFieldAccess.isFinal()) {
                    if (val != null) {
                        V newVal = val.leastUpperBound(otherVal);
                        entry.setValue(newVal);
                    } else {
                        // remove information completely
                        fieldValuesIterator.remove();
                    }
                }
            }
        }
    }
    final Iterator<Map.Entry<ArrayAccess, V>> arrayValuesIterator = arrayValues.entrySet().iterator();
    while (arrayValuesIterator.hasNext()) {
        Map.Entry<ArrayAccess, V> entry = arrayValuesIterator.next();
        ArrayAccess otherArrayAccess = entry.getKey();
        if (otherArrayAccess.containsModifiableAliasOf(this, fieldAccess)) {
            // remove information completely
            arrayValuesIterator.remove();
        }
    }
    // case 3:
    methodValues.clear();
}
Also used : ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) HashMap(java.util.HashMap) Map(java.util.Map)

Example 10 with FieldAccess

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

the class CFAbstractStore method removeConflicting.

/**
 * Remove any information in the store that might not be true any more after {@code arrayAccess}
 * has been assigned a new value (with the abstract value {@code val}). This includes the
 * following steps (assume that {@code arrayAccess} is of the form <em>a[i]</em> for some
 * <em>a</em>.
 *
 * <ol>
 *   <li value="1">Remove any abstract value for other array access <em>b[j]</em> where <em>a</em>
 *       and <em>b</em> can be aliases, or where either <em>b</em> or <em>j</em> contains a
 *       modifiable alias of <em>a[i]</em>.
 *   <li value="2">Remove any abstract values for field accesses <em>b.g</em> where <em>a[i]</em>
 *       might alias any expression in the receiver <em>b</em> and there is an array expression
 *       somewhere in the receiver.
 *   <li value="3">Remove any information about method calls.
 * </ol>
 *
 * @param val the abstract value of the value assigned to {@code n} (or {@code null} if the
 *     abstract value is not known).
 */
protected void removeConflicting(ArrayAccess arrayAccess, @Nullable V val) {
    final Iterator<Map.Entry<ArrayAccess, V>> arrayValuesIterator = arrayValues.entrySet().iterator();
    while (arrayValuesIterator.hasNext()) {
        Map.Entry<ArrayAccess, V> entry = arrayValuesIterator.next();
        ArrayAccess otherArrayAccess = entry.getKey();
        // case 1:
        if (otherArrayAccess.containsModifiableAliasOf(this, arrayAccess)) {
            // remove information completely
            arrayValuesIterator.remove();
        } else if (canAlias(arrayAccess.getArray(), otherArrayAccess.getArray())) {
            // TODO: one could be less strict here, and only raise the abstract
            // value for all array expressions with potentially aliasing receivers.
            // remove information completely
            arrayValuesIterator.remove();
        }
    }
    // case 2:
    final Iterator<Map.Entry<FieldAccess, V>> fieldValuesIterator = fieldValues.entrySet().iterator();
    while (fieldValuesIterator.hasNext()) {
        Map.Entry<FieldAccess, V> entry = fieldValuesIterator.next();
        FieldAccess otherFieldAccess = entry.getKey();
        JavaExpression otherReceiver = otherFieldAccess.getReceiver();
        if (otherReceiver.containsModifiableAliasOf(this, arrayAccess) && otherReceiver.containsOfClass(ArrayAccess.class)) {
            // remove information completely
            fieldValuesIterator.remove();
        }
    }
    // case 3:
    methodValues.clear();
}
Also used : ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)26 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)11 ClassName (org.checkerframework.dataflow.expression.ClassName)10 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)9 MethodCall (org.checkerframework.dataflow.expression.MethodCall)9 HashMap (java.util.HashMap)8 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)8 Map (java.util.Map)7 ThisReference (org.checkerframework.dataflow.expression.ThisReference)7 AnnotationMirror (javax.lang.model.element.AnnotationMirror)5 CFValue (org.checkerframework.framework.flow.CFValue)5 Element (javax.lang.model.element.Element)4 ExecutableElement (javax.lang.model.element.ExecutableElement)4 VariableElement (javax.lang.model.element.VariableElement)4 JavaExpressionParseException (org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)3 MethodTree (com.sun.source.tree.MethodTree)2 Tree (com.sun.source.tree.Tree)2 ArrayList (java.util.ArrayList)2 TypeElement (javax.lang.model.element.TypeElement)2 CFStore (org.checkerframework.framework.flow.CFStore)2