use of org.checkerframework.dataflow.cfg.node.NullLiteralNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitLiteral.
@Override
public Node visitLiteral(LiteralTree tree, Void p) {
Node r = null;
switch(tree.getKind()) {
case BOOLEAN_LITERAL:
r = new BooleanLiteralNode(tree);
break;
case CHAR_LITERAL:
r = new CharacterLiteralNode(tree);
break;
case DOUBLE_LITERAL:
r = new DoubleLiteralNode(tree);
break;
case FLOAT_LITERAL:
r = new FloatLiteralNode(tree);
break;
case INT_LITERAL:
r = new IntegerLiteralNode(tree);
break;
case LONG_LITERAL:
r = new LongLiteralNode(tree);
break;
case NULL_LITERAL:
r = new NullLiteralNode(tree);
break;
case STRING_LITERAL:
r = new StringLiteralNode(tree);
break;
default:
throw new BugInCF("unexpected literal tree");
}
assert r != null : "unexpected literal tree";
extendWithNode(r);
return r;
}
use of org.checkerframework.dataflow.cfg.node.NullLiteralNode in project checker-framework by typetools.
the class MustCallConsistencyAnalyzer method checkReassignmentToField.
/**
* Issues an error if the given re-assignment to a non-final, owning field is not valid. A
* re-assignment is valid if the called methods type of the lhs before the assignment satisfies
* the must-call obligations of the field.
*
* @param obligations current tracked Obligations
* @param node an assignment to a non-final, owning field
*/
private void checkReassignmentToField(Set<Obligation> obligations, AssignmentNode node) {
Node lhsNode = node.getTarget();
if (!(lhsNode instanceof FieldAccessNode)) {
throw new TypeSystemError("checkReassignmentToField: non-field node " + node + " of class " + node.getClass());
}
FieldAccessNode lhs = (FieldAccessNode) lhsNode;
Node receiver = lhs.getReceiver();
// TODO: it would be better to defer getting the path until after checking
// for a CreatesMustCallFor annotation, because getting the path can be expensive.
// It might be possible to exploit the CFG structure to find the containing
// method (rather than using the path, as below), because if a method is being
// analyzed then it should be the root of the CFG (I think).
TreePath currentPath = typeFactory.getPath(node.getTree());
MethodTree enclosingMethodTree = TreePathUtil.enclosingMethod(currentPath);
if (enclosingMethodTree == null) {
// also a declaration must be a field initializer.
if (node.getTree().getKind() == Tree.Kind.VARIABLE) {
return;
} else {
// Issue an error if the field has a non-empty must-call type.
MustCallAnnotatedTypeFactory mcTypeFactory = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
AnnotationMirror mcAnno = mcTypeFactory.getAnnotatedType(lhs.getElement()).getAnnotation(MustCall.class);
List<String> mcValues = AnnotationUtils.getElementValueArray(mcAnno, mcTypeFactory.getMustCallValueElement(), String.class);
if (mcValues.isEmpty()) {
return;
}
Element lhsElement = TreeUtils.elementFromTree(lhs.getTree());
checker.reportError(node.getTree(), "required.method.not.called", formatMissingMustCallMethods(mcValues), "field " + lhsElement.getSimpleName().toString(), lhsElement.asType().toString(), "Field assignment outside method or declaration might overwrite field's current value");
return;
}
}
// on the method declaration), or 2) the rhs is a null literal (so there's nothing to reset).
if (!(receiver instanceof LocalVariableNode && varTrackedInObligations(obligations, (LocalVariableNode) receiver)) && !(node.getExpression() instanceof NullLiteralNode)) {
checkEnclosingMethodIsCreatesMustCallFor(node, enclosingMethodTree);
}
MustCallAnnotatedTypeFactory mcTypeFactory = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
// Get the Must Call type for the field. If there's info about this field in the store, use
// that. Otherwise, use the declared type of the field
CFStore mcStore = mcTypeFactory.getStoreBefore(lhs);
CFValue mcValue = mcStore.getValue(lhs);
AnnotationMirror mcAnno;
if (mcValue == null) {
// No store value, so use the declared type.
mcAnno = mcTypeFactory.getAnnotatedType(lhs.getElement()).getAnnotation(MustCall.class);
} else {
mcAnno = AnnotationUtils.getAnnotationByClass(mcValue.getAnnotations(), MustCall.class);
}
List<String> mcValues = AnnotationUtils.getElementValueArray(mcAnno, mcTypeFactory.getMustCallValueElement(), String.class);
if (mcValues.isEmpty()) {
return;
}
// Get the store before the RHS rather than the assignment node, because the CFG always has
// the RHS first. If the RHS has side-effects, then the assignment node's store will have
// had its inferred types erased.
Node rhs = node.getExpression();
CFStore cmStoreBefore = typeFactory.getStoreBefore(rhs);
CFValue cmValue = cmStoreBefore == null ? null : cmStoreBefore.getValue(lhs);
AnnotationMirror cmAnno = null;
if (cmValue != null) {
for (AnnotationMirror anno : cmValue.getAnnotations()) {
if (AnnotationUtils.areSameByName(anno, "org.checkerframework.checker.calledmethods.qual.CalledMethods")) {
cmAnno = anno;
break;
}
}
}
if (cmAnno == null) {
cmAnno = typeFactory.top;
}
if (!calledMethodsSatisfyMustCall(mcValues, cmAnno)) {
Element lhsElement = TreeUtils.elementFromTree(lhs.getTree());
if (!checker.shouldSkipUses(lhsElement)) {
checker.reportError(node.getTree(), "required.method.not.called", formatMissingMustCallMethods(mcValues), "field " + lhsElement.getSimpleName().toString(), lhsElement.asType().toString(), " Non-final owning field might be overwritten");
}
}
}
use of org.checkerframework.dataflow.cfg.node.NullLiteralNode in project checker-framework by typetools.
the class NullnessTransfer method strengthenAnnotationOfEqualTo.
/**
* {@inheritDoc}
*
* <p>Furthermore, this method refines the type to {@code NonNull} for the appropriate branch if
* an expression is compared to the {@code null} literal (listed as case 1 in the class
* description).
*/
@Override
protected TransferResult<NullnessValue, NullnessStore> strengthenAnnotationOfEqualTo(TransferResult<NullnessValue, NullnessStore> res, Node firstNode, Node secondNode, NullnessValue firstValue, NullnessValue secondValue, boolean notEqualTo) {
res = super.strengthenAnnotationOfEqualTo(res, firstNode, secondNode, firstValue, secondValue, notEqualTo);
if (firstNode instanceof NullLiteralNode) {
NullnessStore thenStore = res.getThenStore();
NullnessStore elseStore = res.getElseStore();
List<Node> secondParts = splitAssignments(secondNode);
for (Node secondPart : secondParts) {
JavaExpression secondInternal = JavaExpression.fromNode(secondPart);
if (CFAbstractStore.canInsertJavaExpression(secondInternal)) {
thenStore = thenStore == null ? res.getThenStore() : thenStore;
elseStore = elseStore == null ? res.getElseStore() : elseStore;
if (notEqualTo) {
thenStore.insertValue(secondInternal, NONNULL);
} else {
elseStore.insertValue(secondInternal, NONNULL);
}
}
}
Set<AnnotationMirror> secondAnnos = secondValue != null ? secondValue.getAnnotations() : AnnotationUtils.createAnnotationSet();
if (nullnessTypeFactory.containsSameByClass(secondAnnos, PolyNull.class)) {
thenStore = thenStore == null ? res.getThenStore() : thenStore;
elseStore = elseStore == null ? res.getElseStore() : elseStore;
// TODO: methodTree is null for lambdas. Handle that case. See Issue3850.java.
MethodTree methodTree = analysis.getContainingMethod(secondNode.getTree());
ExecutableElement methodElem = methodTree == null ? null : TreeUtils.elementFromDeclaration(methodTree);
if (notEqualTo) {
elseStore.setPolyNullNull(true);
if (methodElem != null && polyNullIsNonNull(methodElem, thenStore)) {
thenStore.setPolyNullNonNull(true);
}
} else {
thenStore.setPolyNullNull(true);
if (methodElem != null && polyNullIsNonNull(methodElem, elseStore)) {
elseStore.setPolyNullNonNull(true);
}
}
}
if (thenStore != null) {
return new ConditionalTransferResult<>(res.getResultValue(), thenStore, elseStore);
}
}
return res;
}
Aggregations