private static void printDetails(CGNode method, ExplodedControlFlowGraph cfg, FlowGraph pruned) {
    int deletedEdges = 0;
    int originalEdges = 0;
    for (IExplodedBasicBlock node : cfg) {
      originalEdges += cfg.getSuccNodeCount(node);

      Iterator<IExplodedBasicBlock> it = cfg.getSuccNodes(node);

      int srcNum = node.getNumber();
      while (it.hasNext()) {
        IExplodedBasicBlock dst = it.next();
        int dstNum = dst.getNumber();
        if (pruned.hasEdge(srcNum, dstNum)) {
          deletedEdges++;
        }
      }
    }

    DecimalFormat df = new DecimalFormat("00.00");

    double percent = ((double) deletedEdges / (double) originalEdges) * 100.0;
    Log.info(
        "EXC: "
            + df.format(percent)
            + "% - edges: "
            + originalEdges
            + " deleted: "
            + deletedEdges
            + " - "
            + edu.kit.joana.deprecated.jsdg.util.Util.methodName(method.getMethod()));
  }
    /** flow function for normal intraprocedural edges */
    public IUnaryFlowFunction getNormalFlowFunction(
        final BasicBlockInContext<IExplodedBasicBlock> src,
        BasicBlockInContext<IExplodedBasicBlock> dest) {
      final IExplodedBasicBlock ebb = src.getDelegate();
      SSAInstruction instruction = ebb.getInstruction();

      if (instruction instanceof SSAPutInstruction) {
        final SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
        if (putInstr.isStatic()) {
          return new IUnaryFlowFunction() {

            public IntSet getTargets(int d1) {
              // first, gen this statement
              int factNum =
                  domain.getMappedIndex(Pair.make(src.getNode(), ebb.getFirstInstructionIndex()));
              assert factNum != -1;
              MutableSparseIntSet result = MutableSparseIntSet.makeEmpty();
              result.add(factNum);
              // if incoming statement is some different statement that defs the same static field,
              // kill it; otherwise, keep it
              if (d1 != factNum) {
                IField staticField = cha.resolveField(putInstr.getDeclaredField());
                assert staticField != null;
                Pair<CGNode, Integer> otherPutInstrAndNode = domain.getMappedObject(d1);
                SSAPutInstruction otherPutInstr =
                    (SSAPutInstruction)
                        otherPutInstrAndNode.fst.getIR()
                            .getInstructions()[otherPutInstrAndNode.snd];
                IField otherStaticField = cha.resolveField(otherPutInstr.getDeclaredField());
                if (!staticField.equals(otherStaticField)) {
                  result.add(d1);
                }
              }
              return result;
            }

            public String toString() {
              return "Reaching Defs Normal Flow";
            }
          };
        }
      }
      // identity function when src block isn't for a putstatic
      return IdentityFlowFunction.identity();
    }
 /**
  * collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the
  * analysis
  */
 private Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> collectInitialSeeds() {
   Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> result = HashSetFactory.make();
   for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) {
     IExplodedBasicBlock ebb = bb.getDelegate();
     SSAInstruction instruction = ebb.getInstruction();
     if (instruction instanceof SSAPutInstruction) {
       SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
       if (putInstr.isStatic()) {
         final CGNode cgNode = bb.getNode();
         Pair<CGNode, Integer> fact = Pair.make(cgNode, ebb.getFirstInstructionIndex());
         int factNum = domain.add(fact);
         BasicBlockInContext<IExplodedBasicBlock> fakeEntry = getFakeEntry(cgNode);
         // note that the fact number used for the source of this path edge doesn't really matter
         result.add(PathEdge.createPathEdge(fakeEntry, factNum, bb, factNum));
       }
     }
   }
   return result;
 }
  public AbstractPDGNode getMainPDGNode(IExplodedBasicBlock bb) {
    AbstractPDGNode pdgnode = null;

    SSAInstruction instr = bb.getInstruction();
    if (instr == null) {
      return null;
    }

    List<AbstractPDGNode> nodes = pdg.getNodesForInstruction(instr);
    if (nodes == null || nodes.isEmpty()) {
      return null;
    }

    // the first element of the node list is per convention always the
    // main node concerning the instruction
    pdgnode = nodes.get(0);

    return pdgnode;
  }
 public boolean hasNormalEdge(IExplodedBasicBlock src, IExplodedBasicBlock dst) {
   return finalGraph.hasEdge(src.getNumber(), dst.getNumber());
 }
  private void createFirstAndLastNodes(IExplodedBasicBlock block) {
    final SSAInstruction instr = block.getInstruction();

    if (block == ecfg.entry()) {
      assert (entry == null);

      CFGNode cfgNode = createNode(block);

      Set<CFGNode> first = HashSetFactory.make(1);
      first.add(cfgNode);
      firstNodes.put(block, first);

      entry = cfgNode;

      Set<? extends AbstractParameterNode> after = getAllHeapLocatedFormIns();

      CFGNode current = cfgNode;
      for (AbstractParameterNode p : after) {
        CFGNode param = findOrCreateNode(block, p);
        cfg.addEdge(current, param);
        current = param;
        numberOfParameterNodes++;
      }

      if (instr != null) {
        AbstractPDGNode node = pdg.getMainNodeForInstruction(instr);
        if (node != null) {
          CFGNode artificialNode = createArtificialNode(block, node);
          cfg.addEdge(current, artificialNode);
          current = artificialNode;
        }
      }

      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(current);
      lastNodes.put(block, last);
    } else if (block == ecfg.exit()) {
      assert (exit == null);

      CFGNode cfgNode = createNode(block);

      Set<AbstractParameterNode> before = getAllHeapLocatedFormOuts();
      if (!pdg.isIgnoreExceptions() && pdg.getExceptionalExit() != null) {
        before.add(pdg.getExceptionalExit());
      }

      if (before.isEmpty()) {
        Set<CFGNode> first = HashSetFactory.make(1);
        first.add(cfgNode);
        firstNodes.put(block, first);
      } else {
        CFGNode current = null;
        for (AbstractParameterNode p : before) {
          CFGNode param = findOrCreateNode(block, p);
          if (current == null) {
            Set<CFGNode> first = HashSetFactory.make(1);
            first.add(param);
            firstNodes.put(block, first);
          } else {
            cfg.addEdge(current, param);
          }
          current = param;
          numberOfParameterNodes++;
        }

        cfg.addEdge(current, cfgNode);
      }

      exit = cfgNode;

      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(cfgNode);
      lastNodes.put(block, last);
    } else if (block.isCatchBlock() && instr != null) {
      // special case where a single cfg node corresponds to 2 statements...

      CFGNode cfgNode = createNode(block);
      Set<CFGNode> first = HashSetFactory.make(1);
      first.add(cfgNode);
      firstNodes.put(block, first);
      AbstractPDGNode pdgNode = pdg.getMainNodeForInstruction(instr);
      CFGNode lastNode = createArtificialNode(block, pdgNode);
      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(lastNode);
      lastNodes.put(block, last);
      cfg.addEdge(cfgNode, lastNode);

      List<AbstractPDGNode> nodes = pdg.getNodesForInstruction(instr);
      for (AbstractPDGNode node : nodes) {
        if (node instanceof ExpressionNode) {
          sdg2cfg.put((ExpressionNode) node, lastNode);
        }
      }
    } else if (instr instanceof SSAInvokeInstruction) {
      // method call found - add actual in nodes before and actual-out
      // nodes after the call
      Set<CFGNode> first = HashSetFactory.make();
      Set<CFGNode> last = HashSetFactory.make();

      Set<CallNode> calls = getCallsForInstruction((SSAInvokeInstruction) instr);

      CFGNode compoundCallNode = null;
      if (calls.size() > 1) {
        compoundCallNode = createNode(block);
        first.add(compoundCallNode);
      }

      for (CallNode call : calls) {
        CFGNode cfgNode = createNode(block, call);

        Set<? extends AbstractParameterNode> actIns = getAllHeapLocatedActualIns(call);
        numberOfParameterNodes += actIns.size();

        if (actIns.size() == 0) {
          if (compoundCallNode == null) {
            first.add(cfgNode);
          } else {
            cfg.addEdge(compoundCallNode, cfgNode);
          }
        } else {
          CFGNode current = null;
          for (AbstractParameterNode p : actIns) {
            CFGNode param = findOrCreateNode(block, p);
            if (current == null) {
              if (compoundCallNode == null) {
                first.add(param);
              } else {
                cfg.addEdge(compoundCallNode, param);
              }
            } else {
              cfg.addEdge(current, param);
            }

            current = param;
          }

          cfg.addEdge(current, cfgNode);
        }

        Set<? extends AbstractParameterNode> actOuts = getAllHeapLocatedActualOuts(call);
        numberOfParameterNodes += actOuts.size();

        CFGNode current = cfgNode;
        for (AbstractParameterNode p : actOuts) {
          CFGNode param = findOrCreateNode(block, p);
          cfg.addEdge(current, param);
          current = param;
        }
        last.add(current);
      }

      firstNodes.put(block, first);
      lastNodes.put(block, last);
    } else {
      CFGNode cfgNode = createNode(block);

      AbstractPDGNode node = null;
      if (instr != null) {
        node = pdg.getMainNodeForInstruction(instr);
      }

      if (node instanceof ExpressionNode) {
        ExpressionNode expr = (ExpressionNode) node;

        sdg2cfg.put((ExpressionNode) node, cfgNode);

        if (expr.isFieldAccess() || expr.isArrayAccess()) {
          Set<CFGNode> first = HashSetFactory.make(1);
          Set<CFGNode> last = HashSetFactory.make(1);
          last.add(cfgNode);

          CFGNode pred = null;

          if (!expr.isStaticFieldAccess()) {
            CFGNode baseCfg = createArtificialNode(block, expr.getBaseValue());
            first.add(baseCfg);
            pred = baseCfg;
          }

          if (expr.isArrayAccess()) {
            CFGNode indexCfg = createArtificialNode(block, expr.getIndexValue());
            if (pred != null) {
              cfg.addEdge(pred, indexCfg);
            } else {
              first.add(indexCfg);
            }
            pred = indexCfg;
          }

          if (expr.isGet()) {
            CFGNode fieldCfg = createArtificialNode(block, expr.getFieldValue());
            if (pred != null) {
              cfg.addEdge(pred, fieldCfg);
            } else {
              first.add(fieldCfg);
            }
            pred = fieldCfg;
          }

          if (expr.isSet()) {
            CFGNode valCfg = createArtificialNode(block, expr.getSetValue());
            if (pred != null) {
              cfg.addEdge(pred, valCfg);
            } else {
              first.add(valCfg);
            }
            pred = valCfg;
          }

          if (pred != null) {
            cfg.addEdge(pred, cfgNode);
          } else {
            first.add(cfgNode);
          }

          firstNodes.put(block, first);
          lastNodes.put(block, last);
        } else {
          Set<CFGNode> firstAndLast = HashSetFactory.make(1);
          firstAndLast.add(cfgNode);
          firstNodes.put(block, firstAndLast);
          lastNodes.put(block, firstAndLast);
        }
      } else {
        Set<CFGNode> firstAndLast = HashSetFactory.make(1);
        firstAndLast.add(cfgNode);
        firstNodes.put(block, firstAndLast);
        lastNodes.put(block, firstAndLast);
      }
    }
  }