Search in sources :

Example 1 with TransferResult

use of org.checkerframework.dataflow.analysis.TransferResult 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 TransferResult

use of org.checkerframework.dataflow.analysis.TransferResult 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 methodTree 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 methodTree, AnnotationMirror annotation, JavaExpression expression, boolean result) {
    boolean booleanReturnType = TypesUtils.isBooleanType(TreeUtils.typeOf(methodTree.getReturnType()));
    if (!booleanReturnType) {
        checker.reportError(methodTree, "contracts.conditional.postcondition.returntype");
        // annotation is invalid.
        return;
    }
    for (Pair<ReturnNode, ?> pair : atypeFactory.getReturnStatementStores(methodTree)) {
        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.reportError(returnStmt.getTree(), "contracts.conditional.postcondition", methodTree.getName(), result, contractExpressionAndType(expression.toString(), inferredAnno), contractExpressionAndType(expression.toString(), annotation));
        }
    }
}
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)

Aggregations

AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 TransferResult (org.checkerframework.dataflow.analysis.TransferResult)2 BooleanLiteralNode (org.checkerframework.dataflow.cfg.node.BooleanLiteralNode)2 Node (org.checkerframework.dataflow.cfg.node.Node)2 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)2 CFAbstractStore (org.checkerframework.framework.flow.CFAbstractStore)2 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)2