/// <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; }