Search in sources :

Example 16 with MethodInvocationNode

use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.

the class GenericAnnotatedTypeFactory method getAnnotatedTypeVarargsArray.

/**
 * Returns the type of a varargs array of a method invocation or a constructor invocation. Returns
 * null only if private field {@code useFlow} is false.
 *
 * @param tree a method invocation or a constructor invocation
 * @return AnnotatedTypeMirror of varargs array for a method or constructor invocation {@code
 *     tree}; returns null if private field {@code useFlow} is false
 */
@Nullable
public AnnotatedTypeMirror getAnnotatedTypeVarargsArray(Tree tree) {
    if (!useFlow) {
        return null;
    }
    // Get the synthetic NewArray tree that dataflow creates as the last argument of a call to a
    // vararg method. Do this by getting the MethodInvocationNode to which "tree" maps. The last
    // argument node of the MethodInvocationNode stores the synthetic NewArray tree.
    List<Node> args;
    switch(tree.getKind()) {
        case METHOD_INVOCATION:
            args = getFirstNodeOfKindForTree(tree, MethodInvocationNode.class).getArguments();
            break;
        case NEW_CLASS:
            args = getFirstNodeOfKindForTree(tree, ObjectCreationNode.class).getArguments();
            break;
        default:
            throw new BugInCF("Unexpected kind of tree: " + tree);
    }
    assert !args.isEmpty() : "Arguments are empty";
    Node varargsArray = args.get(args.size() - 1);
    AnnotatedTypeMirror varargtype = getAnnotatedType(varargsArray.getTree());
    return varargtype;
}
Also used : AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) BugInCF(org.checkerframework.javacutil.BugInCF) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 17 with MethodInvocationNode

use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.

the class CalledMethodsTransfer method handleEnsuresCalledMethodsVarArgs.

/**
 * Update the types of varargs parameters passed to a method with an {@link
 * EnsuresCalledMethodsVarArgs} annotation. This method is a no-op if no such annotation is
 * present.
 *
 * @param node the method invocation node
 * @param result the current result
 */
private void handleEnsuresCalledMethodsVarArgs(MethodInvocationNode node, TransferResult<CFValue, CFStore> result) {
    ExecutableElement elt = TreeUtils.elementFromUse(node.getTree());
    AnnotationMirror annot = atypeFactory.getDeclAnnotation(elt, EnsuresCalledMethodsVarArgs.class);
    if (annot == null) {
        return;
    }
    List<String> ensuredMethodNames = AnnotationUtils.getElementValueArray(annot, ((CalledMethodsAnnotatedTypeFactory) atypeFactory).ensuresCalledMethodsVarArgsValueElement, String.class);
    List<? extends VariableElement> parameters = elt.getParameters();
    int varArgsPos = parameters.size() - 1;
    Node varArgActual = node.getArguments().get(varArgsPos);
    // an ArrayCreationNode.  This is the only case we handle for now.
    if (varArgActual instanceof ArrayCreationNode) {
        ArrayCreationNode arrayCreationNode = (ArrayCreationNode) varArgActual;
        // add in the called method to all the vararg arguments
        CFStore thenStore = result.getThenStore();
        CFStore elseStore = result.getElseStore();
        for (Node arg : arrayCreationNode.getInitializers()) {
            AnnotatedTypeMirror currentType = atypeFactory.getAnnotatedType(arg.getTree());
            AnnotationMirror newType = getUpdatedCalledMethodsType(currentType, ensuredMethodNames);
            if (newType == null) {
                continue;
            }
            JavaExpression receiverReceiver = JavaExpression.fromNode(arg);
            thenStore.insertValue(receiverReceiver, newType);
            elseStore.insertValue(receiverReceiver, newType);
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) CFStore(org.checkerframework.framework.flow.CFStore) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode)

Example 18 with MethodInvocationNode

use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.

the class FormatterTreeUtil method asFormatCallCategoriesLowLevel.

private ConversionCategory[] asFormatCallCategoriesLowLevel(MethodInvocationNode node) {
    Node vararg = node.getArgument(1);
    if (!(vararg instanceof ArrayCreationNode)) {
        return null;
    }
    List<Node> convs = ((ArrayCreationNode) vararg).getInitializers();
    ConversionCategory[] res = new ConversionCategory[convs.size()];
    for (int i = 0; i < convs.size(); ++i) {
        Node conv = convs.get(i);
        if (conv instanceof FieldAccessNode) {
            Class<? extends Object> clazz = TypesUtils.getClassFromType(((FieldAccessNode) conv).getType());
            if (clazz == ConversionCategory.class) {
                res[i] = ConversionCategory.valueOf(((FieldAccessNode) conv).getFieldName());
                continue;
            /* avoid returning null */
            }
        }
        return null;
    }
    return res;
}
Also used : ConversionCategory(org.checkerframework.checker.formatter.qual.ConversionCategory) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode)

Example 19 with MethodInvocationNode

use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.

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 allowNonDeterministic) {
    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 if (fan.getFieldName().equals("class")) {
            // "className.class" is considered a field access. This makes sense,
            // since .class is similar to a field access which is the equivalent
            // of a call to getClass(). However for the purposes of dataflow
            // analysis, and value stores, this is the equivalent of a ClassNameNode.
            receiver = new ClassName(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 ArrayCreationNode) {
        ArrayCreationNode an = (ArrayCreationNode) receiverNode;
        List<Receiver> dimensions = new ArrayList<>();
        for (Node dimension : an.getDimensions()) {
            dimensions.add(internalReprOf(provider, dimension, allowNonDeterministic));
        }
        List<Receiver> initializers = new ArrayList<>();
        for (Node initializer : an.getInitializers()) {
            initializers.add(internalReprOf(provider, initializer, allowNonDeterministic));
        }
        receiver = new ArrayCreation(an.getType(), dimensions, initializers);
    } 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 (isLongValueOf(mn, invokedMethod)) {
            Node arg = mn.getArgument(0);
            if (arg instanceof ValueLiteralNode) {
                considerDeterministic = true;
            }
        }
        if (PurityUtils.isDeterministic(provider, invokedMethod) || allowNonDeterministic || 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 MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
        }
    }
    if (receiver == null) {
        receiver = new Unknown(receiverNode.getType());
    }
    return receiver;
}
Also used : ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) ArrayCreationNode(org.checkerframework.dataflow.cfg.node.ArrayCreationNode) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) ThisLiteralNode(org.checkerframework.dataflow.cfg.node.ThisLiteralNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) ArrayList(java.util.ArrayList) List(java.util.List) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) SuperNode(org.checkerframework.dataflow.cfg.node.SuperNode) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ExplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) ValueLiteralNode(org.checkerframework.dataflow.cfg.node.ValueLiteralNode)

Example 20 with MethodInvocationNode

use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.

the class WholeProgramInferenceScenes method updateInferredMethodParameterTypes.

/**
 * Updates the parameter types of the method methodElt in the Scene of the receiverTree's
 * enclosing class based on the arguments to the method.
 *
 * <p>For each method parameter in methodElt:
 *
 * <ul>
 *   <li>If the Scene does not contain an annotated type for that parameter, then the type of
 *       the respective value passed as argument in the method call methodInvNode will be added
 *       to the parameter in the Scene.
 *   <li>If the Scene previously contained an annotated type for that parameter, then its new
 *       type will be the LUB between the previous type and the type of the respective value
 *       passed as argument in the method call.
 * </ul>
 *
 * <p>
 *
 * @param methodInvNode the node representing a method invocation
 * @param receiverTree the Tree of the class that contains the method being invoked
 * @param methodElt the element of the method being invoked
 * @param atf the annotated type factory of a given type system, whose type hierarchy will be
 *     used to update the method parameters' types
 */
@Override
public void updateInferredMethodParameterTypes(MethodInvocationNode methodInvNode, Tree receiverTree, ExecutableElement methodElt, AnnotatedTypeFactory atf) {
    if (receiverTree == null) {
        // https://github.com/typetools/checker-framework/issues/682
        return;
    }
    ClassSymbol classSymbol = getEnclosingClassSymbol(receiverTree);
    if (classSymbol == null) {
        // https://github.com/typetools/checker-framework/issues/682
        return;
    }
    // https://github.com/typetools/checker-framework/issues/682
    if (!classSymbol.getEnclosedElements().contains((Symbol) methodElt)) {
        return;
    }
    String className = classSymbol.flatname.toString();
    String jaifPath = helper.getJaifPath(className);
    AClass clazz = helper.getAClass(className, jaifPath);
    String methodName = JVMNames.getJVMMethodName(methodElt);
    AMethod method = clazz.methods.vivify(methodName);
    List<Node> arguments = methodInvNode.getArguments();
    updateInferredExecutableParameterTypes(methodElt, atf, jaifPath, method, arguments);
}
Also used : ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) ImplicitThisLiteralNode(org.checkerframework.dataflow.cfg.node.ImplicitThisLiteralNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) Node(org.checkerframework.dataflow.cfg.node.Node) AClass(scenelib.annotations.el.AClass) AMethod(scenelib.annotations.el.AMethod)

Aggregations

MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)42 Node (org.checkerframework.dataflow.cfg.node.Node)38 FieldAccessNode (org.checkerframework.dataflow.cfg.node.FieldAccessNode)21 ObjectCreationNode (org.checkerframework.dataflow.cfg.node.ObjectCreationNode)16 ExecutableElement (javax.lang.model.element.ExecutableElement)15 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)15 MethodAccessNode (org.checkerframework.dataflow.cfg.node.MethodAccessNode)14 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)13 ClassNameNode (org.checkerframework.dataflow.cfg.node.ClassNameNode)12 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)12 ArrayCreationNode (org.checkerframework.dataflow.cfg.node.ArrayCreationNode)11 GreaterThanNode (org.checkerframework.dataflow.cfg.node.GreaterThanNode)11 GreaterThanOrEqualNode (org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode)11 LessThanNode (org.checkerframework.dataflow.cfg.node.LessThanNode)11 LessThanOrEqualNode (org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode)11 StringConversionNode (org.checkerframework.dataflow.cfg.node.StringConversionNode)11 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)10 ArrayAccessNode (org.checkerframework.dataflow.cfg.node.ArrayAccessNode)10 CFStore (org.checkerframework.framework.flow.CFStore)10 CFValue (org.checkerframework.framework.flow.CFValue)10