Пример #1
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (node.ExceptionFilterOpt == null)
            {
                return(base.VisitCatchBlock(node));
            }

            if (node.ExceptionFilterOpt.ConstantValue?.BooleanValue == false)
            {
                return(null);
            }

            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));
        }
Пример #2
0
        protected override void VisitCatchBlock(BoundCatchBlock catchBlock, ref LocalState finallyState)
        {
            var oldPending = SavePending(); // we do not support branches into a catch block

            base.VisitCatchBlock(catchBlock, ref finallyState);
            RestorePending(oldPending);
        }
Пример #3
0
 public override BoundNode VisitCatchBlock(BoundCatchBlock node)
 {
     AddAll(node.Locals);
     base.VisitCatchBlock(node);
     RemoveAll(node.Locals);
     return(null);
 }
Пример #4
0
 public virtual BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory)
 {
     Debug.Assert(!original.WasCompilerGenerated);
     Debug.Assert(original.Syntax.Kind() == SyntaxKind.CatchClause);
     Debug.Assert(((CatchClauseSyntax)original.Syntax).Filter != null);
     Debug.Assert(factory != null);
     return(rewrittenFilter);
 }
Пример #5
0
        private static bool IsCatchingPossible(BoundCatchBlock catchBlock, TypeSymbol exception)
        {
            // Because IsCatching is called before
            Debug.Assert((object)catchBlock.ExceptionTypeOpt != null);

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            return(catchBlock.ExceptionTypeOpt.IsEqualToOrDerivedFrom(exception, TypeCompareKind.ConsiderEverything, ref useSiteDiagnostics));
        }
Пример #6
0
                public override BoundNode VisitCatchBlock(BoundCatchBlock node)
                {
                    var oldScope = _currentScope;

                    _currentScope = CreateOrReuseScope(node, node.Locals);
                    var result = base.VisitCatchBlock(node);

                    _currentScope = oldScope;
                    return(result);
                }
Пример #7
0
        public override BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory)
        {
            rewrittenFilter = base.InstrumentCatchClauseFilter(original, rewrittenFilter, factory);

            // 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.
            CatchFilterClauseSyntax filterClause = ((CatchClauseSyntax)original.Syntax).Filter;

            return(AddConditionSequencePoint(new BoundSequencePointExpression(filterClause, rewrittenFilter, rewrittenFilter.Type), filterClause, factory));
        }
Пример #8
0
        protected override void VisitCatchBlock(BoundCatchBlock catchBlock, ref LocalState finallyState)
        {
            if (IsInside)
            {
                var local = catchBlock.Locals.FirstOrDefault();

                if (local?.DeclarationKind == LocalDeclarationKind.CatchVariable)
                {
                    _variablesDeclared.Add(local);
                }
            }

            base.VisitCatchBlock(catchBlock, ref finallyState);
        }
Пример #9
0
        private static bool IsCatching(BoundCatchBlock catchBlock, TypeSymbol exception)
        {
            // If it is catching all exceptions
            if ((object)catchBlock.ExceptionTypeOpt == null)
            {
                return(true);
            }

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            if (exception.IsEqualToOrDerivedFrom(catchBlock.ExceptionTypeOpt, TypeCompareKind.ConsiderEverything, ref useSiteDiagnostics))
            {
                return(catchBlock.ExceptionFilterOpt == null);
            }

            return(false);
        }
Пример #10
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!node.Locals.IsDefaultOrEmpty)
            {
                // Yield/await aren't supported in catch block atm, but we need to rewrite the type
                // of the variables owned by the catch block. Note that one of these variables might be a closure frame reference.
                var newLocals = RewriteLocalList(node.Locals);

                return(node.Update(
                           newLocals,
                           (BoundExpression)this.Visit(node.ExceptionSourceOpt),
                           this.VisitType(node.ExceptionTypeOpt),
                           (BoundExpression)this.Visit(node.ExceptionFilterOpt),
                           (BoundBlock)this.Visit(node.Body)));
            }

            return(base.VisitCatchBlock(node));
        }
Пример #11
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if ((object)node.LocalOpt != null)
            {
                // Yield/await aren't supported in catch block atm, but we need to rewrite the type
                // of the variable owned by the catch block. Note that this variable might be a closure frame reference.
                LocalSymbol newLocal;
                TryRewriteLocal(node.LocalOpt, out newLocal);

                return(node.Update(
                           newLocal,
                           (BoundExpression)this.Visit(node.ExceptionSourceOpt),
                           this.VisitType(node.ExceptionTypeOpt),
                           (BoundExpression)this.Visit(node.ExceptionFilterOpt),
                           (BoundBlock)this.Visit(node.Body)));
            }

            return(base.VisitCatchBlock(node));
        }
            public override BoundNode VisitCatchBlock(BoundCatchBlock node)
            {
                var origSeenAwait = _seenAwait;

                _seenAwait = false;

                var result = base.VisitCatchBlock(node);

                if (_seenAwait)
                {
                    var awaitContainingCatches = _awaitContainingCatches;
                    if (awaitContainingCatches == null)
                    {
                        _awaitContainingCatches = awaitContainingCatches = new HashSet <BoundCatchBlock>();
                    }

                    _awaitContainingCatches.Add(node);
                }

                _seenAwait |= origSeenAwait;
                return(result);
            }
Пример #13
0
        internal void Parse(BoundCatchBlock boundCatchBlock)
        {
            if (boundCatchBlock == null)
            {
                throw new ArgumentNullException();
            }

            if (boundCatchBlock.ExceptionTypeOpt != null)
            {
                this.ExceptionTypeOpt = boundCatchBlock.ExceptionTypeOpt;
            }

            if (boundCatchBlock.ExceptionSourceOpt != null)
            {
                this.ExceptionSourceOpt = Deserialize(boundCatchBlock.ExceptionSourceOpt) as Expression;
            }

            if (boundCatchBlock.ExceptionFilterOpt != null)
            {
                this.ExceptionFilterOpt = Deserialize(boundCatchBlock.ExceptionFilterOpt) as Expression;
            }

            Statements = Deserialize(boundCatchBlock.Body);
        }
Пример #14
0
        /// <remarks>
        /// The interesting part in the following method is the support for exception filters. 
        /// === Example:
        ///
        /// try
        /// {
        ///    TryBlock
        /// }
        /// catch (ExceptionType ex) when (Condition)
        /// {
        ///    Handler
        /// }
        ///
        /// gets emitted as something like ===>
        ///
        /// Try           
        ///     TryBlock
        /// Filter 
        ///     var tmp = Pop() as {ExceptionType}
        ///     if (tmp == null)
        ///     {
        ///         Push 0
        ///     }
        ///     else
        ///     {
        ///         ex = tmp
        ///         Push Condition ? 1 : 0
        ///     }
        /// End Filter // leaves 1 or 0 on the stack
        /// Catch      // gets called after finalization of nested exception frames if condition above produced 1
        ///     Pop    // CLR pushes the exception object again
        ///     variable ex can be used here
        ///     Handler
        /// EndCatch
        /// </remarks>
        private void EmitCatchBlock(BoundCatchBlock catchBlock)
        {
            object typeCheckFailedLabel = null;


            _builder.AdjustStack(1); // Account for exception on the stack.

            // Open appropriate exception handler scope. (Catch or Filter)
            // if it is a Filter, emit prologue that checks if the type on the stack
            // converts to what we want.
            if (catchBlock.ExceptionFilterOpt == null)
            {
                var exceptionType = ((object)catchBlock.ExceptionTypeOpt != null) ?
                    _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics) :
                    _module.GetSpecialType(SpecialType.System_Object, catchBlock.Syntax, _diagnostics);

                _builder.OpenLocalScope(ScopeType.Catch, exceptionType);

                if (catchBlock.IsSynthesizedAsyncCatchAll)
                {
                    Debug.Assert(_asyncCatchHandlerOffset < 0); // only one expected
                    _asyncCatchHandlerOffset = _builder.AllocateILMarker();
                }

                // Dev12 inserts the sequence point on catch clause without a filter, just before 
                // the exception object is assigned to the variable.
                // 
                // Also in Dev12 the exception variable scope span starts right after the stloc instruction and 
                // ends right before leave instruction. So when stopped at the sequence point Dev12 inserts,
                // the exception variable is not visible. 
                if (_emitPdbSequencePoints)
                {
                    var syntax = catchBlock.Syntax as CatchClauseSyntax;
                    if (syntax != null)
                    {
                        TextSpan spSpan;
                        var declaration = syntax.Declaration;

                        if (declaration == null)
                        {
                            spSpan = syntax.CatchKeyword.Span;
                        }
                        else
                        {
                            spSpan = TextSpan.FromBounds(syntax.SpanStart, syntax.Declaration.Span.End);
                        }

                        this.EmitSequencePoint(catchBlock.SyntaxTree, spSpan);
                    }
                }
            }
            else
            {
                _builder.OpenLocalScope(ScopeType.Filter);

                // Filtering starts with simulating regular catch through a 
                // type check. If this is not our type then we are done.
                var typeCheckPassedLabel = new object();
                typeCheckFailedLabel = new object();

                if ((object)catchBlock.ExceptionTypeOpt != null)
                {
                    var exceptionType = _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics);

                    _builder.EmitOpCode(ILOpCode.Isinst);
                    _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics);
                    _builder.EmitOpCode(ILOpCode.Dup);
                    _builder.EmitBranch(ILOpCode.Brtrue, typeCheckPassedLabel);
                    _builder.EmitOpCode(ILOpCode.Pop);
                    _builder.EmitIntConstant(0);
                    _builder.EmitBranch(ILOpCode.Br, typeCheckFailedLabel);
                }
                else
                {
                    // no formal exception type means we always pass the check
                }

                _builder.MarkLabel(typeCheckPassedLabel);
            }

            foreach (var local in catchBlock.Locals)
            {
                var declaringReferences = local.DeclaringSyntaxReferences;
                var localSyntax = !declaringReferences.IsEmpty ? (CSharpSyntaxNode)declaringReferences[0].GetSyntax() : catchBlock.Syntax;
                DefineLocal(local, localSyntax);
            }

            var exceptionSourceOpt = catchBlock.ExceptionSourceOpt;
            if (exceptionSourceOpt != null)
            {
                // here we have our exception on the stack in a form of a reference type (O)
                // it means that we have to "unbox" it before storing to the local 
                // if exception's type is a generic type parameter.
                if (!exceptionSourceOpt.Type.IsVerifierReference())
                {
                    Debug.Assert(exceptionSourceOpt.Type.IsTypeParameter()); // only expecting type parameters
                    _builder.EmitOpCode(ILOpCode.Unbox_any);
                    EmitSymbolToken(exceptionSourceOpt.Type, exceptionSourceOpt.Syntax);
                }

                BoundExpression exceptionSource = exceptionSourceOpt;
                while (exceptionSource.Kind == BoundKind.Sequence)
                {
                    var seq = (BoundSequence)exceptionSource;
                    EmitSideEffects(seq);
                    exceptionSource = seq.Value;
                }

                switch (exceptionSource.Kind)
                {
                    case BoundKind.Local:
                        var exceptionSourceLocal = (BoundLocal)exceptionSource;
                        Debug.Assert(exceptionSourceLocal.LocalSymbol.RefKind == RefKind.None);
                        if (!IsStackLocal(exceptionSourceLocal.LocalSymbol))
                        {
                            _builder.EmitLocalStore(GetLocal(exceptionSourceLocal));
                        }

                        break;

                    case BoundKind.FieldAccess:
                        var left = (BoundFieldAccess)exceptionSource;
                        Debug.Assert(!left.FieldSymbol.IsStatic, "Not supported");
                        Debug.Assert(!left.ReceiverOpt.Type.IsTypeParameter());

                        var stateMachineField = left.FieldSymbol as StateMachineFieldSymbol;
                        if (((object)stateMachineField != null) && (stateMachineField.SlotIndex >= 0))
                        {
                            _builder.DefineUserDefinedStateMachineHoistedLocal(stateMachineField.SlotIndex);
                        }

                        // When assigning to a field
                        // we need to push param address below the exception
                        var temp = AllocateTemp(exceptionSource.Type, exceptionSource.Syntax);
                        _builder.EmitLocalStore(temp);

                        var receiverTemp = EmitReceiverRef(left.ReceiverOpt);
                        Debug.Assert(receiverTemp == null);

                        _builder.EmitLocalLoad(temp);
                        FreeTemp(temp);

                        EmitFieldStore(left);
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(exceptionSource.Kind);
                }
            }
            else
            {
                _builder.EmitOpCode(ILOpCode.Pop);
            }

            // Emit the actual filter expression, if we have one, and normalize
            // results.
            if (catchBlock.ExceptionFilterOpt != null)
            {
                EmitCondExpr(catchBlock.ExceptionFilterOpt, true);
                // Normalize the return value because values other than 0 or 1
                // produce unspecified results.
                _builder.EmitIntConstant(0);
                _builder.EmitOpCode(ILOpCode.Cgt_un);
                _builder.MarkLabel(typeCheckFailedLabel);

                // Now we are starting the actual handler
                _builder.MarkFilterConditionEnd();

                // Pop the exception; it should have already been stored to the
                // variable by the filter.
                _builder.EmitOpCode(ILOpCode.Pop);
            }

            EmitBlock(catchBlock.Body);

            _builder.CloseLocalScope();
        }
Пример #15
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if (!node.Locals.IsDefaultOrEmpty)
            {
                // Yield/await aren't supported in catch block atm, but we need to rewrite the type 
                // of the variables owned by the catch block. Note that one of these variables might be a closure frame reference.
                var newLocals = RewriteLocals(node.Locals);

                return node.Update(
                    newLocals,
                    (BoundExpression)this.Visit(node.ExceptionSourceOpt),
                    this.VisitType(node.ExceptionTypeOpt),
                    (BoundExpression)this.Visit(node.ExceptionFilterOpt),
                    (BoundBlock)this.Visit(node.Body),
                    node.IsSynthesizedAsyncCatchAll);
            }

            return base.VisitCatchBlock(node);
        }
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            EnsureOnlyEvalStack();

            var locals = node.Locals;
            var exceptionSourceOpt = node.ExceptionSourceOpt;

            DeclareLocals(locals, stack: 0);

            if (exceptionSourceOpt != null)
            {
                // runtime pushes the exception object
                this.evalStack++;
                this.counter++;

                // We consume it by writing into the exception source.
                if (exceptionSourceOpt.Kind == BoundKind.Local)
                {
                    RecordVarWrite(((BoundLocal)exceptionSourceOpt).LocalSymbol);
                }
                else
                {
                    int prevStack = this.evalStack;
                    exceptionSourceOpt = VisitExpression(exceptionSourceOpt, ExprContext.AssignmentTarget);
                    Debug.Assert(evalStack == prevStack + (LhsUsesStackWhenAssignedTo(exceptionSourceOpt, ExprContext.AssignmentTarget) ? 1 : 0));
                    this.evalStack = prevStack;
                }

                this.evalStack--;
                this.counter++;
            }

            BoundExpression boundFilter;
            if (node.ExceptionFilterOpt != null)
            {
                boundFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt);

                // the value of filter expression is consumed by the VM
                this.evalStack--;
                this.counter++;

                // variables allocated on stack in a filter can't be used in the catch handler 
                EnsureOnlyEvalStack();
            }
            else
            {
                boundFilter = null;
            }

            var boundBlock = (BoundBlock)this.Visit(node.Body);
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            return node.Update(locals, exceptionSourceOpt, exceptionTypeOpt, boundFilter, boundBlock);
        }
        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);
        }
 /// <summary>
 /// Returns true if a catch contains awaits
 /// </summary>
 internal bool CatchContainsAwait(BoundCatchBlock node)
 {
     return(_awaitContainingCatches != null && _awaitContainingCatches.Contains(node));
 }
Пример #19
0
 public override BoundNode VisitCatchBlock(BoundCatchBlock node)
 {
     AddVariables(node.Locals);
     return(base.VisitCatchBlock(node));
 }
Пример #20
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            EnsureOnlyEvalStack();

            var local = node.LocalOpt;
            var exceptionSourceOpt = node.ExceptionSourceOpt;

            if ((object)local != null)
            {
                DeclareLocal(local, stack: 0);
            }

            if (exceptionSourceOpt != null)
            {
                // runtime pushes the exception object
                PushEvalStack(null, ExprContext.Value);
                _counter++;

                // We consume it by writing into the exception source.
                if (exceptionSourceOpt.Kind == BoundKind.Local)
                {
                    RecordVarWrite(((BoundLocal)exceptionSourceOpt).LocalSymbol);
                }
                else
                {
                    int prevStack = StackDepth();
                    exceptionSourceOpt = VisitExpression(exceptionSourceOpt, ExprContext.AssignmentTarget);
                    SetStackDepth(prevStack);
                }

                PopEvalStack();
                _counter++;
            }

            BoundExpression boundFilter;
            if (node.ExceptionFilterOpt != null)
            {
                boundFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt);

                // the value of filter expression is consumed by the VM
                PopEvalStack();
                _counter++;

                // variables allocated on stack in a filter can't be used in the catch handler 
                EnsureOnlyEvalStack();
            }
            else
            {
                boundFilter = null;
            }

            var boundBlock = (BoundBlock)this.Visit(node.Body);
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);

            return node.Update(local, exceptionSourceOpt, exceptionTypeOpt, boundFilter, boundBlock, node.IsSynthesizedAsyncCatchAll);
        }
Пример #21
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            if ((object)node.LocalOpt != null)
            {
                // Yield/await aren't supported in catch block atm, but we need to rewrite the type 
                // of the variable owned by the catch block. Note that this variable might be a closure frame reference.
                LocalSymbol newLocal;
                TryRewriteLocal(node.LocalOpt, out newLocal);

                return node.Update(
                    newLocal,
                    (BoundExpression)this.Visit(node.ExceptionSourceOpt),
                    this.VisitType(node.ExceptionTypeOpt),
                    (BoundExpression)this.Visit(node.ExceptionFilterOpt),
                    (BoundBlock)this.Visit(node.Body),
                    node.IsSynthesizedAsyncCatchAll);
            }

            return base.VisitCatchBlock(node);
        }
Пример #22
0
        public override BoundNode VisitCatchBlock(BoundCatchBlock node)
        {
            var exceptionSource = node.ExceptionSourceOpt;
            var type = node.ExceptionTypeOpt;
            var filter = node.ExceptionFilterOpt;
            var body = node.Body;

            if (exceptionSource != null)
            {
                // runtime pushes the exception object
                _nodeCounter++;

                if (exceptionSource.Kind == BoundKind.Local)
                {
                    var sourceLocal = ((BoundLocal)exceptionSource).LocalSymbol;
                    LocalDefUseInfo locInfo;

                    // If catch is the last access, we do not need to store the exception object.
                    if (_info.TryGetValue(sourceLocal, out locInfo) &&
                        IsLastAccess(locInfo, _nodeCounter))
                    {
                        exceptionSource = null;
                    }
                }
                else
                {
                    exceptionSource = (BoundExpression)Visit(exceptionSource);
                }

                // we consume it by writing into the local
                _nodeCounter++;
            }

            if (filter != null)
            {
                filter = (BoundExpression)this.Visit(filter);

                // the value of filter expression is consumed by the VM
                _nodeCounter++;
            }

            body = (BoundBlock)this.Visit(body);
            type = this.VisitType(type);

            return node.Update(node.LocalOpt, exceptionSource, type, filter, body, node.IsSynthesizedAsyncCatchAll);
        }
Пример #23
0
 public override BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory)
 {
     return(Previous.InstrumentCatchClauseFilter(original, rewrittenFilter, factory));
 }