Search in sources :

Example 11 with LocalVariable

use of org.checkerframework.dataflow.expression.LocalVariable in project checker-framework by typetools.

the class CFAbstractTransfer method addFinalLocalValues.

/**
 * Adds information about effectively final variables (from outer scopes)
 *
 * @param store the store to add to
 * @param enclosingElement the enclosing element of the code we are analyzing
 */
private void addFinalLocalValues(S store, Element enclosingElement) {
    // add information about effectively final variables (from outer scopes)
    for (Map.Entry<Element, V> e : analysis.atypeFactory.getFinalLocalValues().entrySet()) {
        Element elem = e.getKey();
        // TODO: There is a design flaw where the values of final local values leaks
        // into other methods of the same class. For example, in
        // class a { void b() {...} void c() {...} }
        // final local values from b() would be visible in the store for c(),
        // even though they should only be visible in b() and in classes
        // defined inside the method body of b().
        // This is partly because GenericAnnotatedTypeFactory.performFlowAnalysis does not call itself
        // recursively to analyze inner classes, but instead pops classes off of a queue, and the
        // information about known final local values is stored by GenericAnnotatedTypeFactory.analyze
        // in GenericAnnotatedTypeFactory.flowResult, which is visible to all classes in the queue
        // regardless of their level of recursion.
        // We work around this here by ensuring that we only add a final local value to a method's
        // store if that method is enclosed by the method where the local variables were declared.
        // Find the enclosing method of the element
        Element enclosingMethodOfVariableDeclaration = elem.getEnclosingElement();
        if (enclosingMethodOfVariableDeclaration != null) {
            // Now find all the enclosing methods of the code we are analyzing. If any one of
            // them matches the above, then the final local variable value applies.
            Element enclosingMethodOfCurrentMethod = enclosingElement;
            while (enclosingMethodOfCurrentMethod != null) {
                if (enclosingMethodOfVariableDeclaration.equals(enclosingMethodOfCurrentMethod)) {
                    LocalVariable l = new LocalVariable(elem);
                    store.insertValue(l, e.getValue());
                    break;
                }
                enclosingMethodOfCurrentMethod = enclosingMethodOfCurrentMethod.getEnclosingElement();
            }
        }
    }
}
Also used : TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) Map(java.util.Map) HashMap(java.util.HashMap)

Example 12 with LocalVariable

use of org.checkerframework.dataflow.expression.LocalVariable in project checker-framework by typetools.

the class CFAbstractStore method clearValue.

/**
 * Remove any knowledge about the expression {@code expr} (correctly deciding where to remove the
 * information depending on the type of the expression {@code expr}).
 */
public void clearValue(JavaExpression expr) {
    if (expr.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (expr instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) expr;
        localVariableValues.remove(localVar);
    } else if (expr instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) expr;
        fieldValues.remove(fieldAcc);
    } else if (expr instanceof MethodCall) {
        MethodCall method = (MethodCall) expr;
        methodValues.remove(method);
    } else if (expr instanceof ArrayAccess) {
        ArrayAccess a = (ArrayAccess) expr;
        arrayValues.remove(a);
    } else if (expr instanceof ClassName) {
        ClassName c = (ClassName) expr;
        classValues.remove(c);
    } else {
    // thisValue ...
    // No other types of expressions are stored.
    }
}
Also used : ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 13 with LocalVariable

use of org.checkerframework.dataflow.expression.LocalVariable in project checker-framework by typetools.

the class DependentTypesHelper method delocalize.

/**
 * Viewpoint-adapt all dependent type annotations to the method declaration, {@code
 * methodDeclTree}. This method changes occurrences of formal parameter names to the "#2" syntax,
 * and it removes expressions that contain other local variables.
 *
 * <p>If a Java expression in {@code atm} references local variables (other than formal
 * parameters), the expression is removed from the annotation. This could result in dependent type
 * annotations with empty lists of expressions. If this is a problem, a subclass can override
 * {@link #buildAnnotation(AnnotationMirror, Map)} to do something besides creating an annotation
 * with a empty list.
 *
 * @param atm type to viewpoint-adapt; is side-effected by this method
 * @param methodDeclTree the method declaration to which the annotations are viewpoint-adapted
 */
public void delocalize(AnnotatedTypeMirror atm, MethodTree methodDeclTree) {
    if (!hasDependentType(atm)) {
        return;
    }
    TreePath pathToMethodDecl = factory.getPath(methodDeclTree);
    ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodDeclTree);
    List<FormalParameter> parameters = JavaExpression.getFormalParameters(methodElement);
    List<JavaExpression> paramsAsLocals = JavaExpression.getParametersAsLocalVariables(methodElement);
    StringToJavaExpression stringToJavaExpr = expression -> {
        JavaExpression javaExpr;
        try {
            javaExpr = StringToJavaExpression.atPath(expression, pathToMethodDecl, factory.getChecker());
        } catch (JavaExpressionParseException ex) {
            return null;
        }
        JavaExpressionConverter jec = new JavaExpressionConverter() {

            @Override
            protected JavaExpression visitLocalVariable(LocalVariable localVarExpr, Void unused) {
                int index = paramsAsLocals.indexOf(localVarExpr);
                if (index == -1) {
                    throw new FoundLocalException();
                }
                return parameters.get(index);
            }
        };
        try {
            return jec.convert(javaExpr);
        } catch (FoundLocalException ex) {
            return null;
        }
    };
    if (debugStringToJavaExpression) {
        System.out.printf("delocalize(%s, %s) created %s%n", atm, TreeUtils.toStringTruncated(methodDeclTree, 65), stringToJavaExpr);
    }
    convertAnnotatedTypeMirror(stringToJavaExpr, atm);
}
Also used : FormalParameter(org.checkerframework.dataflow.expression.FormalParameter) BugInCF(org.checkerframework.javacutil.BugInCF) TypeElement(javax.lang.model.element.TypeElement) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) Map(java.util.Map) Method(java.lang.reflect.Method) EnumSet(java.util.EnumSet) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) TreePath(com.sun.source.util.TreePath) Set(java.util.Set) Element(javax.lang.model.element.Element) MemberSelectTree(com.sun.source.tree.MemberSelectTree) TreeUtils(org.checkerframework.javacutil.TreeUtils) AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) Unknown(org.checkerframework.dataflow.expression.Unknown) TypeKind(javax.lang.model.type.TypeKind) TreeAnnotator(org.checkerframework.framework.type.treeannotator.TreeAnnotator) List(java.util.List) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) Annotation(java.lang.annotation.Annotation) ModifiersTree(com.sun.source.tree.ModifiersTree) TypesUtils(org.checkerframework.javacutil.TypesUtils) DoubleAnnotatedTypeScanner(org.checkerframework.framework.type.visitor.DoubleAnnotatedTypeScanner) AnnotatedTypeScanner(org.checkerframework.framework.type.visitor.AnnotatedTypeScanner) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) SourceChecker(org.checkerframework.framework.source.SourceChecker) VariableElement(javax.lang.model.element.VariableElement) VariableTree(com.sun.source.tree.VariableTree) HashMap(java.util.HashMap) Function(java.util.function.Function) ArrayList(java.util.ArrayList) NewClassTree(com.sun.source.tree.NewClassTree) TreePathUtil(org.checkerframework.javacutil.TreePathUtil) AnnotationBuilder(org.checkerframework.javacutil.AnnotationBuilder) Tree(com.sun.source.tree.Tree) AnnotationUtils(org.checkerframework.javacutil.AnnotationUtils) ClassTree(com.sun.source.tree.ClassTree) Nullable(org.checkerframework.checker.nullness.qual.Nullable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) ElementKind(javax.lang.model.element.ElementKind) ExpressionTree(com.sun.source.tree.ExpressionTree) ExecutableElement(javax.lang.model.element.ExecutableElement) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) JavaExpressionConverter(org.checkerframework.dataflow.expression.JavaExpressionConverter) JCTree(com.sun.tools.javac.tree.JCTree) AnnotationMirror(javax.lang.model.element.AnnotationMirror) SimpleAnnotatedTypeScanner(org.checkerframework.framework.type.visitor.SimpleAnnotatedTypeScanner) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) TypeMirror(javax.lang.model.type.TypeMirror) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) FormalParameter(org.checkerframework.dataflow.expression.FormalParameter) Collections(java.util.Collections) ElementUtils(org.checkerframework.javacutil.ElementUtils) CollectionsPlume(org.plumelib.util.CollectionsPlume) JavaExpressionConverter(org.checkerframework.dataflow.expression.JavaExpressionConverter) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) TreePath(com.sun.source.util.TreePath) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)

Example 14 with LocalVariable

use of org.checkerframework.dataflow.expression.LocalVariable 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 15 with LocalVariable

use of org.checkerframework.dataflow.expression.LocalVariable in project checker-framework by typetools.

the class UpperBoundVisitor method checkEffectivelyFinalAndParsable.

/**
 * Reports an error if the Java expression named by s is not effectively final when parsed at the
 * declaration of the given class.
 *
 * @param s a Java expression
 * @param classTree the expression is parsed with respect to this class
 * @param whereToReportError the tree at which to possibly report an error
 */
private void checkEffectivelyFinalAndParsable(String s, ClassTree classTree, Tree whereToReportError) {
    JavaExpression je;
    try {
        je = StringToJavaExpression.atTypeDecl(s, TreeUtils.elementFromDeclaration(classTree), checker);
    } catch (JavaExpressionParseException e) {
        checker.report(whereToReportError, e.getDiagMessage());
        return;
    }
    Element element = null;
    if (je instanceof LocalVariable) {
        element = ((LocalVariable) je).getElement();
    } else if (je instanceof FieldAccess) {
        element = ((FieldAccess) je).getField();
    } else if (je instanceof ThisReference || je instanceof ValueLiteral) {
        return;
    }
    if (element == null || !ElementUtils.isEffectivelyFinal(element)) {
        checker.reportError(whereToReportError, NOT_FINAL, je);
    }
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) Element(javax.lang.model.element.Element) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ValueLiteral(org.checkerframework.dataflow.expression.ValueLiteral) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference)

Aggregations

LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)17 FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)11 ClassName (org.checkerframework.dataflow.expression.ClassName)8 ThisReference (org.checkerframework.dataflow.expression.ThisReference)7 Element (javax.lang.model.element.Element)6 ExecutableElement (javax.lang.model.element.ExecutableElement)6 VariableElement (javax.lang.model.element.VariableElement)6 MethodCall (org.checkerframework.dataflow.expression.MethodCall)6 MethodTree (com.sun.source.tree.MethodTree)5 VariableTree (com.sun.source.tree.VariableTree)5 Map (java.util.Map)5 TypeElement (javax.lang.model.element.TypeElement)5 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)5 HashMap (java.util.HashMap)4 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)4 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)3 Tree (com.sun.source.tree.Tree)3 ArrayList (java.util.ArrayList)3 JavaExpressionParseException (org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)3 StringToJavaExpression (org.checkerframework.framework.util.StringToJavaExpression)3