Search in sources :

Example 1 with FieldAccess

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

the class CFAbstractTransfer method addFieldValues.

private void addFieldValues(S info, AnnotatedTypeFactory factory, ClassTree classTree, MethodTree methodTree) {
    // Add knowledge about final fields, or values of non-final fields
    // if we are inside a constructor (information about initializers)
    TypeMirror classType = TreeUtils.typeOf(classTree);
    List<Pair<VariableElement, V>> fieldValues = analysis.getFieldValues();
    for (Pair<VariableElement, V> p : fieldValues) {
        VariableElement element = p.first;
        V value = p.second;
        if (ElementUtils.isFinal(element) || TreeUtils.isConstructor(methodTree)) {
            Receiver receiver;
            if (ElementUtils.isStatic(element)) {
                receiver = new ClassName(classType);
            } else {
                receiver = new ThisReference(classType);
            }
            TypeMirror fieldType = ElementUtils.getType(element);
            Receiver field = new FieldAccess(receiver, fieldType, element);
            info.insertValue(field, value);
        }
    }
    // add properties about fields (static information from type)
    boolean isNotFullyInitializedReceiver = isNotFullyInitializedReceiver(methodTree);
    if (isNotFullyInitializedReceiver && !TreeUtils.isConstructor(methodTree)) {
        // and the method isn't a constructor
        return;
    }
    for (Tree member : classTree.getMembers()) {
        if (member instanceof VariableTree) {
            VariableTree vt = (VariableTree) member;
            final VariableElement element = TreeUtils.elementFromDeclaration(vt);
            AnnotatedTypeMirror type = ((GenericAnnotatedTypeFactory<?, ?, ?, ?>) factory).getAnnotatedTypeLhs(vt);
            TypeMirror fieldType = ElementUtils.getType(element);
            Receiver receiver;
            if (ElementUtils.isStatic(element)) {
                receiver = new ClassName(classType);
            } else {
                receiver = new ThisReference(classType);
            }
            V value = analysis.createAbstractValue(type);
            if (value == null)
                continue;
            if (TreeUtils.isConstructor(methodTree)) {
                // if we are in a constructor,
                // then we can still use the static type, but only
                // if there is also an initializer that already does
                // some initialization.
                boolean found = false;
                for (Pair<VariableElement, V> fieldValue : fieldValues) {
                    if (fieldValue.first.equals(element)) {
                        value = value.leastUpperBound(fieldValue.second);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    // no initializer found, cannot use static type
                    continue;
                }
            }
            Receiver field = new FieldAccess(receiver, fieldType, element);
            info.insertValue(field, value);
        }
    }
}
Also used : GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) VariableTree(com.sun.source.tree.VariableTree) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) VariableElement(javax.lang.model.element.VariableElement) ThisReference(org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) Pair(org.checkerframework.javacutil.Pair)

Example 2 with FieldAccess

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

the class FlowExpressionParseUtil method getReceiverField.

private static Receiver getReceiverField(String s, FlowExpressionContext context, boolean originalReceiver, VariableElement fieldElem) throws FlowExpressionParseException {
    TypeMirror receiverType = context.receiver.getType();
    TypeMirror fieldType = ElementUtils.getType(fieldElem);
    if (ElementUtils.isStatic(fieldElem)) {
        Element classElem = fieldElem.getEnclosingElement();
        Receiver staticClassReceiver = new ClassName(ElementUtils.getType(classElem));
        return new FieldAccess(staticClassReceiver, fieldType, fieldElem);
    }
    Receiver locationOfField;
    if (originalReceiver) {
        locationOfField = context.receiver;
    } else {
        locationOfField = FlowExpressions.internalReprOf(context.checkerContext.getAnnotationProvider(), new ImplicitThisLiteralNode(receiverType));
    }
    if (locationOfField instanceof ClassName) {
        throw constructParserException(s, "a non-static field cannot have a class name as a receiver.");
    }
    return new FieldAccess(locationOfField, fieldType, fieldElem);
}
Also used : ImplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ImplicitThisLiteralNode) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Example 3 with FieldAccess

use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess 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) {
    Receiver receiver = null;
    // If lengthAccess is "receiver.length - c" where c is an integer constant, stores c
    // into lengthOffset
    int lengthOffset = 0;
    if (lengthAccess instanceof NumericalSubtractionNode) {
        NumericalSubtractionNode subtraction = (NumericalSubtractionNode) lengthAccess;
        Node offsetNode = subtraction.getRightOperand();
        Long offsetValue = IndexUtil.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;
        }
    }
    if (NodeUtils.isArrayLengthFieldAccess(lengthAccess)) {
        FieldAccess fa = FlowExpressions.internalReprOfFieldAccess(atypeFactory, (FieldAccessNode) lengthAccess);
        receiver = fa.getReceiver();
    } else if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(lengthAccess)) {
        Receiver ma = FlowExpressions.internalReprOf(atypeFactory, lengthAccess);
        if (ma instanceof MethodCall) {
            receiver = ((MethodCall) ma).getReceiver();
        }
    }
    if (receiver != null && !receiver.containsUnknown()) {
        UBQualifier otherQualifier = UBQualifier.createUBQualifier(otherNodeAnno);
        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)) {
                Receiver leftRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
                store.insertValue(leftRec, atypeFactory.convertUBQualifierToAnnotation(otherQualifier));
            }
        }
    }
}
Also used : 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) Node(org.checkerframework.dataflow.cfg.node.Node) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode)

Example 4 with FieldAccess

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

the class InitializationStore method supersetOf.

@Override
protected boolean supersetOf(CFAbstractStore<V, S> o) {
    if (!(o instanceof InitializationStore)) {
        return false;
    }
    @SuppressWarnings("unchecked") S other = (S) o;
    for (Element field : other.initializedFields) {
        if (!initializedFields.contains(field)) {
            return false;
        }
    }
    for (FieldAccess invariantField : other.invariantFields.keySet()) {
        if (!invariantFields.containsKey(invariantField)) {
            return false;
        }
    }
    Map<FlowExpressions.FieldAccess, V> removedFieldValues = new HashMap<>();
    Map<FlowExpressions.FieldAccess, V> removedOtherFieldValues = new HashMap<>();
    try {
        // Remove invariant annotated fields to avoid performance issue reported in #1438.
        for (FieldAccess invariantField : invariantFields.keySet()) {
            V v = fieldValues.remove(invariantField);
            removedFieldValues.put(invariantField, v);
        }
        for (FieldAccess invariantField : other.invariantFields.keySet()) {
            V v = other.fieldValues.remove(invariantField);
            removedOtherFieldValues.put(invariantField, v);
        }
        return super.supersetOf(other);
    } finally {
        // Restore removed values.
        fieldValues.putAll(removedFieldValues);
        other.fieldValues.putAll(removedOtherFieldValues);
    }
}
Also used : HashMap(java.util.HashMap) VariableElement(javax.lang.model.element.VariableElement) Element(javax.lang.model.element.Element) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Example 5 with FieldAccess

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

the class InitializationStore method insertValue.

/**
 * {@inheritDoc}
 *
 * <p>If the receiver is a field, and has an invariant annotation, then it can be considered
 * initialized.
 */
@Override
public void insertValue(Receiver r, V value) {
    if (value == null) {
        // top and top is also the default value.
        return;
    }
    InitializationAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory = (InitializationAnnotatedTypeFactory<?, ?, ?, ?>) analysis.getTypeFactory();
    QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
    AnnotationMirror invariantAnno = atypeFactory.getFieldInvariantAnnotation();
    // Remember fields that have the 'invariant' annotation in the store.
    if (r instanceof FieldAccess) {
        FieldAccess fieldAccess = (FieldAccess) r;
        if (!fieldValues.containsKey(r)) {
            Set<AnnotationMirror> declaredAnnos = atypeFactory.getAnnotatedType(fieldAccess.getField()).getAnnotations();
            if (AnnotationUtils.containsSame(declaredAnnos, invariantAnno)) {
                if (!invariantFields.containsKey(fieldAccess)) {
                    invariantFields.put(fieldAccess, analysis.createSingleAnnotationValue(invariantAnno, r.getType()));
                }
            }
        }
    }
    super.insertValue(r, value);
    for (AnnotationMirror a : value.getAnnotations()) {
        if (qualifierHierarchy.isSubtype(a, invariantAnno)) {
            if (r instanceof FieldAccess) {
                FieldAccess fa = (FieldAccess) r;
                if (fa.getReceiver() instanceof ThisReference || fa.getReceiver() instanceof ClassName) {
                    addInitializedField(fa.getField());
                }
            }
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ThisReference(org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference)

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