Search in sources :

Example 1 with CFAbstractStore

use of org.checkerframework.framework.flow.CFAbstractStore in project checker-framework by typetools.

the class BaseTypeVisitor method checkConditionalPostcondition.

/**
 * Check that the expression's type is annotated with {@code annotation} at every regular exit
 * that returns {@code result}
 *
 * @param node tree of method with the postcondition
 * @param annotation expression's type must have this annotation
 * @param expression the expression that the postcondition concerns
 * @param result result for which the postcondition is valid
 */
protected void checkConditionalPostcondition(MethodTree node, AnnotationMirror annotation, Receiver expression, boolean result) {
    boolean booleanReturnType = TypesUtils.isBooleanType(TreeUtils.typeOf(node.getReturnType()));
    if (!booleanReturnType) {
        checker.report(Result.failure("contracts.conditional.postcondition.invalid.returntype"), node);
        // annotation is invalid.
        return;
    }
    for (Pair<ReturnNode, ?> pair : atypeFactory.getReturnStatementStores(node)) {
        ReturnNode returnStmt = pair.first;
        Node retValNode = returnStmt.getResult();
        Boolean retVal = retValNode instanceof BooleanLiteralNode ? ((BooleanLiteralNode) retValNode).getValue() : null;
        TransferResult<?, ?> transferResult = (TransferResult<?, ?>) pair.second;
        if (transferResult == null) {
            // Unreachable return statements have no stores, but there is no need to check them.
            continue;
        }
        CFAbstractStore<?, ?> exitStore = (CFAbstractStore<?, ?>) (result ? transferResult.getThenStore() : transferResult.getElseStore());
        CFAbstractValue<?> value = exitStore.getValue(expression);
        // this means the result is a boolean literal
        if (!(retVal == null || retVal == result)) {
            continue;
        }
        AnnotationMirror inferredAnno = null;
        if (value != null) {
            QualifierHierarchy hierarchy = atypeFactory.getQualifierHierarchy();
            Set<AnnotationMirror> annos = value.getAnnotations();
            inferredAnno = hierarchy.findAnnotationInSameHierarchy(annos, annotation);
        }
        if (!checkContract(expression, annotation, inferredAnno, exitStore)) {
            checker.report(Result.failure("contracts.conditional.postcondition.not.satisfied", expression.toString()), returnStmt.getTree());
        }
    }
}
Also used : BooleanLiteralNode(org.checkerframework.dataflow.cfg.node.BooleanLiteralNode) BooleanLiteralNode(org.checkerframework.dataflow.cfg.node.BooleanLiteralNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) Node(org.checkerframework.dataflow.cfg.node.Node) TransferResult(org.checkerframework.dataflow.analysis.TransferResult) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy)

Example 2 with CFAbstractStore

use of org.checkerframework.framework.flow.CFAbstractStore 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)

Aggregations

AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 CFAbstractStore (org.checkerframework.framework.flow.CFAbstractStore)2 Element (javax.lang.model.element.Element)1 VariableElement (javax.lang.model.element.VariableElement)1 ClassName (org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)1 FieldAccess (org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)1 LocalVariable (org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable)1 ThisReference (org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference)1 TransferResult (org.checkerframework.dataflow.analysis.TransferResult)1 BooleanLiteralNode (org.checkerframework.dataflow.cfg.node.BooleanLiteralNode)1 Node (org.checkerframework.dataflow.cfg.node.Node)1 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)1 CFAbstractValue (org.checkerframework.framework.flow.CFAbstractValue)1 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)1 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)1