public override void VisitTry(BoundTry node) { // Rules for try/catch: // * Try stays the default; // * Catch becomes a fork (it's only taken when an exception is // thrown); // * Finally is treated special. It's also executed on the default // branch, but it's also executed from break/continue/throw/return's, // because these flow through the finally. We don't do this here, // but in JoinOnBlock. var block = new Block(_branch, null, false, false, node.Finally); PushBlock(block); Visit(node.Try); if (node.Catch != null) { // Create a block for the catch. var catchBlock = new Block(block.Branch, null, false, false, null); PushBlock(catchBlock); _branch = catchBlock.Branch.Fork(); Visit(node.Catch); catchBlock.JoinBranch(_branch); // Create an empty fork to tell the Join algorithm that the // Catch was an optional branch. catchBlock.JoinBranch(catchBlock.Branch.Fork()); PopBlock(catchBlock); } Visit(node.Finally); PopBlock(block); }
public virtual void VisitTry(BoundTry node) { DefaultVisit(node); }
private void EmitTry(BoundTry node) { _scope.EntryTryCatch(); IL.BeginExceptionBlock(); EmitStatement(node.Try); // Emit the catch block. if (node.Catch != null) { IL.BeginCatchBlock(typeof(Exception)); if (node.Catch.Target == null) { IL.Emit(OpCodes.Pop); } else { // Store the unwrapped exception in a local. var exceptionTarget = IL.DeclareLocal(typeof(Exception)); IL.Emit(OpCodes.Stloc, exceptionTarget); // Wrap the exception. _scope.EmitLoad(SpecialLocal.Runtime); IL.Emit(OpCodes.Ldloc, exceptionTarget); IL.EmitCall(_runtimeWrapException); // Assign the exception to a local. var wrappedExceptionTarget = IL.DeclareLocal(typeof(object)); IL.Emit(OpCodes.Stloc, wrappedExceptionTarget); // Assign the wrapped exception to the target. EmitSetVariable( node.Catch.Target, new BoundEmitExpression( BoundValueType.Unknown, () => IL.Emit(OpCodes.Ldloc, wrappedExceptionTarget) ) ); } // Emit the body for the catch. EmitStatement(node.Catch.Body); } // Emit the finally block. if (node.Finally != null) { IL.BeginFinallyBlock(); EmitStatement(node.Finally.Body); } IL.EndExceptionBlock(); _scope.LeaveTryCatch(); }