Search in sources :

Example 26 with FieldAccess

use of org.checkerframework.dataflow.expression.FieldAccess in project checker-framework by typetools.

the class GenericAnnotatedTypeFactory method performFlowAnalysis.

/**
 * Perform a org.checkerframework.dataflow analysis over a single class tree and its nested
 * classes.
 *
 * @param classTree the class to analyze
 */
protected void performFlowAnalysis(ClassTree classTree) {
    if (flowResult == null) {
        regularExitStores = new IdentityHashMap<>();
        exceptionalExitStores = new IdentityHashMap<>();
        returnStatementStores = new IdentityHashMap<>();
        flowResult = new AnalysisResult<>(flowResultAnalysisCaches);
    }
    // no need to scan annotations
    if (classTree.getKind() == Tree.Kind.ANNOTATION_TYPE) {
        // Mark finished so that default annotations will be applied.
        scannedClasses.put(classTree, ScanState.FINISHED);
        return;
    }
    Queue<Pair<ClassTree, Store>> queue = new ArrayDeque<>();
    List<FieldInitialValue<Value>> fieldValues = new ArrayList<>();
    // No captured store for top-level classes.
    queue.add(Pair.of(classTree, null));
    while (!queue.isEmpty()) {
        final Pair<ClassTree, Store> qel = queue.remove();
        final ClassTree ct = qel.first;
        final Store capturedStore = qel.second;
        scannedClasses.put(ct, ScanState.IN_PROGRESS);
        TreePath preTreePath = getVisitorTreePath();
        // Don't use getPath, because that depends on the assignmentContext path.
        setVisitorTreePath(TreePath.getPath(this.root, ct));
        // start with the captured store as initialization store
        initializationStaticStore = capturedStore;
        initializationStore = capturedStore;
        Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue = new ArrayDeque<>();
        try {
            List<CFGMethod> methods = new ArrayList<>();
            List<? extends Tree> members = ct.getMembers();
            if (!Ordering.from(sortVariablesFirst).isOrdered(members)) {
                members = new ArrayList<>(members);
                // Process variables before methods, so all field initializers are observed before the
                // constructor is analyzed and reports uninitialized variables.
                members.sort(sortVariablesFirst);
            }
            for (Tree m : members) {
                switch(TreeUtils.getKindRecordAsClass(m)) {
                    case METHOD:
                        MethodTree mt = (MethodTree) m;
                        // Skip abstract and native methods because they have no body.
                        Set<Modifier> flags = mt.getModifiers().getFlags();
                        if (flags.contains(Modifier.ABSTRACT) || flags.contains(Modifier.NATIVE)) {
                            break;
                        }
                        // ABSTRACT flag.
                        if (mt.getBody() == null) {
                            break;
                        }
                        // Wait with scanning the method until all other members
                        // have been processed.
                        CFGMethod met = new CFGMethod(mt, ct);
                        methods.add(met);
                        break;
                    case VARIABLE:
                        VariableTree vt = (VariableTree) m;
                        ExpressionTree initializer = vt.getInitializer();
                        AnnotatedTypeMirror declaredType = getAnnotatedTypeLhs(vt);
                        Value declaredValue = analysis.createAbstractValue(declaredType);
                        FieldAccess fieldExpr = (FieldAccess) JavaExpression.fromVariableTree(vt);
                        // analyze initializer if present
                        if (initializer != null) {
                            boolean isStatic = vt.getModifiers().getFlags().contains(Modifier.STATIC);
                            analyze(queue, lambdaQueue, new CFGStatement(vt, ct), fieldValues, classTree, true, true, isStatic, capturedStore);
                            Value initializerValue = flowResult.getValue(initializer);
                            if (initializerValue != null) {
                                fieldValues.add(new FieldInitialValue<>(fieldExpr, declaredValue, initializerValue));
                                break;
                            }
                        }
                        fieldValues.add(new FieldInitialValue<>(fieldExpr, declaredValue, null));
                        break;
                    // Including RECORD
                    case CLASS:
                    case ANNOTATION_TYPE:
                    case INTERFACE:
                    case ENUM:
                        // Visit inner and nested class trees.
                        // TODO: Use no store for them? What can be captured?
                        queue.add(Pair.of((ClassTree) m, capturedStore));
                        break;
                    case BLOCK:
                        BlockTree b = (BlockTree) m;
                        analyze(queue, lambdaQueue, new CFGStatement(b, ct), fieldValues, ct, true, true, b.isStatic(), capturedStore);
                        break;
                    default:
                        assert false : "Unexpected member: " + m.getKind();
                        break;
                }
            }
            // fields of superclasses.
            for (CFGMethod met : methods) {
                analyze(queue, lambdaQueue, met, fieldValues, classTree, TreeUtils.isConstructor(met.getMethod()), false, false, capturedStore);
            }
            while (!lambdaQueue.isEmpty()) {
                Pair<LambdaExpressionTree, Store> lambdaPair = lambdaQueue.poll();
                MethodTree mt = (MethodTree) TreePathUtil.enclosingOfKind(getPath(lambdaPair.first), Tree.Kind.METHOD);
                analyze(queue, lambdaQueue, new CFGLambda(lambdaPair.first, classTree, mt), fieldValues, classTree, false, false, false, lambdaPair.second);
            }
            // See InitializationVisitor.visitClass().
            if (initializationStaticStore == null) {
                regularExitStores.put(ct, emptyStore);
            } else {
                regularExitStores.put(ct, initializationStaticStore);
            }
        } finally {
            setVisitorTreePath(preTreePath);
        }
        scannedClasses.put(ct, ScanState.FINISHED);
    }
}
Also used : CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) MethodTree(com.sun.source.tree.MethodTree) CFGStatement(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement) ArrayList(java.util.ArrayList) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) VariableTree(com.sun.source.tree.VariableTree) CFStore(org.checkerframework.framework.flow.CFStore) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) BlockTree(com.sun.source.tree.BlockTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BlockTree(com.sun.source.tree.BlockTree) Modifier(javax.lang.model.element.Modifier) Pair(org.checkerframework.javacutil.Pair) ArrayDeque(java.util.ArrayDeque) TreePath(com.sun.source.util.TreePath) FieldInitialValue(org.checkerframework.framework.flow.CFAbstractAnalysis.FieldInitialValue) CFAbstractValue(org.checkerframework.framework.flow.CFAbstractValue) CFValue(org.checkerframework.framework.flow.CFValue) FieldInitialValue(org.checkerframework.framework.flow.CFAbstractAnalysis.FieldInitialValue) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess)

Aggregations

FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)26 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)11 ClassName (org.checkerframework.dataflow.expression.ClassName)10 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)9 MethodCall (org.checkerframework.dataflow.expression.MethodCall)9 HashMap (java.util.HashMap)8 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)8 Map (java.util.Map)7 ThisReference (org.checkerframework.dataflow.expression.ThisReference)7 AnnotationMirror (javax.lang.model.element.AnnotationMirror)5 CFValue (org.checkerframework.framework.flow.CFValue)5 Element (javax.lang.model.element.Element)4 ExecutableElement (javax.lang.model.element.ExecutableElement)4 VariableElement (javax.lang.model.element.VariableElement)4 JavaExpressionParseException (org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)3 MethodTree (com.sun.source.tree.MethodTree)2 Tree (com.sun.source.tree.Tree)2 ArrayList (java.util.ArrayList)2 TypeElement (javax.lang.model.element.TypeElement)2 CFStore (org.checkerframework.framework.flow.CFStore)2