use of org.checkerframework.dataflow.expression.FieldAccess in project checker-framework by typetools.
the class LockStore method insertLockPossiblyHeld.
/*
* Insert an annotation exactly, without regard to whether an annotation was already present.
* This is only done for @LockPossiblyHeld. This is not sound for other type qualifiers.
*/
public void insertLockPossiblyHeld(JavaExpression je) {
if (je.containsUnknown()) {
// Expressions containing unknown expressions are not stored.
return;
}
if (je instanceof LocalVariable) {
LocalVariable localVar = (LocalVariable) je;
CFValue current = localVariableValues.get(localVar);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
localVariableValues.put(localVar, value);
}
} else if (je instanceof FieldAccess) {
FieldAccess fieldAcc = (FieldAccess) je;
CFValue current = fieldValues.get(fieldAcc);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
fieldValues.put(fieldAcc, value);
}
} else if (je instanceof MethodCall) {
MethodCall method = (MethodCall) je;
CFValue current = methodValues.get(method);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
methodValues.put(method, value);
}
} else if (je instanceof ArrayAccess) {
ArrayAccess arrayAccess = (ArrayAccess) je;
CFValue current = arrayValues.get(arrayAccess);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
arrayValues.put(arrayAccess, value);
}
} else if (je instanceof ThisReference) {
thisValue = changeLockAnnoToTop(je, thisValue);
} else if (je instanceof ClassName) {
ClassName className = (ClassName) je;
CFValue current = classValues.get(className);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
classValues.put(className, value);
}
} else {
// No other types of expressions need to be stored.
}
}
use of org.checkerframework.dataflow.expression.FieldAccess in project checker-framework by typetools.
the class LessThanAnnotatedTypeFactory method getMinValueFromString.
/**
* Returns the minimum value of {@code expression} at {@code tree}.
*
* @param expression the expression whose minimum value to retrieve
* @param tree where to determine the value
* @param path the path to {@code tree}
* @return the minimum value of {@code expression} at {@code tree}
*/
private long getMinValueFromString(String expression, Tree tree, TreePath path) {
ValueAnnotatedTypeFactory valueAtypeFactory = getValueAnnotatedTypeFactory();
JavaExpression expressionJe;
try {
expressionJe = valueAtypeFactory.parseJavaExpressionString(expression, path);
} catch (JavaExpressionParseException e) {
return Long.MIN_VALUE;
}
AnnotationMirror intRange = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, IntRange.class);
if (intRange != null) {
return valueAtypeFactory.getRange(intRange).from;
}
AnnotationMirror intValue = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, IntVal.class);
if (intValue != null) {
List<Long> possibleValues = valueAtypeFactory.getIntValues(intValue);
return Collections.min(possibleValues);
}
if (expressionJe instanceof FieldAccess) {
FieldAccess fieldAccess = ((FieldAccess) expressionJe);
if (fieldAccess.getReceiver().getType().getKind() == TypeKind.ARRAY) {
// array.length might not be in the store, so check for the length of the array.
AnnotationMirror arrayRange = valueAtypeFactory.getAnnotationFromJavaExpression(fieldAccess.getReceiver(), tree, ArrayLenRange.class);
if (arrayRange != null) {
return valueAtypeFactory.getRange(arrayRange).from;
}
AnnotationMirror arrayLen = valueAtypeFactory.getAnnotationFromJavaExpression(expressionJe, tree, ArrayLen.class);
if (arrayLen != null) {
List<Integer> possibleValues = valueAtypeFactory.getArrayLength(arrayLen);
return Collections.min(possibleValues);
}
// Even arrays that we know nothing about must have at least zero length.
return 0;
}
}
return Long.MIN_VALUE;
}
use of org.checkerframework.dataflow.expression.FieldAccess 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.FieldAccess in project checker-framework by typetools.
the class CFAbstractStore method removeConflicting.
/**
* Remove any information in this store that might not be true any more after {@code fieldAccess}
* has been assigned a new value (with the abstract value {@code val}). This includes the
* following steps (assume that {@code fieldAccess} is of the form <em>a.f</em> for some
* <em>a</em>.
*
* <ol>
* <li value="1">Update the abstract value of other field accesses <em>b.g</em> where the field
* is equal (that is, <em>f=g</em>), and the receiver <em>b</em> might alias the receiver of
* {@code fieldAccess}, <em>a</em>. This update will raise the abstract value for such field
* accesses to at least {@code val} (or the old value, if that was less precise). However,
* this is only necessary if the field <em>g</em> is not final.
* <li value="2">Remove any abstract values for field accesses <em>b.g</em> where {@code
* fieldAccess} might alias any expression in the receiver <em>b</em>.
* <li value="3">Remove any information about method calls.
* <li value="4">Remove any abstract values an array access <em>b[i]</em> where {@code
* fieldAccess} might alias any expression in the receiver <em>a</em> or index <em>i</em>.
* </ol>
*
* @param val the abstract value of the value assigned to {@code n} (or {@code null} if the
* abstract value is not known).
*/
protected void removeConflicting(FieldAccess fieldAccess, @Nullable V val) {
final Iterator<Map.Entry<FieldAccess, V>> fieldValuesIterator = fieldValues.entrySet().iterator();
while (fieldValuesIterator.hasNext()) {
Map.Entry<FieldAccess, V> entry = fieldValuesIterator.next();
FieldAccess otherFieldAccess = entry.getKey();
V otherVal = entry.getValue();
// case 2:
if (otherFieldAccess.getReceiver().containsModifiableAliasOf(this, fieldAccess)) {
// remove information completely
fieldValuesIterator.remove();
} else // case 1:
if (fieldAccess.getField().equals(otherFieldAccess.getField())) {
if (canAlias(fieldAccess.getReceiver(), otherFieldAccess.getReceiver())) {
if (!otherFieldAccess.isFinal()) {
if (val != null) {
V newVal = val.leastUpperBound(otherVal);
entry.setValue(newVal);
} else {
// remove information completely
fieldValuesIterator.remove();
}
}
}
}
}
final Iterator<Map.Entry<ArrayAccess, V>> arrayValuesIterator = arrayValues.entrySet().iterator();
while (arrayValuesIterator.hasNext()) {
Map.Entry<ArrayAccess, V> entry = arrayValuesIterator.next();
ArrayAccess otherArrayAccess = entry.getKey();
if (otherArrayAccess.containsModifiableAliasOf(this, fieldAccess)) {
// remove information completely
arrayValuesIterator.remove();
}
}
// case 3:
methodValues.clear();
}
use of org.checkerframework.dataflow.expression.FieldAccess in project checker-framework by typetools.
the class CFAbstractStore method removeConflicting.
/**
* Remove any information in the store that might not be true any more after {@code arrayAccess}
* has been assigned a new value (with the abstract value {@code val}). This includes the
* following steps (assume that {@code arrayAccess} is of the form <em>a[i]</em> for some
* <em>a</em>.
*
* <ol>
* <li value="1">Remove any abstract value for other array access <em>b[j]</em> where <em>a</em>
* and <em>b</em> can be aliases, or where either <em>b</em> or <em>j</em> contains a
* modifiable alias of <em>a[i]</em>.
* <li value="2">Remove any abstract values for field accesses <em>b.g</em> where <em>a[i]</em>
* might alias any expression in the receiver <em>b</em> and there is an array expression
* somewhere in the receiver.
* <li value="3">Remove any information about method calls.
* </ol>
*
* @param val the abstract value of the value assigned to {@code n} (or {@code null} if the
* abstract value is not known).
*/
protected void removeConflicting(ArrayAccess arrayAccess, @Nullable V val) {
final Iterator<Map.Entry<ArrayAccess, V>> arrayValuesIterator = arrayValues.entrySet().iterator();
while (arrayValuesIterator.hasNext()) {
Map.Entry<ArrayAccess, V> entry = arrayValuesIterator.next();
ArrayAccess otherArrayAccess = entry.getKey();
// case 1:
if (otherArrayAccess.containsModifiableAliasOf(this, arrayAccess)) {
// remove information completely
arrayValuesIterator.remove();
} else if (canAlias(arrayAccess.getArray(), otherArrayAccess.getArray())) {
// TODO: one could be less strict here, and only raise the abstract
// value for all array expressions with potentially aliasing receivers.
// remove information completely
arrayValuesIterator.remove();
}
}
// case 2:
final Iterator<Map.Entry<FieldAccess, V>> fieldValuesIterator = fieldValues.entrySet().iterator();
while (fieldValuesIterator.hasNext()) {
Map.Entry<FieldAccess, V> entry = fieldValuesIterator.next();
FieldAccess otherFieldAccess = entry.getKey();
JavaExpression otherReceiver = otherFieldAccess.getReceiver();
if (otherReceiver.containsModifiableAliasOf(this, arrayAccess) && otherReceiver.containsOfClass(ArrayAccess.class)) {
// remove information completely
fieldValuesIterator.remove();
}
}
// case 3:
methodValues.clear();
}
Aggregations