Search in sources :

Example 1 with GuardSatisfied

use of org.checkerframework.checker.lock.qual.GuardSatisfied in project checker-framework by typetools.

the class LockVisitor method commonAssignmentCheck.

@Override
protected void commonAssignmentCheck(AnnotatedTypeMirror varType, AnnotatedTypeMirror valueType, Tree valueTree, @CompilerMessageKey String errorKey) {
    Kind valueTreeKind = valueTree.getKind();
    switch(valueTreeKind) {
        case NEW_CLASS:
        case NEW_ARRAY:
            // Do NOT do this if the LHS is @GuardedByBottom.
            if (!varType.hasAnnotation(GuardedByBottom.class)) {
                return;
            }
            break;
        case INT_LITERAL:
        case LONG_LITERAL:
        case FLOAT_LITERAL:
        case DOUBLE_LITERAL:
        case BOOLEAN_LITERAL:
        case CHAR_LITERAL:
        case STRING_LITERAL:
            // Do NOT do this if the LHS is @GuardedByBottom.
            if (!varType.hasAnnotation(GuardedByBottom.class)) {
                return;
            }
            break;
        default:
    }
    if (varType.hasAnnotation(GuardSatisfied.class)) {
        if (valueType.hasAnnotation(GuardedBy.class)) {
            checkLock(valueTree, valueType.getAnnotation(GuardedBy.class));
            return;
        } else if (valueType.hasAnnotation(GuardSatisfied.class)) {
            if (!errorKey.equals("argument.type.incompatible")) {
                // If both @GuardSatisfied have no index, the assignment is not allowed because
                // the LHS and RHS expressions may be guarded by different lock expressions.
                // The assignment is allowed when matching a formal parameter to an actual
                // parameter (see the if block above).
                int varTypeGuardSatisfiedIndex = atypeFactory.getGuardSatisfiedIndex(varType);
                int valueTypeGuardSatisfiedIndex = atypeFactory.getGuardSatisfiedIndex(valueType);
                if (varTypeGuardSatisfiedIndex == -1 && valueTypeGuardSatisfiedIndex == -1) {
                    checker.report(Result.failure("guardsatisfied.assignment.disallowed", varType, valueType), valueTree);
                }
            } else {
                return;
            }
        } else if (!atypeFactory.getTypeHierarchy().isSubtype(valueType, varType)) {
            // Special case: replace the @GuardSatisfied primary annotation on the LHS with
            // @GuardedBy({}) and see if it type checks.
            AnnotatedTypeMirror varType2 = // TODO: Would shallowCopy be sufficient?
            varType.deepCopy();
            varType2.replaceAnnotation(atypeFactory.GUARDEDBY);
            if (atypeFactory.getTypeHierarchy().isSubtype(valueType, varType2)) {
                return;
            }
        }
    }
    super.commonAssignmentCheck(varType, valueType, valueTree, errorKey);
}
Also used : GuardedBy(org.checkerframework.checker.lock.qual.GuardedBy) GuardedByBottom(org.checkerframework.checker.lock.qual.GuardedByBottom) TypeKind(javax.lang.model.type.TypeKind) Kind(com.sun.source.tree.Tree.Kind) ElementKind(javax.lang.model.element.ElementKind) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) GuardSatisfied(org.checkerframework.checker.lock.qual.GuardSatisfied)

Example 2 with GuardSatisfied

use of org.checkerframework.checker.lock.qual.GuardSatisfied in project checker-framework by typetools.

the class LockVisitor method visitMethod.

/**
 * Issues an error if a method (explicitly or implicitly) annotated with @MayReleaseLocks has a
 * formal parameter or receiver (explicitly or implicitly) annotated with @GuardSatisfied. Also
 * issues an error if a synchronized method has a @LockingFree, @SideEffectFree or @Pure
 * annotation.
 *
 * @param node the MethodTree of the method definition to visit
 */
@Override
public Void visitMethod(MethodTree node, Void p) {
    ExecutableElement methodElement = TreeUtils.elementFromDeclaration(node);
    issueErrorIfMoreThanOneLockPreconditionMethodAnnotationPresent(methodElement, node);
    SideEffectAnnotation sea = atypeFactory.methodSideEffectAnnotation(methodElement, true);
    if (sea == SideEffectAnnotation.MAYRELEASELOCKS) {
        boolean issueGSwithMRLWarning = false;
        VariableTree receiver = node.getReceiverParameter();
        if (receiver != null) {
            if (atypeFactory.getAnnotatedType(receiver).hasAnnotation(checkerGuardSatisfiedClass)) {
                issueGSwithMRLWarning = true;
            }
        }
        if (!issueGSwithMRLWarning) {
            // Skip loop if we already decided to issue the warning.
            for (VariableTree vt : node.getParameters()) {
                if (atypeFactory.getAnnotatedType(vt).hasAnnotation(checkerGuardSatisfiedClass)) {
                    issueGSwithMRLWarning = true;
                    break;
                }
            }
        }
        if (issueGSwithMRLWarning) {
            checker.report(Result.failure("guardsatisfied.with.mayreleaselocks"), node);
        }
    }
    // @GuardSatisfied without an index.
    if (methodElement != null && methodElement.getKind() != ElementKind.CONSTRUCTOR) {
        AnnotatedTypeMirror returnTypeATM = atypeFactory.getAnnotatedType(node).getReturnType();
        if (returnTypeATM != null && returnTypeATM.hasAnnotation(GuardSatisfied.class)) {
            int returnGuardSatisfiedIndex = atypeFactory.getGuardSatisfiedIndex(returnTypeATM);
            if (returnGuardSatisfiedIndex == -1) {
                checker.report(Result.failure("guardsatisfied.return.must.have.index"), node);
            }
        }
    }
    if (!sea.isWeakerThan(SideEffectAnnotation.LOCKINGFREE) && methodElement.getModifiers().contains(Modifier.SYNCHRONIZED)) {
        checker.report(Result.failure("lockingfree.synchronized.method", sea), node);
    }
    return super.visitMethod(node, p);
}
Also used : ExecutableElement(javax.lang.model.element.ExecutableElement) VariableTree(com.sun.source.tree.VariableTree) SideEffectAnnotation(org.checkerframework.checker.lock.LockAnnotatedTypeFactory.SideEffectAnnotation) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) GuardSatisfied(org.checkerframework.checker.lock.qual.GuardSatisfied)

Aggregations

GuardSatisfied (org.checkerframework.checker.lock.qual.GuardSatisfied)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 Kind (com.sun.source.tree.Tree.Kind)1 VariableTree (com.sun.source.tree.VariableTree)1 ElementKind (javax.lang.model.element.ElementKind)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 TypeKind (javax.lang.model.type.TypeKind)1 SideEffectAnnotation (org.checkerframework.checker.lock.LockAnnotatedTypeFactory.SideEffectAnnotation)1 GuardedBy (org.checkerframework.checker.lock.qual.GuardedBy)1 GuardedByBottom (org.checkerframework.checker.lock.qual.GuardedByBottom)1