Search in sources :

Example 6 with ThisReference

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

the class CFAbstractStore method computeNewValueAndInsert.

/**
 * Inserts the result of applying {@code merger} to {@code value} and the previous value for
 * {@code expr}.
 *
 * @param expr the JavaExpression
 * @param value the value of the JavaExpression
 * @param merger the function used to merge {@code value} and the previous value of {@code expr}
 * @param permitNondeterministic if false, does nothing if {@code expr} is nondeterministic; if
 *     true, permits nondeterministic expressions to be placed in the store
 */
protected void computeNewValueAndInsert(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) {
    if (!shouldInsert(expr, value, permitNondeterministic)) {
        return;
    }
    if (expr instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) expr;
        V oldValue = localVariableValues.get(localVar);
        V newValue = merger.apply(oldValue, value);
        if (newValue != null) {
            localVariableValues.put(localVar, newValue);
        }
    } else if (expr instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) expr;
        // Only store information about final fields (where the receiver is
        // also fixed) if concurrent semantics are enabled.
        boolean isMonotonic = isMonotonicUpdate(fieldAcc, value);
        if (sequentialSemantics || isMonotonic || fieldAcc.isUnassignableByOtherCode()) {
            V oldValue = fieldValues.get(fieldAcc);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                fieldValues.put(fieldAcc, newValue);
            }
        }
    } else if (expr instanceof MethodCall) {
        MethodCall method = (MethodCall) expr;
        // Don't store any information if concurrent semantics are enabled.
        if (sequentialSemantics) {
            V oldValue = methodValues.get(method);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                methodValues.put(method, newValue);
            }
        }
    } else if (expr instanceof ArrayAccess) {
        ArrayAccess arrayAccess = (ArrayAccess) expr;
        if (sequentialSemantics) {
            V oldValue = arrayValues.get(arrayAccess);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                arrayValues.put(arrayAccess, newValue);
            }
        }
    } else if (expr instanceof ThisReference) {
        ThisReference thisRef = (ThisReference) expr;
        if (sequentialSemantics || thisRef.isUnassignableByOtherCode()) {
            V oldValue = thisValue;
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                thisValue = newValue;
            }
        }
    } else if (expr instanceof ClassName) {
        ClassName className = (ClassName) expr;
        if (sequentialSemantics || className.isUnassignableByOtherCode()) {
            V oldValue = classValues.get(className);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                classValues.put(className, newValue);
            }
        }
    } else {
    // No other types of expressions need to be 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) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 7 with ThisReference

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

the class WholeProgramInferenceImplementation method updateContracts.

@Override
public void updateContracts(Analysis.BeforeOrAfter preOrPost, ExecutableElement methodElt, CFAbstractStore<?, ?> store) {
    // Don't infer types for code that isn't presented as source.
    if (!ElementUtils.isElementFromSourceCode(methodElt)) {
        return;
    }
    if (store == null) {
        throw new BugInCF("updateContracts(%s, %s, null) for %s", preOrPost, methodElt, atypeFactory.getClass().getSimpleName());
    }
    if (!storage.hasStorageLocationForMethod(methodElt)) {
        return;
    }
    // TODO: Probably move some part of this into the AnnotatedTypeFactory.
    // This code handles fields of "this" and method parameters (including the receiver parameter
    // "this"), for now.  In the future, extend it to other expressions.
    TypeElement containingClass = (TypeElement) methodElt.getEnclosingElement();
    ThisReference thisReference = new ThisReference(containingClass.asType());
    ClassName classNameReceiver = new ClassName(containingClass.asType());
    // Fields of "this":
    for (VariableElement fieldElement : ElementFilter.fieldsIn(containingClass.getEnclosedElements())) {
        if (atypeFactory.wpiOutputFormat == OutputFormat.JAIF && containingClass.getNestingKind().isNested()) {
            // places the annotations incorrectly on the class declarations.
            continue;
        }
        FieldAccess fa = new FieldAccess((ElementUtils.isStatic(fieldElement) ? classNameReceiver : thisReference), fieldElement.asType(), fieldElement);
        CFAbstractValue<?> v = store.getFieldValue(fa);
        AnnotatedTypeMirror fieldDeclType = atypeFactory.getAnnotatedType(fieldElement);
        AnnotatedTypeMirror inferredType;
        if (v != null) {
            // This field is in the store.
            inferredType = convertCFAbstractValueToAnnotatedTypeMirror(v, fieldDeclType);
            atypeFactory.wpiAdjustForUpdateNonField(inferredType);
        } else {
            // This field is not in the store. Use the declared type.
            inferredType = fieldDeclType;
        }
        T preOrPostConditionAnnos = storage.getPreOrPostconditions(preOrPost, methodElt, fa.toString(), fieldDeclType, atypeFactory);
        if (preOrPostConditionAnnos == null) {
            continue;
        }
        String file = storage.getFileForElement(methodElt);
        updateAnnotationSet(preOrPostConditionAnnos, TypeUseLocation.FIELD, inferredType, fieldDeclType, file, false);
    }
    // This loop is 1-indexed to match the syntax used in annotation arguments.
    for (int index = 1; index <= methodElt.getParameters().size(); index++) {
        VariableElement paramElt = methodElt.getParameters().get(index - 1);
        // spurious flowexpr.parameter.not.final warnings.
        if (!ElementUtils.isEffectivelyFinal(paramElt)) {
            continue;
        }
        LocalVariable param = new LocalVariable(paramElt);
        CFAbstractValue<?> v = store.getValue(param);
        AnnotatedTypeMirror declType = atypeFactory.getAnnotatedType(paramElt);
        AnnotatedTypeMirror inferredType;
        if (v != null) {
            // This parameter is in the store.
            inferredType = convertCFAbstractValueToAnnotatedTypeMirror(v, declType);
            atypeFactory.wpiAdjustForUpdateNonField(inferredType);
        } else {
            // are supported for parameters.)
            continue;
        }
        T preOrPostConditionAnnos = storage.getPreOrPostconditions(preOrPost, methodElt, "#" + index, declType, atypeFactory);
        if (preOrPostConditionAnnos != null) {
            String file = storage.getFileForElement(methodElt);
            updateAnnotationSet(preOrPostConditionAnnos, TypeUseLocation.PARAMETER, inferredType, declType, file, false);
        }
    }
    // Receiver parameter ("this"):
    if (!ElementUtils.isStatic(methodElt)) {
        // Static methods do not have a receiver.
        CFAbstractValue<?> v = store.getValue(thisReference);
        if (v != null) {
            // This parameter is in the store.
            AnnotatedTypeMirror declaredType = atypeFactory.getAnnotatedType(methodElt).getReceiverType();
            if (declaredType == null) {
                // have a receiver).
                return;
            }
            AnnotatedTypeMirror inferredType = AnnotatedTypeMirror.createType(declaredType.getUnderlyingType(), atypeFactory, false);
            inferredType.replaceAnnotations(v.getAnnotations());
            atypeFactory.wpiAdjustForUpdateNonField(inferredType);
            T preOrPostConditionAnnos = storage.getPreOrPostconditions(preOrPost, methodElt, "this", declaredType, atypeFactory);
            if (preOrPostConditionAnnos != null) {
                String file = storage.getFileForElement(methodElt);
                updateAnnotationSet(preOrPostConditionAnnos, TypeUseLocation.PARAMETER, inferredType, declaredType, file, false);
            }
        }
    }
}
Also used : TypeElement(javax.lang.model.element.TypeElement) ClassName(org.checkerframework.dataflow.expression.ClassName) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) VariableElement(javax.lang.model.element.VariableElement) BugInCF(org.checkerframework.javacutil.BugInCF) ThisReference(org.checkerframework.dataflow.expression.ThisReference) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 8 with ThisReference

use of org.checkerframework.dataflow.expression.ThisReference 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)

Example 9 with ThisReference

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

the class LockAnnotatedTypeFactory method isExpressionEffectivelyFinal.

/**
 * Returns whether or not the expression is effectively final.
 *
 * <p>This method returns true in the following cases when expr is:
 *
 * <p>1. a field access and the field is final and the field access expression is effectively
 * final as specified by this method.
 *
 * <p>2. an effectively final local variable.
 *
 * <p>3. a deterministic method call whose arguments and receiver expression are effectively final
 * as specified by this method.
 *
 * <p>4. a this reference or a class literal
 *
 * @param expr expression
 * @return whether or not the expression is effectively final
 */
boolean isExpressionEffectivelyFinal(JavaExpression expr) {
    if (expr instanceof FieldAccess) {
        FieldAccess fieldAccess = (FieldAccess) expr;
        JavaExpression receiver = fieldAccess.getReceiver();
        // Don't call fieldAccess
        return fieldAccess.isFinal() && isExpressionEffectivelyFinal(receiver);
    } else if (expr instanceof LocalVariable) {
        return ElementUtils.isEffectivelyFinal(((LocalVariable) expr).getElement());
    } else if (expr instanceof MethodCall) {
        MethodCall methodCall = (MethodCall) expr;
        for (JavaExpression arg : methodCall.getArguments()) {
            if (!isExpressionEffectivelyFinal(arg)) {
                return false;
            }
        }
        return PurityUtils.isDeterministic(this, methodCall.getElement()) && isExpressionEffectivelyFinal(methodCall.getReceiver());
    } else if (expr instanceof ThisReference || expr instanceof ClassName) {
        // too.
        return true;
    } else {
        // type of 'expr' is not supported in @GuardedBy(...) lock expressions
        return false;
    }
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 10 with ThisReference

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

the class StringToJavaExpression method atFieldDecl.

/**
 * Parses a string to a {@link JavaExpression} as if it were written at {@code fieldElement}.
 *
 * @param expression a Java expression to parse
 * @param fieldElement variable element at which {@code expression} is parsed
 * @param checker checker used to get the {@link
 *     javax.annotation.processing.ProcessingEnvironment} and current {@link
 *     com.sun.source.tree.CompilationUnitTree}
 * @return a {@code JavaExpression} for {@code expression}
 * @throws JavaExpressionParseException if {@code expression} cannot be parsed
 */
static JavaExpression atFieldDecl(String expression, VariableElement fieldElement, SourceChecker checker) throws JavaExpressionParseException {
    TypeMirror enclosingType = ElementUtils.enclosingTypeElement(fieldElement).asType();
    ThisReference thisReference;
    if (ElementUtils.isStatic(fieldElement)) {
        // Can't use "this" on a static fieldElement
        thisReference = null;
    } else {
        thisReference = new ThisReference(enclosingType);
    }
    List<FormalParameter> parameters = null;
    return JavaExpressionParseUtil.parse(expression, enclosingType, thisReference, parameters, null, checker.getPathToCompilationUnit(), checker.getProcessingEnvironment());
}
Also used : FormalParameter(org.checkerframework.dataflow.expression.FormalParameter) TypeMirror(javax.lang.model.type.TypeMirror) ThisReference(org.checkerframework.dataflow.expression.ThisReference)

Aggregations

ThisReference (org.checkerframework.dataflow.expression.ThisReference)12 FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)7 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)7 ClassName (org.checkerframework.dataflow.expression.ClassName)6 FormalParameter (org.checkerframework.dataflow.expression.FormalParameter)5 TypeMirror (javax.lang.model.type.TypeMirror)4 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)4 MethodCall (org.checkerframework.dataflow.expression.MethodCall)3 AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 Element (javax.lang.model.element.Element)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 VariableElement (javax.lang.model.element.VariableElement)2 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)2 ViewpointAdaptJavaExpression (org.checkerframework.dataflow.expression.ViewpointAdaptJavaExpression)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 MethodTree (com.sun.source.tree.MethodTree)1 VariableTree (com.sun.source.tree.VariableTree)1 ArrayList (java.util.ArrayList)1 TypeElement (javax.lang.model.element.TypeElement)1 ValueLiteral (org.checkerframework.dataflow.expression.ValueLiteral)1