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)); }
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)); }
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 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); }
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); }