示例#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
        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));
        }
示例#3
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));
        }
示例#4
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);
        }
示例#5
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);
        }
        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)
        {
            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);
        }
        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)
        {
            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);
        }