Search in sources :

Example 51 with Receiver

use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.

the class DependentTypesHelper method viewpointAdaptExecutable.

private void viewpointAdaptExecutable(ExpressionTree tree, ExpressionTree receiverTree, AnnotatedExecutableType typeFromUse, List<? extends ExpressionTree> args) {
    Element element = TreeUtils.elementFromUse(tree);
    AnnotatedExecutableType viewpointAdaptedType = (AnnotatedExecutableType) factory.getAnnotatedType(element);
    if (!hasDependentType(viewpointAdaptedType)) {
        return;
    }
    FlowExpressions.Receiver receiver;
    if (receiverTree == null) {
        receiver = FlowExpressions.internalReprOfImplicitReceiver(TreeUtils.elementFromUse(tree));
    } else {
        receiver = FlowExpressions.internalReprOf(factory, receiverTree);
    }
    List<FlowExpressions.Receiver> argReceivers = new ArrayList<>(args.size());
    for (ExpressionTree argTree : args) {
        argReceivers.add(FlowExpressions.internalReprOf(factory, argTree));
    }
    TreePath currentPath = factory.getPath(tree);
    FlowExpressionContext context = new FlowExpressionContext(receiver, argReceivers, factory.getContext());
    // typeForUse cannot be viewpoint adapted directly because it is the type post type variable
    // substitution.  Dependent type annotations on type arguments do not (and cannot) be
    // viewpoint adapted along with the dependent type annotations that are on the method
    // declaration. For example:
    // Map<String, String> map = ...;
    // List<@KeyFor("map") String> list = ...;
    // list.get(0)
    // If the type of List.get is viewpoint adapted for the invocation "list.get(0)", then
    // typeFromUse would be @KeyFor("map") String get(int).
    // Instead, use the type for the method (viewpointAdaptedType) and viewpoint adapt that
    // type.
    // Then copy annotations from the viewpoint adapted type to typeFromUse, if that annotation
    // is not on a type that was substituted for a type variable.
    standardizeDoNotUseLocals(context, currentPath, viewpointAdaptedType);
    new ViewpointAdaptedCopier().visit(viewpointAdaptedType, typeFromUse);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) TreePath(com.sun.source.util.TreePath) FlowExpressionContext(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) ArrayList(java.util.ArrayList) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)

Example 52 with Receiver

use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.

the class DependentTypesHelper method standardizeVariable.

public void standardizeVariable(Tree node, AnnotatedTypeMirror type, Element ele) {
    if (!hasDependentType(type)) {
        return;
    }
    TreePath path = factory.getPath(node);
    if (path == null) {
        return;
    }
    switch(ele.getKind()) {
        case PARAMETER:
            Tree enclTree = TreeUtils.enclosingOfKind(path, new HashSet<>(Arrays.asList(Kind.METHOD, Kind.LAMBDA_EXPRESSION)));
            if (enclTree.getKind() == Kind.METHOD) {
                // If the most enclosing tree is a method, the parameter is a method parameter
                MethodTree methodTree = (MethodTree) enclTree;
                TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
                FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, enclosingType, factory.getContext());
                standardizeDoNotUseLocals(parameterContext, path, type);
            } else {
                // Otherwise, the parameter is a lambda parameter
                LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclTree;
                FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForLambda(lambdaTree, path, factory.getContext());
                // TODO: test this.
                // TODO: use path.getParentPath to prevent a StackOverflowError, see Issue
                // #1027.
                standardizeUseLocals(parameterContext, path.getParentPath(), type);
            }
            break;
        case LOCAL_VARIABLE:
        case RESOURCE_VARIABLE:
        case EXCEPTION_PARAMETER:
            TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
            FlowExpressions.Receiver receiver = FlowExpressions.internalReprOfPseudoReceiver(path, enclosingType);
            List<Receiver> params = FlowExpressions.getParametersOfEnclosingMethod(factory, path);
            FlowExpressionContext localContext = new FlowExpressionContext(receiver, params, factory.getContext());
            standardizeUseLocals(localContext, path, type);
            break;
        case FIELD:
            FlowExpressions.Receiver receiverF;
            if (node.getKind() == Tree.Kind.IDENTIFIER) {
                FlowExpressions.Receiver r = FlowExpressions.internalReprOf(factory, (IdentifierTree) node);
                receiverF = r instanceof FlowExpressions.FieldAccess ? ((FlowExpressions.FieldAccess) r).getReceiver() : r;
            } else {
                receiverF = FlowExpressions.internalReprOfImplicitReceiver(ele);
            }
            FlowExpressionContext fieldContext = new FlowExpressionContext(receiverF, null, factory.getContext());
            standardizeDoNotUseLocals(fieldContext, path, type);
            break;
        default:
    }
}
Also used : LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) TreePath(com.sun.source.util.TreePath) MethodTree(com.sun.source.tree.MethodTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) FlowExpressionContext(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) IdentifierTree(com.sun.source.tree.IdentifierTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ModifiersTree(com.sun.source.tree.ModifiersTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)

Example 53 with Receiver

use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.

the class BaseTypeVisitor method resolveContracts.

/**
 * Takes a set of contracts identified by their expression and annotation strings and resolves
 * them to the correct {@link Receiver} and {@link AnnotationMirror}.
 */
private Set<Pair<Receiver, AnnotationMirror>> resolveContracts(Set<? extends Contract> contractSet, AnnotatedExecutableType method) {
    Set<Pair<Receiver, AnnotationMirror>> result = new HashSet<>();
    MethodTree methodTree = visitorState.getMethodTree();
    TreePath path = atypeFactory.getPath(methodTree);
    FlowExpressionContext flowExprContext = null;
    for (Contract p : contractSet) {
        String expression = p.expression;
        AnnotationMirror annotation = p.annotation;
        if (flowExprContext == null) {
            flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, method.getReceiverType().getUnderlyingType(), checker.getContext());
        }
        annotation = standardizeAnnotationFromContract(annotation, flowExprContext, path);
        try {
            // TODO: currently, these expressions are parsed many times.
            // this could
            // be optimized to store the result the first time.
            // (same for other annotations)
            FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, path, false);
            result.add(Pair.of(expr, annotation));
        } catch (FlowExpressionParseException e) {
            // report errors here
            checker.report(e.getResult(), methodTree);
        }
    }
    return result;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) TreePath(com.sun.source.util.TreePath) MethodTree(com.sun.source.tree.MethodTree) FlowExpressionContext(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FlowExpressionParseException(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionParseException) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) Contract(org.checkerframework.framework.util.ContractsUtils.Contract) Pair(org.checkerframework.javacutil.Pair) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet)

Example 54 with Receiver

use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.

the class ValueTransfer method processConditionalPostconditions.

@Override
protected void processConditionalPostconditions(MethodInvocationNode n, ExecutableElement methodElement, Tree tree, CFStore thenStore, CFStore elseStore) {
    // For String.startsWith(String) and String.endsWith(String), refine the minimum length
    // of the receiver to the minimum length of the argument.
    ValueMethodIdentifier methodIdentifier = atypefactory.getMethodIdentifier();
    if (methodIdentifier.isStartsWithMethod(methodElement) || methodIdentifier.isEndsWithMethod(methodElement)) {
        Node argumentNode = n.getArgument(0);
        AnnotationMirror argumentAnno = getArrayOrStringAnnotation(argumentNode);
        int minLength = atypefactory.getMinLenValue(argumentAnno);
        // Update the annotation of the receiver
        if (minLength != 0) {
            Receiver receiver = FlowExpressions.internalReprOf(atypefactory, n.getTarget().getReceiver());
            AnnotationMirror minLenAnno = atypefactory.createArrayLenRangeAnnotation(minLength, Integer.MAX_VALUE);
            thenStore.insertValue(receiver, minLenAnno);
        }
    }
    super.processConditionalPostconditions(n, methodElement, tree, thenStore, elseStore);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) NumericalMultiplicationNode(org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode) MethodAccessNode(org.checkerframework.dataflow.cfg.node.MethodAccessNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) UnsignedRightShiftNode(org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode) LeftShiftNode(org.checkerframework.dataflow.cfg.node.LeftShiftNode) FloatingRemainderNode(org.checkerframework.dataflow.cfg.node.FloatingRemainderNode) LessThanNode(org.checkerframework.dataflow.cfg.node.LessThanNode) BitwiseOrNode(org.checkerframework.dataflow.cfg.node.BitwiseOrNode) SignedRightShiftNode(org.checkerframework.dataflow.cfg.node.SignedRightShiftNode) NumericalPlusNode(org.checkerframework.dataflow.cfg.node.NumericalPlusNode) ConditionalAndNode(org.checkerframework.dataflow.cfg.node.ConditionalAndNode) GreaterThanOrEqualNode(org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode) BitwiseAndNode(org.checkerframework.dataflow.cfg.node.BitwiseAndNode) IntegerDivisionNode(org.checkerframework.dataflow.cfg.node.IntegerDivisionNode) IntegerRemainderNode(org.checkerframework.dataflow.cfg.node.IntegerRemainderNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ConditionalOrNode(org.checkerframework.dataflow.cfg.node.ConditionalOrNode) NumericalAdditionNode(org.checkerframework.dataflow.cfg.node.NumericalAdditionNode) NumericalSubtractionNode(org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode) BitwiseXorNode(org.checkerframework.dataflow.cfg.node.BitwiseXorNode) BitwiseComplementNode(org.checkerframework.dataflow.cfg.node.BitwiseComplementNode) ConditionalNotNode(org.checkerframework.dataflow.cfg.node.ConditionalNotNode) NumericalMinusNode(org.checkerframework.dataflow.cfg.node.NumericalMinusNode) StringConcatenateNode(org.checkerframework.dataflow.cfg.node.StringConcatenateNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) FloatingDivisionNode(org.checkerframework.dataflow.cfg.node.FloatingDivisionNode) GreaterThanNode(org.checkerframework.dataflow.cfg.node.GreaterThanNode) LessThanOrEqualNode(org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) Node(org.checkerframework.dataflow.cfg.node.Node) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)

Example 55 with Receiver

use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.

the class ValueTransfer method refineAtLengthAccess.

/**
 * Transform @IntVal or @IntRange annotations of a array or string length into an @ArrayLen
 * or @ArrayLenRange annotation for the array or string.
 */
private void refineAtLengthAccess(Node lengthNode, Node receiverNode, CFStore store) {
    Receiver lengthRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), lengthNode);
    // not marked @Pure, then do not refine.
    if (lengthRec instanceof FlowExpressions.Unknown) {
        return;
    }
    CFValue value = store.getValue(lengthRec);
    if (value == null) {
        return;
    }
    AnnotationMirror lengthAnno = getValueAnnotation(value);
    if (lengthAnno == null) {
        return;
    }
    if (AnnotationUtils.areSameByClass(lengthAnno, BottomVal.class)) {
        // If the length is bottom, then this is dead code, so the receiver type
        // should also be bottom.
        Receiver receiver = FlowExpressions.internalReprOf(atypefactory, receiverNode);
        store.insertValue(receiver, lengthAnno);
        return;
    }
    RangeOrListOfValues rolv;
    if (atypefactory.isIntRange(lengthAnno)) {
        rolv = new RangeOrListOfValues(ValueAnnotatedTypeFactory.getRange(lengthAnno));
    } else if (AnnotationUtils.areSameByClass(lengthAnno, IntVal.class)) {
        List<Long> lengthValues = ValueAnnotatedTypeFactory.getIntValues(lengthAnno);
        rolv = new RangeOrListOfValues(RangeOrListOfValues.convertLongsToInts(lengthValues));
    } else {
        return;
    }
    AnnotationMirror newRecAnno = rolv.createAnnotation(atypefactory);
    AnnotationMirror oldRecAnno = getArrayOrStringAnnotation(receiverNode);
    AnnotationMirror combinedRecAnno;
    // with the facts known about its length using GLB.
    if (oldRecAnno == null) {
        combinedRecAnno = newRecAnno;
    } else {
        combinedRecAnno = atypefactory.getQualifierHierarchy().greatestLowerBound(oldRecAnno, newRecAnno);
    }
    Receiver receiver = FlowExpressions.internalReprOf(analysis.getTypeFactory(), receiverNode);
    store.insertValue(receiver, combinedRecAnno);
}
Also used : CFValue(org.checkerframework.framework.flow.CFValue) AnnotationMirror(javax.lang.model.element.AnnotationMirror) IntVal(org.checkerframework.common.value.qual.IntVal) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) List(java.util.List) ArrayList(java.util.ArrayList)

Aggregations

Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)55 AnnotationMirror (javax.lang.model.element.AnnotationMirror)19 Node (org.checkerframework.dataflow.cfg.node.Node)15 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)14 FieldAccessNode (org.checkerframework.dataflow.cfg.node.FieldAccessNode)10 CFValue (org.checkerframework.framework.flow.CFValue)9 FlowExpressions (org.checkerframework.dataflow.analysis.FlowExpressions)8 FieldAccess (org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)8 NumericalAdditionNode (org.checkerframework.dataflow.cfg.node.NumericalAdditionNode)8 NumericalSubtractionNode (org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode)8 ArrayList (java.util.ArrayList)7 TypeMirror (javax.lang.model.type.TypeMirror)7 ClassName (org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)7 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)7 Tree (com.sun.source.tree.Tree)6 TreePath (com.sun.source.util.TreePath)6 ArrayCreationNode (org.checkerframework.dataflow.cfg.node.ArrayCreationNode)6 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)6 MethodTree (com.sun.source.tree.MethodTree)5 CaseNode (org.checkerframework.dataflow.cfg.node.CaseNode)5