Class LowerBoundTransfer
java.lang.Object
org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor<TransferResult<CFValue,CFStore>,TransferInput<CFValue,CFStore>>
org.checkerframework.framework.flow.CFAbstractTransfer<CFValue,CFStore,CFTransfer>
org.checkerframework.framework.flow.CFTransfer
org.checkerframework.checker.index.IndexAbstractTransfer
org.checkerframework.checker.index.lowerbound.LowerBoundTransfer
- All Implemented Interfaces:
ForwardTransferFunction<CFValue,,CFStore> TransferFunction<CFValue,,CFStore> NodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
Implements dataflow refinement rules based on tests: <, >, ==, and their derivatives.
Also implements the logic for binary operations: +, -, *, /, and %.
>, <, ≥, ≤, ==, and != nodes are represented as combinations of > and ≥ (e.g. == is ≥ in both directions in the then branch), and implement refinements based on these decompositions.
Refinement/transfer rules for conditionals:
There are two "primitives":
x > y, which implies things about x based on y's type:
y has type: implies x has type:
gte-1 nn
nn pos
pos pos
and x ≥ y:
y has type: implies x has type:
gte-1 gte-1
nn nn
pos pos
These two "building blocks" can be combined to make all
other conditional expressions:
EXPR THEN ELSE
x > y x > y y ≥ x
x ≥ y x ≥ y y > x
x < y y > x x ≥ y
x ≤ y y ≥ x x > y
Or, more formally:
EXPR THEN ELSE
x > y x_refined = GLB(x_orig, promote(y)) y_refined = GLB(y_orig, x)
x ≥ y x_refined = GLB(x_orig, y) y_refined = GLB(y_orig, promote(x))
x < y y_refined = GLB(y_orig, promote(x)) x_refined = GLB(x_orig, y)
x ≤ y y_refined = GLB(y_orig, x) x_refined = GLB(x_orig, promote(y))
where GLB is the greatest lower bound and promote is the increment
function on types (or, equivalently, the function specified by the "x
> y" information above).
There's also ==, which is a special case. Only the THEN
branch is refined:
EXPR THEN ELSE
x == y x ≥ y && y ≥ x nothing known
or, more formally:
EXPR THEN ELSE
x == y x_refined = GLB(x_orig, y_orig) nothing known
y_refined = GLB(x_orig, y_orig)
finally, not equal:
EXPR THEN ELSE
x != y nothing known x ≥ y && y ≥ x
more formally:
EXPR THEN ELSE
x != y nothing known x_refined = GLB(x_orig, y_orig)
y_refined = GLB(x_orig, y_orig)
Dividing these rules up by cases, this class implements:
- 1. The rule described above for >
- 2. The rule described above for ≥
- 3. The rule described above for <
- 4. The rule described above for ≤
- 5. The rule described above for ==
- 6. The rule described above for !=
- 7. A special refinement for != when the value being compared to is a compile-time constant
with a value exactly equal to -1 or 0 (i.e.
x != -1and x is GTEN1 implies x is non-negative). Maybe two rules? - 8. When a compile-time constant -2 is added to a positive, the result is GTEN1
- 9. When a compile-time constant 2 is added to a GTEN1, the result is positive
- 10. When a positive is added to a positive, the result is positive
- 11. When a non-negative is added to any other type, the result is that other type
- 12. When a GTEN1 is added to a positive, the result is non-negative
- 13. When the left side of a subtraction expression is > the right side according to the LessThanChecker, the result of the subtraction expression is positive
- 14. When the left side of a subtraction expression is ≥ the right side according to the LessThanChecker, the result of the subtraction expression is non-negative
- 15. special handling for when the left side is the length of an array or String that's stored as a field, and the right side is a compile time constant. Do we need this?
- 16. Multiplying any value by a compile time constant of 1 preserves its type
- 17. Multiplying two positives produces a positive
- 18. Multiplying a positive and a non-negative produces a non-negative
- 19. Multiplying two non-negatives produces a non-negative
- 20. When the result of Math.random is multiplied by an array length, the result is NonNegative.
- 21. literal 0 divided by anything is non-negative
- 22. anything divided by literal zero is bottom
- 23. literal 1 divided by a positive or non-negative is non-negative
- 24. literal 1 divided by anything else is GTEN1
- 25. anything divided by literal 1 is itself
- 26. a positive or non-negative divided by a positive or non-negative is non-negative
- 27. anything modded by literal 1 or -1 is non-negative
- 28. a positive or non-negative modded by anything is non-negative
- 29. a GTEN1 modded by anything is GTEN1
- 30. anything right-shifted by a non-negative is non-negative
- 31. anything bitwise-anded by a non-negative is non-negative
- 32. If a and b are non-negative and
a <= banda != b, then b is pos. - 33. A char is always non-negative
-
Field Summary
FieldsModifier and TypeFieldDescriptionfinal AnnotationMirrorThe canonicalGTENegativeOneannotation.final AnnotationMirrorThe canonicalNonNegativeannotation.final AnnotationMirrorThe canonicalPositiveannotation.final AnnotationMirrorThe canonicalLowerBoundUnknownannotation.Fields inherited from class org.checkerframework.framework.flow.CFAbstractTransfer
analysis, sequentialSemantics -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidaddInformationFromPreconditions(CFStore info, AnnotatedTypeFactory factory, UnderlyingAST.CFGMethod method, MethodTree methodTree, ExecutableElement methodElement) Adds a default NonNegative annotation to every character.getAnnotationForRemainder handles these cases:protected voidrefineGT(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store, TransferInput<CFValue, CFStore> in) The implementation of the algorithm for refining a > test.protected voidrefineGTE(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store, TransferInput<CFValue, CFStore> in) Refines left to exactly the level of right, since in the worst case they're equal.protected TransferResult<CFValue, CFStore> strengthenAnnotationOfEqualTo(TransferResult<CFValue, CFStore> result, Node firstNode, Node secondNode, CFValue firstValue, CFValue secondValue, boolean notEqualTo) Implements the transfer rules for both equal nodes and not-equals nodes (i.e.Methods inherited from class org.checkerframework.checker.index.IndexAbstractTransfer
visitGreaterThan, visitGreaterThanOrEqual, visitLessThan, visitLessThanOrEqualMethods inherited from class org.checkerframework.framework.flow.CFAbstractTransfer
createTransferResult, createTransferResult, finishValue, finishValue, getNarrowedValue, getValueFromFactory, getWidenedValue, initialStore, insertIntoStores, insertIntoStoresPermitNonDeterministic, isNotFullyInitializedReceiver, moreSpecificValue, processCommonAssignment, processConditionalPostconditions, processPostconditions, recreateTransferResult, recreateTransferResult, setFixedInitialStore, shouldPerformWholeProgramInference, shouldPerformWholeProgramInference, splitAssignments, usesSequentialSemantics, visitAnyPattern, visitArrayAccess, visitAssignment, visitCase, visitClassName, visitConditionalNot, visitDeconstructorPattern, visitEqualTo, visitExpressionStatement, visitFieldAccess, visitInstanceOf, visitLambdaResultExpression, visitLocalVariable, visitMethodInvocation, visitNarrowingConversion, visitNode, visitNotEqual, visitObjectCreation, visitReturn, visitStringConversion, visitSwitchExpressionNode, visitTernaryExpression, visitThis, visitVariableDeclaration, visitWideningConversionMethods inherited from class org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor
visitArrayCreation, visitArrayType, visitAssertionError, visitBitwiseComplement, visitBitwiseOr, visitBitwiseXor, visitBooleanLiteral, visitCharacterLiteral, visitClassDeclaration, visitConditionalAnd, visitConditionalOr, visitDoubleLiteral, visitExplicitThis, visitFloatingDivision, visitFloatingRemainder, visitFloatLiteral, visitImplicitThis, visitIntegerLiteral, visitLeftShift, visitLongLiteral, visitMarker, visitMemberReference, visitMethodAccess, visitNullChk, visitNullLiteral, visitNumericalMinus, visitNumericalPlus, visitPackageName, visitParameterizedType, visitPrimitiveType, visitShortLiteral, visitStringConcatenate, visitStringLiteral, visitSuper, visitSynchronized, visitThrow, visitTypeCast, visitValueLiteralMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.checkerframework.dataflow.cfg.node.NodeVisitor
visitArrayCreation, visitArrayType, visitAssertionError, visitBitwiseComplement, visitBitwiseOr, visitBitwiseXor, visitBooleanLiteral, visitCharacterLiteral, visitClassDeclaration, visitConditionalAnd, visitConditionalOr, visitDoubleLiteral, visitExplicitThis, visitFloatingDivision, visitFloatingRemainder, visitFloatLiteral, visitImplicitThis, visitIntegerLiteral, visitLeftShift, visitLongLiteral, visitMarker, visitMemberReference, visitMethodAccess, visitNullChk, visitNullLiteral, visitNumericalMinus, visitNumericalPlus, visitPackageName, visitParameterizedType, visitPrimitiveType, visitShortLiteral, visitStringConcatenate, visitStringLiteral, visitSuper, visitSynchronized, visitThrow, visitTypeCast
-
Field Details
-
GTEN1
The canonicalGTENegativeOneannotation. -
NN
The canonicalNonNegativeannotation. -
POS
The canonicalPositiveannotation. -
UNKNOWN
The canonicalLowerBoundUnknownannotation.
-
-
Constructor Details
-
LowerBoundTransfer
Create a new LowerBoundTransfer.- Parameters:
analysis- the CFAnalysis
-
-
Method Details
-
strengthenAnnotationOfEqualTo
protected TransferResult<CFValue,CFStore> strengthenAnnotationOfEqualTo(TransferResult<CFValue, CFStore> result, Node firstNode, Node secondNode, CFValue firstValue, CFValue secondValue, boolean notEqualTo) Implements the transfer rules for both equal nodes and not-equals nodes (i.e. cases 5, 6, 32).- Overrides:
strengthenAnnotationOfEqualToin classCFAbstractTransfer<CFValue,CFStore, CFTransfer> - Parameters:
result- the previous resultfirstNode- the node that might be more precisesecondNode- the node whose type to possibly refinefirstValue- the abstract value that might be more precisesecondValue- the abstract value that might be less precisenotEqualTo- if true, indicates that the logic is flipped (i.e., the information is added to theelseStoreinstead of thethenStore) for a not-equal comparison- Returns:
- the conditional transfer result (if information has been added), or
res
-
refineGT
protected void refineGT(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store, TransferInput<CFValue, CFStore> in) The implementation of the algorithm for refining a > test. Changes the type of left (the greater one) to one closer to bottom than the type of right. Can't call the promote function from the ATF directly because a new expression isn't introduced here - the modifications have to be made to an existing one.This implements parts of cases 1, 2, 3, and 4 using the decomposition strategy described in the Javadoc of this class.
- Specified by:
refineGTin classIndexAbstractTransfer
-
refineGTE
protected void refineGTE(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store, TransferInput<CFValue, CFStore> in) Refines left to exactly the level of right, since in the worst case they're equal. Modifies an existing type in the store, but has to be careful not to overwrite a more precise existing type.This implements parts of cases 1, 2, 3, and 4 using the decomposition strategy described in this class's Javadoc.
- Specified by:
refineGTEin classIndexAbstractTransfer
-
addInformationFromPreconditions
protected void addInformationFromPreconditions(CFStore info, AnnotatedTypeFactory factory, UnderlyingAST.CFGMethod method, MethodTree methodTree, ExecutableElement methodElement) Adds a default NonNegative annotation to every character. Implements case 33.- Overrides:
addInformationFromPreconditionsin classCFAbstractTransfer<CFValue,CFStore, CFTransfer> - Parameters:
info- the initial store for the method bodyfactory- the type factorymethod- the AST for a method declarationmethodTree- the declaration of the method; is a field ofmethodAstmethodElement- the element for the method
-
getAnnotationForRemainder
public AnnotationMirror getAnnotationForRemainder(IntegerRemainderNode node, TransferInput<CFValue, CFStore> p) getAnnotationForRemainder handles these cases:27. * % 1/-1 → nn 28. pos/nn % * → nn 29. gten1 % * → gten1 * % * → lbu -
visitNumericalAddition
public TransferResult<CFValue,CFStore> visitNumericalAddition(NumericalAdditionNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitNumericalAdditionin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalAdditionin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitNumericalSubtraction
public TransferResult<CFValue,CFStore> visitNumericalSubtraction(NumericalSubtractionNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitNumericalSubtractionin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalSubtractionin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitNumericalMultiplication
public TransferResult<CFValue,CFStore> visitNumericalMultiplication(NumericalMultiplicationNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitNumericalMultiplicationin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalMultiplicationin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitIntegerDivision
public TransferResult<CFValue,CFStore> visitIntegerDivision(IntegerDivisionNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitIntegerDivisionin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitIntegerDivisionin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitIntegerRemainder
public TransferResult<CFValue,CFStore> visitIntegerRemainder(IntegerRemainderNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitIntegerRemainderin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitIntegerRemainderin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitSignedRightShift
public TransferResult<CFValue,CFStore> visitSignedRightShift(SignedRightShiftNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitSignedRightShiftin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitSignedRightShiftin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitUnsignedRightShift
public TransferResult<CFValue,CFStore> visitUnsignedRightShift(UnsignedRightShiftNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitUnsignedRightShiftin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitUnsignedRightShiftin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-
visitBitwiseAnd
public TransferResult<CFValue,CFStore> visitBitwiseAnd(BitwiseAndNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitBitwiseAndin interfaceNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitBitwiseAndin classAbstractNodeVisitor<TransferResult<CFValue,CFStore>, TransferInput<CFValue, CFStore>>
-