public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (node.ExceptionFilterOpt == null)
            {
                return(base.VisitCatchBlock(node));
            }

            BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt);
            BoundExpression rewrittenFilter             = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            BoundBlock      rewrittenBody             = (BoundBlock)this.Visit(node.Body);
            TypeSymbol      rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            // EnC: We need to insert a hidden sequence point to handle function remapping in case
            // the containing method is edited while methods invoked in the condition are being executed.
            if (rewrittenFilter != null && !node.WasCompilerGenerated && this.Instrument)
            {
                rewrittenFilter = _instrumenter.InstrumentCatchClauseFilter(node, rewrittenFilter, _factory);
            }

            return(node.Update(
                       node.Locals,
                       rewrittenExceptionSourceOpt,
                       rewrittenExceptionTypeOpt,
                       rewrittenFilter,
                       rewrittenBody,
                       node.IsSynthesizedAsyncCatchAll));
        }
Esempio n. 2
0
        private BoundNode RewriteCatch(BoundCatchBlock node, ArrayBuilder <BoundExpression> prologue, ArrayBuilder <LocalSymbol> newLocals)
        {
            AddLocals(node.Locals, newLocals);
            var rewrittenCatchLocals = newLocals.ToImmutableAndFree();

            // If exception variable got lifted, IntroduceFrame will give us frame init prologue.
            // It needs to run before the exception variable is accessed.
            // To ensure that, we will make exception variable a sequence that performs prologue as its its sideeffecs.
            BoundExpression rewrittenExceptionSource = null;
            var             rewrittenFilter          = (BoundExpression)this.Visit(node.ExceptionFilterOpt);

            if (node.ExceptionSourceOpt != null)
            {
                rewrittenExceptionSource = (BoundExpression)Visit(node.ExceptionSourceOpt);
                if (prologue.Count > 0)
                {
                    rewrittenExceptionSource = new BoundSequence(
                        rewrittenExceptionSource.Syntax,
                        ImmutableArray.Create <LocalSymbol>(),
                        prologue.ToImmutable(),
                        rewrittenExceptionSource,
                        rewrittenExceptionSource.Type);
                }
            }
            else if (prologue.Count > 0)
            {
                Debug.Assert(rewrittenFilter != null);
                rewrittenFilter = new BoundSequence(
                    rewrittenFilter.Syntax,
                    ImmutableArray.Create <LocalSymbol>(),
                    prologue.ToImmutable(),
                    rewrittenFilter,
                    rewrittenFilter.Type);
            }

            // done with this.
            prologue.Free();

            // rewrite filter and body
            // NOTE: this will proxy all accesses to exception local if that got lifted.
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);
            var rewrittenBlock   = (BoundBlock)this.Visit(node.Body);

            return(node.Update(
                       rewrittenCatchLocals,
                       rewrittenExceptionSource,
                       exceptionTypeOpt,
                       rewrittenFilter,
                       rewrittenBlock));
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (node.ExceptionFilterOpt == null)
            {
                return(base.VisitCatchBlock(node));
            }

            BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt);
            BoundExpression rewrittenFilter             = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            BoundBlock      rewrittenBody             = (BoundBlock)this.Visit(node.Body);
            TypeSymbol      rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            // EnC: We need to insert a hidden sequence point to handle function remapping in case
            // the containing method is edited while methods invoked in the condition are being executed.
            return(node.Update(
                       node.LocalOpt,
                       rewrittenExceptionSourceOpt,
                       rewrittenExceptionTypeOpt,
                       AddConditionSequencePoint(rewrittenFilter, node),
                       rewrittenBody,
                       node.IsSynthesizedAsyncCatchAll));
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (node.ExceptionFilterOpt == null)
            {
                return base.VisitCatchBlock(node);
            }

            BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt);
            BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body);
            TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            // EnC: We need to insert a hidden sequence point to handle function remapping in case 
            // the containing method is edited while methods invoked in the condition are being executed.
            return node.Update(
                node.LocalOpt,
                rewrittenExceptionSourceOpt,
                rewrittenExceptionTypeOpt,
                AddConditionSequencePoint(rewrittenFilter, node),
                rewrittenBody,
                node.IsSynthesizedAsyncCatchAll);
        }
        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);
        }
        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;
        }
Esempio n. 7
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;
        }
        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);
        }
Esempio n. 9
0
        private BoundNode RewriteCatch(BoundCatchBlock node, ArrayBuilder <BoundExpression> prologue, ArrayBuilder <LocalSymbol> newLocals)
        {
            LocalSymbol rewrittenCatchLocal = null;

            if (newLocals.Count > 0)
            {
                Debug.Assert(newLocals.Count == 1, "must be only one local that is the frame reference");
                Debug.Assert(this.proxies.ContainsKey(node.LocalOpt), "original local should be proxied");

                // getting new locals means that our original local was lifted into a closure
                // and instead of an actual local catch will own frame reference.
                rewrittenCatchLocal = newLocals[0];
            }
            else if (node.LocalOpt != null)
            {
                // local was not lifted, but its type may need to be rewritten
                // this happens when it has a generic type which needs to be rewritten
                // when lambda body was moved to a separate method.
                var origLocal = node.LocalOpt;
                Debug.Assert(!this.proxies.ContainsKey(origLocal), "captured local should not need rewriting");

                var newType = VisitType(origLocal.Type);
                if (newType == origLocal.Type)
                {
                    // keeping same local
                    rewrittenCatchLocal = origLocal;
                }
                else
                {
                    //  need a local of a different type
                    rewrittenCatchLocal = new SynthesizedLocal(CurrentMethod, newType, origLocal.Name, declarationKind: LocalDeclarationKind.Catch);
                    localMap.Add(origLocal, rewrittenCatchLocal);
                }
            }

            // If exception variable got lifted, IntroduceFrame will give us frame init prologue.
            // It needs to run before the exception variable is accessed.
            // To ensure that, we will make exception variable a sequence that performs prologue as its its sideeffecs.
            BoundExpression rewrittenExceptionSource = null;

            if (node.ExceptionSourceOpt != null)
            {
                rewrittenExceptionSource = (BoundExpression)Visit(node.ExceptionSourceOpt);
                if (prologue.Count > 0)
                {
                    rewrittenExceptionSource = new BoundSequence(
                        rewrittenExceptionSource.Syntax,
                        ImmutableArray.Create <LocalSymbol>(),
                        prologue.ToImmutable(),
                        rewrittenExceptionSource,
                        rewrittenExceptionSource.Type);
                }
            }

            // done with these.
            newLocals.Free();
            prologue.Free();

            // rewrite filter and body
            // NOTE: this will proxy all accesses to exception local if that got lifted.
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);
            var rewrittenFilter  = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            var rewrittenBlock   = (BoundBlock)this.Visit(node.Body);

            return(node.Update(
                       rewrittenCatchLocal,
                       rewrittenExceptionSource,
                       exceptionTypeOpt,
                       rewrittenFilter,
                       rewrittenBlock));
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (node.ExceptionFilterOpt == null)
            {
                return base.VisitCatchBlock(node);
            }

            BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt);
            BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body);
            TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            // EnC: We need to insert a hidden sequence point to handle function remapping in case 
            // the containing method is edited while methods invoked in the condition are being executed.
            if (rewrittenFilter != null && !node.WasCompilerGenerated && this.Instrument)
            {
                rewrittenFilter = _instrumenter.InstrumentCatchClauseFilter(node, rewrittenFilter, _factory);
            }

            return node.Update(
                node.Locals,
                rewrittenExceptionSourceOpt,
                rewrittenExceptionTypeOpt,
                rewrittenFilter,
                rewrittenBody,
                node.IsSynthesizedAsyncCatchAll);
        }