use of org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode in project checker-framework by typetools.
the class UpperBoundTransfer method refineSubtrahendWithOffset.
/**
* Refines the subtrahend in a subtraction which is greater than or equal to a certain offset.
* The type of the subtrahend is refined to the type of the minuend with the offset added. This
* is case 10.
*
* <p>This is based on the fact that if {@code (minuend - subtrahend) >= offset}, and {@code
* minuend + o < l}, then {@code subtrahend + o + offset < l}.
*
* <p>If {@code gtNode} is not a {@link NumericalSubtractionNode}, the method does nothing.
*
* @param gtNode the node that is greater or equal to the offset
* @param offsetNode a node part of the offset
* @param offsetAddOne whether to add one to the offset
* @param in input of the transfer function
* @param store location to store the refined types
*/
private void refineSubtrahendWithOffset(Node gtNode, Node offsetNode, boolean offsetAddOne, TransferInput<CFValue, CFStore> in, CFStore store) {
if (gtNode instanceof NumericalSubtractionNode) {
NumericalSubtractionNode subtractionNode = (NumericalSubtractionNode) gtNode;
Node minuend = subtractionNode.getLeftOperand();
UBQualifier minuendQual = getUBQualifier(minuend, in);
Node subtrahend = subtractionNode.getRightOperand();
UBQualifier subtrahendQual = getUBQualifier(subtrahend, in);
UBQualifier newQual = subtrahendQual.glb(minuendQual.plusOffset(offsetNode, atypeFactory).plusOffset(offsetAddOne ? 1 : 0));
Receiver subtrahendRec = FlowExpressions.internalReprOf(atypeFactory, subtrahend);
store.insertValue(subtrahendRec, atypeFactory.convertUBQualifierToAnnotation(newQual));
}
}
use of org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode in project checker-framework by typetools.
the class UpperBoundTransfer method propagateToOperands.
/**
* {@code node} is known to be {@code typeOfNode}. If the node is a plus or a minus then the
* types of the left and right operands can be refined to include offsets. If the node is a
* multiplication, its operands can also be refined. See {@link
* #propagateToAdditionOperand(LessThanLengthOf, Node, Node, TransferInput, CFStore)}, {@link
* #propagateToSubtractionOperands(LessThanLengthOf, NumericalSubtractionNode, TransferInput,
* CFStore)}, and {@link #propagateToMultiplicationOperand(LessThanLengthOf, Node, Node,
* TransferInput, CFStore)} for details.
*/
private void propagateToOperands(LessThanLengthOf typeOfNode, Node node, TransferInput<CFValue, CFStore> in, CFStore store) {
if (node instanceof NumericalAdditionNode) {
Node right = ((NumericalAdditionNode) node).getRightOperand();
Node left = ((NumericalAdditionNode) node).getLeftOperand();
propagateToAdditionOperand(typeOfNode, left, right, in, store);
propagateToAdditionOperand(typeOfNode, right, left, in, store);
} else if (node instanceof NumericalSubtractionNode) {
propagateToSubtractionOperands(typeOfNode, (NumericalSubtractionNode) node, in, store);
} else if (node instanceof NumericalMultiplicationNode) {
if (atypeFactory.hasLowerBoundTypeByClass(node, Positive.class)) {
Node right = ((NumericalMultiplicationNode) node).getRightOperand();
Node left = ((NumericalMultiplicationNode) node).getLeftOperand();
propagateToMultiplicationOperand(typeOfNode, left, right, in, store);
propagateToMultiplicationOperand(typeOfNode, right, left, in, store);
}
}
}
use of org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode 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.cfg.node.NumericalSubtractionNode in project checker-framework by typetools.
the class OffsetEquation method createOffsetFromNode.
private static void createOffsetFromNode(Node node, AnnotationProvider factory, OffsetEquation eq, char op) {
Receiver r = FlowExpressions.internalReprOf(factory, node);
if (r instanceof Unknown || r == null) {
if (node instanceof NumericalAdditionNode) {
createOffsetFromNode(((NumericalAdditionNode) node).getLeftOperand(), factory, eq, op);
createOffsetFromNode(((NumericalAdditionNode) node).getRightOperand(), factory, eq, op);
} else if (node instanceof NumericalSubtractionNode) {
createOffsetFromNode(((NumericalSubtractionNode) node).getLeftOperand(), factory, eq, op);
char other = op == '+' ? '-' : '+';
createOffsetFromNode(((NumericalSubtractionNode) node).getRightOperand(), factory, eq, other);
} else {
eq.error = node.toString();
}
} else {
eq.addTerm(op, r.toString());
}
}
Aggregations