Search in sources :

Example 1 with ArrayAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.

the class FlowExpressionParseUtil method parseArray.

private static Receiver parseArray(String s, FlowExpressionContext context, TreePath path) throws FlowExpressionParseException {
    Pair<Pair<String, String>, String> array = parseArray(s);
    if (array == null) {
        return null;
    }
    String receiverStr = array.first.first;
    String indexStr = array.first.second;
    Receiver receiver = parseHelper(receiverStr, context, path);
    FlowExpressionContext contextForIndex = context.copyAndUseOuterReceiver();
    Receiver index = parseHelper(indexStr, contextForIndex, path);
    TypeMirror receiverType = receiver.getType();
    if (!(receiverType instanceof ArrayType)) {
        throw constructParserException(s, String.format("receiver not an array: %s : %s", receiver, receiverType));
    }
    TypeMirror componentType = ((ArrayType) receiverType).getComponentType();
    ArrayAccess result = new ArrayAccess(componentType, receiver, index);
    return result;
}
Also used : ArrayType(com.sun.tools.javac.code.Type.ArrayType) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) TypeMirror(javax.lang.model.type.TypeMirror) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) Pair(org.checkerframework.javacutil.Pair)

Example 2 with ArrayAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.

the class CFAbstractStore method insertValue.

/**
 * Add the abstract value {@code value} for the expression {@code r} (correctly deciding where
 * to store the information depending on the type of the expression {@code r}).
 *
 * <p>This method does not take care of removing other information that might be influenced by
 * changes to certain parts of the state.
 *
 * <p>If there is already a value {@code v} present for {@code r}, then the stronger of the new
 * and old value are taken (according to the lattice). Note that this happens per hierarchy, and
 * if the store already contains information about a hierarchy for which {@code value} does not
 * contain information, then that information is preserved.
 */
public void insertValue(FlowExpressions.Receiver r, @Nullable V value) {
    if (value == null) {
        // top and top is also the default value.
        return;
    }
    if (r.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (r instanceof FlowExpressions.LocalVariable) {
        FlowExpressions.LocalVariable localVar = (FlowExpressions.LocalVariable) r;
        V oldValue = localVariableValues.get(localVar);
        V newValue = value.mostSpecific(oldValue, null);
        if (newValue != null) {
            localVariableValues.put(localVar, newValue);
        }
    } else if (r instanceof FlowExpressions.FieldAccess) {
        FlowExpressions.FieldAccess fieldAcc = (FlowExpressions.FieldAccess) r;
        // 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.isUnmodifiableByOtherCode()) {
            V oldValue = fieldValues.get(fieldAcc);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                fieldValues.put(fieldAcc, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.MethodCall) {
        FlowExpressions.MethodCall method = (FlowExpressions.MethodCall) r;
        // Don't store any information if concurrent semantics are enabled.
        if (sequentialSemantics) {
            V oldValue = methodValues.get(method);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                methodValues.put(method, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.ArrayAccess) {
        FlowExpressions.ArrayAccess arrayAccess = (ArrayAccess) r;
        if (sequentialSemantics) {
            V oldValue = arrayValues.get(arrayAccess);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                arrayValues.put(arrayAccess, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.ThisReference) {
        FlowExpressions.ThisReference thisRef = (FlowExpressions.ThisReference) r;
        if (sequentialSemantics || thisRef.isUnmodifiableByOtherCode()) {
            V oldValue = thisValue;
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                thisValue = newValue;
            }
        }
    } else if (r instanceof FlowExpressions.ClassName) {
        FlowExpressions.ClassName className = (FlowExpressions.ClassName) r;
        if (sequentialSemantics || className.isUnmodifiableByOtherCode()) {
            V oldValue = classValues.get(className);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                classValues.put(className, newValue);
            }
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Example 3 with ArrayAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess 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(FlowExpressions.ArrayAccess arrayAccess, @Nullable V val) {
    Map<FlowExpressions.ArrayAccess, V> newArrayValues = new HashMap<>();
    for (Entry<FlowExpressions.ArrayAccess, V> e : arrayValues.entrySet()) {
        FlowExpressions.ArrayAccess otherArrayAccess = e.getKey();
        V otherVal = e.getValue();
        // case 1:
        if (otherArrayAccess.containsModifiableAliasOf(this, arrayAccess)) {
            // remove information completely
            continue;
        }
        if (canAlias(arrayAccess.getReceiver(), otherArrayAccess.getReceiver())) {
            // remove information completely
            continue;
        }
        // information is save to be carried over
        newArrayValues.put(otherArrayAccess, otherVal);
    }
    arrayValues = newArrayValues;
    // case 2:
    Map<FlowExpressions.FieldAccess, V> newFieldValues = new HashMap<>();
    for (Entry<FieldAccess, V> e : fieldValues.entrySet()) {
        FlowExpressions.FieldAccess otherFieldAccess = e.getKey();
        V otherVal = e.getValue();
        Receiver receiver = otherFieldAccess.getReceiver();
        if (receiver.containsModifiableAliasOf(this, arrayAccess) && receiver.containsOfClass(ArrayAccess.class)) {
            // remove information completely
            continue;
        }
        newFieldValues.put(otherFieldAccess, otherVal);
    }
    fieldValues = newFieldValues;
    // case 3:
    methodValues = new HashMap<>();
}
Also used : HashMap(java.util.HashMap) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Example 4 with ArrayAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.

the class CFAbstractStore method clearValue.

/**
 * Remove any knowledge about the expression {@code r} (correctly deciding where to remove the
 * information depending on the type of the expression {@code r}).
 */
public void clearValue(FlowExpressions.Receiver r) {
    if (r.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (r instanceof FlowExpressions.LocalVariable) {
        FlowExpressions.LocalVariable localVar = (FlowExpressions.LocalVariable) r;
        localVariableValues.remove(localVar);
    } else if (r instanceof FlowExpressions.FieldAccess) {
        FlowExpressions.FieldAccess fieldAcc = (FlowExpressions.FieldAccess) r;
        fieldValues.remove(fieldAcc);
    } else if (r instanceof FlowExpressions.MethodCall) {
        MethodCall method = (MethodCall) r;
        methodValues.remove(method);
    } else if (r instanceof FlowExpressions.ArrayAccess) {
        ArrayAccess a = (ArrayAccess) r;
        arrayValues.remove(a);
    } else if (r instanceof FlowExpressions.ClassName) {
        FlowExpressions.ClassName c = (FlowExpressions.ClassName) r;
        classValues.remove(c);
    } else {
    // thisValue ...
    // No other types of expressions are stored.
    }
}
Also used : FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall)

Example 5 with ArrayAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess 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(FlowExpressions.FieldAccess fieldAccess, @Nullable V val) {
    Map<FlowExpressions.FieldAccess, V> newFieldValues = new HashMap<>();
    for (Entry<FlowExpressions.FieldAccess, V> e : fieldValues.entrySet()) {
        FlowExpressions.FieldAccess otherFieldAccess = e.getKey();
        V otherVal = e.getValue();
        // case 2:
        if (otherFieldAccess.getReceiver().containsModifiableAliasOf(this, fieldAccess)) {
            // remove information completely
            continue;
        }
        // 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);
                        newFieldValues.put(otherFieldAccess, newVal);
                    } else {
                    // remove information completely
                    }
                    continue;
                }
            }
        }
        // information is save to be carried over
        newFieldValues.put(otherFieldAccess, otherVal);
    }
    fieldValues = newFieldValues;
    Map<FlowExpressions.ArrayAccess, V> newArrayValues = new HashMap<>();
    for (Entry<ArrayAccess, V> e : arrayValues.entrySet()) {
        FlowExpressions.ArrayAccess otherArrayAccess = e.getKey();
        V otherVal = e.getValue();
        if (otherArrayAccess.containsModifiableAliasOf(this, fieldAccess)) {
            // remove information completely
            continue;
        }
        newArrayValues.put(otherArrayAccess, otherVal);
    }
    arrayValues = newArrayValues;
    // case 3:
    methodValues = new HashMap<>();
}
Also used : FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) HashMap(java.util.HashMap) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Aggregations

ArrayAccess (org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess)6 FlowExpressions (org.checkerframework.dataflow.analysis.FlowExpressions)5 FieldAccess (org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)5 LocalVariable (org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable)3 HashMap (java.util.HashMap)2 ClassName (org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)2 MethodCall (org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall)2 Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)2 ArrayType (com.sun.tools.javac.code.Type.ArrayType)1 TypeMirror (javax.lang.model.type.TypeMirror)1 CFValue (org.checkerframework.framework.flow.CFValue)1 Pair (org.checkerframework.javacutil.Pair)1