blob: c5692e3a1668738bf56c9cbfa2dce5e60202375c [file] [log] [blame]
package org.checkerframework.dataflow.livevariable;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.BackwardTransferFunction;
import org.checkerframework.dataflow.analysis.RegularTransferResult;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.UnderlyingAST;
import org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor;
import org.checkerframework.dataflow.cfg.node.AssignmentNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.ObjectCreationNode;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode;
/** A live variable transfer function. */
public class LiveVarTransfer
extends AbstractNodeVisitor<
TransferResult<LiveVarValue, LiveVarStore>, TransferInput<LiveVarValue, LiveVarStore>>
implements BackwardTransferFunction<LiveVarValue, LiveVarStore> {
@Override
public LiveVarStore initialNormalExitStore(
UnderlyingAST underlyingAST, @Nullable List<ReturnNode> returnNodes) {
return new LiveVarStore();
}
@Override
public LiveVarStore initialExceptionalExitStore(UnderlyingAST underlyingAST) {
return new LiveVarStore();
}
@Override
public RegularTransferResult<LiveVarValue, LiveVarStore> visitNode(
Node n, TransferInput<LiveVarValue, LiveVarStore> p) {
return new RegularTransferResult<>(null, p.getRegularStore());
}
@Override
public RegularTransferResult<LiveVarValue, LiveVarStore> visitAssignment(
AssignmentNode n, TransferInput<LiveVarValue, LiveVarStore> p) {
RegularTransferResult<LiveVarValue, LiveVarStore> transferResult =
(RegularTransferResult<LiveVarValue, LiveVarStore>) super.visitAssignment(n, p);
processLiveVarInAssignment(n.getTarget(), n.getExpression(), transferResult.getRegularStore());
return transferResult;
}
@Override
public RegularTransferResult<LiveVarValue, LiveVarStore> visitStringConcatenateAssignment(
StringConcatenateAssignmentNode n, TransferInput<LiveVarValue, LiveVarStore> p) {
RegularTransferResult<LiveVarValue, LiveVarStore> transferResult =
(RegularTransferResult<LiveVarValue, LiveVarStore>)
super.visitStringConcatenateAssignment(n, p);
processLiveVarInAssignment(
n.getLeftOperand(), n.getRightOperand(), transferResult.getRegularStore());
return transferResult;
}
@Override
public RegularTransferResult<LiveVarValue, LiveVarStore> visitMethodInvocation(
MethodInvocationNode n, TransferInput<LiveVarValue, LiveVarStore> p) {
RegularTransferResult<LiveVarValue, LiveVarStore> transferResult =
(RegularTransferResult<LiveVarValue, LiveVarStore>) super.visitMethodInvocation(n, p);
LiveVarStore store = transferResult.getRegularStore();
for (Node arg : n.getArguments()) {
store.addUseInExpression(arg);
}
return transferResult;
}
@Override
public RegularTransferResult<LiveVarValue, LiveVarStore> visitObjectCreation(
ObjectCreationNode n, TransferInput<LiveVarValue, LiveVarStore> p) {
RegularTransferResult<LiveVarValue, LiveVarStore> transferResult =
(RegularTransferResult<LiveVarValue, LiveVarStore>) super.visitObjectCreation(n, p);
LiveVarStore store = transferResult.getRegularStore();
for (Node arg : n.getArguments()) {
store.addUseInExpression(arg);
}
return transferResult;
}
/**
* Update the information of live variables from an assignment statement.
*
* @param variable the variable that should be killed
* @param expression the expression in which the variables should be added
* @param store the live variable store
*/
private void processLiveVarInAssignment(Node variable, Node expression, LiveVarStore store) {
store.killLiveVar(new LiveVarValue(variable));
store.addUseInExpression(expression);
}
}