Search in sources :

Example 6 with FieldAccess

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

the class InitializationTransfer method visitAssignment.

@Override
public TransferResult<V, S> visitAssignment(AssignmentNode n, TransferInput<V, S> in) {
    TransferResult<V, S> result = super.visitAssignment(n, in);
    assert result instanceof RegularTransferResult;
    Receiver expr = FlowExpressions.internalReprOf(analysis.getTypeFactory(), n.getTarget());
    // initialized.
    if (!expr.containsUnknown()) {
        if (expr instanceof FieldAccess) {
            FieldAccess fa = (FieldAccess) expr;
            result.getRegularStore().addInitializedField(fa);
        }
    }
    return result;
}
Also used : Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) RegularTransferResult(org.checkerframework.dataflow.analysis.RegularTransferResult)

Example 7 with FieldAccess

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

the class InitializationVisitor method checkContract.

@Override
protected boolean checkContract(Receiver expr, AnnotationMirror necessaryAnnotation, AnnotationMirror inferredAnnotation, CFAbstractStore<?, ?> store) {
    // also use the information about initialized fields to check contracts
    final AnnotationMirror invariantAnno = atypeFactory.getFieldInvariantAnnotation();
    if (atypeFactory.getQualifierHierarchy().isSubtype(invariantAnno, necessaryAnnotation)) {
        if (expr instanceof FieldAccess) {
            FieldAccess fa = (FieldAccess) expr;
            if (fa.getReceiver() instanceof ThisReference || fa.getReceiver() instanceof ClassName) {
                @SuppressWarnings("unchecked") Store s = (Store) store;
                if (s.isFieldInitialized(fa.getField())) {
                    AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(fa.getField());
                    // is this an invariant-field?
                    if (AnnotationUtils.containsSame(fieldType.getAnnotations(), invariantAnno)) {
                        return true;
                    }
                }
            } else {
                Set<AnnotationMirror> recvAnnoSet;
                @SuppressWarnings("unchecked") Value value = (Value) store.getValue(fa.getReceiver());
                if (value != null) {
                    recvAnnoSet = value.getAnnotations();
                } else if (fa.getReceiver() instanceof LocalVariable) {
                    Element elem = ((LocalVariable) fa.getReceiver()).getElement();
                    AnnotatedTypeMirror recvType = atypeFactory.getAnnotatedType(elem);
                    recvAnnoSet = recvType.getAnnotations();
                } else {
                    // Is there anything better we could do?
                    return false;
                }
                boolean isRecvCommitted = false;
                for (AnnotationMirror anno : recvAnnoSet) {
                    if (atypeFactory.isCommitted(anno)) {
                        isRecvCommitted = true;
                    }
                }
                AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(fa.getField());
                // has the invariant type.
                if (isRecvCommitted && AnnotationUtils.containsSame(fieldType.getAnnotations(), invariantAnno)) {
                    return true;
                }
            }
        }
    }
    return super.checkContract(expr, necessaryAnnotation, inferredAnnotation, store);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) VariableElement(javax.lang.model.element.VariableElement) Element(javax.lang.model.element.Element) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) CFAbstractValue(org.checkerframework.framework.flow.CFAbstractValue) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ThisReference(org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 8 with FieldAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.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(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 9 with FieldAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.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(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)

Example 10 with FieldAccess

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

the class CFAbstractStore method updateForMethodCall.

/* --------------------------------------------------------- */
/* Handling of fields */
/* --------------------------------------------------------- */
/**
 * Remove any information that might not be valid any more after a method call, and add
 * information guaranteed by the method.
 *
 * <ol>
 *   <li>If the method is side-effect-free (as indicated by {@link
 *       org.checkerframework.dataflow.qual.SideEffectFree} or {@link
 *       org.checkerframework.dataflow.qual.Pure}), then no information needs to be removed.
 *   <li>Otherwise, all information about field accesses {@code a.f} needs to be removed, except
 *       if the method {@code n} cannot modify {@code a.f} (e.g., if {@code a} is a local
 *       variable or {@code this}, and {@code f} is final).
 *   <li>Furthermore, if the field has a monotonic annotation, then its information can also be
 *       kept.
 * </ol>
 *
 * Furthermore, if the method is deterministic, we store its result {@code val} in the store.
 */
public void updateForMethodCall(MethodInvocationNode n, AnnotatedTypeFactory atypeFactory, V val) {
    ExecutableElement method = n.getTarget().getMethod();
    // case 1: remove information if necessary
    if (!(analysis.checker.hasOption("assumeSideEffectFree") || isSideEffectFree(atypeFactory, method))) {
        // update field values
        Map<FlowExpressions.FieldAccess, V> newFieldValues = new HashMap<>();
        for (Entry<FlowExpressions.FieldAccess, V> e : fieldValues.entrySet()) {
            FlowExpressions.FieldAccess fieldAccess = e.getKey();
            V otherVal = e.getValue();
            // case 3:
            List<Pair<AnnotationMirror, AnnotationMirror>> fieldAnnotations = atypeFactory.getAnnotationWithMetaAnnotation(fieldAccess.getField(), MonotonicQualifier.class);
            V newOtherVal = null;
            for (Pair<AnnotationMirror, AnnotationMirror> fieldAnnotation : fieldAnnotations) {
                AnnotationMirror monotonicAnnotation = fieldAnnotation.second;
                Name annotation = AnnotationUtils.getElementValueClassName(monotonicAnnotation, "value", false);
                AnnotationMirror target = AnnotationBuilder.fromName(atypeFactory.getElementUtils(), annotation);
                // Make sure the 'target' annotation is present.
                if (AnnotationUtils.containsSame(otherVal.getAnnotations(), target)) {
                    newOtherVal = analysis.createSingleAnnotationValue(target, otherVal.getUnderlyingType()).mostSpecific(newOtherVal, null);
                }
            }
            if (newOtherVal != null) {
                // keep information for all hierarchies where we had a
                // monotone annotation.
                newFieldValues.put(fieldAccess, newOtherVal);
                continue;
            }
            // case 2:
            if (!fieldAccess.isUnmodifiableByOtherCode()) {
                // remove information completely
                continue;
            }
            // keep information
            newFieldValues.put(fieldAccess, otherVal);
        }
        fieldValues = newFieldValues;
        // update method values
        methodValues.clear();
        arrayValues.clear();
    }
    // store information about method call if possible
    Receiver methodCall = FlowExpressions.internalReprOf(analysis.getTypeFactory(), n);
    replaceValue(methodCall, val);
}
Also used : HashMap(java.util.HashMap) ExecutableElement(javax.lang.model.element.ExecutableElement) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) Name(javax.lang.model.element.Name) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) AnnotationMirror(javax.lang.model.element.AnnotationMirror) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) Pair(org.checkerframework.javacutil.Pair)

Aggregations

FieldAccess (org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)16 Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)8 ClassName (org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)6 HashMap (java.util.HashMap)5 VariableElement (javax.lang.model.element.VariableElement)5 AnnotationMirror (javax.lang.model.element.AnnotationMirror)4 Element (javax.lang.model.element.Element)4 LocalVariable (org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable)4 ThisReference (org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference)4 ExecutableElement (javax.lang.model.element.ExecutableElement)3 FlowExpressions (org.checkerframework.dataflow.analysis.FlowExpressions)3 CFValue (org.checkerframework.framework.flow.CFValue)3 Tree (com.sun.source.tree.Tree)2 TypeElement (javax.lang.model.element.TypeElement)2 TypeMirror (javax.lang.model.type.TypeMirror)2 ArrayAccess (org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess)2 MethodCall (org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall)2 CFAbstractStore (org.checkerframework.framework.flow.CFAbstractStore)2 CFAbstractValue (org.checkerframework.framework.flow.CFAbstractValue)2 CFStore (org.checkerframework.framework.flow.CFStore)2