use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project bazel by bazelbuild.
the class FlowExpressions method internalReprOf.
/**
* We ignore operations such as widening and
* narrowing when computing the internal representation.
*
* @return The internal representation (as {@link Receiver}) of any
* {@link Node}. Might contain {@link Unknown}.
*/
public static Receiver internalReprOf(AnnotationProvider provider, Node receiverNode, boolean allowNonDeterminitic) {
Receiver receiver = null;
if (receiverNode instanceof FieldAccessNode) {
FieldAccessNode fan = (FieldAccessNode) receiverNode;
if (fan.getFieldName().equals("this")) {
// For some reason, "className.this" is considered a field access.
// We right this wrong here.
receiver = new ThisReference(fan.getReceiver().getType());
} else {
receiver = internalReprOfFieldAccess(provider, fan);
}
} else if (receiverNode instanceof ExplicitThisLiteralNode) {
receiver = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof ThisLiteralNode) {
receiver = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof SuperNode) {
receiver = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof LocalVariableNode) {
LocalVariableNode lv = (LocalVariableNode) receiverNode;
receiver = new LocalVariable(lv);
} else if (receiverNode instanceof ArrayAccessNode) {
ArrayAccessNode a = (ArrayAccessNode) receiverNode;
receiver = internalReprOfArrayAccess(provider, a);
} else if (receiverNode instanceof StringConversionNode) {
// ignore string conversion
return internalReprOf(provider, ((StringConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof WideningConversionNode) {
// ignore widening
return internalReprOf(provider, ((WideningConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof NarrowingConversionNode) {
// ignore narrowing
return internalReprOf(provider, ((NarrowingConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof ClassNameNode) {
ClassNameNode cn = (ClassNameNode) receiverNode;
receiver = new ClassName(cn.getType());
} else if (receiverNode instanceof ValueLiteralNode) {
ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
receiver = new ValueLiteral(vn.getType(), vn);
} else if (receiverNode instanceof MethodInvocationNode) {
MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn.getTree());
// check if this represents a boxing operation of a constant, in which
// case we treat the method call as deterministic, because there is no way
// to behave differently in two executions where two constants are being used.
boolean considerDeterministic = false;
if (invokedMethod.toString().equals("valueOf(long)") && mn.getTarget().getReceiver().toString().equals("Long")) {
Node arg = mn.getArgument(0);
if (arg instanceof ValueLiteralNode) {
considerDeterministic = true;
}
}
if (PurityUtils.isDeterministic(provider, invokedMethod) || allowNonDeterminitic || considerDeterministic) {
List<Receiver> parameters = new ArrayList<>();
for (Node p : mn.getArguments()) {
parameters.add(internalReprOf(provider, p));
}
Receiver methodReceiver;
if (ElementUtils.isStatic(invokedMethod)) {
methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
} else {
methodReceiver = internalReprOf(provider, mn.getTarget().getReceiver());
}
receiver = new PureMethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
}
}
if (receiver == null) {
receiver = new Unknown(receiverNode.getType());
}
return receiver;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class ValueTransfer method addAnnotationToStore.
private void addAnnotationToStore(CFStore store, AnnotationMirror anno, Node node) {
for (Node internal : splitAssignments(node)) {
AnnotationMirror currentAnno = atypefactory.getAnnotatedType(internal.getTree()).getAnnotationInHierarchy(atypefactory.BOTTOMVAL);
Receiver rec = FlowExpressions.internalReprOf(analysis.getTypeFactory(), internal);
// Combine the new annotations based on the results of the comparison with the existing
// type.
store.insertValue(rec, atypefactory.getQualifierHierarchy().greatestLowerBound(anno, currentAnno));
if (node instanceof FieldAccessNode) {
refineArrayAtLengthAccess((FieldAccessNode) internal, store);
} else if (node instanceof MethodInvocationNode) {
refineStringAtLengthInvocation((MethodInvocationNode) internal, store);
}
}
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class AliasingTransfer method processPostconditions.
/**
* Handling pseudo-assignments. Called by {@code CFAbstractTransfer.visitMethodInvocation()}.
*
* <p>Case 2: Given a method call, traverses all formal parameters of the method declaration,
* and if it doesn't have the {@literal @}NonLeaked or {@literal @}LeakedToResult annotations,
* we remove the node of the respective argument in the method call from the store. If parameter
* has {@literal @}LeakedToResult, {@code visitMethodInvocation()} handles it.
*/
@Override
protected void processPostconditions(MethodInvocationNode n, CFStore store, ExecutableElement methodElement, Tree tree) {
super.processPostconditions(n, store, methodElement, tree);
if (TreeUtils.isEnumSuper(n.getTree())) {
// Skipping the init() method for enums.
return;
}
List<Node> args = n.getArguments();
List<? extends VariableElement> params = methodElement.getParameters();
assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement);
List<AnnotatedTypeMirror> paramTypes = annotatedType.getParameterTypes();
for (int i = 0; i < args.size(); i++) {
Node arg = args.get(i);
AnnotatedTypeMirror paramType = paramTypes.get(i);
if (!paramType.hasAnnotation(NonLeaked.class) && !paramType.hasAnnotation(LeakedToResult.class)) {
store.clearValue(FlowExpressions.internalReprOf(factory, arg));
}
}
// Now, doing the same as above for the receiver parameter
Node receiver = n.getTarget().getReceiver();
AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
if (receiverType != null && !receiverType.hasAnnotation(LeakedToResult.class) && !receiverType.hasAnnotation(NonLeaked.class)) {
store.clearValue(FlowExpressions.internalReprOf(factory, receiver));
}
}
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.isInvocationOfMapMethod(node, "containsKey") || factory.isInvocationOfMapMethod(node, "put")) {
Node receiver = node.getTarget().getReceiver();
Receiver internalReceiver = FlowExpressions.internalReprOf(factory, receiver);
String mapName = internalReceiver.toString();
Receiver keyReceiver = FlowExpressions.internalReprOf(factory, 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 && AnnotationUtils.areSameByClass(prevAm, KeyFor.class)) {
keyForMaps.addAll(getKeys(prevAm));
}
}
}
AnnotationMirror am = factory.createKeyForAnnotationMirrorWithValue(keyForMaps);
if (factory.getMethodName(node).equals("containsKey")) {
result.getThenStore().insertValue(keyReceiver, am);
} else {
// method name is "put"
result.getThenStore().insertValue(keyReceiver, am);
result.getElseStore().insertValue(keyReceiver, am);
}
}
return result;
}
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;
}
Aggregations