use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method createAnnotationForStringConcatenation.
/**
* Creates an annotation for a result of string concatenation.
*/
private AnnotationMirror createAnnotationForStringConcatenation(Node leftOperand, Node rightOperand, TransferInput<CFValue, CFStore> p) {
// Try using sets of string values
List<String> leftValues = getStringValues(leftOperand, p);
List<String> rightValues = getStringValues(rightOperand, p);
if (leftValues != null && rightValues != null) {
// Both operands have known string values, compute set of results
List<String> concatValues = new ArrayList<>();
if (leftValues.isEmpty()) {
leftValues = Collections.singletonList("null");
}
if (rightValues.isEmpty()) {
rightValues = Collections.singletonList("null");
}
for (String left : leftValues) {
for (String right : rightValues) {
concatValues.add(left + right);
}
}
return atypefactory.createStringAnnotation(concatValues);
}
// Try using sets of lengths
List<Integer> leftLengths = leftValues != null ? ValueCheckerUtils.getLengthsForStringValues(leftValues) : getStringLengths(leftOperand, p);
List<Integer> rightLengths = rightValues != null ? ValueCheckerUtils.getLengthsForStringValues(rightValues) : getStringLengths(rightOperand, p);
if (leftLengths != null && rightLengths != null) {
// Both operands have known lengths, compute set of result lengths
List<Integer> concatLengths = calculateLengthAddition(leftLengths, rightLengths);
return atypefactory.createArrayLenAnnotation(concatLengths);
}
// Try using ranges of lengths
Range leftLengthRange = leftLengths != null ? ValueCheckerUtils.getRangeFromValues(leftLengths) : getStringLengthRange(leftOperand, p);
Range rightLengthRange = rightLengths != null ? ValueCheckerUtils.getRangeFromValues(rightLengths) : getStringLengthRange(rightOperand, p);
if (leftLengthRange != null && rightLengthRange != null) {
// Both operands have a length from a known range, compute a range of result lengths
Range concatLengthRange = calculateLengthRangeAddition(leftLengthRange, rightLengthRange);
return atypefactory.createArrayLenRangeAnnotation(concatLengthRange);
}
return atypefactory.UNKNOWNVAL;
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method refineIntRanges.
/**
* Calculates the result of a binary comparison on a pair of intRange annotations, and refines
* annotations appropriately.
*/
private List<Boolean> refineIntRanges(Node leftNode, AnnotationMirror leftAnno, Node rightNode, AnnotationMirror rightAnno, ComparisonOperators op, CFStore thenStore, CFStore elseStore) {
Range leftRange = getIntRangeFromAnnotation(leftNode, leftAnno);
Range rightRange = getIntRangeFromAnnotation(rightNode, rightAnno);
final Range thenRightRange;
final Range thenLeftRange;
final Range elseRightRange;
final Range elseLeftRange;
switch(op) {
case EQUAL:
thenRightRange = rightRange.refineEqualTo(leftRange);
// Only needs to be computed once.
thenLeftRange = thenRightRange;
elseRightRange = rightRange.refineNotEqualTo(leftRange);
elseLeftRange = leftRange.refineNotEqualTo(rightRange);
break;
case GREATER_THAN:
thenLeftRange = leftRange.refineGreaterThan(rightRange);
thenRightRange = rightRange.refineLessThan(leftRange);
elseRightRange = rightRange.refineGreaterThanEq(leftRange);
elseLeftRange = leftRange.refineLessThanEq(rightRange);
break;
case GREATER_THAN_EQ:
thenRightRange = rightRange.refineLessThanEq(leftRange);
thenLeftRange = leftRange.refineGreaterThanEq(rightRange);
elseLeftRange = leftRange.refineLessThan(rightRange);
elseRightRange = rightRange.refineGreaterThan(leftRange);
break;
case LESS_THAN:
thenLeftRange = leftRange.refineLessThan(rightRange);
thenRightRange = rightRange.refineGreaterThan(leftRange);
elseRightRange = rightRange.refineLessThanEq(leftRange);
elseLeftRange = leftRange.refineGreaterThanEq(rightRange);
break;
case LESS_THAN_EQ:
thenRightRange = rightRange.refineGreaterThanEq(leftRange);
thenLeftRange = leftRange.refineLessThanEq(rightRange);
elseLeftRange = leftRange.refineGreaterThan(rightRange);
elseRightRange = rightRange.refineLessThan(leftRange);
break;
case NOT_EQUAL:
thenRightRange = rightRange.refineNotEqualTo(leftRange);
thenLeftRange = leftRange.refineNotEqualTo(rightRange);
elseRightRange = rightRange.refineEqualTo(leftRange);
// Equality only needs to be computed once.
elseLeftRange = elseRightRange;
break;
default:
ErrorReporter.errorAbort("ValueTransfer: unsupported operation: " + op);
throw new RuntimeException("this is impossible, but javac issues a warning");
}
createAnnotationFromRangeAndAddToStore(thenStore, thenRightRange, rightNode);
createAnnotationFromRangeAndAddToStore(thenStore, thenLeftRange, leftNode);
createAnnotationFromRangeAndAddToStore(elseStore, elseRightRange, rightNode);
createAnnotationFromRangeAndAddToStore(elseStore, elseLeftRange, leftNode);
// TODO: Refine the type of the comparison.
return null;
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method getIntRangeFromAnnotation.
private Range getIntRangeFromAnnotation(Node node, AnnotationMirror val) {
Range range;
if (val == null || AnnotationUtils.areSameByClass(val, UnknownVal.class)) {
range = Range.EVERYTHING;
} else if (atypefactory.isIntRange(val)) {
range = ValueAnnotatedTypeFactory.getRange(val);
} else if (AnnotationUtils.areSameByClass(val, IntVal.class)) {
List<Long> values = ValueAnnotatedTypeFactory.getIntValues(val);
range = ValueCheckerUtils.getRangeFromValues(values);
} else if (AnnotationUtils.areSameByClass(val, DoubleVal.class)) {
List<Double> values = ValueAnnotatedTypeFactory.getDoubleValues(val);
range = ValueCheckerUtils.getRangeFromValues(values);
} else if (AnnotationUtils.areSameByClass(val, BottomVal.class)) {
return Range.NOTHING;
} else {
range = Range.EVERYTHING;
}
return NumberUtils.castRange(node.getType(), range);
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class IndexUtil method getMinValue.
/**
* Finds the minimum value in a Value Checker type. If there is no information (such as when the
* list of possible values is empty or null), returns null. Otherwise, returns the smallest
* value in the list of possible values.
*/
public static Long getMinValue(Tree tree, ValueAnnotatedTypeFactory factory) {
AnnotatedTypeMirror valueType = factory.getAnnotatedType(tree);
Range possibleValues = getPossibleValues(valueType, factory);
if (possibleValues != null) {
return possibleValues.from;
} else {
return null;
}
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class LowerBoundAnnotatedTypeFactory method getLowerBoundAnnotationFromValueType.
/**
* Returns the type in the lower bound hierarchy that a Value Checker type corresponds to.
*/
private AnnotationMirror getLowerBoundAnnotationFromValueType(AnnotatedTypeMirror valueType) {
Range possibleValues = getPossibleValues(valueType, getValueAnnotatedTypeFactory());
// possibleValues is null if the Value Checker does not have any estimate.
if (possibleValues == null) {
// when there is a BottomVal annotation. In that case, give this the LBC's bottom type.
if (AnnotationUtils.containsSameByClass(valueType.getAnnotations(), BottomVal.class)) {
return BOTTOM;
}
return UNKNOWN;
}
// The annotation of the whole list is the min of the list.
long lvalMin = possibleValues.from;
// Turn it into an integer.
int valMin = (int) Math.max(Math.min(Integer.MAX_VALUE, lvalMin), Integer.MIN_VALUE);
return anmFromVal(valMin);
}
Aggregations