use of org.checkerframework.dataflow.cfg.node.ThisNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitAssignment.
@Override
public Node visitAssignment(AssignmentTree tree, Void p) {
// see JLS 15.26.1
AssignmentNode assignmentNode;
ExpressionTree variable = tree.getVariable();
TypeMirror varType = TreeUtils.typeOf(variable);
// case 1: lhs is field access
if (TreeUtils.isFieldAccess(variable)) {
// visit receiver
Node receiver = getReceiver(variable);
// visit expression
Node expression = scan(tree.getExpression(), p);
expression = assignConvert(expression, varType);
// visit field access (throws null-pointer exception)
FieldAccessNode target = new FieldAccessNode(variable, receiver);
target.setLValue();
Element element = TreeUtils.elementFromUse(variable);
if (ElementUtils.isStatic(element) || receiver instanceof ThisNode) {
// No NullPointerException can be thrown, use normal node
extendWithNode(target);
} else {
extendWithNodeWithException(target, nullPointerExceptionType);
}
// add assignment node
assignmentNode = new AssignmentNode(tree, target, expression);
extendWithNode(assignmentNode);
} else // case 2: lhs is not a field access
{
Node target = scan(variable, p);
target.setLValue();
assignmentNode = translateAssignment(tree, target, tree.getExpression());
}
return assignmentNode;
}
use of org.checkerframework.dataflow.cfg.node.ThisNode in project checker-framework by typetools.
the class InitializationTransfer method initializedFieldsAfterCall.
/**
* Returns the fields that can safely be considered initialized after the method call {@code
* node}.
*
* @param node a method call
* @return the fields that are initialized after the method call
*/
protected List<VariableElement> initializedFieldsAfterCall(MethodInvocationNode node) {
List<VariableElement> result = new ArrayList<>();
MethodInvocationTree tree = node.getTree();
ExecutableElement method = TreeUtils.elementFromUse(tree);
boolean isConstructor = method.getSimpleName().contentEquals("<init>");
Node receiver = node.getTarget().getReceiver();
String methodString = tree.getMethodSelect().toString();
// invariant fields are guaranteed to be initialized.
if (isConstructor && receiver instanceof ThisNode && methodString.equals("this")) {
ClassTree clazz = TreePathUtil.enclosingClass(analysis.getTypeFactory().getPath(tree));
TypeElement clazzElem = TreeUtils.elementFromDeclaration(clazz);
markInvariantFieldsAsInitialized(result, clazzElem);
}
// invariant fields of any super class are guaranteed to be initialized.
if (isConstructor && receiver instanceof ThisNode && methodString.equals("super")) {
ClassTree clazz = TreePathUtil.enclosingClass(analysis.getTypeFactory().getPath(tree));
TypeElement clazzElem = TreeUtils.elementFromDeclaration(clazz);
TypeMirror superClass = clazzElem.getSuperclass();
while (superClass != null && superClass.getKind() != TypeKind.NONE) {
clazzElem = (TypeElement) analysis.getTypes().asElement(superClass);
superClass = clazzElem.getSuperclass();
markInvariantFieldsAsInitialized(result, clazzElem);
}
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.ThisNode in project checker-framework by typetools.
the class InitializationTransfer method visitFieldAccess.
/**
* If an invariant field is initialized and has the invariant annotation, than it has at least the
* invariant annotation. Note that only fields of the 'this' receiver are tracked for
* initialization.
*/
@Override
public TransferResult<V, S> visitFieldAccess(FieldAccessNode n, TransferInput<V, S> p) {
TransferResult<V, S> result = super.visitFieldAccess(n, p);
assert !result.containsTwoStores();
S store = result.getRegularStore();
if (store.isFieldInitialized(n.getElement()) && n.getReceiver() instanceof ThisNode) {
AnnotatedTypeMirror fieldAnno = analysis.getTypeFactory().getAnnotatedType(n.getElement());
// such as @NonNull.
if (fieldAnno.hasAnnotation(atypeFactory.getFieldInvariantAnnotation())) {
AnnotationMirror inv = atypeFactory.getFieldInvariantAnnotation();
V oldResultValue = result.getResultValue();
V refinedResultValue = analysis.createSingleAnnotationValue(inv, oldResultValue.getUnderlyingType());
V newResultValue = refinedResultValue.mostSpecific(oldResultValue, null);
result.setResultValue(newResultValue);
}
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.ThisNode in project checker-framework by typetools.
the class JavaExpression method fromNode.
/**
* We ignore operations such as widening and narrowing when computing the internal representation.
*
* @param receiverNode a node to convert to a JavaExpression
* @return the internal representation of the given node. Might contain {@link Unknown}.
*/
public static JavaExpression fromNode(Node receiverNode) {
JavaExpression result = null;
if (receiverNode instanceof FieldAccessNode) {
result = fromNodeFieldAccess((FieldAccessNode) receiverNode);
} else if (receiverNode instanceof ExplicitThisNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof ThisNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof SuperNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof LocalVariableNode) {
LocalVariableNode lv = (LocalVariableNode) receiverNode;
result = new LocalVariable(lv);
} else if (receiverNode instanceof ArrayAccessNode) {
ArrayAccessNode a = (ArrayAccessNode) receiverNode;
result = fromArrayAccess(a);
} else if (receiverNode instanceof StringConversionNode) {
// ignore string conversion
return fromNode(((StringConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof WideningConversionNode) {
// ignore widening
return fromNode(((WideningConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof NarrowingConversionNode) {
// ignore narrowing
return fromNode(((NarrowingConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof UnaryOperationNode) {
UnaryOperationNode uopn = (UnaryOperationNode) receiverNode;
return new UnaryOperation(uopn, fromNode(uopn.getOperand()));
} else if (receiverNode instanceof BinaryOperationNode) {
BinaryOperationNode bopn = (BinaryOperationNode) receiverNode;
return new BinaryOperation(bopn, fromNode(bopn.getLeftOperand()), fromNode(bopn.getRightOperand()));
} else if (receiverNode instanceof ClassNameNode) {
ClassNameNode cn = (ClassNameNode) receiverNode;
result = new ClassName(cn.getType());
} else if (receiverNode instanceof ValueLiteralNode) {
ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
result = new ValueLiteral(vn.getType(), vn);
} else if (receiverNode instanceof ArrayCreationNode) {
ArrayCreationNode an = (ArrayCreationNode) receiverNode;
List<@Nullable JavaExpression> dimensions = CollectionsPlume.mapList(JavaExpression::fromNode, an.getDimensions());
List<JavaExpression> initializers = CollectionsPlume.mapList(JavaExpression::fromNode, an.getInitializers());
result = new ArrayCreation(an.getType(), dimensions, initializers);
} else if (receiverNode instanceof MethodInvocationNode) {
MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
MethodInvocationTree t = mn.getTree();
if (t == null) {
throw new BugInCF("Unexpected null tree for node: " + mn);
}
assert TreeUtils.isUseOfElement(t) : "@AssumeAssertion(nullness): tree kind";
ExecutableElement invokedMethod = TreeUtils.elementFromUse(t);
// Note that the method might be nondeterministic.
List<JavaExpression> parameters = CollectionsPlume.mapList(JavaExpression::fromNode, mn.getArguments());
JavaExpression methodReceiver;
if (ElementUtils.isStatic(invokedMethod)) {
methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
} else {
methodReceiver = fromNode(mn.getTarget().getReceiver());
}
result = new MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
}
if (result == null) {
result = new Unknown(receiverNode);
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.ThisNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitMethodInvocation.
@Override
public MethodInvocationNode visitMethodInvocation(MethodInvocationTree tree, Void p) {
// see JLS 15.12.4
// First, compute the receiver, if any (15.12.4.1).
// Second, evaluate the actual arguments, left to right and possibly some arguments are stored
// into an array for variable arguments calls (15.12.4.2).
// Third, test the receiver, if any, for nullness (15.12.4.4).
// Fourth, convert the arguments to the type of the formal parameters (15.12.4.5).
// Fifth, if the method is synchronized, lock the receiving object or class (15.12.4.5).
ExecutableElement method = TreeUtils.elementFromUse(tree);
if (method == null) {
// The method wasn't found, e.g. because of a compilation error.
return null;
}
ExpressionTree methodSelect = tree.getMethodSelect();
assert TreeUtils.isMethodAccess(methodSelect) : "Expected a method access, but got: " + methodSelect;
List<? extends ExpressionTree> actualExprs = tree.getArguments();
// Look up method to invoke and possibly throw NullPointerException
Node receiver = getReceiver(methodSelect);
MethodAccessNode target = new MethodAccessNode(methodSelect, receiver);
ExecutableElement element = TreeUtils.elementFromUse(tree);
if (ElementUtils.isStatic(element) || receiver instanceof ThisNode) {
// No NullPointerException can be thrown, use normal node
extendWithNode(target);
} else {
extendWithNodeWithException(target, nullPointerExceptionType);
}
List<Node> arguments;
if (TreeUtils.isEnumSuper(tree)) {
// Don't convert arguments for enum super calls. The AST contains no actual arguments, while
// the method element expects two arguments, leading to an exception in convertCallArguments.
// Since no actual arguments are present in the AST that is being checked, it shouldn't cause
// any harm to omit the conversions.
// See also BaseTypeVisitor.visitMethodInvocation and QualifierPolymorphism.annotate.
arguments = Collections.emptyList();
} else {
arguments = convertCallArguments(method, actualExprs);
}
// TODO: lock the receiver for synchronized methods
MethodInvocationNode node = new MethodInvocationNode(tree, target, arguments, getCurrentPath());
List<? extends TypeMirror> thrownTypes = element.getThrownTypes();
Set<TypeMirror> thrownSet = new LinkedHashSet<>(thrownTypes.size() + uncheckedExceptionTypes.size());
// Add exceptions explicitly mentioned in the throws clause.
thrownSet.addAll(thrownTypes);
// Add types to account for unchecked exceptions
thrownSet.addAll(uncheckedExceptionTypes);
ExtendedNode extendedNode = extendWithNodeWithExceptions(node, thrownSet);
/* Check for the TerminatesExecution annotation. */
Element methodElement = TreeUtils.elementFromTree(tree);
boolean terminatesExecution = annotationProvider.getDeclAnnotation(methodElement, TerminatesExecution.class) != null;
if (terminatesExecution) {
extendedNode.setTerminatesExecution(true);
}
return node;
}
Aggregations