/// <summary>
        /// Builds the try body of the specified exception handler starting from the given entry node.
        /// </summary>
        /// <remarks>
        /// We assume that all nodes before reaching the finally block are in the try construct.
        /// </remarks>
        /// <param name="handlerInfo"></param>
        /// <param name="entryOfTry"></param>
        private void BuildTryBody(YieldExceptionHandlerInfo handlerInfo)
        {
            newTryBody = new HashSet <ILogicalConstruct>();
            newTryBody.Add(entryOfTry);
            newFinallyBody = null;

            HashSet <ILogicalConstruct> traversedNodes = new HashSet <ILogicalConstruct>();
            Queue <ILogicalConstruct>   bfsQueue       = new Queue <ILogicalConstruct>();

            foreach (ILogicalConstruct successor in entryOfTry.SameParentSuccessors)
            {
                bfsQueue.Enqueue(successor);
            }

            while (bfsQueue.Count > 0)
            {
                ILogicalConstruct currentNode = bfsQueue.Dequeue();
                if (!traversedNodes.Add(currentNode) || finallyBlocks.Contains(currentNode))
                {
                    continue;
                }

                ProcessCurrentNode(handlerInfo, bfsQueue, currentNode);
            }
        }
 private void BuildTryBody(YieldExceptionHandlerInfo handlerInfo)
 {
     this.newTryBody     = new HashSet <ILogicalConstruct>();
     dummyVar0           = this.newTryBody.Add(this.entryOfTry);
     this.newFinallyBody = null;
     V_0 = new HashSet <ILogicalConstruct>();
     V_1 = new Queue <ILogicalConstruct>();
     V_2 = this.entryOfTry.get_SameParentSuccessors().GetEnumerator();
     try
     {
         while (V_2.MoveNext())
         {
             V_3 = (ILogicalConstruct)V_2.get_Current();
             V_1.Enqueue(V_3);
         }
     }
     finally
     {
         ((IDisposable)V_2).Dispose();
     }
     while (V_1.get_Count() > 0)
     {
         V_4 = V_1.Dequeue();
         if (!V_0.Add(V_4) || this.finallyBlocks.Contains(V_4))
         {
             continue;
         }
         this.ProcessCurrentNode(handlerInfo, V_1, V_4);
     }
     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 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>
        /// Determines whether or not there is a conditional dispose starting from this block.
        /// </summary>
        /// <remarks>
        /// Since the conditional dispose is the same as in the Dispose method, we are trying to find the same pattern.
        /// <code>
        /// this.stateField = nextState;
        /// (this.disposableField = this.enumeratorField as IDisposable;)   -- this might be missing
        /// if(this.disposableField != null)
        /// {
        ///     this.disposableField.Dispose();
        /// }
        /// </code>
        /// </remarks>
        /// <param name="yieldExceptionHandler"></param>
        /// <param name="startBlock"></param>
        /// <returns></returns>
        private bool TryProcessConditionalDisposeHandler(YieldExceptionHandlerInfo yieldExceptionHandler, CFGBlockLogicalConstruct startBlock)
        {
            if (finallyBlocks.Count > 0)
            {
                return(false);
            }

            if (!(startBlock is PartialCFGBlockLogicalConstruct) || startBlock.CFGSuccessors.Count != 1)
            {
                return(false);
            }

            if (startBlock.LogicalConstructExpressions.Count == 0)
            {
                return(false);
            }

            BinaryExpression stateAssignExpression = startBlock.LogicalConstructExpressions[0] as BinaryExpression;

            if (stateAssignExpression == null || !stateAssignExpression.IsAssignmentExpression ||
                stateAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (stateAssignExpression.Left as FieldReferenceExpression).Field.Resolve() != stateFieldRef ||
                stateAssignExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (int)((stateAssignExpression.Right as LiteralExpression).Value) != yieldExceptionHandler.NextState)
            {
                return(false);
            }

            if (startBlock.LogicalConstructExpressions.Count == 2 && yieldExceptionHandler.HandlerType == YieldExceptionHandlerType.ConditionalDispose)
            {
                BinaryExpression disposableAssignExpression = startBlock.LogicalConstructExpressions[1] as BinaryExpression;
                if (disposableAssignExpression == null || !disposableAssignExpression.IsAssignmentExpression ||
                    disposableAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    (disposableAssignExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                    disposableAssignExpression.Right.CodeNodeType != CodeNodeType.SafeCastExpression ||
                    (disposableAssignExpression.Right as SafeCastExpression).Expression.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    ((disposableAssignExpression.Right as SafeCastExpression).Expression as FieldReferenceExpression).Field != yieldExceptionHandler.EnumeratorField)
                {
                    return(false);
                }
            }
            else if (startBlock.LogicalConstructExpressions.Count != 1 || yieldExceptionHandler.HandlerType != YieldExceptionHandlerType.SimpleConditionalDispose)
            {
                return(false);
            }


            CFGBlockLogicalConstruct conditionBlock;
            IEnumerator <CFGBlockLogicalConstruct> enumerator = startBlock.CFGSuccessors.GetEnumerator();

            using (enumerator)
            {
                enumerator.MoveNext();
                conditionBlock = enumerator.Current;
            }

            if (conditionBlock.LogicalConstructExpressions.Count != 1)
            {
                return(false);
            }

            BinaryExpression isNullCheckExpression = conditionBlock.LogicalConstructExpressions[0] as BinaryExpression;

            if (isNullCheckExpression == null || isNullCheckExpression.Operator != BinaryOperator.ValueEquality ||
                isNullCheckExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (isNullCheckExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                isNullCheckExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (isNullCheckExpression.Right as LiteralExpression).Value != null)
            {
                return(false);
            }

            CFGBlockLogicalConstruct disposeCallBlock = null;

            foreach (ILogicalConstruct successor in conditionBlock.CFGSuccessors)
            {
                CFGBlockLogicalConstruct cfgSuccessor = successor as CFGBlockLogicalConstruct;
                if (cfgSuccessor != null && cfgSuccessor.CFGPredecessors.Count == 1)
                {
                    disposeCallBlock = cfgSuccessor;
                    break;
                }
            }

            if (disposeCallBlock == null || disposeCallBlock.LogicalConstructExpressions.Count != 1)
            {
                return(false);
            }

            MethodInvocationExpression disposeMethodInvocation = disposeCallBlock.LogicalConstructExpressions[0] as MethodInvocationExpression;

            if (disposeMethodInvocation == null || !disposeMethodInvocation.VirtualCall ||
                disposeMethodInvocation.MethodExpression.Target.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (disposeMethodInvocation.MethodExpression.Target as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                disposeMethodInvocation.MethodExpression.Method.Name != "Dispose")
            {
                return(false);
            }

            this.finallyEntryBlock = startBlock;
            finallyBlocks.Add(startBlock);

            this.conditionBlock = conditionBlock;
            finallyBlocks.Add(conditionBlock);

            this.disposeCallBlock = disposeCallBlock;
            finallyBlocks.Add(disposeCallBlock);

            return(true);
        }
        /// <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);
            }
        }
        /// <summary>
        /// Determines whether or not there is a conditional dispose starting from this block.
        /// </summary>
        /// <remarks>
        /// Since the conditional dispose is the same as in the Dispose method, we are trying to find the same pattern.
        /// <code>
        /// this.stateField = nextState;
        /// (this.disposableField = this.enumeratorField as IDisposable;)   -- this might be missing
        /// if(this.disposableField != null)
        /// {
        ///     this.disposableField.Dispose();
        /// }
        /// </code>
        /// </remarks>
        /// <param name="yieldExceptionHandler"></param>
        /// <param name="startBlock"></param>
        /// <returns></returns>
        private bool TryProcessConditionalDisposeHandler(YieldExceptionHandlerInfo yieldExceptionHandler, CFGBlockLogicalConstruct startBlock)
        {
            if(finallyBlocks.Count > 0)
            {
                return false;
            }

            if(!(startBlock is PartialCFGBlockLogicalConstruct) || startBlock.CFGSuccessors.Count != 1)
            {
                return false;
            }

            if(startBlock.LogicalConstructExpressions.Count == 0)
            {
                return false;
            }

            BinaryExpression stateAssignExpression = startBlock.LogicalConstructExpressions[0] as BinaryExpression;
            if(stateAssignExpression == null || !stateAssignExpression.IsAssignmentExpression ||
                stateAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (stateAssignExpression.Left as FieldReferenceExpression).Field.Resolve() != stateFieldRef ||
                stateAssignExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (int)((stateAssignExpression.Right as LiteralExpression).Value) != yieldExceptionHandler.NextState)
            {
                return false;
            }

            if(startBlock.LogicalConstructExpressions.Count == 2 && yieldExceptionHandler.HandlerType == YieldExceptionHandlerType.ConditionalDispose)
            {
                BinaryExpression disposableAssignExpression = startBlock.LogicalConstructExpressions[1] as BinaryExpression;
                if (disposableAssignExpression == null || !disposableAssignExpression.IsAssignmentExpression ||
                    disposableAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    (disposableAssignExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                    disposableAssignExpression.Right.CodeNodeType != CodeNodeType.SafeCastExpression ||
                    (disposableAssignExpression.Right as SafeCastExpression).Expression.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    ((disposableAssignExpression.Right as SafeCastExpression).Expression as FieldReferenceExpression).Field != yieldExceptionHandler.EnumeratorField)
                {
                    return false;
                }
            }
            else if(startBlock.LogicalConstructExpressions.Count != 1 || yieldExceptionHandler.HandlerType != YieldExceptionHandlerType.SimpleConditionalDispose)
            {
                return false;
            }

            CFGBlockLogicalConstruct conditionBlock;
            IEnumerator<CFGBlockLogicalConstruct> enumerator = startBlock.CFGSuccessors.GetEnumerator();
            using(enumerator)
            {
                enumerator.MoveNext();
                conditionBlock = enumerator.Current;
            }

            if(conditionBlock.LogicalConstructExpressions.Count != 1)
            {
                return false;
            }

            BinaryExpression isNullCheckExpression = conditionBlock.LogicalConstructExpressions[0] as BinaryExpression;
            if(isNullCheckExpression == null || isNullCheckExpression.Operator != BinaryOperator.ValueEquality ||
                isNullCheckExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (isNullCheckExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                isNullCheckExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (isNullCheckExpression.Right as LiteralExpression).Value != null)
            {
                return false;
            }

            CFGBlockLogicalConstruct disposeCallBlock = null;
            foreach (ILogicalConstruct successor in conditionBlock.CFGSuccessors)
            {
                CFGBlockLogicalConstruct cfgSuccessor = successor as CFGBlockLogicalConstruct;
                if(cfgSuccessor != null && cfgSuccessor.CFGPredecessors.Count == 1)
                {
                    disposeCallBlock = cfgSuccessor;
                    break;
                }
            }

            if(disposeCallBlock == null || disposeCallBlock.LogicalConstructExpressions.Count != 1)
            {
                return false;
            }

            MethodInvocationExpression disposeMethodInvocation = disposeCallBlock.LogicalConstructExpressions[0] as MethodInvocationExpression;
            if(disposeMethodInvocation == null || !disposeMethodInvocation.VirtualCall ||
                disposeMethodInvocation.MethodExpression.Target.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (disposeMethodInvocation.MethodExpression.Target as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                disposeMethodInvocation.MethodExpression.Method.Name != "Dispose")
            {
                return false;
            }

            this.finallyEntryBlock = startBlock;
            finallyBlocks.Add(startBlock);

            this.conditionBlock = conditionBlock;
            finallyBlocks.Add(conditionBlock);

            this.disposeCallBlock = disposeCallBlock;
            finallyBlocks.Add(disposeCallBlock);

            return true;
        }
        /// <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(value < handlerInfo.TryBeginState || value > handlerInfo.TryEndState) //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.TryBeginState < handlerInfo.TryBeginState || oldHandlerInfo.TryEndState > handlerInfo.TryEndState))
                {
                    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);
            }
        }
        /// <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.TryBeginState);

            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);
        }
        /// <summary>
        /// Builds the try body of the specified exception handler starting from the given entry node.
        /// </summary>
        /// <remarks>
        /// We assume that all nodes before reaching the finally block are in the try construct.
        /// </remarks>
        /// <param name="handlerInfo"></param>
        /// <param name="entryOfTry"></param>
        private void BuildTryBody(YieldExceptionHandlerInfo handlerInfo)
        {
            newTryBody = new HashSet<ILogicalConstruct>();
            newTryBody.Add(entryOfTry);
            newFinallyBody = null;

            HashSet<ILogicalConstruct> traversedNodes = new HashSet<ILogicalConstruct>();
            Queue<ILogicalConstruct> bfsQueue = new Queue<ILogicalConstruct>();
            foreach (ILogicalConstruct successor in entryOfTry.SameParentSuccessors)
            {
                bfsQueue.Enqueue(successor);
            }

            while (bfsQueue.Count > 0)
            {
                ILogicalConstruct currentNode = bfsQueue.Dequeue();
                if (!traversedNodes.Add(currentNode) || finallyBlocks.Contains(currentNode))
                {
                    continue;
                }

                ProcessCurrentNode(handlerInfo, bfsQueue, currentNode);
            }
        }
        private bool TryProcessConditionalDisposeHandler(YieldExceptionHandlerInfo yieldExceptionHandler, CFGBlockLogicalConstruct startBlock)
        {
            if (this.finallyBlocks.get_Count() > 0)
            {
                return(false);
            }
            if (startBlock as PartialCFGBlockLogicalConstruct == null || startBlock.get_CFGSuccessors().get_Count() != 1)
            {
                return(false);
            }
            if (startBlock.get_LogicalConstructExpressions().get_Count() == 0)
            {
                return(false);
            }
            V_0 = startBlock.get_LogicalConstructExpressions().get_Item(0) as BinaryExpression;
            if (V_0 == null || !V_0.get_IsAssignmentExpression() || V_0.get_Left().get_CodeNodeType() != 30 || (V_0.get_Left() as FieldReferenceExpression).get_Field().Resolve() != this.stateFieldRef || V_0.get_Right().get_CodeNodeType() != 22 || (Int32)(V_0.get_Right() as LiteralExpression).get_Value() != yieldExceptionHandler.get_NextState())
            {
                return(false);
            }
            if (startBlock.get_LogicalConstructExpressions().get_Count() != 2 || yieldExceptionHandler.get_HandlerType() != 2)
            {
                if (startBlock.get_LogicalConstructExpressions().get_Count() != 1 || yieldExceptionHandler.get_HandlerType() != 1)
                {
                    return(false);
                }
            }
            else
            {
                V_6 = startBlock.get_LogicalConstructExpressions().get_Item(1) as BinaryExpression;
                if (V_6 == null || !V_6.get_IsAssignmentExpression() || V_6.get_Left().get_CodeNodeType() != 30 || (object)(V_6.get_Left() as FieldReferenceExpression).get_Field() != (object)yieldExceptionHandler.get_DisposableField() || V_6.get_Right().get_CodeNodeType() != 33 || (V_6.get_Right() as SafeCastExpression).get_Expression().get_CodeNodeType() != 30 || (object)((V_6.get_Right() as SafeCastExpression).get_Expression() as FieldReferenceExpression).get_Field() != (object)yieldExceptionHandler.get_EnumeratorField())
                {
                    return(false);
                }
            }
            V_2 = startBlock.get_CFGSuccessors().GetEnumerator();
            V_7 = V_2;
            try
            {
                dummyVar0 = V_2.MoveNext();
                V_1       = V_2.get_Current();
            }
            finally
            {
                if (V_7 != null)
                {
                    V_7.Dispose();
                }
            }
            if (V_1.get_LogicalConstructExpressions().get_Count() != 1)
            {
                return(false);
            }
            V_3 = V_1.get_LogicalConstructExpressions().get_Item(0) as BinaryExpression;
            if (V_3 == null || V_3.get_Operator() != 9 || V_3.get_Left().get_CodeNodeType() != 30 || (object)(V_3.get_Left() as FieldReferenceExpression).get_Field() != (object)yieldExceptionHandler.get_DisposableField() || V_3.get_Right().get_CodeNodeType() != 22 || (V_3.get_Right() as LiteralExpression).get_Value() != null)
            {
                return(false);
            }
            V_4 = null;
            V_8 = V_1.get_CFGSuccessors().GetEnumerator();
            try
            {
                while (V_8.MoveNext())
                {
                    V_9 = V_8.get_Current() as CFGBlockLogicalConstruct;
                    if (V_9 == null || V_9.get_CFGPredecessors().get_Count() != 1)
                    {
                        continue;
                    }
                    V_4 = V_9;
                    goto Label0;
                }
            }
            finally
            {
                ((IDisposable)V_8).Dispose();
            }
Label0:
            if (V_4 == null || V_4.get_LogicalConstructExpressions().get_Count() != 1)
            {
                return(false);
            }
            V_5 = V_4.get_LogicalConstructExpressions().get_Item(0) as MethodInvocationExpression;
            if (V_5 == null || !V_5.get_VirtualCall() || V_5.get_MethodExpression().get_Target().get_CodeNodeType() != 30 || (object)(V_5.get_MethodExpression().get_Target() as FieldReferenceExpression).get_Field() != (object)yieldExceptionHandler.get_DisposableField() || String.op_Inequality(V_5.get_MethodExpression().get_Method().get_Name(), "Dispose"))
            {
                return(false);
            }
            this.finallyEntryBlock = startBlock;
            dummyVar1             = this.finallyBlocks.Add(startBlock);
            this.conditionBlock   = V_1;
            dummyVar2             = this.finallyBlocks.Add(V_1);
            this.disposeCallBlock = V_4;
            dummyVar3             = this.finallyBlocks.Add(V_4);
            return(true);
        }
 private void ProcessCurrentNode(YieldExceptionHandlerInfo handlerInfo, Queue <ILogicalConstruct> bfsQueue, ILogicalConstruct currentNode)
 {
     if (currentNode as CFGBlockLogicalConstruct == null)
     {
         if (currentNode as TryFinallyLogicalConstruct != null && this.createdConstructsToIntervalMap.TryGetValue(currentNode as TryFinallyLogicalConstruct, out V_10) && V_10.get_TryStates().IsProperSupersetOf(handlerInfo.get_TryStates()))
         {
             throw new Exception("This try/finally construct cannot be nested in the current construct");
         }
     }
     else
     {
         V_0 = currentNode as CFGBlockLogicalConstruct;
         V_1 = 0;
         while (V_1 < V_0.get_LogicalConstructExpressions().get_Count())
         {
             V_2 = V_0.get_LogicalConstructExpressions().get_Item(V_1);
             if (!this.TryGetStateAssignValue(V_2, out V_3))
             {
                 if (handlerInfo.get_HandlerType() == YieldExceptionHandlerType.Method && V_2.get_CodeNodeType() == 19 && (object)(V_2 as MethodInvocationExpression).get_MethodExpression().get_MethodDefinition() == (object)handlerInfo.get_FinallyMethodDefinition())
                 {
                     if (V_0.get_LogicalConstructExpressions().get_Count() == 1)
                     {
                         if (this.newFinallyBody == null)
                         {
                             this.newFinallyBody = V_0;
                         }
                         dummyVar0 = this.finallyBlocks.Add(this.newFinallyBody);
                         dummyVar1 = this.orderedCFGNodes.Remove(V_0);
                         return;
                     }
                     if (V_1 != 0)
                     {
                         if (V_1 >= V_0.get_LogicalConstructExpressions().get_Count() - 1)
                         {
                             V_8       = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1);
                             dummyVar3 = this.newTryBody.Add(V_8.get_Key());
                             V_4       = V_8.get_Value();
                             dummyVar4 = this.orderedCFGNodes.Remove(V_0);
                         }
                         else
                         {
                             V_6       = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1);
                             dummyVar2 = this.newTryBody.Add(V_6.get_Key());
                             V_7       = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_6.get_Value(), 1);
                             V_4       = V_7.get_Key();
                             this.orderedCFGNodes.set_Item(this.orderedCFGNodes.IndexOf(V_0), V_7.get_Value());
                         }
                     }
                     else
                     {
                         V_5 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1 + 1);
                         V_4 = V_5.get_Key();
                         this.orderedCFGNodes.set_Item(this.orderedCFGNodes.IndexOf(V_0), V_5.get_Value());
                     }
                     if (this.newFinallyBody == null)
                     {
                         this.newFinallyBody = V_4;
                     }
                     dummyVar5 = this.finallyBlocks.Add(V_4);
                     return;
                 }
             }
             else
             {
                 if (!handlerInfo.get_TryStates().Contains(V_3))
                 {
                     if (handlerInfo.get_HandlerType() == YieldExceptionHandlerType.Method || !this.TryProcessConditionalDisposeHandler(handlerInfo, V_0))
                     {
                         throw new Exception("Invalid state value");
                     }
                     return;
                 }
             }
             V_1 = V_1 + 1;
         }
     }
     dummyVar6 = this.newTryBody.Add(currentNode);
     V_11      = currentNode.get_SameParentSuccessors().GetEnumerator();
     try
     {
         while (V_11.MoveNext())
         {
             V_12 = (ILogicalConstruct)V_11.get_Current();
             bfsQueue.Enqueue(V_12);
         }
     }
     finally
     {
         ((IDisposable)V_11).Dispose();
     }
     return;
 }