use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.
the class FlowExpressionParseUtil method parseArray.
private static Receiver parseArray(String s, FlowExpressionContext context, TreePath path) throws FlowExpressionParseException {
Pair<Pair<String, String>, String> array = parseArray(s);
if (array == null) {
return null;
}
String receiverStr = array.first.first;
String indexStr = array.first.second;
Receiver receiver = parseHelper(receiverStr, context, path);
FlowExpressionContext contextForIndex = context.copyAndUseOuterReceiver();
Receiver index = parseHelper(indexStr, contextForIndex, path);
TypeMirror receiverType = receiver.getType();
if (!(receiverType instanceof ArrayType)) {
throw constructParserException(s, String.format("receiver not an array: %s : %s", receiver, receiverType));
}
TypeMirror componentType = ((ArrayType) receiverType).getComponentType();
ArrayAccess result = new ArrayAccess(componentType, receiver, index);
return result;
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.
the class CFAbstractStore method insertValue.
/**
* Add the abstract value {@code value} for the expression {@code r} (correctly deciding where
* to store the information depending on the type of the expression {@code r}).
*
* <p>This method does not take care of removing other information that might be influenced by
* changes to certain parts of the state.
*
* <p>If there is already a value {@code v} present for {@code r}, then the stronger of the new
* and old value are taken (according to the lattice). Note that this happens per hierarchy, and
* if the store already contains information about a hierarchy for which {@code value} does not
* contain information, then that information is preserved.
*/
public void insertValue(FlowExpressions.Receiver r, @Nullable V value) {
if (value == null) {
// top and top is also the default value.
return;
}
if (r.containsUnknown()) {
// Expressions containing unknown expressions are not stored.
return;
}
if (r instanceof FlowExpressions.LocalVariable) {
FlowExpressions.LocalVariable localVar = (FlowExpressions.LocalVariable) r;
V oldValue = localVariableValues.get(localVar);
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
localVariableValues.put(localVar, newValue);
}
} else if (r instanceof FlowExpressions.FieldAccess) {
FlowExpressions.FieldAccess fieldAcc = (FlowExpressions.FieldAccess) r;
// 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.isUnmodifiableByOtherCode()) {
V oldValue = fieldValues.get(fieldAcc);
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
fieldValues.put(fieldAcc, newValue);
}
}
} else if (r instanceof FlowExpressions.MethodCall) {
FlowExpressions.MethodCall method = (FlowExpressions.MethodCall) r;
// Don't store any information if concurrent semantics are enabled.
if (sequentialSemantics) {
V oldValue = methodValues.get(method);
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
methodValues.put(method, newValue);
}
}
} else if (r instanceof FlowExpressions.ArrayAccess) {
FlowExpressions.ArrayAccess arrayAccess = (ArrayAccess) r;
if (sequentialSemantics) {
V oldValue = arrayValues.get(arrayAccess);
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
arrayValues.put(arrayAccess, newValue);
}
}
} else if (r instanceof FlowExpressions.ThisReference) {
FlowExpressions.ThisReference thisRef = (FlowExpressions.ThisReference) r;
if (sequentialSemantics || thisRef.isUnmodifiableByOtherCode()) {
V oldValue = thisValue;
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
thisValue = newValue;
}
}
} else if (r instanceof FlowExpressions.ClassName) {
FlowExpressions.ClassName className = (FlowExpressions.ClassName) r;
if (sequentialSemantics || className.isUnmodifiableByOtherCode()) {
V oldValue = classValues.get(className);
V newValue = value.mostSpecific(oldValue, null);
if (newValue != null) {
classValues.put(className, newValue);
}
}
} else {
// No other types of expressions need to be stored.
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess 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(FlowExpressions.ArrayAccess arrayAccess, @Nullable V val) {
Map<FlowExpressions.ArrayAccess, V> newArrayValues = new HashMap<>();
for (Entry<FlowExpressions.ArrayAccess, V> e : arrayValues.entrySet()) {
FlowExpressions.ArrayAccess otherArrayAccess = e.getKey();
V otherVal = e.getValue();
// case 1:
if (otherArrayAccess.containsModifiableAliasOf(this, arrayAccess)) {
// remove information completely
continue;
}
if (canAlias(arrayAccess.getReceiver(), otherArrayAccess.getReceiver())) {
// remove information completely
continue;
}
// information is save to be carried over
newArrayValues.put(otherArrayAccess, otherVal);
}
arrayValues = newArrayValues;
// case 2:
Map<FlowExpressions.FieldAccess, V> newFieldValues = new HashMap<>();
for (Entry<FieldAccess, V> e : fieldValues.entrySet()) {
FlowExpressions.FieldAccess otherFieldAccess = e.getKey();
V otherVal = e.getValue();
Receiver receiver = otherFieldAccess.getReceiver();
if (receiver.containsModifiableAliasOf(this, arrayAccess) && receiver.containsOfClass(ArrayAccess.class)) {
// remove information completely
continue;
}
newFieldValues.put(otherFieldAccess, otherVal);
}
fieldValues = newFieldValues;
// case 3:
methodValues = new HashMap<>();
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess in project checker-framework by typetools.
the class CFAbstractStore method clearValue.
/**
* Remove any knowledge about the expression {@code r} (correctly deciding where to remove the
* information depending on the type of the expression {@code r}).
*/
public void clearValue(FlowExpressions.Receiver r) {
if (r.containsUnknown()) {
// Expressions containing unknown expressions are not stored.
return;
}
if (r instanceof FlowExpressions.LocalVariable) {
FlowExpressions.LocalVariable localVar = (FlowExpressions.LocalVariable) r;
localVariableValues.remove(localVar);
} else if (r instanceof FlowExpressions.FieldAccess) {
FlowExpressions.FieldAccess fieldAcc = (FlowExpressions.FieldAccess) r;
fieldValues.remove(fieldAcc);
} else if (r instanceof FlowExpressions.MethodCall) {
MethodCall method = (MethodCall) r;
methodValues.remove(method);
} else if (r instanceof FlowExpressions.ArrayAccess) {
ArrayAccess a = (ArrayAccess) r;
arrayValues.remove(a);
} else if (r instanceof FlowExpressions.ClassName) {
FlowExpressions.ClassName c = (FlowExpressions.ClassName) r;
classValues.remove(c);
} else {
// thisValue ...
// No other types of expressions are stored.
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess 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(FlowExpressions.FieldAccess fieldAccess, @Nullable V val) {
Map<FlowExpressions.FieldAccess, V> newFieldValues = new HashMap<>();
for (Entry<FlowExpressions.FieldAccess, V> e : fieldValues.entrySet()) {
FlowExpressions.FieldAccess otherFieldAccess = e.getKey();
V otherVal = e.getValue();
// case 2:
if (otherFieldAccess.getReceiver().containsModifiableAliasOf(this, fieldAccess)) {
// remove information completely
continue;
}
// 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);
newFieldValues.put(otherFieldAccess, newVal);
} else {
// remove information completely
}
continue;
}
}
}
// information is save to be carried over
newFieldValues.put(otherFieldAccess, otherVal);
}
fieldValues = newFieldValues;
Map<FlowExpressions.ArrayAccess, V> newArrayValues = new HashMap<>();
for (Entry<ArrayAccess, V> e : arrayValues.entrySet()) {
FlowExpressions.ArrayAccess otherArrayAccess = e.getKey();
V otherVal = e.getValue();
if (otherArrayAccess.containsModifiableAliasOf(this, fieldAccess)) {
// remove information completely
continue;
}
newArrayValues.put(otherArrayAccess, otherVal);
}
arrayValues = newArrayValues;
// case 3:
methodValues = new HashMap<>();
}
Aggregations