Search in sources :

Example 1 with AnnotatedTypeFactory

use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.

the class BaseTypeVisitor method createTypeFactory.

/**
 * Constructs an instance of the appropriate type factory for the implemented type system.
 *
 * <p>The default implementation uses the checker naming convention to create the appropriate type
 * factory. If no factory is found, it returns {@link BaseAnnotatedTypeFactory}. It reflectively
 * invokes the constructor that accepts this checker and compilation unit tree (in that order) as
 * arguments.
 *
 * <p>Subclasses have to override this method to create the appropriate visitor if they do not
 * follow the checker naming convention.
 *
 * @return the appropriate type factory
 */
// unchecked cast to type variable
@SuppressWarnings("unchecked")
protected Factory createTypeFactory() {
    // Try to reflectively load the type factory.
    Class<?> checkerClass = checker.getClass();
    while (checkerClass != BaseTypeChecker.class) {
        AnnotatedTypeFactory result = BaseTypeChecker.invokeConstructorFor(BaseTypeChecker.getRelatedClassName(checkerClass, "AnnotatedTypeFactory"), new Class<?>[] { BaseTypeChecker.class }, new Object[] { checker });
        if (result != null) {
            return (Factory) result;
        }
        checkerClass = checkerClass.getSuperclass();
    }
    try {
        return (Factory) new BaseAnnotatedTypeFactory(checker);
    } catch (Throwable t) {
        throw new BugInCF("Unexpected " + t.getClass().getSimpleName() + " when invoking BaseAnnotatedTypeFactory for checker " + checker.getClass().getSimpleName(), t);
    }
}
Also used : GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) BugInCF(org.checkerframework.javacutil.BugInCF)

Example 2 with AnnotatedTypeFactory

use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.

the class MethodNameValidator method visitDeclared.

@Override
public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
    AnnotationMirror methodVal = type.getAnnotation(MethodVal.class);
    if (methodVal != null) {
        AnnotatedTypeFactory atypeFactory = checker.getTypeFactory();
        List<String> classNames = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValClassNameElement, String.class);
        List<String> methodNames = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValMethodNameElement, String.class);
        List<Integer> params = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValParamsElement, Integer.class);
        if (!(classNames.size() == methodNames.size() && classNames.size() == params.size())) {
            checker.reportError(tree, "invalid.methodval", methodVal);
        }
        for (String methodName : methodNames) {
            if (!legalMethodName(methodName)) {
                checker.reportError(tree, "illegal.methodname", methodName, type);
            }
        }
    }
    return super.visitDeclared(type, tree);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory)

Example 3 with AnnotatedTypeFactory

use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.

the class CFAbstractTransfer method initialStore.

/**
 * The initial store maps method formal parameters to their currently most refined type.
 */
@Override
public S initialStore(UnderlyingAST underlyingAST, List<LocalVariableNode> parameters) {
    if (underlyingAST.getKind() != UnderlyingAST.Kind.LAMBDA && underlyingAST.getKind() != UnderlyingAST.Kind.METHOD) {
        if (fixedInitialStore != null) {
            return fixedInitialStore;
        } else {
            return analysis.createEmptyStore(sequentialSemantics);
        }
    }
    S store;
    if (underlyingAST.getKind() == UnderlyingAST.Kind.METHOD) {
        if (fixedInitialStore != null) {
            // copy knowledge
            store = analysis.createCopiedStore(fixedInitialStore);
        } else {
            store = analysis.createEmptyStore(sequentialSemantics);
        }
        AnnotatedTypeFactory factory = analysis.getTypeFactory();
        for (LocalVariableNode p : parameters) {
            AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
            store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
        }
        // add properties known through precondition
        CFGMethod method = (CFGMethod) underlyingAST;
        MethodTree methodDeclTree = method.getMethod();
        ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodDeclTree);
        addInformationFromPreconditions(store, factory, method, methodDeclTree, methodElem);
        addInitialFieldValues(store, method.getClassTree(), methodDeclTree);
        addFinalLocalValues(store, methodElem);
        if (shouldPerformWholeProgramInference(methodDeclTree, methodElem)) {
            Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(analysis.atypeFactory.getElementUtils(), analysis.atypeFactory, methodElem);
            for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
                AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(analysis.atypeFactory.getProcessingEnv().getTypeUtils(), analysis.atypeFactory, pair.getKey(), pair.getValue());
                // Infers parameter and receiver types of the method based
                // on the overridden method.
                analysis.atypeFactory.getWholeProgramInference().updateFromOverride(methodDeclTree, methodElem, overriddenMethod);
            }
        }
    } else if (underlyingAST.getKind() == UnderlyingAST.Kind.LAMBDA) {
        // Create a copy and keep only the field values (nothing else applies).
        store = analysis.createCopiedStore(fixedInitialStore);
        // Allow that local variables are retained; they are effectively final,
        // otherwise Java wouldn't allow access from within the lambda.
        // TODO: what about the other information? Can code further down be simplified?
        // store.localVariableValues.clear();
        store.classValues.clear();
        store.arrayValues.clear();
        store.methodValues.clear();
        AnnotatedTypeFactory factory = analysis.getTypeFactory();
        for (LocalVariableNode p : parameters) {
            AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
            store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
        }
        CFGLambda lambda = (CFGLambda) underlyingAST;
        // used in == tests
        @SuppressWarnings("interning:assignment") @InternedDistinct Tree enclosingTree = TreePathUtil.enclosingOfKind(factory.getPath(lambda.getLambdaTree()), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, // Tree.Kind for which TreeUtils.isClassTree is true
        Tree.Kind.CLASS, Tree.Kind.INTERFACE, Tree.Kind.ANNOTATION_TYPE, Tree.Kind.ENUM)));
        Element enclosingElement = null;
        if (enclosingTree.getKind() == Tree.Kind.METHOD) {
            // If it is in an initializer, we need to use locals from the initializer.
            enclosingElement = TreeUtils.elementFromTree(enclosingTree);
        } else if (TreeUtils.isClassTree(enclosingTree)) {
            // Try to find an enclosing initializer block.
            // Would love to know if there was a better way.
            // Find any enclosing element of the lambda (using trees).
            // Then go up the elements to find an initializer element (which can't be found with the
            // tree).
            TreePath loopTree = factory.getPath(lambda.getLambdaTree()).getParentPath();
            Element anEnclosingElement = null;
            while (loopTree.getLeaf() != enclosingTree) {
                Element sym = TreeUtils.elementFromTree(loopTree.getLeaf());
                if (sym != null) {
                    anEnclosingElement = sym;
                    break;
                }
                loopTree = loopTree.getParentPath();
            }
            while (anEnclosingElement != null && !anEnclosingElement.equals(TreeUtils.elementFromTree(enclosingTree))) {
                if (anEnclosingElement.getKind() == ElementKind.INSTANCE_INIT || anEnclosingElement.getKind() == ElementKind.STATIC_INIT) {
                    enclosingElement = anEnclosingElement;
                    break;
                }
                anEnclosingElement = anEnclosingElement.getEnclosingElement();
            }
        }
        if (enclosingElement != null) {
            addFinalLocalValues(store, enclosingElement);
        }
        // We want the initialization stuff, but need to throw out any refinements.
        Map<FieldAccess, V> fieldValuesClone = new HashMap<>(store.fieldValues);
        for (Map.Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
            AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
            V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
            store.fieldValues.put(fieldValue.getKey(), lubbedValue);
        }
    } else {
        assert false : "Unexpected tree: " + underlyingAST;
        store = null;
    }
    return store;
}
Also used : CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) MethodTree(com.sun.source.tree.MethodTree) 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) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) TreePath(com.sun.source.util.TreePath) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) MethodTree(com.sun.source.tree.MethodTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ExpressionTree(com.sun.source.tree.ExpressionTree) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 4 with AnnotatedTypeFactory

use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.

the class CFAbstractTransfer method addInformationFromPreconditions.

/**
 * Add the information from all the preconditions of a method to the initial store in the method
 * body.
 *
 * @param initialStore the initial store for the method body
 * @param factory the type factory
 * @param methodAst the AST for a method declaration
 * @param methodDeclTree the declaration of the method; is a field of {@code methodAst}
 * @param methodElement the element for the method
 */
protected void addInformationFromPreconditions(S initialStore, AnnotatedTypeFactory factory, CFGMethod methodAst, MethodTree methodDeclTree, ExecutableElement methodElement) {
    ContractsFromMethod contractsUtils = analysis.atypeFactory.getContractsFromMethod();
    Set<Precondition> preconditions = contractsUtils.getPreconditions(methodElement);
    StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
    for (Precondition p : preconditions) {
        String stringExpr = p.expressionString;
        AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(analysis.atypeFactory, stringToJavaExpr, /*errorTree=*/
        null);
        JavaExpression exprJe;
        try {
            // TODO: currently, these expressions are parsed at the declaration (i.e. here) and for
            // every use. this could be optimized to store the result the first time.
            // (same for other annotations)
            exprJe = StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
        } catch (JavaExpressionParseException e) {
            // Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration().
            continue;
        }
        initialStore.insertValuePermitNondeterministic(exprJe, annotation);
    }
}
Also used : NodeUtils(org.checkerframework.dataflow.util.NodeUtils) Arrays(java.util.Arrays) TransferResult(org.checkerframework.dataflow.analysis.TransferResult) Modifier(javax.lang.model.element.Modifier) ForwardTransferFunction(org.checkerframework.dataflow.analysis.ForwardTransferFunction) TypeElement(javax.lang.model.element.TypeElement) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) StringConversionNode(org.checkerframework.dataflow.cfg.node.StringConversionNode) GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) Map(java.util.Map) WideningConversionNode(org.checkerframework.dataflow.cfg.node.WideningConversionNode) InternedDistinct(org.checkerframework.checker.interning.qual.InternedDistinct) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) ClassNameNode(org.checkerframework.dataflow.cfg.node.ClassNameNode) TreePath(com.sun.source.util.TreePath) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) UnderlyingAST(org.checkerframework.dataflow.cfg.UnderlyingAST) AbstractNodeVisitor(org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor) Set(java.util.Set) Element(javax.lang.model.element.Element) Contract(org.checkerframework.framework.util.Contract) TreeUtils(org.checkerframework.javacutil.TreeUtils) CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) NarrowingConversionNode(org.checkerframework.dataflow.cfg.node.NarrowingConversionNode) List(java.util.List) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) EqualToNode(org.checkerframework.dataflow.cfg.node.EqualToNode) AnnotatedTypes(org.checkerframework.framework.util.AnnotatedTypes) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda) VariableDeclarationNode(org.checkerframework.dataflow.cfg.node.VariableDeclarationNode) RegularTransferResult(org.checkerframework.dataflow.analysis.RegularTransferResult) TernaryExpressionNode(org.checkerframework.dataflow.cfg.node.TernaryExpressionNode) Postcondition(org.checkerframework.framework.util.Contract.Postcondition) MethodTree(com.sun.source.tree.MethodTree) ConditionalPostcondition(org.checkerframework.framework.util.Contract.ConditionalPostcondition) VariableElement(javax.lang.model.element.VariableElement) InstanceOfNode(org.checkerframework.dataflow.cfg.node.InstanceOfNode) HashMap(java.util.HashMap) ThisNode(org.checkerframework.dataflow.cfg.node.ThisNode) ArrayList(java.util.ArrayList) ConditionalTransferResult(org.checkerframework.dataflow.analysis.ConditionalTransferResult) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) CaseNode(org.checkerframework.dataflow.cfg.node.CaseNode) HashSet(java.util.HashSet) LambdaResultExpressionNode(org.checkerframework.dataflow.cfg.node.LambdaResultExpressionNode) Precondition(org.checkerframework.framework.util.Contract.Precondition) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) TreePathUtil(org.checkerframework.javacutil.TreePathUtil) SwitchExpressionNode(org.checkerframework.dataflow.cfg.node.SwitchExpressionNode) NotEqualNode(org.checkerframework.dataflow.cfg.node.NotEqualNode) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) Nullable(org.checkerframework.checker.nullness.qual.Nullable) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) TransferInput(org.checkerframework.dataflow.analysis.TransferInput) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) ArrayAccessNode(org.checkerframework.dataflow.cfg.node.ArrayAccessNode) ConditionalNotNode(org.checkerframework.dataflow.cfg.node.ConditionalNotNode) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) ElementKind(javax.lang.model.element.ElementKind) ExpressionTree(com.sun.source.tree.ExpressionTree) ExecutableElement(javax.lang.model.element.ExecutableElement) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) FieldInitialValue(org.checkerframework.framework.flow.CFAbstractAnalysis.FieldInitialValue) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) AnnotationMirror(javax.lang.model.element.AnnotationMirror) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) StringConcatenateAssignmentNode(org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode) TypeMirror(javax.lang.model.type.TypeMirror) Collections(java.util.Collections) ElementUtils(org.checkerframework.javacutil.ElementUtils) Node(org.checkerframework.dataflow.cfg.node.Node) ContractsFromMethod(org.checkerframework.framework.util.ContractsFromMethod) AnnotationMirror(javax.lang.model.element.AnnotationMirror) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) Precondition(org.checkerframework.framework.util.Contract.Precondition) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) ContractsFromMethod(org.checkerframework.framework.util.ContractsFromMethod)

Example 5 with AnnotatedTypeFactory

use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.

the class CFAbstractStore method isMonotonicUpdate.

/**
 * Return true if fieldAcc is an update of a monotonic qualifier to its target qualifier.
 * (e.g. @MonotonicNonNull to @NonNull). Always returns false if {@code sequentialSemantics} is
 * true.
 *
 * @return true if fieldAcc is an update of a monotonic qualifier to its target qualifier
 *     (e.g. @MonotonicNonNull to @NonNull)
 */
protected boolean isMonotonicUpdate(FieldAccess fieldAcc, V value) {
    if (analysis.atypeFactory.getSupportedMonotonicTypeQualifiers().isEmpty()) {
        return false;
    }
    boolean isMonotonic = false;
    // TODO: Update the javadoc of this method when the above to-do item is addressed.
    if (!sequentialSemantics) {
        // only compute if necessary
        AnnotatedTypeFactory atypeFactory = this.analysis.atypeFactory;
        List<Pair<AnnotationMirror, AnnotationMirror>> fieldAnnotations = atypeFactory.getAnnotationWithMetaAnnotation(fieldAcc.getField(), MonotonicQualifier.class);
        for (Pair<AnnotationMirror, AnnotationMirror> fieldAnnotation : fieldAnnotations) {
            AnnotationMirror monotonicAnnotation = fieldAnnotation.second;
            // permitted for use in the framework
            @SuppressWarnings("deprecation") Name annotation = AnnotationUtils.getElementValueClassName(monotonicAnnotation, "value", false);
            AnnotationMirror target = AnnotationBuilder.fromName(atypeFactory.getElementUtils(), annotation);
            // Make sure the 'target' annotation is present.
            if (AnnotationUtils.containsSame(value.getAnnotations(), target)) {
                isMonotonic = true;
                break;
            }
        }
    }
    return isMonotonic;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) Pair(org.checkerframework.javacutil.Pair) Name(javax.lang.model.element.Name) ClassName(org.checkerframework.dataflow.expression.ClassName)

Aggregations

AnnotatedTypeFactory (org.checkerframework.framework.type.AnnotatedTypeFactory)6 GenericAnnotatedTypeFactory (org.checkerframework.framework.type.GenericAnnotatedTypeFactory)5 AnnotationMirror (javax.lang.model.element.AnnotationMirror)3 TypeElement (javax.lang.model.element.TypeElement)3 ClassTree (com.sun.source.tree.ClassTree)2 ExpressionTree (com.sun.source.tree.ExpressionTree)2 MethodTree (com.sun.source.tree.MethodTree)2 Tree (com.sun.source.tree.Tree)2 TreePath (com.sun.source.util.TreePath)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Map (java.util.Map)2 Element (javax.lang.model.element.Element)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 VariableElement (javax.lang.model.element.VariableElement)2 CFGLambda (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda)2 CFGMethod (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod)2 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)2