private static boolean isReturnVar(String var, FunctionExitNode functionExitNode) { return functionExitNode.getEntryNode().getReturnVariable().isPresent() && functionExitNode.getEntryNode().getReturnVariable().get().getQualifiedName().equals(var); }
@Override public AbstractState rebuildStateAfterFunctionCall( AbstractState pRootState, AbstractState pEntryState, AbstractState pExpandedState, FunctionExitNode exitLocation) { final PredicateAbstractState rootState = (PredicateAbstractState) pRootState; final PredicateAbstractState entryState = (PredicateAbstractState) pEntryState; final PredicateAbstractState expandedState = (PredicateAbstractState) pExpandedState; final PersistentMap<CFANode, Integer> abstractionLocations = expandedState.getAbstractionLocationsOnPath(); // TODO why did I copy the next if-statement? when is it used? if (!expandedState.isAbstractionState()) { return expandedState; } // we have: // - abstraction of rootState with ssa --> use as it is // - callEdge-pathFormula with ssa (from rootState) --> use as it is, with updated SSAMap // - abstraction of functioncall (expandedSSA) --> instantiate, with updated SSAMap, so // that: // - only param and return-var overlap to callEdge // - all other vars are distinct final String calledFunction = exitLocation.getFunctionName(); final PathFormula functionCall = entryState.getAbstractionFormula().getBlockFormula(); final SSAMap entrySsaWithRet = functionCall.getSsa(); final SSAMapBuilder entrySsaWithRetBuilder = entrySsaWithRet.builder(); final SSAMapBuilder summSsa = rootState.getAbstractionFormula().getBlockFormula().getSsa().builder(); final SSAMap expandedSSA = expandedState.getAbstractionFormula().getBlockFormula().getSsa(); for (String var : expandedSSA.allVariables()) { final CType type = expandedSSA.getType(var); if (var.startsWith(calledFunction + "::") && var.endsWith(PARAM_VARIABLE_NAME)) { int newIndex = entrySsaWithRet.getIndex(var); assert entrySsaWithRet.containsVariable(var) : "param for function is not used in functioncall"; entrySsaWithRetBuilder.setIndex(var, type, newIndex); setFreshValueBasis(summSsa, var, newIndex); } else if (exitLocation.getEntryNode().getReturnVariable().isPresent() && exitLocation.getEntryNode().getReturnVariable().get().getQualifiedName().equals(var)) { // var.startsWith(calledFunction + "::") && var.endsWith(RETURN_VARIABLE_NAME) final int newIndex = Math.max(expandedSSA.getIndex(var), entrySsaWithRetBuilder.getFreshIndex(var)); entrySsaWithRetBuilder.setIndex(var, type, newIndex); summSsa.setIndex(var, type, newIndex); } else if (!entrySsaWithRet.containsVariable(var)) { // non-existent index for variable only used in functioncall, just copy final int newIndex = expandedSSA.getIndex(var); entrySsaWithRetBuilder.setIndex(var, type, newIndex); summSsa.setIndex(var, type, newIndex); } else { final int newIndex = entrySsaWithRetBuilder.getFreshIndex(var); entrySsaWithRetBuilder.setIndex(var, type, newIndex); setFreshValueBasis(summSsa, var, newIndex); } } final SSAMap newEntrySsaWithRet = entrySsaWithRetBuilder.build(); final SSAMap newSummSsa = summSsa.build(); // function-call needs have new retvars-indices. PathFormula functionCallWithSSA = new PathFormula( functionCall.getFormula(), newEntrySsaWithRet, functionCall.getPointerTargetSet(), functionCall.getLength()); // concat function-call with function-summary, // function-summary will be instantiated with indices for params and retvars. PathFormula executedFunction = pmgr.makeAnd(functionCallWithSSA, expandedState.getAbstractionFormula().asFormula()); // after function-execution we have to re-use the previous indices (fromouter scope), // thus lets change the SSAmap. PathFormula executedFunctionWithSSA = new PathFormula( executedFunction.getFormula(), newSummSsa, executedFunction.getPointerTargetSet(), executedFunction.getLength()); // everything is prepared, so build a new AbstractionState. // we do this as 'future abstraction', because we do not have enough information // (necessary classes and managers) for the abstraction-process at this place. PredicateAbstractState rebuildState = new PredicateAbstractState.ComputeAbstractionState( executedFunctionWithSSA, rootState.getAbstractionFormula(), exitLocation, abstractionLocations); logger.log( Level.ALL, "\noldAbs: ", rootState.getAbstractionFormula().asInstantiatedFormula(), "\ncall: ", functionCallWithSSA, "\nsumm: ", expandedState.getAbstractionFormula().asFormula(), "\nexe: ", executedFunction, "\nentrySsaRet", newEntrySsaWithRet, "\nsummSsaRet", newSummSsa); return rebuildState; }