Search in sources :

Example 6 with ClassName

use of org.checkerframework.dataflow.analysis.FlowExpressions.ClassName in project checker-framework by typetools.

the class CFAbstractStore method insertValue.

/**
 * Add the abstract value {@code value} for the expression {@code r} (correctly deciding where
 * to store the information depending on the type of the expression {@code r}).
 *
 * <p>This method does not take care of removing other information that might be influenced by
 * changes to certain parts of the state.
 *
 * <p>If there is already a value {@code v} present for {@code r}, then the stronger of the new
 * and old value are taken (according to the lattice). Note that this happens per hierarchy, and
 * if the store already contains information about a hierarchy for which {@code value} does not
 * contain information, then that information is preserved.
 */
public void insertValue(FlowExpressions.Receiver r, @Nullable V value) {
    if (value == null) {
        // top and top is also the default value.
        return;
    }
    if (r.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (r instanceof FlowExpressions.LocalVariable) {
        FlowExpressions.LocalVariable localVar = (FlowExpressions.LocalVariable) r;
        V oldValue = localVariableValues.get(localVar);
        V newValue = value.mostSpecific(oldValue, null);
        if (newValue != null) {
            localVariableValues.put(localVar, newValue);
        }
    } else if (r instanceof FlowExpressions.FieldAccess) {
        FlowExpressions.FieldAccess fieldAcc = (FlowExpressions.FieldAccess) r;
        // Only store information about final fields (where the receiver is
        // also fixed) if concurrent semantics are enabled.
        boolean isMonotonic = isMonotonicUpdate(fieldAcc, value);
        if (sequentialSemantics || isMonotonic || fieldAcc.isUnmodifiableByOtherCode()) {
            V oldValue = fieldValues.get(fieldAcc);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                fieldValues.put(fieldAcc, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.MethodCall) {
        FlowExpressions.MethodCall method = (FlowExpressions.MethodCall) r;
        // Don't store any information if concurrent semantics are enabled.
        if (sequentialSemantics) {
            V oldValue = methodValues.get(method);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                methodValues.put(method, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.ArrayAccess) {
        FlowExpressions.ArrayAccess arrayAccess = (ArrayAccess) r;
        if (sequentialSemantics) {
            V oldValue = arrayValues.get(arrayAccess);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                arrayValues.put(arrayAccess, newValue);
            }
        }
    } else if (r instanceof FlowExpressions.ThisReference) {
        FlowExpressions.ThisReference thisRef = (FlowExpressions.ThisReference) r;
        if (sequentialSemantics || thisRef.isUnmodifiableByOtherCode()) {
            V oldValue = thisValue;
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                thisValue = newValue;
            }
        }
    } else if (r instanceof FlowExpressions.ClassName) {
        FlowExpressions.ClassName className = (FlowExpressions.ClassName) r;
        if (sequentialSemantics || className.isUnmodifiableByOtherCode()) {
            V oldValue = classValues.get(className);
            V newValue = value.mostSpecific(oldValue, null);
            if (newValue != null) {
                classValues.put(className, newValue);
            }
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) ArrayAccess(org.checkerframework.dataflow.analysis.FlowExpressions.ArrayAccess) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)

Example 7 with ClassName

use of org.checkerframework.dataflow.analysis.FlowExpressions.ClassName in project checker-framework by typetools.

the class FlowExpressionParseUtil method parseMemberSelect.

private static Receiver parseMemberSelect(String s, ProcessingEnvironment env, FlowExpressionContext context, TreePath path) throws FlowExpressionParseException {
    Pair<String, String> select = parseMemberSelect(s);
    assert select != null : "isMemberSelect must be called first";
    Receiver receiver;
    String memberSelected;
    Resolver resolver = new Resolver(env);
    // Attempt to match a package and class name first.
    Pair<ClassName, String> classAndRemainingString = matchPackageAndClassNameWithinExpression(s, resolver, path);
    if (classAndRemainingString != null) {
        receiver = classAndRemainingString.first;
        memberSelected = classAndRemainingString.second;
        if (memberSelected == null) {
            throw constructParserException(s, "a class cannot terminate a flow expression string");
        }
    } else {
        String receiverString = select.first;
        memberSelected = select.second;
        receiver = parseHelper(receiverString, context, path);
    }
    if (memberSelected.equals("class")) {
        if (receiver instanceof FlowExpressions.ClassName && !context.parsingMember) {
            return receiver;
        } else {
            throw constructParserException(s, "class is not a legal identifier");
        }
    }
    // Parse the rest, with a new receiver.
    FlowExpressionContext newContext = context.copyChangeToParsingMemberOfReceiver(receiver);
    return parseHelper(memberSelected, newContext, path);
}
Also used : ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) Resolver(org.checkerframework.javacutil.Resolver) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions)

Example 8 with ClassName

use of org.checkerframework.dataflow.analysis.FlowExpressions.ClassName in project checker-framework by typetools.

the class FlowExpressionParseUtil method matchPackageAndClassNameWithinExpression.

/**
 * Matches a substring of {@code expression} to a package and class name (starting from the
 * beginning of the string).
 *
 * @param expression the expression string that may start with a package and class name
 * @param resolver the {@code Resolver} for the current processing environment
 * @param path the tree path to the local scope
 * @return {@code null} if the expression string did not start with a package name; otherwise a
 *     {@code Pair} containing the {@code ClassName} for the matched class, and the remaining
 *     substring of the expression (possibly null) after the package and class name.
 * @throws FlowExpressionParseException if the entire expression string matches a package name
 *     (but no class name), or if a package name was matched but the class could not be found
 *     within the package (e.g., {@code "myExistingPackage.myNonExistentClass"}).
 */
private static Pair<ClassName, String> matchPackageAndClassNameWithinExpression(String expression, Resolver resolver, TreePath path) throws FlowExpressionParseException {
    Pair<PackageSymbol, String> packageSymbolAndRemainingString = matchPackageNameWithinExpression(expression, resolver, path);
    if (packageSymbolAndRemainingString == null) {
        return null;
    }
    PackageSymbol packageSymbol = packageSymbolAndRemainingString.first;
    String packageRemainingString = packageSymbolAndRemainingString.second;
    Pair<String, String> select = parseMemberSelect(packageRemainingString);
    String classNameString;
    String remainingString;
    if (select != null) {
        classNameString = select.first;
        remainingString = select.second;
    } else {
        classNameString = packageRemainingString;
        remainingString = null;
    }
    ClassSymbol classSymbol;
    try {
        classSymbol = resolver.findClassInPackage(classNameString, packageSymbol, path);
    } catch (Throwable t) {
        throw constructParserException(expression, " findClassInPackage threw an exception when looking up class " + classNameString + " in package " + packageSymbol.toString(), t);
    }
    if (classSymbol == null) {
        throw constructParserException(expression, "classSymbol==null when looking up class " + classNameString + " in package " + packageSymbol.toString());
    }
    TypeMirror classType = ElementUtils.getType(classSymbol);
    if (classType == null) {
        throw constructParserException(expression, "classType==null when looking for class symbol " + classSymbol);
    }
    return Pair.of(new ClassName(classType), remainingString);
}
Also used : PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) TypeMirror(javax.lang.model.type.TypeMirror) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)

Example 9 with ClassName

use of org.checkerframework.dataflow.analysis.FlowExpressions.ClassName in project checker-framework by typetools.

the class FlowExpressionParseUtil method parseIdentifier.

private static Receiver parseIdentifier(String s, ProcessingEnvironment env, TreePath path, FlowExpressionContext context) throws FlowExpressionParseException {
    Resolver resolver = new Resolver(env);
    if (!context.parsingMember && context.useLocalScope) {
        // Attempt to match a local variable within the scope of the
        // given path before attempting to match a field.
        VariableElement varElem = resolver.findLocalVariableOrParameterOrField(s, path);
        if (varElem != null) {
            if (varElem.getKind() == ElementKind.FIELD) {
                boolean isOriginalReceiver = context.receiver instanceof ThisReference;
                return getReceiverField(s, context, isOriginalReceiver, varElem);
            } else {
                return new LocalVariable(varElem);
            }
        }
    }
    // field access
    TypeMirror receiverType = context.receiver.getType();
    boolean originalReceiver = true;
    VariableElement fieldElem = null;
    if (receiverType.getKind() == TypeKind.ARRAY && s.equals("length")) {
        fieldElem = resolver.findField(s, receiverType, path);
    }
    // Search for field in each enclosing class.
    while (receiverType.getKind() == TypeKind.DECLARED) {
        fieldElem = resolver.findField(s, receiverType, path);
        if (fieldElem != null) {
            break;
        }
        receiverType = getTypeOfEnclosingClass((DeclaredType) receiverType);
        originalReceiver = false;
    }
    if (fieldElem != null && fieldElem.getKind() == ElementKind.FIELD) {
        return getReceiverField(s, context, originalReceiver, fieldElem);
    }
    // Class name
    Element classElem = resolver.findClass(s, path);
    TypeMirror classType = ElementUtils.getType(classElem);
    if (classType != null) {
        return new ClassName(classType);
    }
    throw constructParserException(s, "identifier not found");
}
Also used : Resolver(org.checkerframework.javacutil.Resolver) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) VariableElement(javax.lang.model.element.VariableElement) ThisReference(org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference) DeclaredType(javax.lang.model.type.DeclaredType)

Example 10 with ClassName

use of org.checkerframework.dataflow.analysis.FlowExpressions.ClassName in project checker-framework by typetools.

the class FlowExpressionParseUtil method parseMethod.

private static Receiver parseMethod(String s, FlowExpressionContext context, TreePath path, ProcessingEnvironment env) throws FlowExpressionParseException {
    Pair<Pair<String, String>, String> method = parseMethod(s);
    if (method == null) {
        return null;
    }
    String methodName = method.first.first;
    // parse parameter list
    String parameterList = method.first.second;
    List<Receiver> parameters = ParameterListParser.parseParameterList(parameterList, true, context.copyAndUseOuterReceiver(), path);
    // get types for parameters
    List<TypeMirror> parameterTypes = new ArrayList<>();
    for (Receiver p : parameters) {
        parameterTypes.add(p.getType());
    }
    ExecutableElement methodElement = null;
    try {
        Element element = null;
        // try to find the correct method
        Resolver resolver = new Resolver(env);
        TypeMirror receiverType = context.receiver.getType();
        if (receiverType.getKind() == TypeKind.ARRAY) {
            element = resolver.findMethod(methodName, receiverType, path, parameterTypes);
        }
        // Search for method in each enclosing class.
        while (receiverType.getKind() == TypeKind.DECLARED) {
            element = resolver.findMethod(methodName, receiverType, path, parameterTypes);
            if (element.getKind() == ElementKind.METHOD) {
                break;
            }
            receiverType = getTypeOfEnclosingClass((DeclaredType) receiverType);
        }
        if (element == null) {
            throw constructParserException(s, "element==null");
        }
        if (element.getKind() != ElementKind.METHOD) {
            throw constructParserException(s, "element.getKind()==" + element.getKind());
        }
        methodElement = (ExecutableElement) element;
        for (int i = 0; i < parameters.size(); i++) {
            VariableElement formal = methodElement.getParameters().get(i);
            TypeMirror formalType = formal.asType();
            Receiver actual = parameters.get(i);
            TypeMirror actualType = actual.getType();
            // boxing necessary
            if (TypesUtils.isBoxedPrimitive(formalType) && TypesUtils.isPrimitive(actualType)) {
                MethodSymbol valueOfMethod = TreeBuilder.getValueOfMethod(env, formalType);
                List<Receiver> p = new ArrayList<>();
                p.add(actual);
                Receiver boxedParam = new MethodCall(formalType, valueOfMethod, new ClassName(formalType), p);
                parameters.set(i, boxedParam);
            }
        }
    } catch (Throwable t) {
        throw constructParserException(s, t);
    }
    assert methodElement != null;
    /*if (!PurityUtils.isDeterministic(context.checkerContext.getAnnotationProvider(),
                methodElement)) {
            throw new FlowExpressionParseException(Result.failure(
                    "flowexpr.method.not.deterministic",
                    methodElement.getSimpleName()));
        }*/
    if (ElementUtils.isStatic(methodElement)) {
        Element classElem = methodElement.getEnclosingElement();
        Receiver staticClassReceiver = new ClassName(ElementUtils.getType(classElem));
        return new MethodCall(ElementUtils.getType(methodElement), methodElement, staticClassReceiver, parameters);
    } else {
        if (context.receiver instanceof ClassName) {
            throw constructParserException(s, "a non-static method call cannot have a class name as a receiver.");
        }
        TypeMirror methodType = TypesUtils.substituteMethodReturnType(methodElement, context.receiver.getType(), env);
        return new MethodCall(methodType, methodElement, context.receiver, parameters);
    }
}
Also used : Resolver(org.checkerframework.javacutil.Resolver) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) VariableElement(javax.lang.model.element.VariableElement) MethodCall(org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) Pair(org.checkerframework.javacutil.Pair) DeclaredType(javax.lang.model.type.DeclaredType)

Aggregations

ClassName (org.checkerframework.dataflow.analysis.FlowExpressions.ClassName)11 FieldAccess (org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess)6 Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)6 VariableElement (javax.lang.model.element.VariableElement)5 TypeMirror (javax.lang.model.type.TypeMirror)5 ThisReference (org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference)5 Element (javax.lang.model.element.Element)4 LocalVariable (org.checkerframework.dataflow.analysis.FlowExpressions.LocalVariable)4 ExecutableElement (javax.lang.model.element.ExecutableElement)3 TypeElement (javax.lang.model.element.TypeElement)3 FlowExpressions (org.checkerframework.dataflow.analysis.FlowExpressions)3 MethodCall (org.checkerframework.dataflow.analysis.FlowExpressions.MethodCall)3 Resolver (org.checkerframework.javacutil.Resolver)3 AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 DeclaredType (javax.lang.model.type.DeclaredType)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 Pair (org.checkerframework.javacutil.Pair)2 ClassTree (com.sun.source.tree.ClassTree)1 MethodTree (com.sun.source.tree.MethodTree)1 Tree (com.sun.source.tree.Tree)1