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);
}
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);
}
Aggregations