private Block BuildTryStatement(TryStatementSyntax tryStatement, Block currentBlock) { // successor - either finally of next block after try statement var catchSuccessor = currentBlock; var hasFinally = tryStatement.Finally?.Block != null; if (hasFinally) { // Wire exit in case we have a return inside the try/catch block catchSuccessor = BuildBlock(tryStatement.Finally.Block, CreateBranchBlock(tryStatement.Finally, new[] { catchSuccessor, ExitTarget.Peek() })); ExitTarget.Push(catchSuccessor); } var catchBlocks = tryStatement.Catches .Reverse() .Select(catchClause => BuildBlock(catchClause.Block, CreateBlock(catchSuccessor))) .ToList(); // If there is a catch with no Exception filter or equivalent we don't want to // join the tryStatement start/end blocks with the exit block because all // exceptions will be caught before going to finally var areAllExceptionsCaught = tryStatement.Catches.Any(SyntaxHelper.IsCatchingAllExceptions); // try end var tryEndStatementConnections = catchBlocks.ToList(); tryEndStatementConnections.Add(catchSuccessor); // happy path, no exceptions thrown if (!areAllExceptionsCaught) // unexpected exception thrown, go to exit (through finally if present) { tryEndStatementConnections.Add(ExitTarget.Peek()); } var tryBody = BuildBlock(tryStatement.Block, CreateBranchBlock(tryStatement, tryEndStatementConnections.Distinct())); var tryStartStatementConnections = catchBlocks.ToList(); tryStartStatementConnections.Add(tryBody); // try body if (!areAllExceptionsCaught) // unexpected exception thrown, go to exit (through finally if present) { tryStartStatementConnections.Add(ExitTarget.Peek()); } var tryStartBlock = CreateBranchBlock(tryStatement, tryStartStatementConnections.Distinct()); if (hasFinally) { ExitTarget.Pop(); } return(tryStartBlock); }
private Block BuildJumpToExitStatement(StatementSyntax statement, Block currentBlock, ExpressionSyntax expression = null) { return(BuildExpression(expression, CreateJumpBlock(statement, ExitTarget.Peek(), currentBlock))); }