/// <summary> /// Removes the nodes added to the new try construct from the orderedCFGNodes collection. /// </summary> /// <param name="theNewTryConstruct"></param> private void CleanUpOrderedNodes(TryFinallyLogicalConstruct theNewTryConstruct) { foreach (CFGBlockLogicalConstruct cfgChild in theNewTryConstruct.CFGBlocks) { orderedCFGNodes.Remove(cfgChild); } }
private void GenerateTryFinallyHandler(YieldExceptionHandlerInfo handlerInfo) { this.finallyBlocks = new HashSet <ILogicalConstruct>(); this.entryOfTry = this.GetStateBeginBlockConstruct(handlerInfo.get_TryStates()); this.BuildTryBody(handlerInfo); if (handlerInfo.get_HandlerType() != YieldExceptionHandlerType.Method) { V_0 = this.GenerateFinallyBlock(); } else { if (this.newFinallyBody == null) { throw new Exception("Could not determine the end ot the try block"); } this.RemoveExcessNodesFromTheTryBlock(); this.ProcessFinallyNodes(); stackVariable31 = this.newFinallyBody; stackVariable33 = new ILogicalConstruct[1]; stackVariable33[0] = this.newFinallyBody; V_0 = new BlockLogicalConstruct(stackVariable31, stackVariable33); } V_1 = new TryFinallyLogicalConstruct(new BlockLogicalConstruct(this.entryOfTry, this.newTryBody), V_0); this.createdConstructsToIntervalMap.set_Item(V_1, handlerInfo); this.CleanUpOrderedNodes(V_1); return; }
/// <summary> /// Generates the try/finally construct that is represented by the specifed exception handler info and attaches it to the logical tree. /// </summary> /// <param name="handlerInfo"></param> private void GenerateTryFinallyHandler(YieldExceptionHandlerInfo handlerInfo) { finallyBlocks = new HashSet <ILogicalConstruct>(); entryOfTry = GetStateBeginBlockConstruct(handlerInfo.TryStates); BuildTryBody(handlerInfo); BlockLogicalConstruct newFinally; if (handlerInfo.HandlerType == YieldExceptionHandlerType.Method) { if (newFinallyBody == null) { throw new Exception("Could not determine the end ot the try block"); } RemoveExcessNodesFromTheTryBlock(); ProcessFinallyNodes(); newFinally = new BlockLogicalConstruct(newFinallyBody, new ILogicalConstruct[] { newFinallyBody }); } else { newFinally = GenerateFinallyBlock(); } BlockLogicalConstruct newTry = new BlockLogicalConstruct(entryOfTry, newTryBody); TryFinallyLogicalConstruct newTryFinallyConstruct = new TryFinallyLogicalConstruct(newTry, newFinally); createdConstructsToIntervalMap[newTryFinallyConstruct] = handlerInfo; CleanUpOrderedNodes(newTryFinallyConstruct); }
private void CleanUpOrderedNodes(TryFinallyLogicalConstruct theNewTryConstruct) { V_0 = theNewTryConstruct.get_CFGBlocks().GetEnumerator(); try { while (V_0.MoveNext()) { V_1 = V_0.get_Current(); dummyVar0 = this.orderedCFGNodes.Remove(V_1); } } finally { ((IDisposable)V_0).Dispose(); } return; }
/// <summary> /// Checks each a node before adding its successors to the <paramref name="bfsQueue"/>. /// </summary> /// <remarks> /// If the node is a CFGBlockLC and it contains the invocation of the finally method, or the entry of the finally block, /// then we should not continue the traversal. /// </remarks> /// <param name="handlerInfo"></param> /// <param name="bfsQueue"></param> /// <param name="currentNode"></param> private void ProcessCurrentNode(YieldExceptionHandlerInfo handlerInfo, Queue <ILogicalConstruct> bfsQueue, ILogicalConstruct currentNode) { if (currentNode is CFGBlockLogicalConstruct) { CFGBlockLogicalConstruct currentCFGNode = currentNode as CFGBlockLogicalConstruct; for (int i = 0; i < currentCFGNode.LogicalConstructExpressions.Count; i++) { Expression currentExpression = currentCFGNode.LogicalConstructExpressions[i]; int value; if (TryGetStateAssignValue(currentExpression, out value)) { if (!handlerInfo.TryStates.Contains(value)) //sanity check { if (handlerInfo.HandlerType != YieldExceptionHandlerType.Method && TryProcessConditionalDisposeHandler(handlerInfo, currentCFGNode)) { return; } throw new Exception("Invalid state value"); } } else if (handlerInfo.HandlerType == YieldExceptionHandlerType.Method && currentExpression.CodeNodeType == CodeNodeType.MethodInvocationExpression && (currentExpression as MethodInvocationExpression).MethodExpression.MethodDefinition == handlerInfo.FinallyMethodDefinition) { //For the finally block we need the CFGBlockLC that contains only the invocation of the finally method. //That's why we need to split the CFGBlockLC, if there are other expressions besides the invocation. CFGBlockLogicalConstruct currentFinallyBlock; if (currentCFGNode.LogicalConstructExpressions.Count == 1) { if (newFinallyBody == null) { newFinallyBody = currentCFGNode; } finallyBlocks.Add(newFinallyBody); orderedCFGNodes.Remove(currentCFGNode); return; } if (i == 0) { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> newConstructsPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i + 1); currentFinallyBlock = newConstructsPair.Key; orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = newConstructsPair.Value; } else if (i < currentCFGNode.LogicalConstructExpressions.Count - 1) { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> endOfTryPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i); newTryBody.Add(endOfTryPair.Key); KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> finallyRestOfBlockPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, endOfTryPair.Value, 1); currentFinallyBlock = finallyRestOfBlockPair.Key; orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = finallyRestOfBlockPair.Value; } else // i == count - 1 { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> tryFinallyPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i); newTryBody.Add(tryFinallyPair.Key); currentFinallyBlock = tryFinallyPair.Value; orderedCFGNodes.Remove(currentCFGNode); } if (newFinallyBody == null) { newFinallyBody = currentFinallyBlock; } finallyBlocks.Add(currentFinallyBlock); return; } } } else if (currentNode is TryFinallyLogicalConstruct) { TryFinallyLogicalConstruct tryFinallyConstruct = currentNode as TryFinallyLogicalConstruct; YieldExceptionHandlerInfo oldHandlerInfo; if (createdConstructsToIntervalMap.TryGetValue(tryFinallyConstruct, out oldHandlerInfo) && oldHandlerInfo.TryStates.IsProperSupersetOf(handlerInfo.TryStates)) { throw new Exception("This try/finally construct cannot be nested in the current construct"); } } newTryBody.Add(currentNode); foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors) { bfsQueue.Enqueue(successor); } }