use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class RegexTransfer method visitMethodInvocation.
// TODO: These are special cases for isRegex(String, int) and asRegex(String, int). They should
// be replaced by adding an @EnsuresQualifierIf annotation that supports specifying attributes.
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
TransferResult<CFValue, CFStore> result = super.visitMethodInvocation(n, in);
// refine result for some helper methods
MethodAccessNode target = n.getTarget();
ExecutableElement method = target.getMethod();
Node receiver = target.getReceiver();
if (receiver instanceof ClassNameNode) {
ClassNameNode cnn = (ClassNameNode) receiver;
String receiverName = cnn.getElement().toString();
if (isRegexUtil(receiverName)) {
result = handleRegexUtil(n, method, result);
}
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class MustCallInferenceLogic method checkForMustCallInvocationOnField.
/**
* If the receiver of {@code mNode} is a candidate owning field and the method invocation
* satisfies the field's must-call obligation, then adds that field to the {@link #owningFields}
* set.
*
* @param mNode the MethodInvocationNode
*/
private void checkForMustCallInvocationOnField(MethodInvocationNode mNode) {
Node receiver = mNode.getTarget().getReceiver();
if (receiver.getTree() == null) {
return;
}
Element receiverEl = TreeUtils.elementFromTree(receiver.getTree());
if (receiverEl != null && typeFactory.isCandidateOwningField(receiverEl)) {
Element method = TreeUtils.elementFromTree(mNode.getTree());
List<String> mustCallValues = typeFactory.getMustCallValue(receiverEl);
// TODO: generalize this to MustCall annotations with more than one element.
if (mustCallValues.size() == 1 && mustCallValues.contains(method.getSimpleName().toString())) {
owningFields.add(receiverEl);
}
}
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class KeyForTransfer method visitMethodInvocation.
/*
* Provided that m is of a type that implements interface java.util.Map:
* <ul>
* <li>Given a call m.containsKey(k), ensures that k is @KeyFor("m") in the thenStore of the transfer result.
* <li>Given a call m.put(k, ...), ensures that k is @KeyFor("m") in the thenStore and elseStore of the transfer result.
* </ul>
*/
@Override
public TransferResult<KeyForValue, KeyForStore> visitMethodInvocation(MethodInvocationNode node, TransferInput<KeyForValue, KeyForStore> in) {
TransferResult<KeyForValue, KeyForStore> result = super.visitMethodInvocation(node, in);
KeyForAnnotatedTypeFactory factory = (KeyForAnnotatedTypeFactory) analysis.getTypeFactory();
if (factory.isMapContainsKey(node) || factory.isMapPut(node)) {
Node receiver = node.getTarget().getReceiver();
JavaExpression receiverJe = JavaExpression.fromNode(receiver);
String mapName = receiverJe.toString();
JavaExpression keyExpr = JavaExpression.fromNode(node.getArgument(0));
LinkedHashSet<String> keyForMaps = new LinkedHashSet<>();
keyForMaps.add(mapName);
final KeyForValue previousKeyValue = in.getValueOfSubNode(node.getArgument(0));
if (previousKeyValue != null) {
for (AnnotationMirror prevAm : previousKeyValue.getAnnotations()) {
if (prevAm != null && factory.areSameByClass(prevAm, KeyFor.class)) {
keyForMaps.addAll(getKeys(prevAm));
}
}
}
AnnotationMirror am = factory.createKeyForAnnotationMirrorWithValue(keyForMaps);
if (factory.isMapContainsKey(node)) {
// method is Map.containsKey
result.getThenStore().insertValue(keyExpr, am);
} else {
// method is Map.put
result.getThenStore().insertValue(keyExpr, am);
result.getElseStore().insertValue(keyExpr, am);
}
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method box.
/**
* If the input node is an unboxed primitive type, insert a call to the appropriate valueOf
* method, otherwise leave it alone.
*
* @param node in input node
* @return a Node representing the boxed version of the input, which may simply be the input node
*/
protected Node box(Node node) {
// For boxing conversion, see JLS 5.1.7
if (TypesUtils.isPrimitive(node.getType())) {
PrimitiveType primitive = types.getPrimitiveType(node.getType().getKind());
TypeMirror boxedType = types.getDeclaredType(types.boxedClass(primitive));
TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();
IdentifierTree classTree = treeBuilder.buildClassUse(boxedElement);
handleArtificialTree(classTree);
// No need to handle possible errors from evaluating a class literal here
// since this is synthetic code that can't fail.
ClassNameNode className = new ClassNameNode(classTree);
className.setInSource(false);
insertNodeAfter(className, node);
MemberSelectTree valueOfSelect = treeBuilder.buildValueOfMethodAccess(classTree);
handleArtificialTree(valueOfSelect);
MethodAccessNode valueOfAccess = new MethodAccessNode(valueOfSelect, className);
valueOfAccess.setInSource(false);
insertNodeAfter(valueOfAccess, className);
MethodInvocationTree valueOfCall = treeBuilder.buildMethodInvocation(valueOfSelect, (ExpressionTree) node.getTree());
handleArtificialTree(valueOfCall);
Node boxed = new MethodInvocationNode(valueOfCall, valueOfAccess, Collections.singletonList(node), getCurrentPath());
boxed.setInSource(false);
// Add Throwable to account for unchecked exceptions
addToConvertedLookupMap(node.getTree(), boxed);
insertNodeWithExceptionsAfter(boxed, uncheckedExceptionTypes, valueOfAccess);
return boxed;
} else {
return node;
}
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitEnhancedForLoop.
@Override
public Node visitEnhancedForLoop(EnhancedForLoopTree tree, Void p) {
// see JLS 14.14.2
Name parentLabel = getLabel(getCurrentPath());
Label conditionStart = new Label();
Label loopEntry = new Label();
Label loopExit = new Label();
// If the loop is a labeled statement, then its continue target is identical for continues with
// no label and continues with the loop's label.
Label updateStart;
if (parentLabel != null) {
updateStart = continueLabels.get(parentLabel);
} else {
updateStart = new Label();
}
TryFinallyScopeCell oldBreakTargetL = breakTargetL;
breakTargetL = new TryFinallyScopeCell(loopExit);
TryFinallyScopeCell oldContinueTargetL = continueTargetL;
continueTargetL = new TryFinallyScopeCell(updateStart);
// Distinguish loops over Iterables from loops over arrays.
VariableTree variable = tree.getVariable();
VariableElement variableElement = TreeUtils.elementFromDeclaration(variable);
ExpressionTree expression = tree.getExpression();
StatementTree statement = tree.getStatement();
TypeMirror exprType = TreeUtils.typeOf(expression);
if (types.isSubtype(exprType, iterableType)) {
// Take the upper bound of a type variable or wildcard
exprType = TypesUtils.upperBound(exprType);
assert (exprType instanceof DeclaredType) : "an Iterable must be a DeclaredType";
DeclaredType declaredExprType = (DeclaredType) exprType;
declaredExprType.getTypeArguments();
MemberSelectTree iteratorSelect = treeBuilder.buildIteratorMethodAccess(expression);
handleArtificialTree(iteratorSelect);
MethodInvocationTree iteratorCall = treeBuilder.buildMethodInvocation(iteratorSelect);
handleArtificialTree(iteratorCall);
VariableTree iteratorVariable = createEnhancedForLoopIteratorVariable(iteratorCall, variableElement);
handleArtificialTree(iteratorVariable);
VariableDeclarationNode iteratorVariableDecl = new VariableDeclarationNode(iteratorVariable);
iteratorVariableDecl.setInSource(false);
extendWithNode(iteratorVariableDecl);
Node expressionNode = scan(expression, p);
MethodAccessNode iteratorAccessNode = new MethodAccessNode(iteratorSelect, expressionNode);
iteratorAccessNode.setInSource(false);
extendWithNode(iteratorAccessNode);
MethodInvocationNode iteratorCallNode = new MethodInvocationNode(iteratorCall, iteratorAccessNode, Collections.emptyList(), getCurrentPath());
iteratorCallNode.setInSource(false);
extendWithNode(iteratorCallNode);
translateAssignment(iteratorVariable, new LocalVariableNode(iteratorVariable), iteratorCallNode);
// Test the loop ending condition
addLabelForNextNode(conditionStart);
IdentifierTree iteratorUse1 = treeBuilder.buildVariableUse(iteratorVariable);
handleArtificialTree(iteratorUse1);
LocalVariableNode iteratorReceiverNode = new LocalVariableNode(iteratorUse1);
iteratorReceiverNode.setInSource(false);
extendWithNode(iteratorReceiverNode);
MemberSelectTree hasNextSelect = treeBuilder.buildHasNextMethodAccess(iteratorUse1);
handleArtificialTree(hasNextSelect);
MethodAccessNode hasNextAccessNode = new MethodAccessNode(hasNextSelect, iteratorReceiverNode);
hasNextAccessNode.setInSource(false);
extendWithNode(hasNextAccessNode);
MethodInvocationTree hasNextCall = treeBuilder.buildMethodInvocation(hasNextSelect);
handleArtificialTree(hasNextCall);
MethodInvocationNode hasNextCallNode = new MethodInvocationNode(hasNextCall, hasNextAccessNode, Collections.emptyList(), getCurrentPath());
hasNextCallNode.setInSource(false);
extendWithNode(hasNextCallNode);
extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit));
// Loop body, starting with declaration of the loop iteration variable
addLabelForNextNode(loopEntry);
extendWithNode(new VariableDeclarationNode(variable));
IdentifierTree iteratorUse2 = treeBuilder.buildVariableUse(iteratorVariable);
handleArtificialTree(iteratorUse2);
LocalVariableNode iteratorReceiverNode2 = new LocalVariableNode(iteratorUse2);
iteratorReceiverNode2.setInSource(false);
extendWithNode(iteratorReceiverNode2);
MemberSelectTree nextSelect = treeBuilder.buildNextMethodAccess(iteratorUse2);
handleArtificialTree(nextSelect);
MethodAccessNode nextAccessNode = new MethodAccessNode(nextSelect, iteratorReceiverNode2);
nextAccessNode.setInSource(false);
extendWithNode(nextAccessNode);
MethodInvocationTree nextCall = treeBuilder.buildMethodInvocation(nextSelect);
handleArtificialTree(nextCall);
MethodInvocationNode nextCallNode = new MethodInvocationNode(nextCall, nextAccessNode, Collections.emptyList(), getCurrentPath());
// If the type of iteratorVariable is a capture, its type tree may be missing annotations, so
// save the expression in the node so that the full type can be found later.
nextCallNode.setIterableExpression(expression);
nextCallNode.setInSource(false);
extendWithNode(nextCallNode);
AssignmentNode assignNode = translateAssignment(variable, new LocalVariableNode(variable), nextCall);
// translateAssignment() scans variable and creates new nodes, so set the expression
// there, too.
((MethodInvocationNode) assignNode.getExpression()).setIterableExpression(expression);
assert statement != null;
scan(statement, p);
// Loop back edge
addLabelForNextNode(updateStart);
extendWithExtendedNode(new UnconditionalJump(conditionStart));
} else {
// TODO: Shift any labels after the initialization of the
// temporary array variable.
VariableTree arrayVariable = createEnhancedForLoopArrayVariable(expression, variableElement);
handleArtificialTree(arrayVariable);
VariableDeclarationNode arrayVariableNode = new VariableDeclarationNode(arrayVariable);
arrayVariableNode.setInSource(false);
extendWithNode(arrayVariableNode);
Node expressionNode = scan(expression, p);
translateAssignment(arrayVariable, new LocalVariableNode(arrayVariable), expressionNode);
// Declare and initialize the loop index variable
TypeMirror intType = types.getPrimitiveType(TypeKind.INT);
LiteralTree zero = treeBuilder.buildLiteral(Integer.valueOf(0));
handleArtificialTree(zero);
VariableTree indexVariable = treeBuilder.buildVariableDecl(intType, uniqueName("index"), variableElement.getEnclosingElement(), zero);
handleArtificialTree(indexVariable);
VariableDeclarationNode indexVariableNode = new VariableDeclarationNode(indexVariable);
indexVariableNode.setInSource(false);
extendWithNode(indexVariableNode);
IntegerLiteralNode zeroNode = new IntegerLiteralNode(zero);
extendWithNode(zeroNode);
translateAssignment(indexVariable, new LocalVariableNode(indexVariable), zeroNode);
// Compare index to array length
addLabelForNextNode(conditionStart);
IdentifierTree indexUse1 = treeBuilder.buildVariableUse(indexVariable);
handleArtificialTree(indexUse1);
LocalVariableNode indexNode1 = new LocalVariableNode(indexUse1);
indexNode1.setInSource(false);
extendWithNode(indexNode1);
IdentifierTree arrayUse1 = treeBuilder.buildVariableUse(arrayVariable);
handleArtificialTree(arrayUse1);
LocalVariableNode arrayNode1 = new LocalVariableNode(arrayUse1);
extendWithNode(arrayNode1);
MemberSelectTree lengthSelect = treeBuilder.buildArrayLengthAccess(arrayUse1);
handleArtificialTree(lengthSelect);
FieldAccessNode lengthAccessNode = new FieldAccessNode(lengthSelect, arrayNode1);
lengthAccessNode.setInSource(false);
extendWithNode(lengthAccessNode);
BinaryTree lessThan = treeBuilder.buildLessThan(indexUse1, lengthSelect);
handleArtificialTree(lessThan);
LessThanNode lessThanNode = new LessThanNode(lessThan, indexNode1, lengthAccessNode);
lessThanNode.setInSource(false);
extendWithNode(lessThanNode);
extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit));
// Loop body, starting with declaration of the loop iteration variable
addLabelForNextNode(loopEntry);
extendWithNode(new VariableDeclarationNode(variable));
IdentifierTree arrayUse2 = treeBuilder.buildVariableUse(arrayVariable);
handleArtificialTree(arrayUse2);
LocalVariableNode arrayNode2 = new LocalVariableNode(arrayUse2);
arrayNode2.setInSource(false);
extendWithNode(arrayNode2);
IdentifierTree indexUse2 = treeBuilder.buildVariableUse(indexVariable);
handleArtificialTree(indexUse2);
LocalVariableNode indexNode2 = new LocalVariableNode(indexUse2);
indexNode2.setInSource(false);
extendWithNode(indexNode2);
ArrayAccessTree arrayAccess = treeBuilder.buildArrayAccess(arrayUse2, indexUse2);
handleArtificialTree(arrayAccess);
ArrayAccessNode arrayAccessNode = new ArrayAccessNode(arrayAccess, arrayNode2, indexNode2);
arrayAccessNode.setArrayExpression(expression);
arrayAccessNode.setInSource(false);
extendWithNode(arrayAccessNode);
AssignmentNode arrayAccessAssignNode = translateAssignment(variable, new LocalVariableNode(variable), arrayAccessNode);
extendWithNodeWithException(arrayAccessNode, nullPointerExceptionType);
// translateAssignment() scans variable and creates new nodes, so set the expression
// there, too.
Node arrayAccessAssignNodeExpr = arrayAccessAssignNode.getExpression();
if (arrayAccessAssignNodeExpr instanceof ArrayAccessNode) {
((ArrayAccessNode) arrayAccessAssignNodeExpr).setArrayExpression(expression);
} else if (arrayAccessAssignNodeExpr instanceof MethodInvocationNode) {
// If the array component type is a primitive, there may be a boxing or unboxing
// conversion. Treat that as an iterator.
MethodInvocationNode boxingNode = (MethodInvocationNode) arrayAccessAssignNodeExpr;
boxingNode.setIterableExpression(expression);
}
assert statement != null;
scan(statement, p);
// Loop back edge
addLabelForNextNode(updateStart);
IdentifierTree indexUse3 = treeBuilder.buildVariableUse(indexVariable);
handleArtificialTree(indexUse3);
LocalVariableNode indexNode3 = new LocalVariableNode(indexUse3);
indexNode3.setInSource(false);
extendWithNode(indexNode3);
LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1));
handleArtificialTree(oneTree);
Node one = new IntegerLiteralNode(oneTree);
one.setInSource(false);
extendWithNode(one);
BinaryTree addOneTree = treeBuilder.buildBinary(intType, Tree.Kind.PLUS, indexUse3, oneTree);
handleArtificialTree(addOneTree);
Node addOneNode = new NumericalAdditionNode(addOneTree, indexNode3, one);
addOneNode.setInSource(false);
extendWithNode(addOneNode);
AssignmentTree assignTree = treeBuilder.buildAssignment(indexUse3, addOneTree);
handleArtificialTree(assignTree);
Node assignNode = new AssignmentNode(assignTree, indexNode3, addOneNode);
assignNode.setInSource(false);
extendWithNode(assignNode);
extendWithExtendedNode(new UnconditionalJump(conditionStart));
}
// Loop exit
addLabelForNextNode(loopExit);
breakTargetL = oldBreakTargetL;
continueTargetL = oldContinueTargetL;
return null;
}
Aggregations