org.checkerframework.dataflow.expression.ValueLiteral Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dataflow-shaded Show documentation
Show all versions of dataflow-shaded Show documentation
dataflow-shaded is a dataflow framework based on the javac compiler.
It differs from the org.checkerframework:dataflow artifact in two ways.
First, the packages in this artifact have been renamed to org.checkerframework.shaded.*.
Second, unlike the dataflow artifact, this artifact contains the dependencies it requires.
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 static 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, @Nullable 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;
}
@SuppressWarnings("unchecked") // generic cast
@Override
public @Nullable T containedOfClass(Class clazz) {
return getClass() == clazz ? (T) this : null;
}
@Override
public boolean isDeterministic(AnnotationProvider provider) {
return true;
}
@Override
public boolean isAssignableByOtherCode() {
return false;
}
@Override
public boolean isModifiableByOtherCode() {
return false;
}
@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);
}
}