예제 #1
0
        /// <summary>
        /// Begins a catch block for the given exception type in the given exception block.
        ///
        /// The given exception block must still be open.
        /// </summary>
        public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType)
        {
            if (exceptionType == null)
            {
                throw new ArgumentNullException("exceptionType");
            }

            if (forTry == null)
            {
                throw new ArgumentNullException("forTry");
            }

            if (((IOwned)forTry).Owner != this)
            {
                FailOwnership(forTry);
            }

            if (CurrentExceptionBlock.Count > 0 && forTry != CurrentExceptionBlock.Peek())
            {
                throw new InvalidOperationException("Cannot start CatchBlock on " + forTry + " while inner ExceptionBlock is still open");
            }

            if (!typeof(Exception).IsAssignableFrom(exceptionType))
            {
                throw new ArgumentException("BeginCatchBlock expects a type descending from Exception, found " + exceptionType, "exceptionType");
            }

            var currentlyOpen = CatchBlocks.Where(c => c.Key.ExceptionBlock == forTry && c.Value.Item2 == -1).Select(s => s.Key).SingleOrDefault();

            if (currentlyOpen != null)
            {
                throw new InvalidOperationException("Cannot start a new catch block, " + currentlyOpen + " has not been ended");
            }

            if (MustMark)
            {
                MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel")));
            }

            UpdateState(Wrap(new[] { new StackTransition(0) }, "BeginCatchBlock"));

            var tryBlock = TryBlocks[forTry];

            if (tryBlock.Item2 != -1)
            {
                throw new SigilVerificationException("BeginCatchBlock expects an unclosed exception block, but " + forTry + " is already closed", IL.Instructions(AllLocals));
            }

            IL.BeginCatchBlock(exceptionType);

            UpdateState(Wrap(StackTransition.Push(exceptionType), "BeginCatchBlock"));

            var ret = new CatchBlock(exceptionType, forTry);

            CatchBlocks[ret] = SigilTuple.Create(IL.Index, -1);

            return(ret);
        }
예제 #2
0
        private void ValidateTryCatchFinallyBranches()
        {
            foreach (var branch in Branches.AsEnumerable())
            {
                var instr = BranchPatches[branch.Item3];

                var toLabel   = branch.Item2;
                var fromIndex = branch.Item3;

                var toIndex = Marks[toLabel];

                var fromTryBlocks     = TryBlocks.Where(t => fromIndex >= t.Value.Item1 && fromIndex <= t.Value.Item2).ToList();
                var fromCatchBlocks   = CatchBlocks.Where(c => fromIndex >= c.Value.Item1 && fromIndex <= c.Value.Item2).ToList();
                var fromFinallyBlocks = FinallyBlocks.Where(f => fromIndex >= f.Value.Item1 && fromIndex <= f.Value.Item2).ToList();

                var toTryBlocks     = TryBlocks.Where(t => toIndex >= t.Value.Item1 && toIndex <= t.Value.Item2).ToList();
                var toCatchBlocks   = CatchBlocks.Where(c => toIndex >= c.Value.Item1 && toIndex <= c.Value.Item2).ToList();
                var toFinallyBlocks = FinallyBlocks.Where(f => toIndex >= f.Value.Item1 && toIndex <= f.Value.Item2).ToList();

                var fromTryBlock     = fromTryBlocks.OrderByDescending(t => t.Value.Item1).Select(t => t.Key).FirstOrDefault();
                var fromCatchBlock   = fromCatchBlocks.OrderByDescending(c => c.Value.Item1).Select(c => c.Key).FirstOrDefault();
                var fromFinallyBlock = fromFinallyBlocks.OrderByDescending(f => f.Value.Item1).Select(f => f.Key).FirstOrDefault();

                var toTryBlock     = toTryBlocks.OrderByDescending(t => t.Value.Item1).Select(t => t.Key).FirstOrDefault();
                var toCatchBlock   = toCatchBlocks.OrderByDescending(c => c.Value.Item1).Select(c => c.Key).FirstOrDefault();
                var toFinallyBlock = toFinallyBlocks.OrderByDescending(f => f.Value.Item1).Select(f => f.Key).FirstOrDefault();

                // Nothing funky going on, carry on
                if (fromTryBlock == null && fromCatchBlock == null && fromFinallyBlock == null && toTryBlock == null && toCatchBlock == null && toFinallyBlock == null)
                {
                    continue;
                }

                if (fromCatchBlock != null && toCatchBlock != fromCatchBlock)
                {
                    if (instr.Item3 != OpCodes.Leave)
                    {
                        throw
                            new SigilVerificationException(
                                "Cannot branch from inside " + fromCatchBlock + " to outside, exit the ExceptionBlock first",
                                IL.Instructions(AllLocals)
                                );
                    }
                }

                if (fromFinallyBlock != null && toFinallyBlock != fromFinallyBlock)
                {
                    throw
                        new SigilVerificationException(
                            "Cannot branch from inside " + fromFinallyBlock + " to outside, exit the ExceptionBlock first",
                            IL.Instructions(AllLocals)
                            );
                }

                if (toFinallyBlock != null && fromFinallyBlock != toFinallyBlock)
                {
                    throw
                        new SigilVerificationException(
                            "Cannot branch into a FinallyBlock",
                            IL.Instructions(AllLocals)
                            );
                }

                if (fromTryBlock != null && toTryBlock != fromTryBlock)
                {
                    if (instr.Item3 != OpCodes.Leave)
                    {
                        throw
                            new SigilVerificationException(
                                "Cannot branch from inside " + fromTryBlock + " to outside, exit the ExceptionBlock first",
                                IL.Instructions(AllLocals)
                                );
                    }
                }
            }
        }