Search in sources :

Example 6 with MustCallAnnotatedTypeFactory

use of org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory in project checker-framework by typetools.

the class MustCallConsistencyAnalyzer method checkEnclosingMethodIsCreatesMustCallFor.

/**
 * Checks that the method that encloses an assignment is marked with @CreatesMustCallFor
 * annotation whose target is the object whose field is being re-assigned.
 *
 * @param node an assignment node whose lhs is a non-final, owning field
 * @param enclosingMethod the MethodTree in which the re-assignment takes place
 */
private void checkEnclosingMethodIsCreatesMustCallFor(AssignmentNode node, MethodTree enclosingMethod) {
    Node lhs = node.getTarget();
    if (!(lhs instanceof FieldAccessNode)) {
        return;
    }
    String receiverString = receiverAsString((FieldAccessNode) lhs);
    if ("this".equals(receiverString) && TreeUtils.isConstructor(enclosingMethod)) {
        // be annotated.
        return;
    }
    ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethod);
    MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
    List<String> cmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
    if (cmcfValues.isEmpty()) {
        checker.reportError(enclosingMethod, "missing.creates.mustcall.for", enclosingMethodElt.getSimpleName().toString(), receiverString, ((FieldAccessNode) lhs).getFieldName());
        return;
    }
    List<String> checked = new ArrayList<>();
    for (String targetStrWithoutAdaptation : cmcfValues) {
        String targetStr;
        try {
            targetStr = StringToJavaExpression.atMethodBody(targetStrWithoutAdaptation, enclosingMethod, checker).toString();
        } catch (JavaExpressionParseException e) {
            targetStr = targetStrWithoutAdaptation;
        }
        if (targetStr.equals(receiverString)) {
            // This @CreatesMustCallFor annotation matches.
            return;
        }
        checked.add(targetStr);
    }
    checker.reportError(enclosingMethod, "incompatible.creates.mustcall.for", enclosingMethodElt.getSimpleName().toString(), receiverString, ((FieldAccessNode) lhs).getFieldName(), String.join(", ", checked));
}
Also used : TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) ThisNode(org.checkerframework.dataflow.cfg.node.ThisNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) NullLiteralNode(org.checkerframework.dataflow.cfg.node.NullLiteralNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode)

Example 7 with MustCallAnnotatedTypeFactory

use of org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory in project checker-framework by typetools.

the class MustCallConsistencyAnalyzer method isMustCallClose.

/**
 * Returns true if must-call type of node only contains close. This is a helper method for
 * handling try-with-resources statements.
 *
 * @param node the node.
 * @return true if must-call type of node only contains close.
 */
boolean isMustCallClose(Node node) {
    MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
    AnnotatedTypeMirror mustCallAnnotatedType = mcAtf.getAnnotatedType(node.getTree());
    AnnotationMirror mustCallAnnotation = mustCallAnnotatedType.getAnnotation(MustCall.class);
    return typeFactory.getMustCallValues(mcAtf.withoutClose(mustCallAnnotation)).isEmpty();
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 8 with MustCallAnnotatedTypeFactory

use of org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory in project checker-framework by typetools.

the class MustCallConsistencyAnalyzer method isValidCreatesMustCallForExpression.

/**
 * Checks the validity of the given expression from an invoked method's {@link
 * org.checkerframework.checker.mustcall.qual.CreatesMustCallFor} annotation. Helper method for
 * {@link #checkCreatesMustCallForInvocation(Set, MethodInvocationNode)}.
 *
 * <p>An expression is valid if one of the following conditions is true: 1) the expression is an
 * owning pointer, 2) the expression already has a tracked Obligation (i.e. there is already a
 * resource alias in some Obligation's resource alias set that refers to the expression), or 3)
 * the method in which the invocation occurs also has an @CreatesMustCallFor annotation, with the
 * same expression.
 *
 * @param obligations the currently-tracked Obligations; this value is side-effected if there is
 *     an Obligation in it which tracks {@code expression} as one of its resource aliases
 * @param expression an element of a method's @CreatesMustCallFor annotation
 * @param path the path to the invocation of the method from whose @CreateMustCallFor annotation
 *     {@code expression} came
 * @return true iff the expression is valid, as defined above
 */
private boolean isValidCreatesMustCallForExpression(Set<Obligation> obligations, JavaExpression expression, TreePath path) {
    if (expression instanceof FieldAccess) {
        Element elt = ((FieldAccess) expression).getField();
        if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
            // The expression is an Owning field.  This satisfies case 1.
            return true;
        }
    } else if (expression instanceof LocalVariable) {
        Element elt = ((LocalVariable) expression).getElement();
        if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
            // This satisfies case 1.
            return true;
        } else {
            Obligation toRemove = null;
            Obligation toAdd = null;
            for (Obligation obligation : obligations) {
                ResourceAlias alias = obligation.getResourceAlias(expression);
                if (alias != null) {
                    // This satisfies case 2 above. Remove all its aliases, then return below.
                    if (toRemove != null) {
                        throw new TypeSystemError("tried to remove multiple sets containing a reset expression at once");
                    }
                    toRemove = obligation;
                    toAdd = new Obligation(ImmutableSet.of(alias));
                }
            }
            if (toRemove != null) {
                obligations.remove(toRemove);
                obligations.add(toAdd);
                // This satisfies case 2.
                return true;
            }
        }
    }
    // TODO: Getting this every time is inefficient if a method has many @CreatesMustCallFor
    // annotations, but that should be rare.
    MethodTree enclosingMethodTree = TreePathUtil.enclosingMethod(path);
    if (enclosingMethodTree == null) {
        return false;
    }
    ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethodTree);
    MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
    List<String> enclosingCmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
    if (enclosingCmcfValues.isEmpty()) {
        return false;
    }
    for (String enclosingCmcfValue : enclosingCmcfValues) {
        JavaExpression enclosingTarget;
        try {
            enclosingTarget = StringToJavaExpression.atMethodBody(enclosingCmcfValue, enclosingMethodTree, checker);
        } catch (JavaExpressionParseException e) {
            // Do not issue an error here, because it would be a duplicate.
            // The error will be issued by the Transfer class of the checker,
            // via the CreatesMustCallForElementSupplier interface.
            enclosingTarget = null;
        }
        if (areSame(expression, enclosingTarget)) {
            // This satisfies case 3.
            return true;
        }
    }
    return false;
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) MethodTree(com.sun.source.tree.MethodTree) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) TypeSystemError(org.checkerframework.javacutil.TypeSystemError) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) NotOwning(org.checkerframework.checker.mustcall.qual.NotOwning) Owning(org.checkerframework.checker.mustcall.qual.Owning) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess)

Example 9 with MustCallAnnotatedTypeFactory

use of org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory in project checker-framework by typetools.

the class ResourceLeakAnnotatedTypeFactory method getMustCallValue.

/**
 * Returns the {@link MustCall#value} element/argument of the @MustCall annotation on the class
 * type of {@code element}.
 *
 * <p>Do not use this method to get the MustCall value of an {@link
 * org.checkerframework.checker.resourceleak.MustCallConsistencyAnalyzer.Obligation}. Instead, use
 * {@link
 * org.checkerframework.checker.resourceleak.MustCallConsistencyAnalyzer.Obligation#getMustCallMethods(ResourceLeakAnnotatedTypeFactory,
 * CFStore)}.
 *
 * @param element an element
 * @return the strings in its must-call type
 */
/* package-private */
List<String> getMustCallValue(Element element) {
    MustCallAnnotatedTypeFactory mustCallAnnotatedTypeFactory = getTypeFactoryOfSubchecker(MustCallChecker.class);
    AnnotatedTypeMirror mustCallAnnotatedType = mustCallAnnotatedTypeFactory.getAnnotatedType(element);
    AnnotationMirror mustCallAnnotation = mustCallAnnotatedType.getAnnotation(MustCall.class);
    return getMustCallValues(mustCallAnnotation);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 10 with MustCallAnnotatedTypeFactory

use of org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory in project checker-framework by typetools.

the class ResourceLeakAnnotatedTypeFactory method getMustCallValue.

/**
 * Returns the {@link MustCall#value} element/argument of the @MustCall annotation on the type of
 * {@code tree}.
 *
 * <p>If possible, prefer {@link #getMustCallValue(Tree)}, which accounts for flow-sensitive
 * refinement.
 *
 * @param tree a tree
 * @return the strings in its must-call type
 */
/* package-private */
List<String> getMustCallValue(Tree tree) {
    MustCallAnnotatedTypeFactory mustCallAnnotatedTypeFactory = getTypeFactoryOfSubchecker(MustCallChecker.class);
    AnnotatedTypeMirror mustCallAnnotatedType = mustCallAnnotatedTypeFactory.getAnnotatedType(tree);
    AnnotationMirror mustCallAnnotation = mustCallAnnotatedType.getAnnotation(MustCall.class);
    return getMustCallValues(mustCallAnnotation);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

MustCallAnnotatedTypeFactory (org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory)12 AnnotationMirror (javax.lang.model.element.AnnotationMirror)6 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)6 ExecutableElement (javax.lang.model.element.ExecutableElement)5 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)4 Node (org.checkerframework.dataflow.cfg.node.Node)4 ObjectCreationNode (org.checkerframework.dataflow.cfg.node.ObjectCreationNode)4 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)4 MethodTree (com.sun.source.tree.MethodTree)3 TypeElement (javax.lang.model.element.TypeElement)3 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)3 FieldAccessNode (org.checkerframework.dataflow.cfg.node.FieldAccessNode)3 NullLiteralNode (org.checkerframework.dataflow.cfg.node.NullLiteralNode)3 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)3 ThisNode (org.checkerframework.dataflow.cfg.node.ThisNode)3 TypeCastNode (org.checkerframework.dataflow.cfg.node.TypeCastNode)3 CFStore (org.checkerframework.framework.flow.CFStore)3 Element (javax.lang.model.element.Element)2 VariableElement (javax.lang.model.element.VariableElement)2 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)2