use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.
the class JavaExpressionOptimizer method visitMethodCall.
@Override
protected JavaExpression visitMethodCall(MethodCall methodCallExpr, Void unused) {
JavaExpression optReceiver = convert(methodCallExpr.getReceiver());
List<JavaExpression> optArguments = convert(methodCallExpr.getArguments());
// Length of string literal: convert it to an integer literal.
if (methodCallExpr.getElement().getSimpleName().contentEquals("length") && optReceiver instanceof ValueLiteral) {
Object value = ((ValueLiteral) optReceiver).getValue();
if (value instanceof String) {
return new ValueLiteral(factory.types.getPrimitiveType(TypeKind.INT), ((String) value).length());
}
}
return new MethodCall(methodCallExpr.getType(), methodCallExpr.getElement(), optReceiver, optArguments);
}
use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.
the class UpperBoundTransfer method refineNeqSequenceLength.
/**
* If lengthAccess node is an sequence length field or method access (optionally with a constant
* offset subtracted) and the other node is less than or equal to that sequence length (minus the
* offset), then refine the other node's type to less than the sequence length (minus the offset).
* This is case 12.
*/
private void refineNeqSequenceLength(Node lengthAccess, Node otherNode, AnnotationMirror otherNodeAnno, CFStore store) {
// If lengthAccess is "receiver.length - c" where c is an integer constant,
// then lengthOffset is "c".
int lengthOffset = 0;
if (lengthAccess instanceof NumericalSubtractionNode) {
NumericalSubtractionNode subtraction = (NumericalSubtractionNode) lengthAccess;
Node offsetNode = subtraction.getRightOperand();
Long offsetValue = ValueCheckerUtils.getExactValue(offsetNode.getTree(), atypeFactory.getValueAnnotatedTypeFactory());
if (offsetValue != null && offsetValue > Integer.MIN_VALUE && offsetValue <= Integer.MAX_VALUE) {
lengthOffset = offsetValue.intValue();
lengthAccess = subtraction.getLeftOperand();
} else {
// Subtraction of non-constant expressions is not supported
return;
}
}
JavaExpression receiver = null;
if (NodeUtils.isArrayLengthFieldAccess(lengthAccess)) {
FieldAccess fa = (FieldAccess) JavaExpression.fromNodeFieldAccess((FieldAccessNode) lengthAccess);
receiver = fa.getReceiver();
} else if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(lengthAccess)) {
JavaExpression ma = JavaExpression.fromNode(lengthAccess);
if (ma instanceof MethodCall) {
receiver = ((MethodCall) ma).getReceiver();
}
}
if (receiver != null && !receiver.containsUnknown()) {
UBQualifier otherQualifier = UBQualifier.createUBQualifier(otherNodeAnno, (UpperBoundChecker) atypeFactory.getChecker());
String sequence = receiver.toString();
// Check if otherNode + c - 1 < receiver.length
if (otherQualifier.hasSequenceWithOffset(sequence, lengthOffset - 1)) {
// Add otherNode + c < receiver.length
UBQualifier newQualifier = UBQualifier.createUBQualifier(sequence, Integer.toString(lengthOffset));
otherQualifier = otherQualifier.glb(newQualifier);
for (Node internal : splitAssignments(otherNode)) {
JavaExpression leftJe = JavaExpression.fromNode(internal);
store.insertValue(leftJe, atypeFactory.convertUBQualifierToAnnotation(otherQualifier));
}
}
}
}
use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.
the class UpperBoundTransfer method visitMethodInvocation.
/**
* If n is a String.length() method invocation, then the type of s.length() is the glb
* of @LTEqLengthOf("s") and the value of s.length() in the store. This is case 20.
*/
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
if (atypeFactory.getMethodIdentifier().isLengthOfMethodInvocation(n)) {
JavaExpression stringLength = JavaExpression.fromNode(n);
if (stringLength instanceof MethodCall) {
JavaExpression receiverJe = ((MethodCall) stringLength).getReceiver();
Tree receiverTree = n.getTarget().getReceiver().getTree();
// receiverTree is null when the receiver is implicit "this".
if (receiverTree != null) {
TransferResult<CFValue, CFStore> result = visitLengthAccess(n, in, receiverJe, receiverTree);
if (result != null) {
return result;
}
}
}
}
return super.visitMethodInvocation(n, in);
}
use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.
the class LockStore method insertLockPossiblyHeld.
/*
* Insert an annotation exactly, without regard to whether an annotation was already present.
* This is only done for @LockPossiblyHeld. This is not sound for other type qualifiers.
*/
public void insertLockPossiblyHeld(JavaExpression je) {
if (je.containsUnknown()) {
// Expressions containing unknown expressions are not stored.
return;
}
if (je instanceof LocalVariable) {
LocalVariable localVar = (LocalVariable) je;
CFValue current = localVariableValues.get(localVar);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
localVariableValues.put(localVar, value);
}
} else if (je instanceof FieldAccess) {
FieldAccess fieldAcc = (FieldAccess) je;
CFValue current = fieldValues.get(fieldAcc);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
fieldValues.put(fieldAcc, value);
}
} else if (je instanceof MethodCall) {
MethodCall method = (MethodCall) je;
CFValue current = methodValues.get(method);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
methodValues.put(method, value);
}
} else if (je instanceof ArrayAccess) {
ArrayAccess arrayAccess = (ArrayAccess) je;
CFValue current = arrayValues.get(arrayAccess);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
arrayValues.put(arrayAccess, value);
}
} else if (je instanceof ThisReference) {
thisValue = changeLockAnnoToTop(je, thisValue);
} else if (je instanceof ClassName) {
ClassName className = (ClassName) je;
CFValue current = classValues.get(className);
CFValue value = changeLockAnnoToTop(je, current);
if (value != null) {
classValues.put(className, value);
}
} else {
// No other types of expressions need to be stored.
}
}
use of org.checkerframework.dataflow.expression.MethodCall in project checker-framework by typetools.
the class CFAbstractStore method computeNewValueAndInsert.
/**
* Inserts the result of applying {@code merger} to {@code value} and the previous value for
* {@code expr}.
*
* @param expr the JavaExpression
* @param value the value of the JavaExpression
* @param merger the function used to merge {@code value} and the previous value of {@code expr}
* @param permitNondeterministic if false, does nothing if {@code expr} is nondeterministic; if
* true, permits nondeterministic expressions to be placed in the store
*/
protected void computeNewValueAndInsert(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) {
if (!shouldInsert(expr, value, permitNondeterministic)) {
return;
}
if (expr instanceof LocalVariable) {
LocalVariable localVar = (LocalVariable) expr;
V oldValue = localVariableValues.get(localVar);
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
localVariableValues.put(localVar, newValue);
}
} else if (expr instanceof FieldAccess) {
FieldAccess fieldAcc = (FieldAccess) expr;
// Only store information about final fields (where the receiver is
// also fixed) if concurrent semantics are enabled.
boolean isMonotonic = isMonotonicUpdate(fieldAcc, value);
if (sequentialSemantics || isMonotonic || fieldAcc.isUnassignableByOtherCode()) {
V oldValue = fieldValues.get(fieldAcc);
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
fieldValues.put(fieldAcc, newValue);
}
}
} else if (expr instanceof MethodCall) {
MethodCall method = (MethodCall) expr;
// Don't store any information if concurrent semantics are enabled.
if (sequentialSemantics) {
V oldValue = methodValues.get(method);
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
methodValues.put(method, newValue);
}
}
} else if (expr instanceof ArrayAccess) {
ArrayAccess arrayAccess = (ArrayAccess) expr;
if (sequentialSemantics) {
V oldValue = arrayValues.get(arrayAccess);
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
arrayValues.put(arrayAccess, newValue);
}
}
} else if (expr instanceof ThisReference) {
ThisReference thisRef = (ThisReference) expr;
if (sequentialSemantics || thisRef.isUnassignableByOtherCode()) {
V oldValue = thisValue;
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
thisValue = newValue;
}
}
} else if (expr instanceof ClassName) {
ClassName className = (ClassName) expr;
if (sequentialSemantics || className.isUnassignableByOtherCode()) {
V oldValue = classValues.get(className);
V newValue = merger.apply(oldValue, value);
if (newValue != null) {
classValues.put(className, newValue);
}
}
} else {
// No other types of expressions need to be stored.
}
}
Aggregations