protected void FindUnhandledExceptions() { Hashtable methodExMarks = this.GetExceptionMarks(); bool hasHandlers = true; if (methodExMarks.Count > 0) { // This method can throw exceptions. ArrayList exHandlers = this.mTargetMethod.RetrieveEHClauses(); if (exHandlers != null && exHandlers.Count > 0) { // Remove the unneeded handlers. for (int i = exHandlers.Count - 1; i >= 0; i--) { EHClause cTest = (EHClause)exHandlers[i]; if (cTest.Type != EHClauseTypes.EHNone) { exHandlers.Remove(cTest); } } if (exHandlers.Count > 0) { foreach (object key in methodExMarks.Keys) { uint keyValue = (uint)((int)key); ArrayList foundExceptions = (ArrayList)methodExMarks[key]; foreach (Type foundExType in foundExceptions) { bool areAllTryBlocksProcessed = false; bool isHandled = false; int maxDistance = this.mCIL.Length; int minDistance = -1; do { bool foundOneHandler = false; foreach (EHClause clause in exHandlers) { uint tryEnd = clause.TryOffset + clause.TryLength; if (keyValue >= clause.TryOffset && keyValue <= tryEnd) { int distance = Math.Abs((int)clause.TryOffset - (int)keyValue) + Math.Abs((int)tryEnd - (int)keyValue); if (distance <= maxDistance && distance > minDistance) { foundOneHandler = true; maxDistance = distance; Type handlerEx = Type.GetType( ILServices.GetNameForToken(this.mTargetMethod.ModuleName, clause.ClassTokenOrFilterOffset)); if (foundExType == handlerEx || foundExType.IsSubclassOf(handlerEx)) { isHandled = true; areAllTryBlocksProcessed = true; break; } } } } if (foundOneHandler == true) { minDistance = maxDistance; } else { areAllTryBlocksProcessed = true; } } while(areAllTryBlocksProcessed == false); if (isHandled == false) { this.CheckExceptionTypeInThrowsAttribute(foundExType); } } } } else { hasHandlers = false; } } else { hasHandlers = false; } if (hasHandlers == false) { // ALL of the found exceptions from GetExceptionMarks() // must be marked by this method, or it's a compilation error foreach (object key in methodExMarks.Keys) { uint keyValue = (uint)(int)key; ArrayList foundExceptions = (ArrayList)methodExMarks[key]; foreach (Type foundEx in foundExceptions) { this.CheckExceptionTypeInThrowsAttribute(foundEx); } } } } }
private static void FindNextBlockStart(EHClausesArray clauses, out BlockType blockType, ref int blockStart, ref int blockEnd, out Type catchBlockType, out int index) { //given a block [blockStart,blockEnd) we search for the block [newBlockStart,newBlockEnd) such that: //1) IsBlockLater([blockStart,blockEnd) , [newBlockStart,newBlockEnd)) //2) if IsBlockLater([blockStart,blockEnd) , [newBlockStart',newBlockEnd')) // then IsBlockLater([newBlockStart,newBlockEnd) , [newBlockStart',newBlockEnd')) int newBlockStart = 1 << 30; int newBlockEnd = 1 << 30; blockType = BlockType.None; catchBlockType = null; index = -1; for (int i = 0; i < clauses.Count; i++) { EHClause c = clauses[i]; if (IsBlockLater(blockStart, blockEnd, c.TryStart, c.TryEnd) && IsBlockLater(c.TryStart, c.TryEnd, newBlockStart, newBlockEnd)) { blockType = BlockType.Try; newBlockStart = c.TryStart; newBlockEnd = c.TryEnd; index = i; } if (IsBlockLater(blockStart, blockEnd, c.HandlerStart, c.HandlerEnd) && IsBlockLater(c.HandlerStart, c.HandlerEnd, newBlockStart, newBlockEnd)) { //Andrew: mb treat filters another way... newBlockStart = c.HandlerStart; newBlockEnd = c.HandlerEnd; index = i; switch (c.Kind) { case EHClauseKind.FinallyHandler: blockType = BlockType.Finally; break; case EHClauseKind.TypeFilteredHandler: blockType = BlockType.Catch; catchBlockType = c.ClassObject; break; case EHClauseKind.FaultHandler: blockType = BlockType.Catch; break; case EHClauseKind.UserFilteredHandler: blockType = BlockType.FilteredCatch; break; } } if (c.Kind == EHClauseKind.UserFilteredHandler) { if (IsBlockLater(blockStart, blockEnd, c.FilterStart, c.FilterEnd) && IsBlockLater(c.FilterStart, c.FilterEnd, newBlockStart, newBlockEnd)) { newBlockStart = c.FilterStart; newBlockEnd = c.FilterEnd; blockType = BlockType.Filter; index = i; } } } blockStart = newBlockStart; blockEnd = newBlockEnd; }