use of org.checkerframework.checker.index.Subsequence in project checker-framework by typetools.
the class UpperBoundTransfer method visitNumericalSubtraction.
/**
* If some Node a is known to be less than the length of some sequence x, then the type of a - b
* is @LTLengthOf(value="x", offset="b"). If b is known to be less than the length of some other
* sequence, this doesn't add any information about the type of a - b. But, if b is non-negative
* or positive, then a - b should keep the types of a. This corresponds to cases 16 and 17.
*/
@Override
public TransferResult<CFValue, CFStore> visitNumericalSubtraction(NumericalSubtractionNode n, TransferInput<CFValue, CFStore> in) {
UBQualifier left = getUBQualifier(n.getLeftOperand(), in);
UBQualifier leftWithOffset = left.plusOffset(n.getRightOperand(), atypeFactory);
if (atypeFactory.hasLowerBoundTypeByClass(n.getRightOperand(), NonNegative.class) || atypeFactory.hasLowerBoundTypeByClass(n.getRightOperand(), Positive.class)) {
// annotations should be kept.
if (left.isLessThanLengthQualifier()) {
leftWithOffset = left.glb(leftWithOffset);
}
}
if (leftWithOffset.isLessThanLengthQualifier()) {
LessThanLengthOf subtractionResult = (LessThanLengthOf) leftWithOffset;
for (String b : subtractionResult.getSequences()) {
if (subtractionResult.hasSequenceWithOffset(b, -1) || subtractionResult.hasSequenceWithOffset(b, 0)) {
TreePath currentPath = this.atypeFactory.getPath(n.getTree());
JavaExpression je;
try {
je = UpperBoundVisitor.parseJavaExpressionString(b, atypeFactory, currentPath);
} catch (NullPointerException npe) {
// optional, but useful elsewhere, catching this NPE here and returning is always safe.
return createTransferResult(n, in, leftWithOffset);
}
Subsequence subsequence = Subsequence.getSubsequenceFromReceiver(je, atypeFactory);
if (subsequence != null) {
String from = subsequence.from;
String to = subsequence.to;
String a = subsequence.array;
JavaExpression leftOp = JavaExpression.fromNode(n.getLeftOperand());
JavaExpression rightOp = JavaExpression.fromNode(n.getRightOperand());
if (rightOp.toString().equals(from)) {
LessThanAnnotatedTypeFactory lessThanAtypeFactory = atypeFactory.getLessThanAnnotatedTypeFactory();
AnnotationMirror lessThanType = lessThanAtypeFactory.getAnnotatedType(n.getLeftOperand().getTree()).getAnnotation(LessThan.class);
if (lessThanType != null && lessThanAtypeFactory.isLessThan(lessThanType, to)) {
UBQualifier ltlA = UBQualifier.createUBQualifier(a, "0");
leftWithOffset = leftWithOffset.glb(ltlA);
} else if (leftOp.toString().equals(to) || (lessThanType != null && lessThanAtypeFactory.isLessThanOrEqual(lessThanType, to))) {
// It's necessary to check if leftOp == to because LessThan doesn't
// infer that things are less than or equal to themselves.
UBQualifier ltelA = UBQualifier.createUBQualifier(a, "-1");
leftWithOffset = leftWithOffset.glb(ltelA);
}
}
}
}
}
}
return createTransferResult(n, in, leftWithOffset);
}
use of org.checkerframework.checker.index.Subsequence in project checker-framework by typetools.
the class UpperBoundVisitor method processSubsequenceForLHS.
/* Returns the new value of the left hand side after processing the arrays named in the lhs.
* Iff varLtlQual includes LTL(lhsSeq),
* lhsSeq has HSS, and expQual includes LTL(a, -from), then the LTL(lhsSeq) will be removed from varLtlQual
*/
private UBQualifier processSubsequenceForLHS(LessThanLengthOf varLtlQual, UBQualifier expQual) {
UBQualifier newLHS = varLtlQual;
for (String lhsSeq : varLtlQual.getSequences()) {
// check is lhsSeq is an actual LTL
if (varLtlQual.hasSequenceWithOffset(lhsSeq, 0)) {
JavaExpression lhsSeqExpr = parseJavaExpressionString(lhsSeq, atypeFactory, getCurrentPath());
Subsequence subSeq = Subsequence.getSubsequenceFromReceiver(lhsSeqExpr, atypeFactory);
if (subSeq != null) {
String from = subSeq.from;
String a = subSeq.array;
if (expQual.hasSequenceWithOffset(a, Subsequence.negateString(from))) {
// This cast is safe because LTLs cannot contain duplicates.
// Note that this updates newLHS on each iteration from its old value,
// so even if there are multiple HSS arrays the result will be correct.
newLHS = ((LessThanLengthOf) newLHS).removeOffset(lhsSeq, 0);
}
}
}
}
return newLHS;
}
use of org.checkerframework.checker.index.Subsequence in project checker-framework by typetools.
the class UpperBoundVisitor method commonAssignmentCheck.
@Override
protected void commonAssignmentCheck(Tree varTree, ExpressionTree valueTree, @CompilerMessageKey String errorKey, Object... extraArgs) {
// check that when an assignment to a variable b declared as @HasSubsequence(a, from, to)
// occurs, to <= a.length, i.e. to is @LTEqLengthOf(a).
Subsequence subSeq = Subsequence.getSubsequenceFromTree(varTree, atypeFactory);
if (subSeq != null) {
AnnotationMirror anm;
try {
anm = atypeFactory.getAnnotationMirrorFromJavaExpressionString(subSeq.to, varTree, getCurrentPath());
} catch (JavaExpressionParseException e) {
anm = null;
}
boolean ltelCheckFailed = true;
if (anm != null) {
UBQualifier qual = UBQualifier.createUBQualifier(anm, (UpperBoundChecker) checker);
ltelCheckFailed = !qual.isLessThanOrEqualTo(subSeq.array);
}
if (ltelCheckFailed) {
// issue an error
checker.reportError(valueTree, TO_NOT_LTEL, subSeq.to, subSeq.array, anm == null ? "@UpperBoundUnknown" : anm, subSeq.array, subSeq.array, subSeq.array);
} else {
checker.reportWarning(valueTree, HSS, subSeq.array, subSeq.from, subSeq.from, subSeq.to, subSeq.to, subSeq.array, subSeq.array);
}
}
super.commonAssignmentCheck(varTree, valueTree, errorKey, extraArgs);
}
use of org.checkerframework.checker.index.Subsequence in project checker-framework by typetools.
the class LowerBoundVisitor method commonAssignmentCheck.
@Override
protected void commonAssignmentCheck(Tree varTree, ExpressionTree valueTree, @CompilerMessageKey String errorKey, Object... extraArgs) {
// check that when an assignment to a variable declared as @HasSubsequence(a, from, to)
// occurs, from is non-negative.
Subsequence subSeq = Subsequence.getSubsequenceFromTree(varTree, atypeFactory);
if (subSeq != null) {
AnnotationMirror anm;
try {
anm = atypeFactory.getAnnotationMirrorFromJavaExpressionString(subSeq.from, varTree, getCurrentPath());
} catch (JavaExpressionParseUtil.JavaExpressionParseException e) {
anm = null;
}
if (anm == null || !(atypeFactory.areSameByClass(anm, NonNegative.class) || atypeFactory.areSameByClass(anm, Positive.class))) {
checker.reportError(valueTree, FROM_NOT_NN, subSeq.from, anm == null ? "@LowerBoundUnknown" : anm);
}
}
super.commonAssignmentCheck(varTree, valueTree, errorKey, extraArgs);
}
use of org.checkerframework.checker.index.Subsequence in project checker-framework by typetools.
the class LessThanVisitor method commonAssignmentCheck.
@Override
protected void commonAssignmentCheck(Tree varTree, ExpressionTree valueTree, @CompilerMessageKey String errorKey, Object... extraArgs) {
// check that when an assignment to a variable declared as @HasSubsequence(a, from, to)
// occurs, from <= to.
Subsequence subSeq = Subsequence.getSubsequenceFromTree(varTree, atypeFactory);
if (subSeq != null) {
AnnotationMirror anm;
try {
anm = atypeFactory.getAnnotationMirrorFromJavaExpressionString(subSeq.from, varTree, getCurrentPath());
} catch (JavaExpressionParseUtil.JavaExpressionParseException e) {
anm = null;
}
LessThanAnnotatedTypeFactory factory = getTypeFactory();
if (anm == null || !factory.isLessThanOrEqual(anm, subSeq.to)) {
// issue an error
checker.reportError(valueTree, FROM_GT_TO, subSeq.from, subSeq.to, anm == null ? "@LessThanUnknown" : anm, subSeq.to, subSeq.to);
}
}
super.commonAssignmentCheck(varTree, valueTree, errorKey, extraArgs);
}
Aggregations