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

org.checkerframework.dataflow.expression.ValueLiteral 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.43.0
Show newest version
package org.checkerframework.dataflow.expression;

import java.math.BigInteger;
import java.util.Objects;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.ValueLiteralNode;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TypesUtils;

/** JavaExpression for literals. */
public class ValueLiteral extends JavaExpression {

  /** The value of the literal. */
  protected final @Nullable Object value;

  /** The negative of Long.MIN_VALUE, which does not fit in a long. */
  private final BigInteger NEGATIVE_LONG_MIN_VALUE = new BigInteger("9223372036854775808");

  /**
   * Creates a ValueLiteral from the node with the given type.
   *
   * @param type type of the literal
   * @param node the literal represents by this {@link
   *     org.checkerframework.dataflow.expression.ValueLiteral}
   */
  public ValueLiteral(TypeMirror type, ValueLiteralNode node) {
    super(type);
    value = node.getValue();
  }

  /**
   * Creates a ValueLiteral where the value is {@code value} that has the given type.
   *
   * @param type type of the literal
   * @param value the literal value
   */
  public ValueLiteral(TypeMirror type, Object value) {
    super(type);
    this.value = value;
  }

  /**
   * Returns the negation of this literal. Throws an exception if negation is not possible.
   *
   * @return the negation of this literal
   */
  public ValueLiteral negate() {
    if (TypesUtils.isIntegralPrimitive(type)) {
      if (value == null) {
        throw new BugInCF("null value of integral type " + type);
      }
      return new ValueLiteral(type, negateBoxedPrimitive(value));
    }
    throw new BugInCF(String.format("cannot negate: %s type=%s", this, type));
  }

  /**
   * Negate a boxed primitive.
   *
   * @param o a boxed primitive
   * @return a boxed primitive that is the negation of the argument
   */
  private Object negateBoxedPrimitive(Object o) {
    if (value instanceof Byte) {
      return (byte) -(Byte) value;
    }
    if (value instanceof Short) {
      return (short) -(Short) value;
    }
    if (value instanceof Integer) {
      return -(Integer) value;
    }
    if (value instanceof Long) {
      return -(Long) value;
    }
    if (value instanceof Float) {
      return -(Float) value;
    }
    if (value instanceof Double) {
      return -(Double) value;
    }
    if (value instanceof BigInteger) {
      assert value.equals(NEGATIVE_LONG_MIN_VALUE);
      return Long.MIN_VALUE;
    }
    throw new BugInCF("Cannot be negated: " + o + " " + o.getClass());
  }

  /**
   * Returns the value of this literal.
   *
   * @return the value of this literal
   */
  public @Nullable Object getValue() {
    return value;
  }

  @Override
  public boolean containsOfClass(Class clazz) {
    return getClass() == clazz;
  }

  @Override
  public boolean isDeterministic(AnnotationProvider provider) {
    return true;
  }

  @Override
  public boolean isUnassignableByOtherCode() {
    return true;
  }

  @Override
  public boolean isUnmodifiableByOtherCode() {
    return true;
  }

  @Override
  public boolean syntacticEquals(JavaExpression je) {
    return this.equals(je);
  }

  @Override
  public boolean containsSyntacticEqualJavaExpression(JavaExpression other) {
    return this.syntacticEquals(other);
  }

  @Override
  public boolean containsModifiableAliasOf(Store store, JavaExpression other) {
    return false; // not modifiable
  }

  /// java.lang.Object methods

  @Override
  public boolean equals(@Nullable Object obj) {
    if (!(obj instanceof ValueLiteral)) {
      return false;
    }
    ValueLiteral other = (ValueLiteral) obj;
    // TODO:  Can this string comparison be cleaned up?
    // Cannot use Types.isSameType(type, other.type) because we don't have a Types object.
    return type.toString().equals(other.type.toString()) && Objects.equals(value, other.value);
  }

  @Override
  public String toString() {
    if (TypesUtils.isString(type)) {
      return "\"" + value + "\"";
    } else if (type.getKind() == TypeKind.LONG) {
      assert value != null : "@AssumeAssertion(nullness): invariant";
      return value.toString() + "L";
    } else if (type.getKind() == TypeKind.CHAR) {
      return "\'" + value + "\'";
    }
    return value == null ? "null" : value.toString();
  }

  @Override
  public int hashCode() {
    return Objects.hash(value, type.toString());
  }

  @Override
  public  R accept(JavaExpressionVisitor visitor, P p) {
    return visitor.visitValueLiteral(this, p);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy