示例#1
0
        /// <summary>
        /// Rewrites Try/Catch part of the Try/Catch/Finally
        /// </summary>
        private Statement RewriteFinalizedRegion(TryStatement node)
        {
            var rewrittenTry = (Block)Visit(node.ProtectedBlock);

            var catches = node.ExceptionHandlers;

            if (catches.IsEmpty)
            {
                return(rewrittenTry);
            }

            var origAwaitCatchFrame = _currentAwaitCatchFrame;

            _currentAwaitCatchFrame = null;

            Visit(node.ExceptionHandlers);
            Statement tryWithCatches = new TryStatement {
                EnsureBlock = rewrittenTry
            };

            ((TryStatement)tryWithCatches).ExceptionHandlers = node.ExceptionHandlers;

            var currentAwaitCatchFrame = _currentAwaitCatchFrame;

            if (currentAwaitCatchFrame != null)
            {
                var handledLabel = _F.CreateLabel(tryWithCatches, CompilerContext.Current.GetUniqueName("handled"), _tryDepth);
                var handlersList = currentAwaitCatchFrame.handlers;
                _tryDepth = node.GetAncestors <TryStatement>().Count() + 1;
                var handlers = new List <Statement> {
                    _F.CreateGoto(handledLabel, _tryDepth)
                };
                for (int i = 0, l = handlersList.Count; i < l; i++)
                {
                    handlers.Add(
                        new Block(
                            handlersList[i],
                            _F.CreateGoto(handledLabel, _tryDepth)));
                }

                _containingMethod.Locals.Add(currentAwaitCatchFrame.pendingCaughtException.Local);
                _containingMethod.Locals.Add(currentAwaitCatchFrame.pendingCatch.Local);
                _containingMethod.Locals.AddRange(currentAwaitCatchFrame.GetHoistedLocals().Select(l => l.Local));

                tryWithCatches = new Block(
                    new ExpressionStatement(
                        _F.CreateAssignment(
                            _F.CreateLocalReference(currentAwaitCatchFrame.pendingCatch),
                            _F.CreateDefaultInvocation(LexicalInfo.Empty, currentAwaitCatchFrame.pendingCatch.Type))),
                    tryWithCatches,
                    CreateSwitch(handlers, handledLabel, currentAwaitCatchFrame.pendingCatch));
            }

            _currentAwaitCatchFrame = origAwaitCatchFrame;

            return(tryWithCatches);
        }
        /// <summary>
        /// Rewrites Try/Catch part of the Try/Catch/Finally
        /// </summary>
        private BoundStatement RewriteFinalizedRegion(BoundTryStatement node)
        {
            var rewrittenTry = (BoundBlock)this.VisitBlock(node.TryBlock);

            var catches = node.CatchBlocks;

            if (catches.IsDefaultOrEmpty)
            {
                return(rewrittenTry);
            }

            var origAwaitCatchFrame = _currentAwaitCatchFrame;

            _currentAwaitCatchFrame = null;

            var            rewrittenCatches = this.VisitList(node.CatchBlocks);
            BoundStatement tryWithCatches   = _F.Try(rewrittenTry, rewrittenCatches);

            var currentAwaitCatchFrame = _currentAwaitCatchFrame;

            if (currentAwaitCatchFrame != null)
            {
                var handledLabel = _F.GenerateLabel("handled");
                var handlersList = currentAwaitCatchFrame.handlers;
                var handlers     = ArrayBuilder <BoundSwitchSection> .GetInstance(handlersList.Count);

                for (int i = 0, l = handlersList.Count; i < l; i++)
                {
                    handlers.Add(_F.SwitchSection(
                                     i + 1,
                                     _F.Block(
                                         handlersList[i],
                                         _F.Goto(handledLabel))));
                }

                tryWithCatches = _F.Block(
                    ImmutableArray.Create <LocalSymbol>(
                        currentAwaitCatchFrame.pendingCaughtException,
                        currentAwaitCatchFrame.pendingCatch).
                    AddRange(currentAwaitCatchFrame.GetHoistedLocals()),
                    _F.HiddenSequencePoint(),
                    _F.Assignment(
                        _F.Local(currentAwaitCatchFrame.pendingCatch),
                        _F.Default(currentAwaitCatchFrame.pendingCatch.Type.TypeSymbol)),
                    tryWithCatches,
                    _F.HiddenSequencePoint(),
                    _F.Switch(
                        _F.Local(currentAwaitCatchFrame.pendingCatch),
                        handlers.ToImmutableAndFree()),
                    _F.HiddenSequencePoint(),
                    _F.Label(handledLabel));
            }

            _currentAwaitCatchFrame = origAwaitCatchFrame;

            return(tryWithCatches);
        }
        private BoundExpression AssignCatchSource(BoundExpression rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame)
        {
            BoundExpression assignSource = null;

            if (rewrittenSource != null)
            {
                // exceptionSource = (exceptionSourceType)pendingCaughtException;
                assignSource = _F.AssignmentExpression(
                    rewrittenSource,
                    _F.Convert(
                        rewrittenSource.Type,
                        _F.Local(currentAwaitCatchFrame.pendingCaughtException)));
            }

            return(assignSource);
        }
示例#4
0
        private Expression AssignCatchSource(Declaration rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame)
        {
            Expression assignSource = null;

            if (rewrittenSource != null)
            {
                // exceptionSource = (exceptionSourceType)pendingCaughtException;
                assignSource = _F.CreateAssignment(
                    _F.CreateLocalReference((InternalLocal)rewrittenSource.Entity),
                    _F.CreateCast(
                        (IType)rewrittenSource.Type.Entity,
                        _F.CreateLocalReference(currentAwaitCatchFrame.pendingCaughtException)));
            }

            return(assignSource);
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!_analysis.CatchContainsAwait(node))
            {
                var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame;
                _currentAwaitCatchFrame = null;

                var result = base.VisitCatchBlock(node);
                _currentAwaitCatchFrame = origCurrentAwaitCatchFrame;
                return(result);
            }

            var currentAwaitCatchFrame = _currentAwaitCatchFrame;

            if (currentAwaitCatchFrame == null)
            {
                Debug.Assert(node.Syntax.IsKind(SyntaxKind.CatchClause));
                var tryStatementSyntax = (TryStatementSyntax)node.Syntax.Parent;

                currentAwaitCatchFrame = _currentAwaitCatchFrame = new AwaitCatchFrame(_F, tryStatementSyntax);
            }

            var catchType = node.ExceptionTypeOpt ?? _F.SpecialType(SpecialType.System_Object);
            var catchTemp = _F.SynthesizedLocal(catchType);

            var storePending = _F.AssignmentExpression(
                _F.Local(currentAwaitCatchFrame.pendingCaughtException),
                _F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type.TypeSymbol,
                           _F.Local(catchTemp)));

            var setPendingCatchNum = _F.Assignment(
                _F.Local(currentAwaitCatchFrame.pendingCatch),
                _F.Literal(currentAwaitCatchFrame.handlers.Count + 1));

            //  catch (ExType exTemp)
            //  {
            //      pendingCaughtException = exTemp;
            //      catchNo = X;
            //  }
            BoundCatchBlock catchAndPend;
            ImmutableArray <LocalSymbol> handlerLocals;

            var filterOpt = node.ExceptionFilterOpt;

            if (filterOpt == null)
            {
                // store pending exception
                // as the first statement in a catch
                catchAndPend = node.Update(
                    ImmutableArray.Create(catchTemp),
                    _F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: null,
                    body: _F.Block(
                        _F.HiddenSequencePoint(),
                        _F.ExpressionStatement(storePending),
                        setPendingCatchNum),
                    isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll);

                // catch locals live on the synthetic catch handler block
                handlerLocals = node.Locals;
            }
            else
            {
                handlerLocals = ImmutableArray <LocalSymbol> .Empty;

                // catch locals move up into hoisted locals
                // since we might need to access them from both the filter and the catch
                foreach (var local in node.Locals)
                {
                    currentAwaitCatchFrame.HoistLocal(local, _F);
                }

                // store pending exception
                // as the first expression in a filter
                var sourceOpt       = node.ExceptionSourceOpt;
                var rewrittenFilter = (BoundExpression)this.Visit(filterOpt);
                var newFilter       = sourceOpt == null?
                                      _F.MakeSequence(
                    storePending,
                    rewrittenFilter) :
                                          _F.MakeSequence(
                                              storePending,
                                              AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame),
                                              rewrittenFilter);

                catchAndPend = node.Update(
                    ImmutableArray.Create(catchTemp),
                    _F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: newFilter,
                    body: _F.Block(
                        _F.HiddenSequencePoint(),
                        setPendingCatchNum),
                    isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll);
            }

            var handlerStatements = ArrayBuilder <BoundStatement> .GetInstance();

            handlerStatements.Add(_F.HiddenSequencePoint());

            if (filterOpt == null)
            {
                var sourceOpt = node.ExceptionSourceOpt;
                if (sourceOpt != null)
                {
                    BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame);
                    handlerStatements.Add(_F.ExpressionStatement(assignSource));
                }
            }

            handlerStatements.Add((BoundStatement)this.Visit(node.Body));

            var handler = _F.Block(
                handlerLocals,
                handlerStatements.ToImmutableAndFree()
                );

            currentAwaitCatchFrame.handlers.Add(handler);

            return(catchAndPend);
        }
        private BoundExpression AssignCatchSource(BoundExpression rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame)
        {
            BoundExpression assignSource = null;
            if (rewrittenSource != null)
            {
                // exceptionSource = (exceptionSourceType)pendingCaughtException;
                assignSource = _F.AssignmentExpression(
                                    rewrittenSource,
                                    _F.Convert(
                                        rewrittenSource.Type,
                                        _F.Local(currentAwaitCatchFrame.pendingCaughtException)));
            }

            return assignSource;
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!_analysis.CatchContainsAwait(node))
            {
                var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame;
                _currentAwaitCatchFrame = null;

                var result = base.VisitCatchBlock(node);
                _currentAwaitCatchFrame = origCurrentAwaitCatchFrame;
                return result;
            }

            var currentAwaitCatchFrame = _currentAwaitCatchFrame;
            if (currentAwaitCatchFrame == null)
            {
                Debug.Assert(node.Syntax.IsKind(SyntaxKind.CatchClause));
                var tryStatementSyntax = (TryStatementSyntax)node.Syntax.Parent;

                currentAwaitCatchFrame = _currentAwaitCatchFrame = new AwaitCatchFrame(_F, tryStatementSyntax);
            }

            var catchType = node.ExceptionTypeOpt ?? _F.SpecialType(SpecialType.System_Object);
            var catchTemp = _F.SynthesizedLocal(catchType);

            var storePending = _F.AssignmentExpression(
                        _F.Local(currentAwaitCatchFrame.pendingCaughtException),
                        _F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type,
                            _F.Local(catchTemp)));

            var setPendingCatchNum = _F.Assignment(
                            _F.Local(currentAwaitCatchFrame.pendingCatch),
                            _F.Literal(currentAwaitCatchFrame.handlers.Count + 1));

            //  catch (ExType exTemp)
            //  {
            //      pendingCaughtException = exTemp;
            //      catchNo = X;
            //  }
            BoundCatchBlock catchAndPend;
            var handlerLocals = ImmutableArray<LocalSymbol>.Empty;

            var filterOpt = node.ExceptionFilterOpt;
            if (filterOpt == null)
            {
                // store pending exception 
                // as the first statement in a catch
                catchAndPend = node.Update(
                    catchTemp,
                    _F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: null,
                    body: _F.Block(
                        _F.HiddenSequencePoint(),
                        _F.ExpressionStatement(storePending),
                        setPendingCatchNum),
                    isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll);

                // catch locals live on the synthetic catch handler block
                if ((object)node.LocalOpt != null)
                {
                    handlerLocals = ImmutableArray.Create(node.LocalOpt);
                }
            }
            else
            {
                // catch locals move up into hoisted locals
                // since we might need to access them from both the filter and the catch
                if ((object)node.LocalOpt != null)
                {
                    currentAwaitCatchFrame.HoistLocal(node.LocalOpt, _F);
                }

                // store pending exception 
                // as the first expression in a filter
                var sourceOpt = node.ExceptionSourceOpt;
                var rewrittenFilter = (BoundExpression)this.Visit(filterOpt);
                var newFilter = sourceOpt == null ?
                                _F.Sequence(
                                    storePending,
                                    rewrittenFilter) :
                                _F.Sequence(
                                    storePending,
                                    AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame),
                                    rewrittenFilter);

                catchAndPend = node.Update(
                    catchTemp,
                    _F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: newFilter,
                    body: _F.Block(
                        _F.HiddenSequencePoint(),
                        setPendingCatchNum),
                    isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll);
            }

            var handlerStatements = ArrayBuilder<BoundStatement>.GetInstance();

            handlerStatements.Add(_F.HiddenSequencePoint());

            if (filterOpt == null)
            {
                var sourceOpt = node.ExceptionSourceOpt;
                if (sourceOpt != null)
                {
                    BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame);
                    handlerStatements.Add(_F.ExpressionStatement(assignSource));
                }
            }

            handlerStatements.Add((BoundStatement)this.Visit(node.Body));

            var handler = _F.Block(
                    handlerLocals,
                    ImmutableArray<LocalFunctionSymbol>.Empty,
                    handlerStatements.ToImmutableAndFree()
                );

            currentAwaitCatchFrame.handlers.Add(handler);

            return catchAndPend;
        }
        /// <summary>
        /// Rewrites Try/Catch part of the Try/Catch/Finally
        /// </summary>
        private BoundStatement RewriteFinalizedRegion(BoundTryStatement node)
        {
            var rewrittenTry = (BoundBlock)this.VisitBlock(node.TryBlock);

            var catches = node.CatchBlocks;
            if (catches.IsDefaultOrEmpty)
            {
                return rewrittenTry;
            }

            var origAwaitCatchFrame = _currentAwaitCatchFrame;
            _currentAwaitCatchFrame = null;

            var rewrittenCatches = this.VisitList(node.CatchBlocks);
            BoundStatement tryWithCatches = _F.Try(rewrittenTry, rewrittenCatches);

            var currentAwaitCatchFrame = _currentAwaitCatchFrame;
            if (currentAwaitCatchFrame != null)
            {
                var handledLabel = _F.GenerateLabel("handled");
                var handlersList = currentAwaitCatchFrame.handlers;
                var handlers = ArrayBuilder<BoundSwitchSection>.GetInstance(handlersList.Count);
                for (int i = 0, l = handlersList.Count; i < l; i++)
                {
                    handlers.Add(_F.SwitchSection(
                        i + 1,
                        _F.Block(
                            handlersList[i],
                            _F.Goto(handledLabel))));
                }

                tryWithCatches = _F.Block(
                    ImmutableArray.Create<LocalSymbol>(
                        currentAwaitCatchFrame.pendingCaughtException,
                        currentAwaitCatchFrame.pendingCatch).
                        AddRange(currentAwaitCatchFrame.GetHoistedLocals()),
                    ImmutableArray<LocalFunctionSymbol>.Empty,
                    _F.HiddenSequencePoint(),
                    _F.Assignment(
                        _F.Local(currentAwaitCatchFrame.pendingCatch),
                        _F.Default(currentAwaitCatchFrame.pendingCatch.Type)),
                    tryWithCatches,
                    _F.HiddenSequencePoint(),
                    _F.Switch(
                        _F.Local(currentAwaitCatchFrame.pendingCatch),
                        handlers.ToImmutableAndFree()),
                    _F.HiddenSequencePoint(),
                    _F.Label(handledLabel));
            }

            _currentAwaitCatchFrame = origAwaitCatchFrame;

            return tryWithCatches;
        }
示例#9
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!analysis.CatchContainsAwait(node))
            {
                return (BoundCatchBlock)base.VisitCatchBlock(node);
            }

            var currentAwaitCatchFrame = this.currentAwaitCatchFrame;
            if (currentAwaitCatchFrame == null)
            {
                currentAwaitCatchFrame = this.currentAwaitCatchFrame = new AwaitCatchFrame(F);
            }

            var catchType = node.ExceptionTypeOpt ?? F.SpecialType(SpecialType.System_Object);
            var catchTemp = F.SynthesizedLocal(catchType);

            var storePending = F.AssignmentExpression(
                        F.Local(currentAwaitCatchFrame.pendingCaughtException),
                        F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type,
                            F.Local(catchTemp)));

            var setPendingCatchNum = F.Assignment(
                            F.Local(currentAwaitCatchFrame.pendingCatch),
                            F.Literal(currentAwaitCatchFrame.handlers.Count + 1));

            //  catch (ExType exTemp)
            //  {
            //      pendingCaughtException = exTemp;
            //      catchNo = X;
            //  }
            BoundCatchBlock catchAndPend;
            ImmutableArray<LocalSymbol> handlerLocals;

            var filterOpt = node.ExceptionFilterOpt;
            if (filterOpt == null)
            {
                // store pending exception 
                // as the first statement in a catch
                catchAndPend = node.Update(
                    catchTemp,
                    F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: null,
                    body: F.Block(
                        F.HiddenSequencePoint(),
                        F.ExpressionStatement(storePending),
                        setPendingCatchNum));

                // catch local lives on the synthetic catch handler block
                handlerLocals = node.LocalOpt == null ?
                                ImmutableArray<LocalSymbol>.Empty :
                                ImmutableArray.Create(node.LocalOpt);
            }
            else
            {
                // catch local moves up into hoisted locals
                // since we might need to access it from both the filter and the catch
                handlerLocals = ImmutableArray<LocalSymbol>.Empty;
                if (node.LocalOpt != null)
                {
                    currentAwaitCatchFrame.HoistLocal(node.LocalOpt, F);
                }

                // store pending exception 
                // as the first expression in a filter
                var sourceOpt = node.ExceptionSourceOpt;
                var rewrittenFilter = (BoundExpression)this.Visit(filterOpt);
                var newFilter = sourceOpt == null ?
                                F.Sequence(
                                    storePending,
                                    rewrittenFilter) :
                                F.Sequence(
                                    storePending,
                                    AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame),
                                    rewrittenFilter);

                catchAndPend = node.Update(
                    catchTemp,
                    F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: newFilter,
                    body: F.Block(
                        F.HiddenSequencePoint(),
                        setPendingCatchNum));
            }

            var handlerStatements = ArrayBuilder<BoundStatement>.GetInstance();

            handlerStatements.Add(F.HiddenSequencePoint());

            if (filterOpt == null)
            {
                var sourceOpt = node.ExceptionSourceOpt;
                if (sourceOpt != null)
                {
                    BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame);
                    handlerStatements.Add(F.ExpressionStatement(assignSource));
                }
            }

            handlerStatements.Add((BoundStatement)this.Visit(node.Body));

            var handler = F.Block(
                    handlerLocals,
                    handlerStatements.ToImmutableAndFree()
                );

            currentAwaitCatchFrame.handlers.Add(handler);

            return catchAndPend;
        }
示例#10
0
        public override void OnExceptionHandler(ExceptionHandler node)
        {
            if (!_analysis.CatchContainsAwait(node))
            {
                var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame;
                _currentAwaitCatchFrame = null;

                var result = Visit(node);
                _currentAwaitCatchFrame = origCurrentAwaitCatchFrame;
                ReplaceCurrentNode(result);
            }

            var currentAwaitCatchFrame = _currentAwaitCatchFrame ??
                                         (_currentAwaitCatchFrame = new AwaitCatchFrame(_tss, _F, _containingMethod));

            var catchType = node.Declaration != null ? (IType)node.Declaration.Type.Entity : _tss.ObjectType;
            var catchTemp = _F.DeclareTempLocal(_containingMethod, catchType);

            var storePending = _F.CreateAssignment(
                _F.CreateLocalReference(currentAwaitCatchFrame.pendingCaughtException),
                _F.CreateCast(currentAwaitCatchFrame.pendingCaughtException.Type,
                              _F.CreateLocalReference(catchTemp)));

            var setPendingCatchNum = _F.CreateAssignment(
                _F.CreateLocalReference(currentAwaitCatchFrame.pendingCatch),
                _F.CreateIntegerLiteral(currentAwaitCatchFrame.handlers.Count + 1));

            //  catch (ExType exTemp)
            //  {
            //      pendingCaughtException = exTemp;
            //      catchNo = X;
            //  }
            ExceptionHandler catchAndPend;

            var filterOpt = node.FilterCondition;

            if (filterOpt == null)
            {
                // store pending exception
                // as the first statement in a catch
                catchAndPend = new ExceptionHandler
                {
                    Declaration = new Declaration(catchTemp.Name, _F.CreateTypeReference(catchType))
                    {
                        Entity = catchTemp
                    },
                    Block = new Block(
                        new ExpressionStatement(storePending),
                        new ExpressionStatement(setPendingCatchNum))
                };
                // catch locals live on the synthetic catch handler block
            }
            else
            {
                // catch locals move up into hoisted locals
                // since we might need to access them from both the filter and the catch
                foreach (var local in LocalsUsedIn(node))
                {
                    currentAwaitCatchFrame.HoistLocal(local, _F);
                }

                // store pending exception
                // as the first expression in a filter
                var decl            = node.Declaration;
                var sourceOpt       = decl != null && !string.IsNullOrEmpty(decl.Name) ? decl : null;
                var rewrittenFilter = Visit(filterOpt);
                var newFilter       = sourceOpt == null?
                                      _F.CreateEvalInvocation(
                    storePending.LexicalInfo,
                    storePending,
                    rewrittenFilter) :
                                          _F.CreateEvalInvocation(
                                              storePending.LexicalInfo,
                                              storePending,
                                              AssignCatchSource((Declaration)Visit(sourceOpt), currentAwaitCatchFrame),
                                              rewrittenFilter);

                catchAndPend = new ExceptionHandler
                {
                    Declaration = new Declaration(catchTemp.Name, _F.CreateTypeReference(catchType))
                    {
                        Entity = catchTemp
                    },
                    FilterCondition = newFilter,
                    Block           = new Block(new ExpressionStatement(setPendingCatchNum))
                };
            }
            if (node.ContainsAnnotation("isSynthesizedAsyncCatchAll"))
            {
                catchAndPend.Annotate("isSynthesizedAsyncCatchAll");
            }

            var handlerStatements = new List <Statement>();

            if (filterOpt == null)
            {
                var sourceOpt = node.Declaration;
                if (sourceOpt != null && sourceOpt.Entity != null)
                {
                    Expression assignSource = AssignCatchSource((Declaration)Visit(sourceOpt), currentAwaitCatchFrame);
                    handlerStatements.Add(new ExpressionStatement(assignSource));
                }
            }

            handlerStatements.Add(Visit(node.Block));

            var handler = new Block(handlerStatements.ToArray());

            currentAwaitCatchFrame.handlers.Add(handler);

            ReplaceCurrentNode(catchAndPend);
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!analysis.CatchContainsAwait(node))
            {
                return((BoundCatchBlock)base.VisitCatchBlock(node));
            }

            var currentAwaitCatchFrame = this.currentAwaitCatchFrame;

            if (currentAwaitCatchFrame == null)
            {
                currentAwaitCatchFrame = this.currentAwaitCatchFrame = new AwaitCatchFrame(F);
            }

            var catchType = node.ExceptionTypeOpt ?? F.SpecialType(SpecialType.System_Object);
            var catchTemp = F.SynthesizedLocal(catchType);

            var storePending = F.AssignmentExpression(
                F.Local(currentAwaitCatchFrame.pendingCaughtException),
                F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type,
                          F.Local(catchTemp)));

            var setPendingCatchNum = F.Assignment(
                F.Local(currentAwaitCatchFrame.pendingCatch),
                F.Literal(currentAwaitCatchFrame.handlers.Count + 1));

            //  catch (ExType exTemp)
            //  {
            //      pendingCaughtException = exTemp;
            //      catchNo = X;
            //  }
            BoundCatchBlock catchAndPend;
            ImmutableArray <LocalSymbol> handlerLocals;

            var filterOpt = node.ExceptionFilterOpt;

            if (filterOpt == null)
            {
                // store pending exception
                // as the first statement in a catch
                catchAndPend = node.Update(
                    catchTemp,
                    F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: null,
                    body: F.Block(
                        F.HiddenSequencePoint(),
                        F.ExpressionStatement(storePending),
                        setPendingCatchNum));

                // catch local lives on the synthetic catch handler block
                handlerLocals = node.LocalOpt == null ?
                                ImmutableArray <LocalSymbol> .Empty :
                                ImmutableArray.Create(node.LocalOpt);
            }
            else
            {
                // catch local moves up into hoisted locals
                // since we might need to access it from both the filter and the catch
                handlerLocals = ImmutableArray <LocalSymbol> .Empty;
                if (node.LocalOpt != null)
                {
                    currentAwaitCatchFrame.HoistLocal(node.LocalOpt, F);
                }

                // store pending exception
                // as the first expression in a filter
                var sourceOpt       = node.ExceptionSourceOpt;
                var rewrittenFilter = (BoundExpression)this.Visit(filterOpt);
                var newFilter       = sourceOpt == null?
                                      F.Sequence(
                    storePending,
                    rewrittenFilter) :
                                          F.Sequence(
                                              storePending,
                                              AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame),
                                              rewrittenFilter);

                catchAndPend = node.Update(
                    catchTemp,
                    F.Local(catchTemp),
                    catchType,
                    exceptionFilterOpt: newFilter,
                    body: F.Block(
                        F.HiddenSequencePoint(),
                        setPendingCatchNum));
            }

            var handlerStatements = ArrayBuilder <BoundStatement> .GetInstance();

            handlerStatements.Add(F.HiddenSequencePoint());

            if (filterOpt == null)
            {
                var sourceOpt = node.ExceptionSourceOpt;
                if (sourceOpt != null)
                {
                    BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame);
                    handlerStatements.Add(F.ExpressionStatement(assignSource));
                }
            }

            handlerStatements.Add((BoundStatement)this.Visit(node.Body));

            var handler = F.Block(
                handlerLocals,
                handlerStatements.ToImmutableAndFree()
                );

            currentAwaitCatchFrame.handlers.Add(handler);

            return(catchAndPend);
        }