Class LowerBoundTransfer
java.lang.Object
org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor<TransferResult<V,S>,TransferInput<V,S>>
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 != -1
and 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 <= b
anda != b
, then b is pos. - 33. A char is always non-negative
-
Field Summary
Modifier and TypeFieldDescriptionfinal AnnotationMirror
The canonicalGTENegativeOne
annotation.final AnnotationMirror
The canonicalNonNegative
annotation.final AnnotationMirror
The canonicalPositive
annotation.final AnnotationMirror
The canonicalLowerBoundUnknown
annotation.Fields inherited from class org.checkerframework.framework.flow.CFAbstractTransfer
analysis, sequentialSemantics
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionprotected void
addInformationFromPreconditions
(CFStore info, AnnotatedTypeFactory factory, UnderlyingAST.CFGMethod method, MethodTree methodTree, ExecutableElement methodElement) Adds a default NonNegative annotation to every character.getAnnotationForRemainder handles these cases: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.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.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, visitLessThanOrEqual
Methods inherited from class org.checkerframework.framework.flow.CFAbstractTransfer
createTransferResult, finishValue, finishValue, getNarrowedValue, getValueFromFactory, getWidenedValue, initialStore, insertIntoStores, isNotFullyInitializedReceiver, moreSpecificValue, processCommonAssignment, processConditionalPostconditions, processPostconditions, recreateTransferResult, setFixedInitialStore, splitAssignments, usesSequentialSemantics, visitArrayAccess, visitAssignment, visitCase, visitClassName, visitConditionalNot, visitEqualTo, visitExpressionStatement, visitFieldAccess, visitInstanceOf, visitLambdaResultExpression, visitLocalVariable, visitMethodInvocation, visitNarrowingConversion, visitNode, visitNotEqual, visitObjectCreation, visitReturn, visitStringConversion, visitSwitchExpressionNode, visitTernaryExpression, visitThis, visitVariableDeclaration, visitWideningConversion
Methods 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, visitValueLiteral
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods 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 canonicalGTENegativeOne
annotation. -
NN
The canonicalNonNegative
annotation. -
POS
The canonicalPositive
annotation. -
UNKNOWN
The canonicalLowerBoundUnknown
annotation.
-
-
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:
strengthenAnnotationOfEqualTo
in 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 theelseStore
instead 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:
refineGT
in 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:
refineGTE
in 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:
addInformationFromPreconditions
in 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 ofmethodAst
methodElement
- 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:
visitNumericalAddition
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalAddition
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitNumericalSubtraction
public TransferResult<CFValue,CFStore> visitNumericalSubtraction(NumericalSubtractionNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitNumericalSubtraction
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalSubtraction
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitNumericalMultiplication
public TransferResult<CFValue,CFStore> visitNumericalMultiplication(NumericalMultiplicationNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitNumericalMultiplication
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitNumericalMultiplication
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitIntegerDivision
public TransferResult<CFValue,CFStore> visitIntegerDivision(IntegerDivisionNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitIntegerDivision
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitIntegerDivision
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitIntegerRemainder
public TransferResult<CFValue,CFStore> visitIntegerRemainder(IntegerRemainderNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitIntegerRemainder
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitIntegerRemainder
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitSignedRightShift
public TransferResult<CFValue,CFStore> visitSignedRightShift(SignedRightShiftNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitSignedRightShift
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitSignedRightShift
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitUnsignedRightShift
public TransferResult<CFValue,CFStore> visitUnsignedRightShift(UnsignedRightShiftNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitUnsignedRightShift
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitUnsignedRightShift
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-
visitBitwiseAnd
public TransferResult<CFValue,CFStore> visitBitwiseAnd(BitwiseAndNode n, TransferInput<CFValue, CFStore> p) - Specified by:
visitBitwiseAnd
in interfaceNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>> - Overrides:
visitBitwiseAnd
in classAbstractNodeVisitor<TransferResult<CFValue,
CFStore>, TransferInput<CFValue, CFStore>>
-