use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class LessThanTransfer method refineGTE.
/**
* Case 2.
*/
@Override
protected void refineGTE(Node left, AnnotationMirror leftAnno, Node right, AnnotationMirror rightAnno, CFStore store, TransferInput<CFValue, CFStore> in) {
// left >= right so right is less than left
// Refine right to @LessThan("left + 1")
// left > right so right is less than left
// Refine right to @LessThan("left")
JavaExpression leftJe = JavaExpression.fromNode(left);
if (leftJe != null && leftJe.isUnassignableByOtherCode()) {
if (isDoubleOrFloatLiteral(leftJe)) {
return;
}
LessThanAnnotatedTypeFactory factory = (LessThanAnnotatedTypeFactory) analysis.getTypeFactory();
List<String> lessThanExpressions = factory.getLessThanExpressions(rightAnno);
if (lessThanExpressions == null) {
// right is already bottom, nothing to refine.
return;
}
String leftIncremented = incrementedExpression(leftJe);
if (!lessThanExpressions.contains(leftIncremented)) {
lessThanExpressions = CollectionsPlume.append(lessThanExpressions, leftIncremented);
JavaExpression rightJe = JavaExpression.fromNode(right);
store.insertValue(rightJe, factory.createLessThanQualifier(lessThanExpressions));
}
}
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class UpperBoundTransfer method visitFieldAccess.
/**
* If n is an array length field access, then the type of a.length is the glb
* of @LTEqLengthOf("a") and the value of a.length in the store. This is case 19.
*/
@Override
public TransferResult<CFValue, CFStore> visitFieldAccess(FieldAccessNode n, TransferInput<CFValue, CFStore> in) {
if (NodeUtils.isArrayLengthFieldAccess(n)) {
FieldAccess arrayLength = (FieldAccess) JavaExpression.fromNodeFieldAccess(n);
JavaExpression arrayJe = arrayLength.getReceiver();
Tree arrayTree = n.getReceiver().getTree();
TransferResult<CFValue, CFStore> result = visitLengthAccess(n, in, arrayJe, arrayTree);
if (result != null) {
return result;
}
}
return super.visitFieldAccess(n, in);
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class UpperBoundTransfer method refineGT.
/**
* Case 8: if x < y, and y has a type that is related to the length of an array, then x has the
* same type, with an offset that is one less.
*/
@Override
protected void refineGT(Node larger, AnnotationMirror largerAnno, Node smaller, AnnotationMirror smallerAnno, CFStore store, TransferInput<CFValue, CFStore> in) {
// larger > smaller
UBQualifier largerQual = UBQualifier.createUBQualifier(largerAnno, (UpperBoundChecker) atypeFactory.getChecker());
// larger + 1 >= smaller
UBQualifier largerQualPlus1 = largerQual.plusOffset(1);
UBQualifier rightQualifier = UBQualifier.createUBQualifier(smallerAnno, (UpperBoundChecker) atypeFactory.getChecker());
UBQualifier refinedRight = rightQualifier.glb(largerQualPlus1);
if (largerQualPlus1.isLessThanLengthQualifier()) {
propagateToOperands((LessThanLengthOf) largerQualPlus1, smaller, in, store);
}
refineSubtrahendWithOffset(larger, smaller, true, in, store);
JavaExpression rightJe = JavaExpression.fromNode(smaller);
store.insertValue(rightJe, atypeFactory.convertUBQualifierToAnnotation(refinedRight));
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method convertAnnotationMirror.
/**
* Given an annotation {@code anno}, this method builds a new annotation with the Java expressions
* transformed according to {@code stringToJavaExpr}. If {@code anno} is not a dependent type
* annotation, {@code null} is returned.
*
* <p>If {@code stringToJavaExpr} returns {@code null}, then that expression is removed from the
* returned annotation.
*
* <p>Instead of overriding this method, subclasses can override the following methods to change
* the behavior of this class:
*
* <ul>
* <li>{@link #shouldPassThroughExpression(String)}: to control which expressions are skipped.
* If this method returns true, then the expression string is not parsed and is included in
* the new annotation unchanged.
* <li>{@link #transform(JavaExpression)}: make changes to the JavaExpression produced by {@code
* stringToJavaExpr}.
* <li>{@link #buildAnnotation(AnnotationMirror, Map)}: to change the annotation returned by
* this method.
* </ul>
*
* @param stringToJavaExpr function that converts strings to {@code JavaExpression}s
* @param anno annotation mirror
* @return an annotation created by applying {@code stringToJavaExpr} to all expression strings in
* {@code anno}, or null if there would be no effect
*/
@Nullable
public AnnotationMirror convertAnnotationMirror(StringToJavaExpression stringToJavaExpr, AnnotationMirror anno) {
if (!isExpressionAnno(anno)) {
return null;
}
Map<ExecutableElement, List<JavaExpression>> newElements = new HashMap<>();
for (ExecutableElement element : getListOfExpressionElements(anno)) {
List<String> expressionStrings = AnnotationUtils.getElementValueArray(anno, element, String.class, Collections.emptyList());
List<JavaExpression> javaExprs = new ArrayList<>(expressionStrings.size());
newElements.put(element, javaExprs);
for (String expression : expressionStrings) {
JavaExpression result;
if (shouldPassThroughExpression(expression)) {
result = new PassThroughExpression(objectTM, expression);
} else {
try {
result = stringToJavaExpr.toJavaExpression(expression);
} catch (JavaExpressionParseException e) {
result = createError(expression, e);
}
}
if (result != null) {
result = transform(result);
javaExprs.add(result);
}
}
}
return buildAnnotation(anno, newElements);
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method delocalize.
/**
* Viewpoint-adapt all dependent type annotations to the method declaration, {@code
* methodDeclTree}. This method changes occurrences of formal parameter names to the "#2" syntax,
* and it removes expressions that contain other local variables.
*
* <p>If a Java expression in {@code atm} references local variables (other than formal
* parameters), the expression is removed from the annotation. This could result in dependent type
* annotations with empty lists of expressions. If this is a problem, a subclass can override
* {@link #buildAnnotation(AnnotationMirror, Map)} to do something besides creating an annotation
* with a empty list.
*
* @param atm type to viewpoint-adapt; is side-effected by this method
* @param methodDeclTree the method declaration to which the annotations are viewpoint-adapted
*/
public void delocalize(AnnotatedTypeMirror atm, MethodTree methodDeclTree) {
if (!hasDependentType(atm)) {
return;
}
TreePath pathToMethodDecl = factory.getPath(methodDeclTree);
ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodDeclTree);
List<FormalParameter> parameters = JavaExpression.getFormalParameters(methodElement);
List<JavaExpression> paramsAsLocals = JavaExpression.getParametersAsLocalVariables(methodElement);
StringToJavaExpression stringToJavaExpr = expression -> {
JavaExpression javaExpr;
try {
javaExpr = StringToJavaExpression.atPath(expression, pathToMethodDecl, factory.getChecker());
} catch (JavaExpressionParseException ex) {
return null;
}
JavaExpressionConverter jec = new JavaExpressionConverter() {
@Override
protected JavaExpression visitLocalVariable(LocalVariable localVarExpr, Void unused) {
int index = paramsAsLocals.indexOf(localVarExpr);
if (index == -1) {
throw new FoundLocalException();
}
return parameters.get(index);
}
};
try {
return jec.convert(javaExpr);
} catch (FoundLocalException ex) {
return null;
}
};
if (debugStringToJavaExpression) {
System.out.printf("delocalize(%s, %s) created %s%n", atm, TreeUtils.toStringTruncated(methodDeclTree, 65), stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, atm);
}
Aggregations