Search in sources :

Example 61 with AnnotatedDeclaredType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.

the class AliasingTransfer method visitMethodInvocation.

/**
 * Case 3: Given a method invocation expression, if the parent of the expression is not a
 * statement, check if there are any arguments of the method call annotated as
 * {@literal @}LeakedToResult and remove it from the store, since it might be leaked.
 */
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
    Tree parent = n.getTreePath().getParentPath().getLeaf();
    boolean parentIsStatement = parent.getKind() == Kind.EXPRESSION_STATEMENT;
    if (!parentIsStatement) {
        ExecutableElement methodElement = TreeUtils.elementFromUse(n.getTree());
        List<Node> args = n.getArguments();
        List<? extends VariableElement> params = methodElement.getParameters();
        assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
        CFStore store = in.getRegularStore();
        for (int i = 0; i < args.size(); i++) {
            Node arg = args.get(i);
            VariableElement param = params.get(i);
            if (factory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class)) {
                // If argument can leak to result, and parent is not a
                // single statement, remove that node from store.
                store.clearValue(FlowExpressions.internalReprOf(factory, arg));
            }
        }
        // Now, doing the same as above for the receiver parameter
        Node receiver = n.getTarget().getReceiver();
        AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement);
        AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
        if (receiverType != null && receiverType.hasAnnotation(LeakedToResult.class)) {
            store.clearValue(FlowExpressions.internalReprOf(factory, receiver));
        }
    }
    // pseudo-assignments.
    return super.visitMethodInvocation(n, in);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) CFStore(org.checkerframework.framework.flow.CFStore) ExecutableElement(javax.lang.model.element.ExecutableElement) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) LeakedToResult(org.checkerframework.common.aliasing.qual.LeakedToResult) Tree(com.sun.source.tree.Tree) VariableElement(javax.lang.model.element.VariableElement)

Example 62 with AnnotatedDeclaredType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.

the class AliasingVisitor method visitMethodInvocation.

/**
 * Checks that if a method call is being invoked inside a constructor with result type
 * {@literal @}Unique, it must not leak the "this" reference. There are 3 ways to make sure that
 * this is not happening:
 *
 * <ol>
 *   <li>{@code this} is not an argument of the method call.
 *   <li>{@code this} is an argument of the method call, but the respective parameter is
 *       annotated as {@literal @}NonLeaked.
 *   <li>{@code this} is an argument of the method call, but the respective parameter is
 *       annotated as {@literal @}LeakedToResult AND the result of the method call is not being
 *       stored (the method call is a statement).
 * </ol>
 *
 * The private method {@code isUniqueCheck} handles cases 2 and 3.
 */
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    // @Unique. We also want to avoid visiting the <init> method.
    if (isInUniqueConstructor(node)) {
        if (TreeUtils.isSuperCall(node)) {
            // Check if a call to super() might create an alias: that
            // happens when the parent's respective constructor is not @Unique.
            AnnotatedTypeMirror superResult = atypeFactory.getAnnotatedType(node);
            if (!superResult.hasAnnotation(Unique.class)) {
                checker.report(Result.failure("unique.leaked"), node);
            }
        } else {
            // TODO: Currently the type of "this" doesn't always return
            // the type of the constructor result, therefore we need
            // this "else" block. Once constructors are implemented
            // correctly we could remove that code below, since the type
            // of "this" in a @Unique constructor will be @Unique.
            Tree parent = getCurrentPath().getParentPath().getLeaf();
            boolean parentIsStatement = parent.getKind() == Kind.EXPRESSION_STATEMENT;
            ExecutableElement methodElement = TreeUtils.elementFromUse(node);
            List<? extends VariableElement> params = methodElement.getParameters();
            List<? extends ExpressionTree> args = node.getArguments();
            assert (args.size() == params.size()) : "Number of arguments in" + " the method call " + node.toString() + " is different from the " + "number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
            for (int i = 0; i < args.size(); i++) {
                // For every argument we check if it is a reference to "this".
                if (TreeUtils.isExplicitThisDereference(args.get(i))) {
                    // If it is a reference to "this", there is still hope that
                    // it is not being leaked (2. and 3. from the javadoc).
                    VariableElement param = params.get(i);
                    boolean hasNonLeaked = atypeFactory.getAnnotatedType(param).hasAnnotation(NonLeaked.class);
                    boolean hasLeakedToResult = atypeFactory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class);
                    isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
                } else {
                // Not possible to leak reference here (case 1. from the javadoc).
                }
            }
            // Now, doing the same as above for the receiver parameter
            AnnotatedExecutableType annotatedType = atypeFactory.getAnnotatedType(methodElement);
            AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
            if (receiverType != null) {
                boolean hasNonLeaked = receiverType.hasAnnotation(NonLeaked.class);
                boolean hasLeakedToResult = receiverType.hasAnnotation(LeakedToResult.class);
                isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
            }
        }
    }
    return super.visitMethodInvocation(node, p);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) MethodTree(com.sun.source.tree.MethodTree) ExpressionTree(com.sun.source.tree.ExpressionTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ThrowTree(com.sun.source.tree.ThrowTree) NewArrayTree(com.sun.source.tree.NewArrayTree) Tree(com.sun.source.tree.Tree) Unique(org.checkerframework.common.aliasing.qual.Unique) VariableElement(javax.lang.model.element.VariableElement) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 63 with AnnotatedDeclaredType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.

the class AliasingVisitor method visitVariable.

@Override
public Void visitVariable(VariableTree node, Void p) {
    // Component types are not allowed to have the @Unique annotation.
    AnnotatedTypeMirror varType = atypeFactory.getAnnotatedType(node);
    VariableElement elt = TreeUtils.elementFromDeclaration(node);
    if (elt.getKind().isField() && varType.hasExplicitAnnotation(Unique.class)) {
        checker.report(Result.failure("unique.location.forbidden"), node);
    } else if (node.getType().getKind() == Kind.ARRAY_TYPE) {
        AnnotatedArrayType arrayType = (AnnotatedArrayType) varType;
        if (arrayType.getComponentType().hasAnnotation(Unique.class)) {
            checker.report(Result.failure("unique.location.forbidden"), node);
        }
    } else if (node.getType().getKind() == Kind.PARAMETERIZED_TYPE) {
        AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) varType;
        for (AnnotatedTypeMirror atm : declaredType.getTypeArguments()) {
            if (atm.hasAnnotation(Unique.class)) {
                checker.report(Result.failure("unique.location.forbidden"), node);
            }
        }
    }
    return super.visitVariable(node, p);
}
Also used : AnnotatedArrayType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) Unique(org.checkerframework.common.aliasing.qual.Unique) VariableElement(javax.lang.model.element.VariableElement) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 64 with AnnotatedDeclaredType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.

the class BaseTypeVisitor method visitClass.

/**
 * Type-check classTree and skips classes specified by the skipDef option. Subclasses should
 * override {@link #processClassTree(ClassTree)} instead of this method.
 *
 * @param classTree class to check
 * @param p null
 * @return null
 */
@Override
public final Void visitClass(ClassTree classTree, Void p) {
    if (checker.shouldSkipDefs(classTree)) {
        // class entirely.
        return null;
    }
    atypeFactory.preProcessClassTree(classTree);
    AnnotatedDeclaredType preACT = visitorState.getClassType();
    ClassTree preCT = visitorState.getClassTree();
    AnnotatedDeclaredType preAMT = visitorState.getMethodReceiver();
    MethodTree preMT = visitorState.getMethodTree();
    Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
    visitorState.setClassType(atypeFactory.getAnnotatedType(classTree));
    visitorState.setClassTree(classTree);
    visitorState.setMethodReceiver(null);
    visitorState.setMethodTree(null);
    visitorState.setAssignmentContext(null);
    try {
        processClassTree(classTree);
        atypeFactory.postProcessClassTree(classTree);
    } finally {
        this.visitorState.setClassType(preACT);
        this.visitorState.setClassTree(preCT);
        this.visitorState.setMethodReceiver(preAMT);
        this.visitorState.setMethodTree(preMT);
        this.visitorState.setAssignmentContext(preAssCtxt);
    }
    return null;
}
Also used : MethodTree(com.sun.source.tree.MethodTree) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ThrowTree(com.sun.source.tree.ThrowTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) JCTree(com.sun.tools.javac.tree.JCTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 65 with AnnotatedDeclaredType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.

the class BaseTypeVisitor method checkConstructorInvocation.

protected boolean checkConstructorInvocation(AnnotatedDeclaredType invocation, AnnotatedExecutableType constructor, NewClassTree newClassTree) {
    AnnotatedDeclaredType returnType = (AnnotatedDeclaredType) constructor.getReturnType();
    // to the declared type and then do a subtyping check.
    if (invocation.getUnderlyingType().asElement().getKind().isInterface() && TypesUtils.isObject(returnType.getUnderlyingType())) {
        final AnnotatedDeclaredType retAsDt = invocation.deepCopy();
        retAsDt.replaceAnnotations(returnType.getAnnotations());
        returnType = retAsDt;
    } else if (newClassTree.getClassBody() != null) {
        // An anonymous class invokes the constructor of its super class, so the underlying
        // types of invocation and returnType are not the same.  Call asSuper so they are the
        // same and the is subtype tests below work correctly
        invocation = AnnotatedTypes.asSuper(atypeFactory, invocation, returnType);
    }
    // constructor invocation (invocation).
    if (!(atypeFactory.getTypeHierarchy().isSubtype(invocation, returnType) || atypeFactory.getTypeHierarchy().isSubtype(returnType, invocation))) {
        checker.report(Result.failure("constructor.invocation.invalid", constructor.toString(), invocation, returnType), newClassTree);
        return false;
    }
    return true;
// TODO: what properties should hold for constructor receivers for
// inner type instantiations?
}
Also used : AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)

Aggregations

AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)72 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)26 ArrayList (java.util.ArrayList)19 ExpressionTree (com.sun.source.tree.ExpressionTree)18 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)18 MethodTree (com.sun.source.tree.MethodTree)17 Tree (com.sun.source.tree.Tree)16 ClassTree (com.sun.source.tree.ClassTree)14 VariableTree (com.sun.source.tree.VariableTree)14 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)13 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)12 NewClassTree (com.sun.source.tree.NewClassTree)12 ExecutableElement (javax.lang.model.element.ExecutableElement)11 IdentifierTree (com.sun.source.tree.IdentifierTree)10 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)10 NewArrayTree (com.sun.source.tree.NewArrayTree)9 ReturnTree (com.sun.source.tree.ReturnTree)9 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)9 AnnotatedWildcardType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType)9 AssignmentTree (com.sun.source.tree.AssignmentTree)8