All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.dataflow.livevariable.LiveVarStore Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.44.0
Show newest version
package org.checkerframework.dataflow.livevariable;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringJoiner;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.BinaryOperationNode;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.dataflow.cfg.node.InstanceOfNode;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.TernaryExpressionNode;
import org.checkerframework.dataflow.cfg.node.TypeCastNode;
import org.checkerframework.dataflow.cfg.node.UnaryOperationNode;
import org.checkerframework.dataflow.cfg.visualize.CFGVisualizer;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.javacutil.BugInCF;

/** A live variable store contains a set of live variables represented by nodes. */
public class LiveVarStore implements Store {

  /** A set of live variable abstract values. */
  private final Set liveVarValueSet;

  /** Create a new LiveVarStore. */
  public LiveVarStore() {
    liveVarValueSet = new LinkedHashSet<>();
  }

  /**
   * Create a new LiveVarStore.
   *
   * @param liveVarValueSet a set of live variable abstract values
   */
  public LiveVarStore(Set liveVarValueSet) {
    this.liveVarValueSet = liveVarValueSet;
  }

  /**
   * Add the information of a live variable into the live variable set.
   *
   * @param variable a live variable
   */
  public void putLiveVar(LiveVarValue variable) {
    liveVarValueSet.add(variable);
  }

  /**
   * Remove the information of a live variable from the live variable set.
   *
   * @param variable a live variable
   */
  public void killLiveVar(LiveVarValue variable) {
    liveVarValueSet.remove(variable);
  }

  /**
   * Add the information of live variables in an expression to the live variable set.
   *
   * @param expression a node
   */
  public void addUseInExpression(Node expression) {
    // TODO Do we need a AbstractNodeScanner to do the following job?
    if (expression instanceof LocalVariableNode || expression instanceof FieldAccessNode) {
      LiveVarValue liveVarValue = new LiveVarValue(expression);
      putLiveVar(liveVarValue);
    } else if (expression instanceof UnaryOperationNode) {
      UnaryOperationNode unaryNode = (UnaryOperationNode) expression;
      addUseInExpression(unaryNode.getOperand());
    } else if (expression instanceof TernaryExpressionNode) {
      TernaryExpressionNode ternaryNode = (TernaryExpressionNode) expression;
      addUseInExpression(ternaryNode.getConditionOperand());
      addUseInExpression(ternaryNode.getThenOperand());
      addUseInExpression(ternaryNode.getElseOperand());
    } else if (expression instanceof TypeCastNode) {
      TypeCastNode typeCastNode = (TypeCastNode) expression;
      addUseInExpression(typeCastNode.getOperand());
    } else if (expression instanceof InstanceOfNode) {
      InstanceOfNode instanceOfNode = (InstanceOfNode) expression;
      addUseInExpression(instanceOfNode.getOperand());
    } else if (expression instanceof BinaryOperationNode) {
      BinaryOperationNode binaryNode = (BinaryOperationNode) expression;
      addUseInExpression(binaryNode.getLeftOperand());
      addUseInExpression(binaryNode.getRightOperand());
    }
  }

  @Override
  public boolean equals(@Nullable Object obj) {
    if (!(obj instanceof LiveVarStore)) {
      return false;
    }
    LiveVarStore other = (LiveVarStore) obj;
    return other.liveVarValueSet.equals(this.liveVarValueSet);
  }

  @Override
  public int hashCode() {
    return this.liveVarValueSet.hashCode();
  }

  @Override
  public LiveVarStore copy() {
    return new LiveVarStore(new HashSet<>(liveVarValueSet));
  }

  @Override
  public LiveVarStore leastUpperBound(LiveVarStore other) {
    Set liveVarValueSetLub =
        new HashSet<>(this.liveVarValueSet.size() + other.liveVarValueSet.size());
    liveVarValueSetLub.addAll(this.liveVarValueSet);
    liveVarValueSetLub.addAll(other.liveVarValueSet);
    return new LiveVarStore(liveVarValueSetLub);
  }

  /** It should not be called since it is not used by the backward analysis. */
  @Override
  public LiveVarStore widenedUpperBound(LiveVarStore previous) {
    throw new BugInCF("wub of LiveVarStore get called!");
  }

  @Override
  public boolean canAlias(JavaExpression a, JavaExpression b) {
    return true;
  }

  @Override
  public String visualize(CFGVisualizer viz) {
    String key = "live variables";
    if (liveVarValueSet.isEmpty()) {
      return viz.visualizeStoreKeyVal(key, "none");
    }
    StringJoiner sjStoreVal = new StringJoiner(", ");
    for (LiveVarValue liveVarValue : liveVarValueSet) {
      sjStoreVal.add(liveVarValue.toString());
    }
    return viz.visualizeStoreKeyVal(key, sjStoreVal.toString());
  }

  @Override
  public String toString() {
    return liveVarValueSet.toString();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy