it.unive.lisa.interprocedural.CFGResults Maven / Gradle / Ivy
package it.unive.lisa.interprocedural;
import it.unive.lisa.analysis.AbstractState;
import it.unive.lisa.analysis.CFGWithAnalysisResults;
import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.heap.HeapDomain;
import it.unive.lisa.analysis.lattices.FunctionalLattice;
import it.unive.lisa.analysis.value.ValueDomain;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
/**
* A {@link FunctionalLattice} from {@link ContextSensitivityToken}s to
* {@link CFGWithAnalysisResults}s. This class is meant to store fixpoint
* results on each token generated during the interprocedural analysis.
*
* @author Luca Negrini
*
* @param the type of {@link AbstractState} contained into the analysis
* state
* @param the type of {@link HeapDomain} contained into the computed
* abstract state
* @param the type of {@link ValueDomain} contained into the computed
* abstract state
*/
public class CFGResults,
H extends HeapDomain,
V extends ValueDomain>
extends FunctionalLattice, ContextSensitivityToken, CFGWithAnalysisResults> {
/**
* Builds a new result.
*
* @param lattice a singleton instance used for retrieving top and bottom
* values
*/
public CFGResults(CFGWithAnalysisResults lattice) {
super(lattice);
}
/**
* Builds a new result.
*
* @param lattice a singleton instance used for retrieving top and bottom
* values
*/
private CFGResults(CFGWithAnalysisResults lattice,
Map> function) {
super(lattice, function);
}
/**
* Stores the result of a fixpoint computation on a cfg, if needed. This
* method returns a pair of a boolean and a {@link CFGWithAnalysisResults},
* where ({@code prev} is the {@link CFGWithAnalysisResults} already present
* for the given {@code token}):
*
* - if no {@code prev} was stored for {@code token}, than that token is
* mapped to {@code result} and this method returns
* {@code
}
* - if {@code prev <= result}, then {@code token} is mapped to
* {@code result} and this method returns {@code
}
* - if {@code result <= prev}, then the mapping is left untouched and
* this method returns {@code
}
* - otherwise, {@code token} is mapped to {@code lub = prev.lub(result)}
* and this method returns {@code
}
*
* The value returned by this method is intended to be a hint that a new
* fixpoint computation is needed to ensure that the results are stable.
*
* @param token the {@link ContextSensitivityToken} that identifying the
* result
* @param result the {@link CFGWithAnalysisResults} to store
*
* @return {@code true} if the previous result has been updated, if any
*
* @throws SemanticException if something goes wrong during the update
*/
public Pair> putResult(ContextSensitivityToken token,
CFGWithAnalysisResults result)
throws SemanticException {
CFGWithAnalysisResults previousResult = function.get(token);
if (previousResult == null) {
// no previous result
function.put(token, result);
return Pair.of(false, result);
} else if (previousResult.lessOrEqual(result)) {
// previous is smaller than result
if (result.lessOrEqual(previousResult))
// they are equal
return Pair.of(false, previousResult);
else {
// result is bigger, store that instead
function.put(token, result);
return Pair.of(true, result);
}
} else if (result.lessOrEqual(previousResult)) {
// result is smaller than previous
return Pair.of(false, previousResult);
} else {
// result and previous are not comparable
CFGWithAnalysisResults lub = previousResult.lub(result);
function.put(token, lub);
return Pair.of(true, lub);
}
}
/**
* Yields {@code true} if a result exists for the given {@code token}.
*
* @param token the {@link ContextSensitivityToken} that identifying the
* result
*
* @return {@code true} if that condition holds
*/
public boolean contains(ContextSensitivityToken token) {
return function != null && function.containsKey(token);
}
/**
* Yields all the results stored in this object, for any possible
* {@link ContextSensitivityToken} used.
*
* @return the results
*/
public Collection> getAll() {
return function.values();
}
@Override
public CFGResults top() {
return new CFGResults<>(lattice.top());
}
@Override
public boolean isTop() {
return lattice.isTop() && (function == null || function.isEmpty());
}
@Override
public CFGResults bottom() {
return new CFGResults<>(lattice.bottom());
}
@Override
public boolean isBottom() {
return lattice.isBottom() && (function == null || function.isEmpty());
}
@Override
protected CFGResults mk(CFGWithAnalysisResults lattice,
Map> function) {
return new CFGResults<>(lattice, function);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy