Esempio n. 1
0
  private Collection<Edge> getRelevantChildrenOfState(
      ARGState currentElement, Stack<FunctionBody> functionStack, Set<ARGState> elementsOnPath) {
    // find the next elements to add to the waitlist

    List<ARGState> relevantChildrenOfElement =
        from(currentElement.getChildren()).filter(in(elementsOnPath)).toList();
    relevantChildrenOfElement = chooseIfArbitrary(currentElement, relevantChildrenOfElement);

    // if there is only one child on the path
    if (relevantChildrenOfElement.size() == 1) {
      // get the next ARG state, create a new edge using the same stack and add it to the waitlist
      ARGState elem = Iterables.getOnlyElement(relevantChildrenOfElement);
      CFAEdge e = currentElement.getEdgeToChild(elem);
      Edge newEdge = new Edge(elem, currentElement, e, functionStack);
      return Collections.singleton(newEdge);

    } else if (relevantChildrenOfElement.size() > 1) {
      // if there are more than one relevant child, then this is a condition
      // we need to update the stack
      assert relevantChildrenOfElement.size() == 2;
      Collection<Edge> result = new ArrayList<>(2);
      int ind = 0;
      for (ARGState elem : relevantChildrenOfElement) {
        Stack<FunctionBody> newStack = cloneStack(functionStack);
        CFAEdge e = currentElement.getEdgeToChild(elem);
        FunctionBody currentFunction = newStack.peek();
        assert e instanceof CAssumeEdge;
        CAssumeEdge assumeEdge = (CAssumeEdge) e;
        boolean truthAssumption = assumeEdge.getTruthAssumption();

        String cond = "";

        if (ind == 0) {
          cond = "if ";
        } else if (ind == 1) {
          cond = "else if ";
        } else {
          throw new AssertionError();
        }
        ind++;

        if (truthAssumption) {
          cond += "(" + assumeEdge.getExpression().toASTString() + ")";
        } else {
          cond += "(!(" + assumeEdge.getExpression().toASTString() + "))";
        }

        // create a new block starting with this condition
        currentFunction.enterBlock(currentElement.getStateId(), assumeEdge, cond);

        Edge newEdge = new Edge(elem, currentElement, e, newStack);
        result.add(newEdge);
      }
      return result;
    }
    return Collections.emptyList();
  }
    @Override
    public ARGPath getNextPathForInterpolation() {
      ARGState current = sources.remove(0);

      assert current.isTarget() : "current element is not a target";

      ARGPathBuilder errorPathBuilder = ARGPath.reverseBuilder();

      errorPathBuilder.add(
          current, FluentIterable.from(AbstractStates.getOutgoingEdges(current)).first().orNull());

      while (predecessorRelation.get(current) != null) {

        ARGState parent = predecessorRelation.get(current);

        if (stateHasFalseInterpolant(parent)) {
          logger.log(
              Level.FINEST,
              "interpolant on path, namely for state ",
              parent.getStateId(),
              " is already false, so return empty path");
          return EMPTY_PATH;
        }

        if (predecessorRelation.get(parent) != null) {
          errorPathBuilder.add(parent, parent.getEdgeToChild(current));
        }

        current = parent;
      }

      return errorPathBuilder.build(current);
    }
    @Override
    public ARGPath getNextPathForInterpolation() {
      ARGPathBuilder errorPathBuilder = ARGPath.builder();

      ARGState current = sources.pop();

      if (!isValidInterpolationRoot(predecessorRelation.get(current))) {
        logger.log(
            Level.FINEST,
            "interpolant of predecessor of ",
            current.getStateId(),
            " is already false, so return empty path");
        return EMPTY_PATH;
      }

      // if the current state is not the root, it is a child of a branch , however, the path should
      // not start with the
      // child, but with the branching node (children are stored on the stack because this needs
      // less book-keeping)
      if (current != root) {
        errorPathBuilder.add(
            predecessorRelation.get(current),
            predecessorRelation.get(current).getEdgeToChild(current));
      }

      while (successorRelation.get(current).iterator().hasNext()) {
        Iterator<ARGState> children = successorRelation.get(current).iterator();
        ARGState child = children.next();
        errorPathBuilder.add(current, current.getEdgeToChild(child));

        // push all other children of the current state, if any, onto the stack for later
        // interpolations
        int size = 1;
        while (children.hasNext()) {
          size++;
          ARGState sibling = children.next();
          logger.log(
              Level.FINEST,
              "\tpush new root ",
              sibling.getStateId(),
              " onto stack for parent ",
              predecessorRelation.get(sibling).getStateId());
          sources.push(sibling);
        }
        assert (size <= 2);

        current = child;
      }

      return errorPathBuilder.build(current);
    }
 @Override
 public boolean apply(ARGState pChild) {
   return pChild != null && predecessor.getEdgeToChild(pChild) == edge;
 }
    private List<BooleanFormula> computeBlockFormulas(final ARGState pRoot)
        throws CPATransferException, InterruptedException {

      final Map<ARGState, ARGState> callStacks =
          new HashMap<>(); // contains states and their next higher callstate
      final Map<ARGState, PathFormula> finishedFormulas = new HashMap<>();
      final List<BooleanFormula> abstractionFormulas = new ArrayList<>();
      final Deque<ARGState> waitlist = new ArrayDeque<>();

      // initialize
      assert pRoot.getParents().isEmpty() : "rootState must be the first state of the program";
      callStacks.put(pRoot, null); // main-start has no callstack
      finishedFormulas.put(pRoot, pfmgr.makeEmptyPathFormula());
      waitlist.addAll(pRoot.getChildren());

      // iterate over all elements in the ARG with BFS
      while (!waitlist.isEmpty()) {
        final ARGState currentState = waitlist.pollFirst();
        if (finishedFormulas.containsKey(currentState)) {
          continue; // already handled
        }

        if (!finishedFormulas.keySet().containsAll(currentState.getParents())) {
          // parent not handled yet, re-queue current element and wait for all parents
          waitlist.addLast(currentState);
          continue;
        }

        // collect formulas for current location
        final List<PathFormula> currentFormulas = new ArrayList<>(currentState.getParents().size());
        final List<ARGState> currentStacks = new ArrayList<>(currentState.getParents().size());
        for (ARGState parentElement : currentState.getParents()) {
          PathFormula parentFormula = finishedFormulas.get(parentElement);
          final CFAEdge edge = parentElement.getEdgeToChild(currentState);
          assert edge != null : "ARG is invalid: parent has no edge to child";

          final ARGState prevCallState;
          // we enter a function, so lets add the previous state to the stack
          if (edge.getEdgeType() == CFAEdgeType.FunctionCallEdge) {
            prevCallState = parentElement;

          } else if (edge.getEdgeType() == CFAEdgeType.FunctionReturnEdge) {
            // we leave a function, so rebuild return-state before assigning the return-value.
            // rebuild states with info from previous state
            assert callStacks.containsKey(parentElement);
            final ARGState callState = callStacks.get(parentElement);

            assert extractLocation(callState).getLeavingSummaryEdge().getSuccessor()
                    == extractLocation(currentState)
                : "callstack does not match entry of current function-exit.";
            assert callState != null || currentState.getChildren().isEmpty()
                : "returning from empty callstack is only possible at program-exit";

            prevCallState = callStacks.get(callState);
            parentFormula =
                rebuildStateAfterFunctionCall(
                    parentFormula,
                    finishedFormulas.get(callState),
                    (FunctionExitNode) extractLocation(parentElement));

          } else {
            assert callStacks.containsKey(parentElement); // check for null is not enough
            prevCallState = callStacks.get(parentElement);
          }

          final PathFormula currentFormula = pfmgr.makeAnd(parentFormula, edge);
          currentFormulas.add(currentFormula);
          currentStacks.add(prevCallState);
        }

        assert currentFormulas.size() >= 1 : "each state except root must have parents";
        assert currentStacks.size() == currentFormulas.size()
            : "number of callstacks must match predecessors";

        // merging after functioncall with different callstates is ugly.
        // this is also guaranteed by the abstraction-locations at function-entries
        // (--> no merge of states with different latest abstractions).
        assert Sets.newHashSet(currentStacks).size() <= 1
            : "function with multiple entry-states not supported";

        callStacks.put(currentState, currentStacks.get(0));

        PathFormula currentFormula;
        final PredicateAbstractState predicateElement =
            extractStateByType(currentState, PredicateAbstractState.class);
        if (predicateElement.isAbstractionState()) {
          // abstraction element is the start of a new part of the ARG

          assert waitlist.isEmpty() : "todo should be empty, because of the special ARG structure";
          assert currentState.getParents().size() == 1
              : "there should be only one parent, because of the special ARG structure";

          // finishedFormulas.clear(); // free some memory
          // TODO disabled, we need to keep callStates for later usage

          // start new block with empty formula
          currentFormula = getOnlyElement(currentFormulas);
          abstractionFormulas.add(currentFormula.getFormula());
          currentFormula = pfmgr.makeEmptyPathFormula(currentFormula);

        } else {
          // merge the formulas
          Iterator<PathFormula> it = currentFormulas.iterator();
          currentFormula = it.next();
          while (it.hasNext()) {
            currentFormula = pfmgr.makeOr(currentFormula, it.next());
          }
        }

        assert !finishedFormulas.containsKey(currentState) : "a state should only be finished once";
        finishedFormulas.put(currentState, currentFormula);
        waitlist.addAll(currentState.getChildren());
      }
      return abstractionFormulas;
    }