Search in sources :

Example 1 with CFGStatement

use of org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement in project checker-framework by typetools.

the class GenericAnnotatedTypeFactory method analyze.

protected void analyze(Queue<ClassTree> queue, Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue, UnderlyingAST ast, List<Pair<VariableElement, Value>> fieldValues, ClassTree currentClass, boolean isInitializationCode, boolean updateInitializationStore, boolean isStatic, Store lambdaStore) {
    CFGBuilder builder = new CFCFGBuilder(checker, this);
    ControlFlowGraph cfg = builder.run(root, processingEnv, ast);
    FlowAnalysis newAnalysis = createFlowAnalysis(fieldValues);
    TransferFunction transfer = newAnalysis.getTransferFunction();
    if (emptyStore == null) {
        emptyStore = newAnalysis.createEmptyStore(transfer.usesSequentialSemantics());
    }
    analyses.addFirst(newAnalysis);
    if (lambdaStore != null) {
        transfer.setFixedInitialStore(lambdaStore);
    } else {
        Store initStore = !isStatic ? initializationStore : initializationStaticStore;
        if (isInitializationCode) {
            if (initStore != null) {
                // we have already seen initialization code and analyzed it, and
                // the analysis ended with the store initStore.
                // use it to start the next analysis.
                transfer.setFixedInitialStore(initStore);
            }
        }
    }
    analyses.getFirst().performAnalysis(cfg);
    AnalysisResult<Value, Store> result = analyses.getFirst().getResult();
    // store result
    flowResult.combine(result);
    if (ast.getKind() == UnderlyingAST.Kind.METHOD) {
        // store exit store (for checking postconditions)
        CFGMethod mast = (CFGMethod) ast;
        MethodTree method = mast.getMethod();
        Store regularExitStore = analyses.getFirst().getRegularExitStore();
        if (regularExitStore != null) {
            regularExitStores.put(method, regularExitStore);
        }
        returnStatementStores.put(method, analyses.getFirst().getReturnStatementStores());
    } else if (ast.getKind() == UnderlyingAST.Kind.ARBITRARY_CODE) {
        CFGStatement block = (CFGStatement) ast;
        Store regularExitStore = analyses.getFirst().getRegularExitStore();
        if (regularExitStore != null) {
            regularExitStores.put(block.getCode(), regularExitStore);
        }
    } else if (ast.getKind() == UnderlyingAST.Kind.LAMBDA) {
        // TODO: Postconditions?
        CFGLambda block = (CFGLambda) ast;
        Store regularExitStore = analyses.getFirst().getRegularExitStore();
        if (regularExitStore != null) {
            regularExitStores.put(block.getCode(), regularExitStore);
        }
    }
    if (isInitializationCode && updateInitializationStore) {
        Store newInitStore = analyses.getFirst().getRegularExitStore();
        if (!isStatic) {
            initializationStore = newInitStore;
        } else {
            initializationStaticStore = newInitStore;
        }
    }
    if (checker.hasOption("flowdotdir") || checker.hasOption("cfgviz")) {
        handleCFGViz();
    }
    analyses.removeFirst();
    // add classes declared in method
    queue.addAll(builder.getDeclaredClasses());
    for (LambdaExpressionTree lambda : builder.getDeclaredLambdas()) {
        lambdaQueue.add(Pair.of(lambda, getStoreBefore(lambda)));
    }
}
Also used : CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) MethodTree(com.sun.source.tree.MethodTree) CFGStatement(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement) CFCFGBuilder(org.checkerframework.framework.flow.CFCFGBuilder) CFGBuilder(org.checkerframework.dataflow.cfg.CFGBuilder) CFStore(org.checkerframework.framework.flow.CFStore) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ControlFlowGraph(org.checkerframework.dataflow.cfg.ControlFlowGraph) CFAbstractValue(org.checkerframework.framework.flow.CFAbstractValue) CFValue(org.checkerframework.framework.flow.CFValue) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda) CFCFGBuilder(org.checkerframework.framework.flow.CFCFGBuilder)

Example 2 with CFGStatement

use of org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement in project checker-framework by typetools.

the class DOTCFGVisualizer method dotOutputFileName.

/**
 * @return the file name used for DOT output.
 */
protected String dotOutputFileName(UnderlyingAST ast) {
    StringBuilder srcloc = new StringBuilder();
    StringBuilder outfile = new StringBuilder(outdir);
    outfile.append('/');
    if (ast.getKind() == UnderlyingAST.Kind.ARBITRARY_CODE) {
        CFGStatement cfgs = (CFGStatement) ast;
        String clsname = cfgs.getClassTree().getSimpleName().toString();
        outfile.append(clsname);
        outfile.append("-initializer-");
        outfile.append(ast.hashCode());
        srcloc.append('<');
        srcloc.append(clsname);
        srcloc.append("::initializer::");
        srcloc.append(((JCTree) cfgs.getCode()).pos);
        srcloc.append('>');
    } else if (ast.getKind() == UnderlyingAST.Kind.METHOD) {
        CFGMethod cfgm = (CFGMethod) ast;
        String clsname = cfgm.getClassTree().getSimpleName().toString();
        String methname = cfgm.getMethod().getName().toString();
        outfile.append(clsname);
        outfile.append('-');
        outfile.append(methname);
        srcloc.append('<');
        srcloc.append(clsname);
        srcloc.append("::");
        srcloc.append(methname);
        srcloc.append('(');
        srcloc.append(cfgm.getMethod().getParameters());
        srcloc.append(")::");
        srcloc.append(((JCTree) cfgm.getMethod()).pos);
        srcloc.append('>');
    } else {
        ErrorReporter.errorAbort("Unexpected AST kind: " + ast.getKind() + " value: " + ast.toString());
        return null;
    }
    outfile.append('-');
    outfile.append(checkerName);
    outfile.append(".dot");
    // make path safe for Windows
    String out = outfile.toString().replace("<", "_").replace(">", "");
    generated.put(srcloc.toString(), out);
    return out;
}
Also used : CFGStatement(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement) CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) JCTree(com.sun.tools.javac.tree.JCTree)

Example 3 with CFGStatement

use of org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement 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.
 */
protected void performFlowAnalysis(ClassTree classTree) {
    if (flowResult == null) {
        regularExitStores = new IdentityHashMap<>();
        returnStatementStores = new IdentityHashMap<>();
        flowResult = new AnalysisResult<>(flowResultAnalysisCaches);
    }
    // no need to scan annotations
    if (classTree.getKind() == Kind.ANNOTATION_TYPE) {
        // Mark finished so that default annotations will be applied.
        scannedClasses.put(classTree, ScanState.FINISHED);
        return;
    }
    Queue<ClassTree> queue = new ArrayDeque<>();
    List<Pair<VariableElement, Value>> fieldValues = new ArrayList<>();
    queue.add(classTree);
    while (!queue.isEmpty()) {
        ClassTree ct = queue.remove();
        scannedClasses.put(ct, ScanState.IN_PROGRESS);
        AnnotatedDeclaredType preClassType = visitorState.getClassType();
        ClassTree preClassTree = visitorState.getClassTree();
        AnnotatedDeclaredType preAMT = visitorState.getMethodReceiver();
        MethodTree preMT = visitorState.getMethodTree();
        visitorState.setClassType(getAnnotatedType(ct));
        visitorState.setClassTree(ct);
        visitorState.setMethodReceiver(null);
        visitorState.setMethodTree(null);
        // start without a initialization store
        initializationStaticStore = null;
        initializationStore = null;
        Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue = new ArrayDeque<>();
        try {
            List<CFGMethod> methods = new ArrayList<>();
            for (Tree m : ct.getMembers()) {
                switch(m.getKind()) {
                    case METHOD:
                        MethodTree mt = (MethodTree) m;
                        // Skip abstract and native methods because they have no body.
                        ModifiersTree modifiers = mt.getModifiers();
                        if (modifiers != null) {
                            Set<Modifier> flags = modifiers.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();
                        // 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);
                            Value value = flowResult.getValue(initializer);
                            if (value != null) {
                                // Store the abstract value for the field.
                                VariableElement element = TreeUtils.elementFromDeclaration(vt);
                                fieldValues.add(Pair.of(element, value));
                            }
                        }
                        break;
                    case CLASS:
                    case ANNOTATION_TYPE:
                    case INTERFACE:
                    case ENUM:
                        // Visit inner and nested class trees.
                        queue.add((ClassTree) m);
                        break;
                    case BLOCK:
                        BlockTree b = (BlockTree) m;
                        analyze(queue, lambdaQueue, new CFGStatement(b, ct), fieldValues, ct, true, true, b.isStatic());
                        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);
            }
            while (!lambdaQueue.isEmpty()) {
                Pair<LambdaExpressionTree, Store> lambdaPair = lambdaQueue.poll();
                analyze(queue, lambdaQueue, new CFGLambda(lambdaPair.first), fieldValues, classTree, false, false, false, lambdaPair.second);
            }
            // see InitializationVisitor.visitClass
            if (initializationStaticStore == null) {
                regularExitStores.put(ct, emptyStore);
            } else {
                regularExitStores.put(ct, initializationStaticStore);
            }
        } finally {
            visitorState.setClassType(preClassType);
            visitorState.setClassTree(preClassTree);
            visitorState.setMethodReceiver(preAMT);
            visitorState.setMethodTree(preMT);
        }
        scannedClasses.put(ct, ScanState.FINISHED);
    }
}
Also used : ModifiersTree(com.sun.source.tree.ModifiersTree) MethodTree(com.sun.source.tree.MethodTree) CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) CFGStatement(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) ArrayList(java.util.ArrayList) VariableTree(com.sun.source.tree.VariableTree) CFStore(org.checkerframework.framework.flow.CFStore) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) VariableElement(javax.lang.model.element.VariableElement) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) BlockTree(com.sun.source.tree.BlockTree) ReturnTree(com.sun.source.tree.ReturnTree) 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) ModifiersTree(com.sun.source.tree.ModifiersTree) 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) CFAbstractValue(org.checkerframework.framework.flow.CFAbstractValue) CFValue(org.checkerframework.framework.flow.CFValue) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda)

Aggregations

CFGMethod (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod)3 CFGStatement (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement)3 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)2 MethodTree (com.sun.source.tree.MethodTree)2 CFGLambda (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda)2 CFAbstractStore (org.checkerframework.framework.flow.CFAbstractStore)2 CFAbstractValue (org.checkerframework.framework.flow.CFAbstractValue)2 CFStore (org.checkerframework.framework.flow.CFStore)2 CFValue (org.checkerframework.framework.flow.CFValue)2 BlockTree (com.sun.source.tree.BlockTree)1 ClassTree (com.sun.source.tree.ClassTree)1 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)1 ExpressionTree (com.sun.source.tree.ExpressionTree)1 MemberReferenceTree (com.sun.source.tree.MemberReferenceTree)1 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)1 ModifiersTree (com.sun.source.tree.ModifiersTree)1 NewClassTree (com.sun.source.tree.NewClassTree)1 ReturnTree (com.sun.source.tree.ReturnTree)1 Tree (com.sun.source.tree.Tree)1 UnaryTree (com.sun.source.tree.UnaryTree)1