Class CFAbstractStore<V extends CFAbstractValue<V>,S extends CFAbstractStore<V,S>>
- All Implemented Interfaces:
Store<S>
,org.plumelib.util.UniqueId
- Direct Known Subclasses:
CFStore
,InitializationStore
,KeyForStore
,LockStore
When adding a new field to track values for a code construct (similar to
localVariableValues
and thisValue
), it is important to review all constructors and
methods in this class for locations where the new field must be handled (such as the copy
constructor and clearValue
), as well as all constructors/methods in subclasses of {code
CFAbstractStore}. Note that this includes not only overridden methods in the subclasses, but new
methods in the subclasses as well. Also check if
BaseTypeVisitor#getJavaExpressionContextFromNode(Node) needs to be updated. Failing to do so may
result in silent failures that are time consuming to debug.
-
Nested Class Summary
Nested classes/interfaces inherited from interface org.checkerframework.dataflow.analysis.Store
Store.FlowRule, Store.Kind
-
Field Summary
Modifier and TypeFieldDescriptionprotected final CFAbstractAnalysis<V,
S, ?> The analysis class this store belongs to.protected final Map<ArrayAccess,
V> Information collected about array elements, using the internal representationArrayAccess
.Information collected about classname.class values, using the internal representationClassName
.protected Map<FieldAccess,
V> Information collected about fields, using the internal representationFieldAccess
.protected final Map<LocalVariable,
V> Information collected about local variables (including method parameters).protected final Map<MethodCall,
V> Information collected about method calls, using the internal representationMethodCall
.protected final boolean
Should the analysis use sequential Java semantics (i.e., assume that only one thread is running at all times)?protected V
Information collected about the current object. -
Constructor Summary
ModifierConstructorDescriptionprotected
CFAbstractStore
(CFAbstractAnalysis<V, S, ?> analysis, boolean sequentialSemantics) Creates a new CFAbstractStore.protected
CFAbstractStore
(CFAbstractStore<V, S> other) Copy constructor. -
Method Summary
Modifier and TypeMethodDescriptionboolean
Can the objectsa
andb
be aliases? Returns a conservative answer (i.e., returnstrue
if not enough information is available to determine aliasing).static boolean
Returns true ifexpr
can be stored in this store.void
clearValue
(JavaExpression expr) Remove any knowledge about the expressionexpr
(correctly deciding where to remove the information depending on the type of the expressionexpr
).protected void
computeNewValueAndInsert
(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) Inserts the result of applyingmerger
tovalue
and the previous value forexpr
.copy()
Returns an exact copy of this store.boolean
Returns true if this is equal to the given argument.getFieldValue
(FieldAccess fieldAccess) Returns the current abstract value of a field access, ornull
if no information is available.Returns information about fields.long
getUid()
Returns the current abstract value of a field access, ornull
if no information is available.Returns the current abstract value of a field access, ornull
if no information is available.Returns the current abstract value of a local variable, ornull
if no information is available.Returns the current abstract value of a method call, ornull
if no information is available.Returns the current abstract value of the current object, ornull
if no information is available.getValue
(JavaExpression expr) Returns the current abstract value of a Java expression, ornull
if no information is available.int
hashCode()
void
initializeMethodParameter
(LocalVariableNode p, @Nullable V value) Set the abstract value of a method parameter (only adds the information to the store, does not remove any other knowledge).void
initializeThisValue
(AnnotationMirror a, TypeMirror underlyingType) Set the value of the current object.final void
insertOrRefine
(JavaExpression expr, AnnotationMirror newAnno) Add the annotationnewAnno
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).protected void
insertOrRefine
(JavaExpression expr, AnnotationMirror newAnno, boolean permitNondeterministic) final void
insertOrRefinePermitNondeterministic
(JavaExpression expr, AnnotationMirror newAnno) LikeinsertOrRefine(JavaExpression, AnnotationMirror)
, but permits nondeterministic expressions to be inserted.void
insertThisValue
(AnnotationMirror a, TypeMirror underlyingType) final void
insertValue
(JavaExpression expr, @Nullable V value) Add the abstract valuevalue
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).protected void
insertValue
(JavaExpression expr, @Nullable V value, boolean permitNondeterministic) void
insertValue
(JavaExpression expr, AnnotationMirror a) Add the annotationa
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).final void
insertValuePermitNondeterministic
(JavaExpression expr, @Nullable V value) LikeinsertValue(JavaExpression, CFAbstractValue)
, but updates the store even ifexpr
is nondeterministic.void
LikeinsertValue(JavaExpression, AnnotationMirror)
, but permits nondeterministic expressions to be stored.protected String
internalVisualize
(CFGVisualizer<V, S, ?> viz) Adds a representation of the internal information of this Store to visualizerviz
.protected boolean
isMonotonicUpdate
(FieldAccess fieldAcc, V value) Return true if fieldAcc is an update of a monotonic qualifier to its target qualifier.protected boolean
isSideEffectFree
(AnnotatedTypeFactory atypeFactory, ExecutableElement method) Deprecated.leastUpperBound
(S other) Compute the least upper bound of two stores.protected void
removeConflicting
(ArrayAccess arrayAccess, @Nullable V val) Remove any information in the store that might not be true any more afterarrayAccess
has been assigned a new value (with the abstract valueval
).protected void
removeConflicting
(FieldAccess fieldAccess, @Nullable V val) Remove any information in this store that might not be true any more afterfieldAccess
has been assigned a new value (with the abstract valueval
).protected void
Remove any information in this store that might not be true any more afterlocalVar
has been assigned a new value.void
replaceValue
(JavaExpression expr, @Nullable V value) Completely replaces the abstract valuevalue
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).protected boolean
shouldInsert
(JavaExpression expr, @Nullable V value, boolean permitNondeterministic) Returns true if the given (expression, value) pair can be inserted in the store, namely if the value is non-null and the expression does not contain unknown or a nondeterministic expression.protected boolean
supersetOf
(CFAbstractStore<V, S> other) Returns true iff thisCFAbstractStore
contains a superset of the map entries of the argumentCFAbstractStore
.toString()
protected void
updateForArrayAssignment
(ArrayAccess arrayAccess, @Nullable V val) Update the information in the store by considering an assignment with targetn
, where the target is an array access.void
updateForAssignment
(Node n, @Nullable V val) Update the information in the store by considering an assignment with targetn
.protected void
updateForFieldAccessAssignment
(FieldAccess fieldAccess, @Nullable V val) Update the information in the store by considering a field assignment with targetn
, where the right hand side has the abstract valueval
.protected void
updateForLocalVariableAssignment
(LocalVariable receiver, @Nullable V val) Set the abstract value of a local variable in the store.void
updateForMethodCall
(MethodInvocationNode methodInvocationNode, AnnotatedTypeFactory atypeFactory, V val) Remove any information that might not be valid any more after a method call, and add information guaranteed by the method.visualize
(CFGVisualizer<?, S, ?> viz) Delegate visualization responsibility to a visualizer.widenedUpperBound
(S previous) Compute an upper bound of two stores that is wider than the least upper bound of the two stores.Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface org.plumelib.util.UniqueId
getClassAndUid
-
Field Details
-
analysis
protected final CFAbstractAnalysis<V extends CFAbstractValue<V>,S extends CFAbstractStore<V, analysisS>, ?> The analysis class this store belongs to. -
localVariableValues
Information collected about local variables (including method parameters). -
thisValue
Information collected about the current object. -
fieldValues
Information collected about fields, using the internal representationFieldAccess
. -
arrayValues
Information collected about array elements, using the internal representationArrayAccess
. -
methodValues
Information collected about method calls, using the internal representationMethodCall
. -
classValues
Information collected about classname.class values, using the internal representationClassName
. -
sequentialSemantics
protected final boolean sequentialSemanticsShould the analysis use sequential Java semantics (i.e., assume that only one thread is running at all times)?
-
-
Constructor Details
-
CFAbstractStore
Creates a new CFAbstractStore.- Parameters:
analysis
- the analysis class this store belongs tosequentialSemantics
- should the analysis use sequential Java semantics?
-
CFAbstractStore
Copy constructor.- Parameters:
other
- a CFAbstractStore to copy into this
-
-
Method Details
-
getFieldValues
Returns information about fields. Clients should not side-effect the returned value, which is aliased to internal state.- Returns:
- information about fields
-
getUid
public long getUid()- Specified by:
getUid
in interfaceorg.plumelib.util.UniqueId
-
initializeMethodParameter
Set the abstract value of a method parameter (only adds the information to the store, does not remove any other knowledge). Any previous information is erased; this method should only be used to initialize the abstract value. -
initializeThisValue
Set the value of the current object. Any previous information is erased; this method should only be used to initialize the value. -
isSideEffectFree
@Deprecated protected boolean isSideEffectFree(AnnotatedTypeFactory atypeFactory, ExecutableElement method) Indicates whether the given method is side-effect-free as far as the current store is concerned. In some cases, a store for a checker allows for other mechanisms to specify whether a method is side-effect-free. For example, unannotated methods may be considered side-effect-free by default.- Parameters:
atypeFactory
- the type factory used to retrieve annotations on the method elementmethod
- the method element- Returns:
- whether the method is side-effect-free
-
updateForMethodCall
public void updateForMethodCall(MethodInvocationNode methodInvocationNode, AnnotatedTypeFactory atypeFactory, V val) Remove any information that might not be valid any more after a method call, and add information guaranteed by the method.- If the method is side-effect-free (as indicated by
SideEffectFree
orPure
), then no information needs to be removed. - Otherwise, all information about field accesses
a.f
needs to be removed, except if the methodn
cannot modifya.f
(e.g., ifa
is a local variable orthis
, andf
is final). - Furthermore, if the field has a monotonic annotation, then its information can also be kept.
val
in the store.- Parameters:
methodInvocationNode
- method whose information is being updatedatypeFactory
- AnnotatedTypeFactory of the associated checkerval
- abstract value of the method call
- If the method is side-effect-free (as indicated by
-
insertValue
Add the annotationa
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).This method does not take care of removing other information that might be influenced by changes to certain parts of the state.
If there is already a value
v
present forexpr
, then the stronger of the new and old value are taken (according to the lattice). Note that this happens per hierarchy, and if the store already contains information about a hierarchy other thana
s hierarchy, that information is preserved.If
expr
is nondeterministic, this method does not insertvalue
into the store.- Parameters:
expr
- an expressiona
- an annotation for the expression
-
insertValuePermitNondeterministic
LikeinsertValue(JavaExpression, AnnotationMirror)
, but permits nondeterministic expressions to be stored.For an explanation of when to permit nondeterministic expressions, see
insertValuePermitNondeterministic(JavaExpression, CFAbstractValue)
.- Parameters:
expr
- an expressiona
- an annotation for the expression
-
insertOrRefine
Add the annotationnewAnno
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).This method does not take care of removing other information that might be influenced by changes to certain parts of the state.
If there is already a value
v
present forexpr
, then the greatest lower bound of the new and old value is inserted into the store.Note that this happens per hierarchy, and if the store already contains information about a hierarchy other than
newAnno
's hierarchy, that information is preserved.If
expr
is nondeterministic, this method does not insertvalue
into the store.- Parameters:
expr
- an expressionnewAnno
- the expression's annotation
-
insertOrRefinePermitNondeterministic
public final void insertOrRefinePermitNondeterministic(JavaExpression expr, AnnotationMirror newAnno) LikeinsertOrRefine(JavaExpression, AnnotationMirror)
, but permits nondeterministic expressions to be inserted.For an explanation of when to permit nondeterministic expressions, see
insertValuePermitNondeterministic(JavaExpression, CFAbstractValue)
.- Parameters:
expr
- an expressionnewAnno
- the expression's annotation
-
insertOrRefine
protected void insertOrRefine(JavaExpression expr, AnnotationMirror newAnno, boolean permitNondeterministic) Helper function forinsertOrRefine(JavaExpression, AnnotationMirror)
andinsertOrRefinePermitNondeterministic(org.checkerframework.dataflow.expression.JavaExpression, javax.lang.model.element.AnnotationMirror)
.- Parameters:
expr
- an expressionnewAnno
- the expression's annotationpermitNondeterministic
- whether nondeterministic expressions may be inserted into the store
-
canInsertJavaExpression
Returns true ifexpr
can be stored in this store. -
insertValue
Add the abstract valuevalue
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
).This method does not take care of removing other information that might be influenced by changes to certain parts of the state.
If there is already a value
v
present forexpr
, then the stronger of the new and old value are taken (according to the lattice). Note that this happens per hierarchy, and if the store already contains information about a hierarchy for whichvalue
does not contain information, then that information is preserved.If
expr
is nondeterministic, this method does not insertvalue
into the store.- Parameters:
expr
- the expression to insert in the storevalue
- the value of the expression
-
insertValuePermitNondeterministic
LikeinsertValue(JavaExpression, CFAbstractValue)
, but updates the store even ifexpr
is nondeterministic.Usually, nondeterministic JavaExpressions should not be stored in a Store. For example, in the body of
if (nondet() == 3) {...}
, the store should not record that the value ofnondet()
is 3, because it might not be 3 the next timenondet()
is executed.However, contracts can mention a nondeterministic JavaExpression. For example, a contract might have a postcondition that
nondet()
is odd. This means that the next call tonondet()
will return odd. Such a postcondition may be evicted from the store by calling a side-effecting method.- Parameters:
expr
- the expression to insert in the storevalue
- the value of the expression
-
shouldInsert
@EnsuresNonNullIf(expression="#2", result=true) protected boolean shouldInsert(JavaExpression expr, @Nullable V value, boolean permitNondeterministic) Returns true if the given (expression, value) pair can be inserted in the store, namely if the value is non-null and the expression does not contain unknown or a nondeterministic expression.This method returning true does not guarantee that the value will be inserted; the implementation of
insertValue(JavaExpression, CFAbstractValue, boolean)
might still not insert it.- Parameters:
expr
- the expression to insert in the storevalue
- the value of the expressionpermitNondeterministic
- if false, returns false ifexpr
is nondeterministic; if true, permits nondeterministic expressions to be placed in the store- Returns:
- true if the given (expression, value) pair can be inserted in the store
-
insertValue
Helper method forinsertValue(JavaExpression, CFAbstractValue)
andinsertValuePermitNondeterministic(org.checkerframework.dataflow.expression.JavaExpression, javax.lang.model.element.AnnotationMirror)
.Every overriding implementation should start with
if (!shouldInsert) { return; }
- Parameters:
expr
- the expression to insert in the storevalue
- the value of the expressionpermitNondeterministic
- if false, does nothing ifexpr
is nondeterministic; if true, permits nondeterministic expressions to be placed in the store
-
computeNewValueAndInsert
protected void computeNewValueAndInsert(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) Inserts the result of applyingmerger
tovalue
and the previous value forexpr
.- Parameters:
expr
- the JavaExpressionvalue
- the value of the JavaExpressionmerger
- the function used to mergevalue
and the previous value ofexpr
permitNondeterministic
- if false, does nothing ifexpr
is nondeterministic; if true, permits nondeterministic expressions to be placed in the store
-
isMonotonicUpdate
Return true if fieldAcc is an update of a monotonic qualifier to its target qualifier. (e.g. @MonotonicNonNull to @NonNull). Always returns false ifsequentialSemantics
is true.- Returns:
- true if fieldAcc is an update of a monotonic qualifier to its target qualifier (e.g. @MonotonicNonNull to @NonNull)
-
insertThisValue
-
replaceValue
Completely replaces the abstract valuevalue
for the expressionexpr
(correctly deciding where to store the information depending on the type of the expressionexpr
). Any previous information is discarded.This method does not take care of removing other information that might be influenced by changes to certain parts of the state.
-
clearValue
Remove any knowledge about the expressionexpr
(correctly deciding where to remove the information depending on the type of the expressionexpr
). -
getValue
Returns the current abstract value of a Java expression, ornull
if no information is available.- Returns:
- the current abstract value of a Java expression, or
null
if no information is available
-
getValue
Returns the current abstract value of a field access, ornull
if no information is available.- Parameters:
n
- the node whose abstract value to return- Returns:
- the current abstract value of a field access, or
null
if no information is available
-
getFieldValue
Returns the current abstract value of a field access, ornull
if no information is available.- Parameters:
fieldAccess
- the field access to look up in this store- Returns:
- current abstract value of a field access, or
null
if no information is available
-
getValue
Returns the current abstract value of a method call, ornull
if no information is available.- Parameters:
n
- a method call- Returns:
- the current abstract value of a method call, or
null
if no information is available
-
getValue
Returns the current abstract value of a field access, ornull
if no information is available.- Parameters:
n
- the node whose abstract value to return- Returns:
- the current abstract value of a field access, or
null
if no information is available
-
updateForAssignment
Update the information in the store by considering an assignment with targetn
.- Parameters:
n
- the left-hand side of an assignmentval
- the right-hand value of an assignment
-
updateForFieldAccessAssignment
Update the information in the store by considering a field assignment with targetn
, where the right hand side has the abstract valueval
.- Parameters:
val
- the abstract value of the value assigned ton
(ornull
if the abstract value is not known).
-
updateForArrayAssignment
Update the information in the store by considering an assignment with targetn
, where the target is an array access.See
removeConflicting(ArrayAccess,CFAbstractValue)
, as it is called first by this method. -
updateForLocalVariableAssignment
Set the abstract value of a local variable in the store. Overwrites any value that might have been available previously.- Parameters:
val
- the abstract value of the value assigned ton
(ornull
if the abstract value is not known).
-
removeConflicting
Remove any information in this store that might not be true any more afterfieldAccess
has been assigned a new value (with the abstract valueval
). This includes the following steps (assume thatfieldAccess
is of the form a.f for some a.- Update the abstract value of other field accesses b.g where the field
is equal (that is, f=g), and the receiver b might alias the receiver of
fieldAccess
, a. This update will raise the abstract value for such field accesses to at leastval
(or the old value, if that was less precise). However, this is only necessary if the field g is not final. - Remove any abstract values for field accesses b.g where
fieldAccess
might alias any expression in the receiver b. - Remove any information about method calls.
- Remove any abstract values an array access b[i] where
fieldAccess
might alias any expression in the receiver a or index i.
- Parameters:
val
- the abstract value of the value assigned ton
(ornull
if the abstract value is not known).
- Update the abstract value of other field accesses b.g where the field
is equal (that is, f=g), and the receiver b might alias the receiver of
-
removeConflicting
Remove any information in the store that might not be true any more afterarrayAccess
has been assigned a new value (with the abstract valueval
). This includes the following steps (assume thatarrayAccess
is of the form a[i] for some a.- Remove any abstract value for other array access b[j] where a and b can be aliases, or where either b or j contains a modifiable alias of a[i].
- Remove any abstract values for field accesses b.g where a[i] might alias any expression in the receiver b and there is an array expression somewhere in the receiver.
- Remove any information about method calls.
- Parameters:
val
- the abstract value of the value assigned ton
(ornull
if the abstract value is not known).
-
removeConflicting
Remove any information in this store that might not be true any more afterlocalVar
has been assigned a new value. This includes the following steps:- Remove any abstract values for field accesses b.g where
localVar
might alias any expression in the receiver b. - Remove any abstract values for array accesses a[i] where
localVar
might alias the receiver a. - Remove any information about method calls where the receiver or any of the
parameters contains
localVar
.
- Remove any abstract values for field accesses b.g where
-
canAlias
Can the objectsa
andb
be aliases? Returns a conservative answer (i.e., returnstrue
if not enough information is available to determine aliasing).- Specified by:
canAlias
in interfaceStore<V extends CFAbstractValue<V>>
-
getValue
Returns the current abstract value of a local variable, ornull
if no information is available.- Parameters:
n
- the local variable- Returns:
- the current abstract value of a local variable, or
null
if no information is available
-
getValue
Returns the current abstract value of the current object, ornull
if no information is available.- Parameters:
n
- a reference to "this"- Returns:
- the current abstract value of the current object, or
null
if no information is available
-
copy
Description copied from interface:Store
Returns an exact copy of this store.- Specified by:
copy
in interfaceStore<V extends CFAbstractValue<V>>
- Returns:
- an exact copy of this store
-
leastUpperBound
Description copied from interface:Store
Compute the least upper bound of two stores.Important: This method must fulfill the following contract:
- Does not change
this
. - Does not change
other
. - Returns a fresh object which is not aliased yet.
- Returns an object of the same (dynamic) type as
this
, even if the signature is more permissive. - Is commutative.
- Specified by:
leastUpperBound
in interfaceStore<V extends CFAbstractValue<V>>
- Does not change
-
widenedUpperBound
Description copied from interface:Store
Compute an upper bound of two stores that is wider than the least upper bound of the two stores. Used to jump to a higher abstraction to allow faster termination of the fixed point computations inAnalysis
.previous
must be the previous store.A particular analysis might not require widening and should implement this method by calling leastUpperBound.
Important: This method must fulfill the following contract:
- Does not change
this
. - Does not change
previous
. - Returns a fresh object which is not aliased yet.
- Returns an object of the same (dynamic) type as
this
, even if the signature is more permissive. - Is commutative.
- Specified by:
widenedUpperBound
in interfaceStore<V extends CFAbstractValue<V>>
- Parameters:
previous
- must be the previous store
- Does not change
-
supersetOf
Returns true iff thisCFAbstractStore
contains a superset of the map entries of the argumentCFAbstractStore
. Note that we test the entry keys and values by Java equality, not by any subtype relationship. This method is used primarily to simplify the equals predicate. -
equals
Description copied from interface:Store
Returns true if this is equal to the given argument. -
hashCode
public int hashCode() -
toString
-
visualize
Description copied from interface:Store
Delegate visualization responsibility to a visualizer.- Specified by:
visualize
in interfaceStore<V extends CFAbstractValue<V>>
- Parameters:
viz
- the visualizer to visualize this store- Returns:
- the String representation of this store
-
internalVisualize
Adds a representation of the internal information of this Store to visualizerviz
.- Parameters:
viz
- the visualizer- Returns:
- a representation of the internal information of this
Store
-
AnnotationProvider.isSideEffectFree(javax.lang.model.element.ExecutableElement)