use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess in project checker-framework by typetools.
the class CFAbstractTransfer method addFieldValues.
private void addFieldValues(S info, AnnotatedTypeFactory factory, ClassTree classTree, MethodTree methodTree) {
// Add knowledge about final fields, or values of non-final fields
// if we are inside a constructor (information about initializers)
TypeMirror classType = TreeUtils.typeOf(classTree);
List<Pair<VariableElement, V>> fieldValues = analysis.getFieldValues();
for (Pair<VariableElement, V> p : fieldValues) {
VariableElement element = p.first;
V value = p.second;
if (ElementUtils.isFinal(element) || TreeUtils.isConstructor(methodTree)) {
Receiver receiver;
if (ElementUtils.isStatic(element)) {
receiver = new ClassName(classType);
} else {
receiver = new ThisReference(classType);
}
TypeMirror fieldType = ElementUtils.getType(element);
Receiver field = new FieldAccess(receiver, fieldType, element);
info.insertValue(field, value);
}
}
// add properties about fields (static information from type)
boolean isNotFullyInitializedReceiver = isNotFullyInitializedReceiver(methodTree);
if (isNotFullyInitializedReceiver && !TreeUtils.isConstructor(methodTree)) {
// and the method isn't a constructor
return;
}
for (Tree member : classTree.getMembers()) {
if (member instanceof VariableTree) {
VariableTree vt = (VariableTree) member;
final VariableElement element = TreeUtils.elementFromDeclaration(vt);
AnnotatedTypeMirror type = ((GenericAnnotatedTypeFactory<?, ?, ?, ?>) factory).getAnnotatedTypeLhs(vt);
TypeMirror fieldType = ElementUtils.getType(element);
Receiver receiver;
if (ElementUtils.isStatic(element)) {
receiver = new ClassName(classType);
} else {
receiver = new ThisReference(classType);
}
V value = analysis.createAbstractValue(type);
if (value == null)
continue;
if (TreeUtils.isConstructor(methodTree)) {
// if we are in a constructor,
// then we can still use the static type, but only
// if there is also an initializer that already does
// some initialization.
boolean found = false;
for (Pair<VariableElement, V> fieldValue : fieldValues) {
if (fieldValue.first.equals(element)) {
value = value.leastUpperBound(fieldValue.second);
found = true;
break;
}
}
if (!found) {
// no initializer found, cannot use static type
continue;
}
}
Receiver field = new FieldAccess(receiver, fieldType, element);
info.insertValue(field, value);
}
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess in project checker-framework by typetools.
the class FlowExpressionParseUtil method getReceiverField.
private static Receiver getReceiverField(String s, FlowExpressionContext context, boolean originalReceiver, VariableElement fieldElem) throws FlowExpressionParseException {
TypeMirror receiverType = context.receiver.getType();
TypeMirror fieldType = ElementUtils.getType(fieldElem);
if (ElementUtils.isStatic(fieldElem)) {
Element classElem = fieldElem.getEnclosingElement();
Receiver staticClassReceiver = new ClassName(ElementUtils.getType(classElem));
return new FieldAccess(staticClassReceiver, fieldType, fieldElem);
}
Receiver locationOfField;
if (originalReceiver) {
locationOfField = context.receiver;
} else {
locationOfField = FlowExpressions.internalReprOf(context.checkerContext.getAnnotationProvider(), new ImplicitThisLiteralNode(receiverType));
}
if (locationOfField instanceof ClassName) {
throw constructParserException(s, "a non-static field cannot have a class name as a receiver.");
}
return new FieldAccess(locationOfField, fieldType, fieldElem);
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess in project checker-framework by typetools.
the class UpperBoundTransfer method refineNeqSequenceLength.
/**
* If lengthAccess node is an sequence length field or method access (optionally with a constant
* offset subtracted) and the other node is less than or equal to that sequence length (minus
* the offset), then refine the other node's type to less than the sequence length (minus the
* offset). This is case 12.
*/
private void refineNeqSequenceLength(Node lengthAccess, Node otherNode, AnnotationMirror otherNodeAnno, CFStore store) {
Receiver receiver = null;
// If lengthAccess is "receiver.length - c" where c is an integer constant, stores c
// into lengthOffset
int lengthOffset = 0;
if (lengthAccess instanceof NumericalSubtractionNode) {
NumericalSubtractionNode subtraction = (NumericalSubtractionNode) lengthAccess;
Node offsetNode = subtraction.getRightOperand();
Long offsetValue = IndexUtil.getExactValue(offsetNode.getTree(), atypeFactory.getValueAnnotatedTypeFactory());
if (offsetValue != null && offsetValue > Integer.MIN_VALUE && offsetValue <= Integer.MAX_VALUE) {
lengthOffset = offsetValue.intValue();
lengthAccess = subtraction.getLeftOperand();
} else {
// Subtraction of non-constant expressions is not supported
return;
}
}
if (NodeUtils.isArrayLengthFieldAccess(lengthAccess)) {
FieldAccess fa = FlowExpressions.internalReprOfFieldAccess(atypeFactory, (FieldAccessNode) lengthAccess);
receiver = fa.getReceiver();
} else if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(lengthAccess)) {
Receiver ma = FlowExpressions.internalReprOf(atypeFactory, lengthAccess);
if (ma instanceof MethodCall) {
receiver = ((MethodCall) ma).getReceiver();
}
}
if (receiver != null && !receiver.containsUnknown()) {
UBQualifier otherQualifier = UBQualifier.createUBQualifier(otherNodeAnno);
String sequence = receiver.toString();
// Check if otherNode + c - 1 < receiver.length
if (otherQualifier.hasSequenceWithOffset(sequence, lengthOffset - 1)) {
// Add otherNode + c < receiver.length
UBQualifier newQualifier = UBQualifier.createUBQualifier(sequence, Integer.toString(lengthOffset));
otherQualifier = otherQualifier.glb(newQualifier);
for (Node internal : splitAssignments(otherNode)) {
Receiver leftRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
store.insertValue(leftRec, atypeFactory.convertUBQualifierToAnnotation(otherQualifier));
}
}
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess in project checker-framework by typetools.
the class InitializationStore method supersetOf.
@Override
protected boolean supersetOf(CFAbstractStore<V, S> o) {
if (!(o instanceof InitializationStore)) {
return false;
}
@SuppressWarnings("unchecked") S other = (S) o;
for (Element field : other.initializedFields) {
if (!initializedFields.contains(field)) {
return false;
}
}
for (FieldAccess invariantField : other.invariantFields.keySet()) {
if (!invariantFields.containsKey(invariantField)) {
return false;
}
}
Map<FlowExpressions.FieldAccess, V> removedFieldValues = new HashMap<>();
Map<FlowExpressions.FieldAccess, V> removedOtherFieldValues = new HashMap<>();
try {
// Remove invariant annotated fields to avoid performance issue reported in #1438.
for (FieldAccess invariantField : invariantFields.keySet()) {
V v = fieldValues.remove(invariantField);
removedFieldValues.put(invariantField, v);
}
for (FieldAccess invariantField : other.invariantFields.keySet()) {
V v = other.fieldValues.remove(invariantField);
removedOtherFieldValues.put(invariantField, v);
}
return super.supersetOf(other);
} finally {
// Restore removed values.
fieldValues.putAll(removedFieldValues);
other.fieldValues.putAll(removedOtherFieldValues);
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess in project checker-framework by typetools.
the class InitializationStore method insertValue.
/**
* {@inheritDoc}
*
* <p>If the receiver is a field, and has an invariant annotation, then it can be considered
* initialized.
*/
@Override
public void insertValue(Receiver r, V value) {
if (value == null) {
// top and top is also the default value.
return;
}
InitializationAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory = (InitializationAnnotatedTypeFactory<?, ?, ?, ?>) analysis.getTypeFactory();
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
AnnotationMirror invariantAnno = atypeFactory.getFieldInvariantAnnotation();
// Remember fields that have the 'invariant' annotation in the store.
if (r instanceof FieldAccess) {
FieldAccess fieldAccess = (FieldAccess) r;
if (!fieldValues.containsKey(r)) {
Set<AnnotationMirror> declaredAnnos = atypeFactory.getAnnotatedType(fieldAccess.getField()).getAnnotations();
if (AnnotationUtils.containsSame(declaredAnnos, invariantAnno)) {
if (!invariantFields.containsKey(fieldAccess)) {
invariantFields.put(fieldAccess, analysis.createSingleAnnotationValue(invariantAnno, r.getType()));
}
}
}
}
super.insertValue(r, value);
for (AnnotationMirror a : value.getAnnotations()) {
if (qualifierHierarchy.isSubtype(a, invariantAnno)) {
if (r instanceof FieldAccess) {
FieldAccess fa = (FieldAccess) r;
if (fa.getReceiver() instanceof ThisReference || fa.getReceiver() instanceof ClassName) {
addInitializedField(fa.getField());
}
}
}
}
}
Aggregations