use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.
the class CFAbstractTransfer method strengthenAnnotationOfEqualTo.
/**
* Refine the annotation of {@code secondNode} if the annotation {@code secondValue} is less
* precise than {@code firstvalue}. This is possible, if {@code secondNode} is an expression
* that is tracked by the store (e.g., a local variable or a field).
*
* <p>Note that when overriding this method, when a new type is inserted into the store,
* splitAssignments should be called, and the new type should be inserted into the store for
* each of the resulting nodes.
*
* @param res the previous result
* @param notEqualTo if true, indicates that the logic is flipped (i.e., the information is
* added to the {@code elseStore} instead of the {@code thenStore}) for a not-equal
* comparison.
* @return the conditional transfer result (if information has been added), or {@code null}.
*/
protected TransferResult<V, S> strengthenAnnotationOfEqualTo(TransferResult<V, S> res, Node firstNode, Node secondNode, V firstValue, V secondValue, boolean notEqualTo) {
if (firstValue != null) {
// Only need to insert if the second value is actually different.
if (!firstValue.equals(secondValue)) {
List<Node> secondParts = splitAssignments(secondNode);
for (Node secondPart : secondParts) {
Receiver secondInternal = FlowExpressions.internalReprOf(analysis.getTypeFactory(), secondPart);
if (CFAbstractStore.canInsertReceiver(secondInternal)) {
S thenStore = res.getThenStore();
S elseStore = res.getElseStore();
if (notEqualTo) {
elseStore.insertValue(secondInternal, firstValue);
} else {
thenStore.insertValue(secondInternal, firstValue);
}
// To handle `(a = b = c) == x`, repeat for all insertable receivers of
// splitted assignments instead of returning.
res = new ConditionalTransferResult<>(res.getResultValue(), thenStore, elseStore);
}
}
}
}
return res;
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver 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.Receiver in project checker-framework by typetools.
the class BaseTypeVisitor method checkContractsSubset.
/**
* Checks that {@code mustSubset} is a subset of {@code set} in the following sense: For every
* expression in {@code mustSubset} there must be the same expression in {@code set}, with the
* same (or a stronger) annotation.
*/
private void checkContractsSubset(String overriderMeth, String overriderTyp, String overriddenMeth, String overriddenTyp, Set<Pair<Receiver, AnnotationMirror>> mustSubset, Set<Pair<Receiver, AnnotationMirror>> set, @CompilerMessageKey String messageKey) {
for (Pair<Receiver, AnnotationMirror> weak : mustSubset) {
boolean found = false;
for (Pair<Receiver, AnnotationMirror> strong : set) {
// are we looking at a contract of the same receiver?
if (weak.first.equals(strong.first)) {
// check subtyping relationship of annotations
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
if (qualifierHierarchy.isSubtype(strong.second, weak.second)) {
found = true;
break;
}
}
}
if (!found) {
MethodTree method = visitorState.getMethodTree();
checker.report(Result.failure(messageKey, overriderMeth, overriderTyp, overriddenMeth, overriddenTyp, weak.second, weak.first), method);
}
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.
the class ValueTransfer method addAnnotationToStore.
private void addAnnotationToStore(CFStore store, AnnotationMirror anno, Node node) {
for (Node internal : splitAssignments(node)) {
AnnotationMirror currentAnno = atypefactory.getAnnotatedType(internal.getTree()).getAnnotationInHierarchy(atypefactory.BOTTOMVAL);
Receiver rec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
// Combine the new annotations based on the results of the comparison with the existing
// type.
store.insertValue(rec, atypefactory.getQualifierHierarchy().greatestLowerBound(anno, currentAnno));
if (node instanceof FieldAccessNode) {
refineArrayAtLengthAccess((FieldAccessNode) internal, store);
} else if (node instanceof MethodInvocationNode) {
refineStringAtLengthInvocation((MethodInvocationNode) internal, store);
}
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver 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);
}
Aggregations