All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.dataflow.cfg.builder.CFGBuilder Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.44.0
Show newest version
package org.checkerframework.dataflow.cfg.builder;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.TreePath;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.dataflow.cfg.ControlFlowGraph;
import org.checkerframework.dataflow.cfg.UnderlyingAST;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod;
import org.checkerframework.dataflow.cfg.block.Block;
import org.checkerframework.dataflow.cfg.block.ConditionalBlockImpl;
import org.checkerframework.dataflow.cfg.block.ExceptionBlockImpl;
import org.checkerframework.dataflow.cfg.block.SingleSuccessorBlockImpl;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BasicAnnotationProvider;
import org.checkerframework.javacutil.trees.TreeBuilder;

/**
 * Builds the control flow graph of some Java code (either a method, or an arbitrary statement).
 *
 * 

The translation of the AST to the CFG is split into three phases: * *

    *
  1. Phase one. In the first phase, the AST is translated into a sequence of {@link * org.checkerframework.dataflow.cfg.builder.ExtendedNode}s. An extended node can either be a * {@link Node}, or one of several meta elements such as a conditional or unconditional jump * or a node with additional information about exceptions. Some of the extended nodes contain * labels (e.g., for the jump target), and phase one additionally creates a mapping from * labels to extended nodes. Finally, the list of leaders is computed: A leader is an extended * node which will give rise to a basic block in phase two. *
  2. Phase two. In this phase, the sequence of extended nodes is translated to a graph * of control flow blocks that contain nodes. The meta elements from phase one are translated * into the correct edges. *
  3. Phase three. The control flow graph generated in phase two can contain degenerate * basic blocks such as empty regular basic blocks or conditional basic blocks that have the * same block as both 'then' and 'else' successor. This phase removes these cases while * preserving the control flow structure. *
*/ public abstract class CFGBuilder { /** * Build the control flow graph of some code. * * @param root the compilation unit * @param underlyingAST the AST that underlies the control frow graph * @param assumeAssertionsDisabled can assertions be assumed to be disabled? * @param assumeAssertionsEnabled can assertions be assumed to be enabled? * @param env annotation processing environment containing type utilities * @return a control flow graph */ public static ControlFlowGraph build( CompilationUnitTree root, UnderlyingAST underlyingAST, boolean assumeAssertionsEnabled, boolean assumeAssertionsDisabled, ProcessingEnvironment env) { TreeBuilder builder = new TreeBuilder(env); AnnotationProvider annotationProvider = new BasicAnnotationProvider(); PhaseOneResult phase1result = new CFGTranslationPhaseOne( builder, annotationProvider, assumeAssertionsEnabled, assumeAssertionsDisabled, env) .process(root, underlyingAST); ControlFlowGraph phase2result = CFGTranslationPhaseTwo.process(phase1result); ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result); return phase3result; } /** * Build the control flow graph of some code (method, initializer block, ...). bodyPath is the * TreePath to the body of that code. */ public static ControlFlowGraph build( TreePath bodyPath, UnderlyingAST underlyingAST, boolean assumeAssertionsEnabled, boolean assumeAssertionsDisabled, ProcessingEnvironment env) { TreeBuilder builder = new TreeBuilder(env); AnnotationProvider annotationProvider = new BasicAnnotationProvider(); PhaseOneResult phase1result = new CFGTranslationPhaseOne( builder, annotationProvider, assumeAssertionsEnabled, assumeAssertionsDisabled, env) .process(bodyPath, underlyingAST); ControlFlowGraph phase2result = CFGTranslationPhaseTwo.process(phase1result); ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result); return phase3result; } /** Build the control flow graph of some code. */ public static ControlFlowGraph build( CompilationUnitTree root, UnderlyingAST underlyingAST, ProcessingEnvironment env) { return build(root, underlyingAST, false, false, env); } /** Build the control flow graph of a method. */ public static ControlFlowGraph build( CompilationUnitTree root, MethodTree tree, ClassTree classTree, ProcessingEnvironment env) { UnderlyingAST underlyingAST = new CFGMethod(tree, classTree); return build(root, underlyingAST, false, false, env); } /** * Return a printed representation of a collection of extended nodes. * * @param nodes a collection of extended nodes to format * @return a printed representation of the given collection */ public static String extendedNodeCollectionToStringDebug( Collection nodes) { StringJoiner result = new StringJoiner(", ", "[", "]"); for (ExtendedNode n : nodes) { result.add(n.toStringDebug()); } return result.toString(); } static A firstNonNull(A first, A second) { if (first != null) { return first; } else if (second != null) { return second; } else { throw new NullPointerException(); } } /* --------------------------------------------------------- */ /* Utility routines for debugging CFG building */ /* --------------------------------------------------------- */ /** * Print a set of {@link Block}s and the edges between them. This is useful for examining the * results of phase two. * * @param blocks the blocks to print */ protected static void printBlocks(Set blocks) { for (Block b : blocks) { System.out.print(b.getUid() + ": " + b); switch (b.getType()) { case REGULAR_BLOCK: case SPECIAL_BLOCK: { Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor(); System.out.println(" -> " + (succ != null ? succ.getUid() : "||")); break; } case EXCEPTION_BLOCK: { Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor(); System.out.print(" -> " + (succ != null ? succ.getUid() : "||") + " {"); for (Map.Entry> entry : ((ExceptionBlockImpl) b).getExceptionalSuccessors().entrySet()) { System.out.print(entry.getKey() + " : " + entry.getValue() + ", "); } System.out.println("}"); break; } case CONDITIONAL_BLOCK: { Block tSucc = ((ConditionalBlockImpl) b).getThenSuccessor(); Block eSucc = ((ConditionalBlockImpl) b).getElseSuccessor(); System.out.println( " -> T " + (tSucc != null ? tSucc.getUid() : "||") + " F " + (eSucc != null ? eSucc.getUid() : "||")); break; } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy