@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 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); }
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(); }
/** * Start the function, puts another body on the function stack. * * @param firstFunctionElement the first state inside the function * @param functionStack the current callstack * @param predecessor the previous node */ protected String startFunction( ARGState firstFunctionElement, Stack<FunctionBody> functionStack, CFANode predecessor) { // create the first stack element using the first element of the function CFunctionEntryNode functionStartNode = extractFunctionCallLocation(firstFunctionElement); String freshFunctionName = getFreshFunctionName(functionStartNode); String lFunctionHeader = functionStartNode.getFunctionDefinition().getType().toASTString(freshFunctionName); // lFunctionHeader is for example "void foo_99(int a)" // create a new function FunctionBody newFunction = new FunctionBody(firstFunctionElement.getStateId(), lFunctionHeader); // register function mFunctionDecls.add(lFunctionHeader + ";"); mFunctionBodies.add(newFunction); functionStack.push(newFunction); // add function to current stack return freshFunctionName; }
private Collection<Edge> handleEdge( Edge nextEdge, Map<Integer, MergeNode> mergeNodes, Set<ARGState> elementsOnPath, EdgeVisitor callback) { ARGState childElement = nextEdge.getChildState(); CFAEdge edge = nextEdge.getEdge(); Stack<FunctionBody> functionStack = nextEdge.getStack(); // clone stack to have a different representation of the function calls and conditions // for every element functionStack = cloneStack(functionStack); // we do not have a single edge, instead a dynamic multi-edge if (edge == null) { List<CFAEdge> edges = nextEdge.getParentState().getEdgesToChild(childElement); for (CFAEdge inner : edges) { callback.visit(childElement, inner, functionStack); } } else { callback.visit(childElement, edge, functionStack); } // how many parents does the child have? // ignore parents not on the error path int noOfParents = from(childElement.getParents()).filter(in(elementsOnPath)).size(); assert noOfParents >= 1; // handle merging if necessary if (noOfParents > 1) { assert !((edge instanceof CFunctionCallEdge) || (childElement.isTarget())); // this is the end of a condition, determine whether we should continue or backtrack int elemId = childElement.getStateId(); FunctionBody currentFunction = functionStack.peek(); currentFunction.write("goto label_" + elemId + ";"); // get the merge node for that node MergeNode mergeNode = mergeNodes.get(elemId); // if null create new and put in the map if (mergeNode == null) { mergeNode = new MergeNode(elemId); mergeNodes.put(elemId, mergeNode); } // this tells us the number of edges (entering that node) processed so far int noOfProcessedBranches = mergeNode.addBranch(currentFunction); // if all edges are processed if (noOfParents == noOfProcessedBranches) { // all branches are processed, now decide which nodes to remove from the stack List<FunctionBody> incomingStacks = mergeNode.getIncomingStates(); FunctionBody newFunction = processIncomingStacks(incomingStacks); // replace the current function body with the right one functionStack.pop(); functionStack.push(newFunction); newFunction.write("label_" + elemId + ": ;"); } else { return Collections.emptySet(); } } return getRelevantChildrenOfState(childElement, functionStack, elementsOnPath); }