Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
framework.src.org.checkerframework.common.value.ValueTransfer Maven / Gradle / Ivy
package org.checkerframework.common.value;
import org.checkerframework.common.value.qual.BoolVal;
import org.checkerframework.common.value.qual.BottomVal;
import org.checkerframework.common.value.qual.DoubleVal;
import org.checkerframework.common.value.qual.IntVal;
import org.checkerframework.common.value.qual.StringVal;
import org.checkerframework.common.value.qual.UnknownVal;
import org.checkerframework.common.value.util.NumberMath;
import org.checkerframework.common.value.util.NumberUtils;
import org.checkerframework.dataflow.analysis.RegularTransferResult;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.node.*;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TypesUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
public class ValueTransfer extends CFTransfer {
AnnotatedTypeFactory atypefactory;
public ValueTransfer(
CFAbstractAnalysis analysis) {
super(analysis);
atypefactory = analysis.getTypeFactory();
}
private List getStringValues(Node subNode,
TransferInput p) {
CFValue value = p.getValueOfSubNode(subNode);
// @StringVal, @BottomVal, @UnknownVal
AnnotationMirror numberAnno = value.getType().getAnnotation(
StringVal.class);
if (numberAnno != null) {
return AnnotationUtils.getElementValueArray(numberAnno, "value",
String.class, true);
}
numberAnno = value.getType().getAnnotation(UnknownVal.class);
if (numberAnno != null) {
return new ArrayList();
}
numberAnno = value.getType().getAnnotation(BottomVal.class);
if (numberAnno != null) {
return Collections.singletonList("null");
}
//@IntVal, @DoubleVal, @BoolVal (have to be converted to string)
List values;
numberAnno = value.getType().getAnnotation(BoolVal.class);
if (numberAnno != null) {
values = getBooleanValues(subNode, p);
} else if (subNode.getType().getKind() == TypeKind.CHAR) {
values = getCharValues(subNode, p);
} else if (subNode instanceof StringConversionNode) {
return getStringValues(
((StringConversionNode) subNode).getOperand(), p);
} else {
values = getNumericalValues(subNode, p);
}
List stringValues = new ArrayList();
for (Object o : values) {
stringValues.add(o.toString());
}
return stringValues;
}
private List getBooleanValues(Node subNode,
TransferInput p) {
CFValue value = p.getValueOfSubNode(subNode);
AnnotationMirror intAnno = value.getType().getAnnotation(BoolVal.class);
return ValueAnnotatedTypeFactory.getBooleanValues(intAnno);
}
private List getCharValues(Node subNode,
TransferInput p) {
CFValue value = p.getValueOfSubNode(subNode);
AnnotationMirror intAnno = value.getType().getAnnotation(IntVal.class);
return ValueAnnotatedTypeFactory.getCharValues(intAnno);
}
private List getNumericalValues(Node subNode,
TransferInput p) {
CFValue value = p.getValueOfSubNode(subNode);
AnnotationMirror numberAnno = value.getType().getAnnotation(
IntVal.class);
List values;
if (numberAnno == null) {
numberAnno = value.getType().getAnnotation(DoubleVal.class);
if (numberAnno != null) {
values = AnnotationUtils.getElementValueArray(numberAnno,
"value", Double.class, true);
} else {
return new ArrayList();
}
} else {
values = AnnotationUtils.getElementValueArray(numberAnno, "value",
Long.class, true);
}
return NumberUtils.castNumbers(subNode.getType(), values);
}
private AnnotationMirror createStringValAnnotationMirror(List values) {
if (values.isEmpty()) {
return ((ValueAnnotatedTypeFactory) atypefactory).UNKNOWNVAL;
}
return ((ValueAnnotatedTypeFactory) atypefactory)
.createStringAnnotation(values);
}
private AnnotationMirror createNumberAnnotationMirror(List values) {
if (values.isEmpty()) {
return ((ValueAnnotatedTypeFactory) atypefactory).UNKNOWNVAL;
}
Number first = values.get(0);
if (first instanceof Integer || first instanceof Short
|| first instanceof Long) {
List intValues = new ArrayList<>();
for (Number number : values) {
intValues.add(number.longValue());
}
return ((ValueAnnotatedTypeFactory) atypefactory)
.createIntValAnnotation(intValues);
}
if (first instanceof Double || first instanceof Float) {
List intValues = new ArrayList<>();
for (Number number : values) {
intValues.add(number.doubleValue());
}
return ((ValueAnnotatedTypeFactory) atypefactory)
.createDoubleValAnnotation(intValues);
}
throw new UnsupportedOperationException();
}
private AnnotationMirror createBooleanAnnotationMirror(List values) {
if (values.isEmpty()) {
return ((ValueAnnotatedTypeFactory) atypefactory).UNKNOWNVAL;
}
return ((ValueAnnotatedTypeFactory) atypefactory)
.createBooleanAnnotation(values);
}
private TransferResult createNewResult(
TransferResult result, List resultValues) {
AnnotationMirror stringVal = createNumberAnnotationMirror(resultValues);
CFValue newResultValue = analysis.createSingleAnnotationValue(
stringVal, result.getResultValue().getType()
.getUnderlyingType());
return new RegularTransferResult<>(newResultValue,
result.getRegularStore());
}
private TransferResult createNewResultBoolean(
TransferResult result, List resultValues) {
AnnotationMirror stringVal = createBooleanAnnotationMirror(resultValues);
CFValue newResultValue = analysis.createSingleAnnotationValue(
stringVal, result.getResultValue().getType()
.getUnderlyingType());
return new RegularTransferResult<>(newResultValue,
result.getRegularStore());
}
@Override
public TransferResult visitStringConcatenateAssignment(StringConcatenateAssignmentNode n,
TransferInput p) {
TransferResult result = super.visitStringConcatenateAssignment(n, p);
return stringConcatenation(n.getLeftOperand(), n.getRightOperand(), p, result);
}
@Override
public TransferResult visitStringConcatenate(StringConcatenateNode n,
TransferInput p) {
TransferResult result = super.visitStringConcatenate(n, p);
return stringConcatenation(n.getLeftOperand(), n.getRightOperand(), p, result);
}
public TransferResult stringConcatenation(Node leftOperand, Node rightOperand,
TransferInput p,
TransferResult result) {
List lefts = getStringValues(leftOperand, p);
List rights = getStringValues(rightOperand, p);
List concat = new ArrayList<>();
for (String left : lefts) {
for (String right : rights) {
concat.add(left + right);
}
}
AnnotationMirror stringVal = createStringValAnnotationMirror(concat);
TypeMirror underlyingType = result.getResultValue().getType().getUnderlyingType();
CFValue newResultValue = analysis.createSingleAnnotationValue(stringVal, underlyingType);
return new RegularTransferResult<>(newResultValue, result.getRegularStore());
}
enum NumbericalBinaryOps {
ADDTION, SUBTRACTION, DIVISION, REMAINDER, MULPLICATION, SHIFT_LEFT, SIGNED_SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT, BITWISE_AND, BITWISE_OR, BITWISE_XOR;
}
private List calcutateNumericalBinaryOp(Node leftNode,
Node rightNode, NumbericalBinaryOps op,
TransferInput p) {
List lefts = getNumericalValues(leftNode, p);
List rights = getNumericalValues(rightNode, p);
List resultValues = new ArrayList<>();
for (Number left : lefts) {
NumberMath nmLeft = NumberMath.getNumberMath(left);
for (Number right : rights) {
switch (op) {
case ADDTION:
resultValues.add(nmLeft.plus(right));
break;
case DIVISION:
resultValues.add(nmLeft.divide(right));
break;
case MULPLICATION:
resultValues.add(nmLeft.times(right));
break;
case REMAINDER:
resultValues.add(nmLeft.remainder(right));
break;
case SUBTRACTION:
resultValues.add(nmLeft.minus(right));
break;
case SHIFT_LEFT:
resultValues.add(nmLeft.shiftLeft(right));
break;
case SIGNED_SHIFT_RIGHT:
resultValues.add(nmLeft.signedSiftRight(right));
break;
case UNSIGNED_SHIFT_RIGHT:
resultValues.add(nmLeft.unsignedSiftRight(right));
break;
case BITWISE_AND:
resultValues.add(nmLeft.bitwiseAnd(right));
break;
case BITWISE_OR:
resultValues.add(nmLeft.bitwiseOr(right));
break;
case BITWISE_XOR:
resultValues.add(nmLeft.bitwiseXor(right));
break;
default:
throw new UnsupportedOperationException();
}
}
}
return resultValues;
}
@Override
public TransferResult visitNumericalAddition(
NumericalAdditionNode n, TransferInput p) {
TransferResult transferResult = super
.visitNumericalAddition(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.ADDTION, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitNumericalSubtraction(
NumericalSubtractionNode n, TransferInput p) {
TransferResult transferResult = super
.visitNumericalSubtraction(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.SUBTRACTION, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitNumericalMultiplication(
NumericalMultiplicationNode n, TransferInput p) {
TransferResult transferResult = super
.visitNumericalMultiplication(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.MULPLICATION, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitIntegerDivision(
IntegerDivisionNode n, TransferInput p) {
TransferResult transferResult = super
.visitIntegerDivision(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.DIVISION, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitFloatingDivision(
FloatingDivisionNode n, TransferInput p) {
TransferResult transferResult = super
.visitFloatingDivision(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.DIVISION, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitIntegerRemainder(
IntegerRemainderNode n, TransferInput p) {
TransferResult transferResult = super
.visitIntegerRemainder(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.REMAINDER, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitFloatingRemainder(
FloatingRemainderNode n, TransferInput p) {
TransferResult transferResult = super
.visitFloatingRemainder(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.REMAINDER, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitLeftShift(LeftShiftNode n,
TransferInput p) {
TransferResult transferResult = super.visitLeftShift(
n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.SHIFT_LEFT, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitSignedRightShift(
SignedRightShiftNode n, TransferInput p) {
TransferResult transferResult = super
.visitSignedRightShift(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.SIGNED_SHIFT_RIGHT, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitUnsignedRightShift(
UnsignedRightShiftNode n, TransferInput p) {
TransferResult transferResult = super
.visitUnsignedRightShift(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.UNSIGNED_SHIFT_RIGHT, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitBitwiseAnd(BitwiseAndNode n,
TransferInput p) {
TransferResult transferResult = super
.visitBitwiseAnd(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.BITWISE_AND, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitBitwiseOr(BitwiseOrNode n,
TransferInput p) {
TransferResult transferResult = super.visitBitwiseOr(
n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.BITWISE_OR, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitBitwiseXor(BitwiseXorNode n,
TransferInput p) {
TransferResult transferResult = super
.visitBitwiseXor(n, p);
List resultValues = calcutateNumericalBinaryOp(
n.getLeftOperand(), n.getRightOperand(),
NumbericalBinaryOps.BITWISE_XOR, p);
return createNewResult(transferResult, resultValues);
}
enum NumbericalUnaryOps {
PLUS, MINUS, BITWISE_COMPLEMENT;
}
private List calcutateNumericalUnaryOp(Node operand,
NumbericalUnaryOps op, TransferInput p) {
List lefts = getNumericalValues(operand, p);
List resultValues = new ArrayList<>();
for (Number left : lefts) {
NumberMath nmLeft = NumberMath.getNumberMath(left);
switch (op) {
case PLUS:
resultValues.add(nmLeft.unaryPlus());
break;
case MINUS:
resultValues.add(nmLeft.unaryMinus());
break;
case BITWISE_COMPLEMENT:
resultValues.add(nmLeft.bitwiseComplement());
break;
default:
throw new UnsupportedOperationException();
}
}
return resultValues;
}
@Override
public TransferResult visitNumericalMinus(
NumericalMinusNode n, TransferInput p) {
TransferResult transferResult = super
.visitNumericalMinus(n, p);
List resultValues = calcutateNumericalUnaryOp(n.getOperand(),
NumbericalUnaryOps.MINUS, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitNumericalPlus(
NumericalPlusNode n, TransferInput p) {
TransferResult transferResult = super
.visitNumericalPlus(n, p);
List resultValues = calcutateNumericalUnaryOp(n.getOperand(),
NumbericalUnaryOps.PLUS, p);
return createNewResult(transferResult, resultValues);
}
@Override
public TransferResult visitBitwiseComplement(
BitwiseComplementNode n, TransferInput p) {
TransferResult transferResult = super
.visitBitwiseComplement(n, p);
List resultValues = calcutateNumericalUnaryOp(n.getOperand(),
NumbericalUnaryOps.BITWISE_COMPLEMENT, p);
return createNewResult(transferResult, resultValues);
}
enum ComparisonOperators {
EQUAL, NOT_EQUAL, GREATER_THAN, GREATER_THAN_EQ, LESS_THAN, LESS_THAN_EQ;
}
private List calcutateBinaryComparison(Node leftNode,
Node rightNode, ComparisonOperators op,
TransferInput p) {
List lefts = getNumericalValues(leftNode, p);
List rights = getNumericalValues(rightNode, p);
List resultValues = new ArrayList<>();
for (Number left : lefts) {
NumberMath nmLeft = NumberMath.getNumberMath(left);
for (Number right : rights) {
switch (op) {
case EQUAL:
resultValues.add(nmLeft.equalTo(right));
break;
case GREATER_THAN:
resultValues.add(nmLeft.greaterThan(right));
break;
case GREATER_THAN_EQ:
resultValues.add(nmLeft.greaterThanEq(right));
break;
case LESS_THAN:
resultValues.add(nmLeft.lessThan(right));
break;
case LESS_THAN_EQ:
resultValues.add(nmLeft.lessThanEq(right));
break;
case NOT_EQUAL:
resultValues.add(nmLeft.notEqualTo(right));
break;
default:
throw new UnsupportedOperationException();
}
}
}
return resultValues;
}
@Override
public TransferResult visitLessThan(LessThanNode n,
TransferInput p) {
TransferResult transferResult = super.visitLessThan(
n, p);
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.LESS_THAN, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitLessThanOrEqual(
LessThanOrEqualNode n, TransferInput p) {
TransferResult transferResult = super
.visitLessThanOrEqual(n, p);
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.LESS_THAN_EQ, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitGreaterThan(GreaterThanNode n,
TransferInput p) {
TransferResult transferResult = super
.visitGreaterThan(n, p);
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.GREATER_THAN, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitGreaterThanOrEqual(
GreaterThanOrEqualNode n, TransferInput p) {
TransferResult transferResult = super
.visitGreaterThanOrEqual(n, p);
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.GREATER_THAN_EQ, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitEqualTo(EqualToNode n,
TransferInput p) {
TransferResult transferResult = super.visitEqualTo(n,
p);
if (TypesUtils.isPrimitive(n.getLeftOperand().getType())
|| TypesUtils.isPrimitive(n.getRightOperand().getType())) {
// At least one must be a primitive otherwise reference equality is used.
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.EQUAL, p);
return createNewResultBoolean(transferResult, resultValues);
}
return super.visitEqualTo(n, p);
}
@Override
public TransferResult visitNotEqual(NotEqualNode n,
TransferInput p) {
TransferResult transferResult = super.visitNotEqual(
n, p);
if (TypesUtils.isPrimitive(n.getLeftOperand().getType())
|| TypesUtils.isPrimitive(n.getRightOperand().getType())) {
// At least one must be a primitive otherwise reference equality is
// used.
List resultValues = calcutateBinaryComparison(
n.getLeftOperand(), n.getRightOperand(),
ComparisonOperators.NOT_EQUAL, p);
return createNewResultBoolean(transferResult, resultValues);
}
return super.visitNotEqual(n, p);
}
enum ConditionalOperators {
NOT, OR, AND;
}
private List calcutateCondtionalOperator(Node leftNode,
Node rightNode, ConditionalOperators op,
TransferInput p) {
List lefts = getBooleanValues(leftNode, p);
List resultValues = new ArrayList<>();
List rights = new ArrayList();
if (rightNode != null) {
rights = getBooleanValues(rightNode, p);
}
switch (op) {
case NOT:
for (Boolean left : lefts) {
resultValues.add(!left);
}
return resultValues;
case OR:
if (lefts.isEmpty() && rights.size() == 1) {
if (rights.get(0)) {
// unknown || true == true
return rights;
}
}
if (rights.isEmpty() && lefts.size() == 1) {
if (lefts.get(0)) {
// true || unknown == true
return lefts;
}
}
for (Boolean left : lefts) {
for (Boolean right : rights) {
resultValues.add(left || right);
}
}
return resultValues;
case AND:
if (lefts.isEmpty() && rights.size() == 1) {
if (!rights.get(0)) {
// unknown && false == false
return rights;
}
}
if (rights.isEmpty() && lefts.size() == 1) {
if (!lefts.get(0)) {
// false && unknown == false
return lefts;
}
}
for (Boolean left : lefts) {
for (Boolean right : rights) {
resultValues.add(left && right);
}
}
return resultValues;
}
return resultValues;
}
@Override
public TransferResult visitConditionalNot(
ConditionalNotNode n, TransferInput p) {
TransferResult transferResult = super
.visitConditionalNot(n, p);
List resultValues = calcutateCondtionalOperator(
n.getOperand(), null, ConditionalOperators.NOT, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitConditionalAnd(
ConditionalAndNode n, TransferInput p) {
TransferResult transferResult = super
.visitConditionalAnd(n, p);
List resultValues = calcutateCondtionalOperator(
n.getLeftOperand(), n.getRightOperand(),
ConditionalOperators.AND, p);
return createNewResultBoolean(transferResult, resultValues);
}
@Override
public TransferResult visitConditionalOr(
ConditionalOrNode n, TransferInput p) {
TransferResult transferResult = super
.visitConditionalOr(n, p);
List resultValues = calcutateCondtionalOperator(
n.getLeftOperand(), n.getRightOperand(),
ConditionalOperators.OR, p);
return createNewResultBoolean(transferResult, resultValues);
}
}