class ReachingDefs extends StructuredAnalysis<Stmt> {
  Object toAnalyze;

  public ReachingDefs(Object analyze) {
    super();
    toAnalyze = analyze;
    process(analyze, new DavaFlowSet<Stmt>());
  }

  @Override
  public DavaFlowSet<Stmt> emptyFlowSet() {
    return new DavaFlowSet<Stmt>();
  }

  /*
   * Initial flow into catch statements is empty meaning no definition reaches
   */
  @Override
  public DavaFlowSet<Stmt> newInitialFlow() {
    DavaFlowSet<Stmt> initial = new DavaFlowSet<Stmt>();
    // find all definitions in the program
    AllDefinitionsFinder defFinder = new AllDefinitionsFinder();
    ((ASTNode) toAnalyze).apply(defFinder);
    List<DefinitionStmt> allDefs = defFinder.getAllDefs();
    // all defs is the list of all augmented stmts which contains
    // DefinitionStmts
    for (DefinitionStmt def : allDefs) {
      initial.add(def);
    }

    // initial is not the universal set of all definitions
    return initial;
  }

  /*
   * Using union
   */
  public void setMergeType() {
    MERGETYPE = UNION;
  }

  @Override
  public DavaFlowSet<Stmt> cloneFlowSet(DavaFlowSet<Stmt> flowSet) {
    return flowSet.clone();
  }

  /*
   * In the case of reachingDefs the evaluation of a condition has no effect on the reachingDefs
   */
  @Override
  public DavaFlowSet<Stmt> processUnaryBinaryCondition(ASTUnaryBinaryCondition cond, DavaFlowSet<Stmt> inSet) {
    return inSet;
  }

  /*
   * In the case of reachingDefs the use of a local has no effect on reachingDefs
   */
  @Override
  public DavaFlowSet<Stmt> processSynchronizedLocal(Local local, DavaFlowSet<Stmt> inSet) {
    return inSet;
  }

  /*
   * In the case of reachingDefs a value has no effect on reachingDefs
   */
  @Override
  public DavaFlowSet<Stmt> processSwitchKey(Value key, DavaFlowSet<Stmt> inSet) {
    return inSet;
  }

  /*
   * This method internally invoked by the process method decides which Statement specialized method to call
   */
  @Override
  public DavaFlowSet<Stmt> processStatement(Stmt s, DavaFlowSet<Stmt> inSet) {<FILL_FUNCTION_BODY>}

  public void gen(DavaFlowSet<Stmt> in, DefinitionStmt s) {
    // System.out.println("Adding Definition Stmt: "+s);
    in.add(s);
  }

  public void kill(DavaFlowSet<Stmt> in, Local redefined) {
    String redefinedLocalName = redefined.getName();

    // kill any previous localpairs which have the redefined Local in the
    // left i.e. previous definitions
    for (Iterator<Stmt> listIt = in.iterator(); listIt.hasNext();) {
      DefinitionStmt tempStmt = (DefinitionStmt) listIt.next();
      Value leftOp = tempStmt.getLeftOp();
      if (leftOp instanceof Local) {
        String storedLocalName = ((Local) leftOp).getName();
        if (redefinedLocalName.compareTo(storedLocalName) == 0) {
          // need to kill this from the list
          // System.out.println("Killing "+tempStmt);
          listIt.remove();
        }
      }
    }
  }

  public List<DefinitionStmt> getReachingDefs(Local local, Object node) {
    ArrayList<DefinitionStmt> toReturn = new ArrayList<DefinitionStmt>();

    // get the reaching defs of this node
    DavaFlowSet<Stmt> beforeSet = null;
    /*
     * If this object is some sort of loop while, for dowhile, unconditional then return after set
     */
    if (node instanceof ASTWhileNode || node instanceof ASTDoWhileNode || node instanceof ASTUnconditionalLoopNode
        || node instanceof ASTForLoopNode) {
      beforeSet = getAfterSet(node);
    } else {
      beforeSet = getBeforeSet(node);
    }

    if (beforeSet == null) {
      throw new RuntimeException("Could not get reaching defs of node");
    }

    // find all reachingdefs matching this local
    for (Object temp : beforeSet) {
      // checking each def to see if it is a def of local
      if (!(temp instanceof DefinitionStmt)) {
        throw new RuntimeException("Not an instanceof DefinitionStmt" + temp);
      }
      DefinitionStmt stmt = (DefinitionStmt) temp;
      Value leftOp = stmt.getLeftOp();
      if (leftOp.toString().compareTo(local.toString()) == 0) {
        toReturn.add(stmt);
      }
    }
    return toReturn;
  }

  public void reachingDefsToString(Object node) {
    // get the reaching defs of this node
    DavaFlowSet<Stmt> beforeSet = null;
    /*
     * If this object is some sort of loop while, for dowhile, unconditional then return after set
     */
    if (node instanceof ASTWhileNode || node instanceof ASTDoWhileNode || node instanceof ASTUnconditionalLoopNode
        || node instanceof ASTForLoopNode) {
      beforeSet = getAfterSet(node);
    } else {
      beforeSet = getBeforeSet(node);
    }

    if (beforeSet == null) {
      throw new RuntimeException("Could not get reaching defs of node");
    }

    // find all reachingdefs matching this local
    for (Object o : beforeSet) {
      System.out.println("Reaching def:" + o);
    }
  }
}

    /*
     * If this path will not be taken return no path straightaway
     */
    if (inSet == NOPATH) {
      return inSet;
    }

    if (s instanceof DefinitionStmt) {
      DavaFlowSet<Stmt> toReturn = cloneFlowSet(inSet);
      // d:x = expr
      // gen is x
      // kill is all previous defs of x

      Value leftOp = ((DefinitionStmt) s).getLeftOp();

      if (leftOp instanceof Local) {
        // KILL any reaching defs of leftOp
        kill(toReturn, (Local) leftOp);
        // GEN
        gen(toReturn, (DefinitionStmt) s);
        return toReturn;
      } // leftop is a local
    }
    return inSet;
  
<methods>public void <init>() ,public abstract DavaFlowSet<soot.jimple.Stmt> cloneFlowSet(DavaFlowSet<soot.jimple.Stmt>) ,public void debug(java.lang.String, java.lang.String) ,public void debug(java.lang.String) ,public abstract DavaFlowSet<soot.jimple.Stmt> emptyFlowSet() ,public DavaFlowSet<soot.jimple.Stmt> getAfterSet(java.lang.Object) ,public DavaFlowSet<soot.jimple.Stmt> getBeforeSet(java.lang.Object) ,public java.lang.String getLabel(soot.dava.internal.AST.ASTNode) ,public DavaFlowSet<soot.jimple.Stmt> handleBreak(java.lang.String, DavaFlowSet<soot.jimple.Stmt>, soot.dava.internal.AST.ASTNode) ,public DavaFlowSet<soot.jimple.Stmt> handleContinue(java.lang.String, DavaFlowSet<soot.jimple.Stmt>, soot.dava.internal.AST.ASTNode) ,public boolean isDifferent(DavaFlowSet<soot.jimple.Stmt>, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> merge(DavaFlowSet<soot.jimple.Stmt>, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> mergeExplicitAndImplicit(java.lang.String, DavaFlowSet<soot.jimple.Stmt>, List<DavaFlowSet<soot.jimple.Stmt>>, List<DavaFlowSet<soot.jimple.Stmt>>) ,public abstract DavaFlowSet<soot.jimple.Stmt> newInitialFlow() ,public void print(java.lang.Object) ,public DavaFlowSet<soot.jimple.Stmt> process(java.lang.Object, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTIfElseNode(soot.dava.internal.AST.ASTIfElseNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTIfNode(soot.dava.internal.AST.ASTIfNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTLabeledBlockNode(soot.dava.internal.AST.ASTLabeledBlockNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTMethodNode(soot.dava.internal.AST.ASTMethodNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTNode(soot.dava.internal.AST.ASTNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTSynchronizedBlockNode(soot.dava.internal.AST.ASTSynchronizedBlockNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTTryNode(soot.dava.internal.AST.ASTTryNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processASTWhileNode(soot.dava.internal.AST.ASTWhileNode, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processAbruptStatements(soot.jimple.Stmt, DavaFlowSet<soot.jimple.Stmt>) ,public DavaFlowSet<soot.jimple.Stmt> processCondition(soot.dava.internal.AST.ASTCondition, DavaFlowSet<soot.jimple.Stmt>) ,public final DavaFlowSet<soot.jimple.Stmt> processSingleSubBodyNode(soot.dava.internal.AST.ASTNode, DavaFlowSet<soot.jimple.Stmt>) ,public abstract DavaFlowSet<soot.jimple.Stmt> processStatement(soot.jimple.Stmt, DavaFlowSet<soot.jimple.Stmt>) ,public abstract DavaFlowSet<soot.jimple.Stmt> processSwitchKey(soot.Value, DavaFlowSet<soot.jimple.Stmt>) ,public abstract DavaFlowSet<soot.jimple.Stmt> processSynchronizedLocal(soot.Local, DavaFlowSet<soot.jimple.Stmt>) ,public abstract DavaFlowSet<soot.jimple.Stmt> processUnaryBinaryCondition(soot.dava.internal.AST.ASTUnaryBinaryCondition, DavaFlowSet<soot.jimple.Stmt>) ,public abstract void setMergeType() <variables>public static boolean DEBUG,public static boolean DEBUG_IF,public static boolean DEBUG_STATEMENTS,public static boolean DEBUG_TRY,public static boolean DEBUG_WHILE,final int INTERSECTION,public int MERGETYPE,DavaFlowSet<soot.jimple.Stmt> NOPATH,final int UNDEFINED,final int UNION,HashMap<java.lang.Object,DavaFlowSet<soot.jimple.Stmt>> afterSets,HashMap<java.lang.Object,DavaFlowSet<soot.jimple.Stmt>> beforeSets