use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver 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.Receiver in project checker-framework by typetools.
the class UpperBoundTransfer method propagateToAdditionOperand.
/**
* Refines the type of {@code operand} to {@code typeOfAddition} plus {@code other}. If {@code
* other} is non-negative, then {@code operand} also less than the length of the arrays in
* {@code typeOfAddition}. If {@code other} is positive, then {@code operand} also less than the
* length of the arrays in {@code typeOfAddition} plus 1. These are cases 5, 6, and 7.
*
* @param typeOfAddition type of {@code operand + other}
* @param operand the Node to refine
* @param other the Node added to {@code operand}
* @param in TransferInput
* @param store location to store the refined types
*/
private void propagateToAdditionOperand(LessThanLengthOf typeOfAddition, Node operand, Node other, TransferInput<CFValue, CFStore> in, CFStore store) {
UBQualifier operandQual = getUBQualifier(operand, in);
UBQualifier newQual = operandQual.glb(typeOfAddition.plusOffset(other, atypeFactory));
/**
* If the node is NN, add an LTEL to the qual. If POS, add an LTL.
*/
if (atypeFactory.hasLowerBoundTypeByClass(other, Positive.class)) {
newQual = newQual.glb(typeOfAddition.plusOffset(1));
} else if (atypeFactory.hasLowerBoundTypeByClass(other, NonNegative.class)) {
newQual = newQual.glb(typeOfAddition);
}
Receiver operandRec = FlowExpressions.internalReprOf(atypeFactory, operand);
store.insertValue(operandRec, atypeFactory.convertUBQualifierToAnnotation(newQual));
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.
the class UpperBoundTransfer method refineEq.
/**
* Refines the type of the left and right node to glb of the left and right annotation.
*/
private void refineEq(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store) {
UBQualifier leftQualifier = UBQualifier.createUBQualifier(leftAnno);
UBQualifier rightQualifier = UBQualifier.createUBQualifier(rightAnno);
UBQualifier glb = rightQualifier.glb(leftQualifier);
AnnotationMirror glbAnno = atypeFactory.convertUBQualifierToAnnotation(glb);
List<Node> internalsRight = splitAssignments(right);
for (Node internal : internalsRight) {
Receiver rightRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
store.insertValue(rightRec, glbAnno);
}
List<Node> internalsLeft = splitAssignments(left);
for (Node internal : internalsLeft) {
Receiver leftRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
store.insertValue(leftRec, glbAnno);
}
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.
the class UpperBoundTransfer method visitMethodInvocation.
/**
* If n is a String.length() method invocation, then the type of s.length() is the glb
* of @LTEqLengthOf("s") and the value of s.length() in the store. This is case 20.
*/
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(n)) {
Receiver stringLength = FlowExpressions.internalReprOf(atypeFactory, n);
if (stringLength instanceof MethodCall) {
Receiver receiverRec = ((MethodCall) stringLength).getReceiver();
Tree receiverTree = n.getTarget().getReceiver().getTree();
// receiverTree is null when the receiver is implicit "this".
if (receiverTree != null) {
TransferResult<CFValue, CFStore> result = visitLengthAccess(n, in, receiverRec, receiverTree);
if (result != null) {
return result;
}
}
}
}
return super.visitMethodInvocation(n, in);
}
use of org.checkerframework.dataflow.analysis.FlowExpressions.Receiver in project checker-framework by typetools.
the class UpperBoundTransfer method visitAssignment.
/**
* Case 1: Refine the type of expressions used as an array dimension to be less than length of
* the array to which the new array is assigned. For example, in "int[] array = new int[expr];",
* the type of expr is @LTEqLength("array").
*/
@Override
public TransferResult<CFValue, CFStore> visitAssignment(AssignmentNode node, TransferInput<CFValue, CFStore> in) {
TransferResult<CFValue, CFStore> result = super.visitAssignment(node, in);
Node expNode = node.getExpression();
// strip off typecast if any
Node expNodeSansCast = (expNode instanceof TypeCastNode) ? ((TypeCastNode) expNode).getOperand() : expNode;
// null if right-hand-side is not an array creation expression
ArrayCreationNode acNode = (expNodeSansCast instanceof ArrayCreationNode) ? acNode = (ArrayCreationNode) expNodeSansCast : null;
if (acNode != null) {
// Right-hand side of assignment is an array creation expression
List<Node> nodeList = acNode.getDimensions();
if (nodeList.size() < 1) {
return result;
}
Node dim = acNode.getDimension(0);
UBQualifier previousQualifier = getUBQualifier(dim, in);
Receiver arrayRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), node.getTarget());
String arrayString = arrayRec.toString();
LessThanLengthOf newInfo = (LessThanLengthOf) UBQualifier.createUBQualifier(arrayString, "-1");
UBQualifier combined = previousQualifier.glb(newInfo);
AnnotationMirror newAnno = atypeFactory.convertUBQualifierToAnnotation(combined);
Receiver dimRec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), dim);
result.getRegularStore().insertValue(dimRec, newAnno);
propagateToOperands(newInfo, dim, in, result.getRegularStore());
}
return result;
}
Aggregations