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.
}
}
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);
}
}
}
}
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);
}
}
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;
}
}
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());
}
Aggregations