File: CodeGen\CodeGenAsyncEHTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit\Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
    public class CodeGenAsyncEHTests : EmitMetadataTestBase
    {
        private static readonly MetadataReference[] s_asyncRefs = new[] { MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929 };
 
        public CodeGenAsyncEHTests()
        {
        }
 
        private CompilationVerifier CompileAndVerify(string source, string expectedOutput = null, IEnumerable<MetadataReference> references = null, CSharpCompilationOptions options = null)
        {
            references = (references != null) ? references.Concat(s_asyncRefs) : s_asyncRefs;
            return base.CompileAndVerify(source, targetFramework: TargetFramework.Empty, expectedOutput: expectedOutput, references: references, options: options);
        }
 
        [Fact]
        [WorkItem(624970, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/624970")]
        public void AsyncWithEH()
        {
            var source = @"
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
 
class Test
{
    static int awaitCount = 0;
    static int finallyCount = 0;
 
    static void LogAwait()
    {
        Interlocked.Increment(ref awaitCount);
    }
 
    static void LogException()
    {
        Interlocked.Increment(ref finallyCount);
    }
 
    public static async void F(AutoResetEvent handle)
    {
        try
        {
            await Task.Factory.StartNew(LogAwait);
            try
            {
                await Task.Factory.StartNew(LogAwait);
                try
                {
                    await Task.Factory.StartNew(LogAwait);
                    try
                    {
                        await Task.Factory.StartNew(LogAwait);
                        throw new Exception();
                    }
                    catch (Exception)
                    {
                    }
                    finally
                    {
                        LogException();
                    }
                    await Task.Factory.StartNew(LogAwait);
                    throw new Exception();
                }
                catch (Exception)
                {
                }
                finally
                {
                    LogException();
                }
                await Task.Factory.StartNew(LogAwait);
                throw new Exception();
            }
            catch (Exception)
            {
            }
            finally
            {
                LogException();
            }
            await Task.Factory.StartNew(LogAwait);
        }
        finally
        {
            handle.Set();
        }
    }
 
    public static void Main2(int i)
    {
        try
        {
            awaitCount = 0;
            finallyCount = 0;
            var handle = new AutoResetEvent(false);
            F(handle);
            var completed = handle.WaitOne(1000 * 60);
            if (completed)
            {
                if (awaitCount != 7 || finallyCount != 3)
                {
                    throw new Exception(""failed at i="" + i);
                }
            }
            else
            {
                Console.WriteLine(""Test did not complete in time."");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(""unexpected exception thrown:"");
            Console.WriteLine(ex.ToString());
        }
    }
 
    public static void Main()
    {
        for (int i = 0; i < 1500; i++)
        {
            Main2(i);
        }
    }
}";
            var expected = @"";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [WorkItem(14878, "https://github.com/dotnet/roslyn/issues/14878")]
        [Fact]
        public void AsyncWithEHCodeQuality()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> G()
    {
        int x = 1;
 
        try
        {
            try
            {
                try
                {
                    await Task.Yield();
                    x += 1;
                    await Task.Yield();
                    x += 1;
                    await Task.Yield();
                    x += 1;
                    await Task.Yield();
                    x += 1;
                    await Task.Yield();
                    x += 1;
                    await Task.Yield();
                    x += 1;
                }
                finally
                {
                    x += 1;
                }
            }
            finally
            {
                x += 1;
            }
        }
        finally
        {
            x += 1;
        }
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
10
";
            CompileAndVerify(source, expectedOutput: expected).
VerifyIL("Test.<G>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      819 (0x333)
  .maxstack  3
  .locals init (int V_0,
                int V_1,
                System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2,
                System.Runtime.CompilerServices.YieldAwaitable V_3,
                System.Exception V_4)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int Test.<G>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  ldc.i4.5
    IL_0009:  ble.un.s   IL_0012
    IL_000b:  ldarg.0
    IL_000c:  ldc.i4.1
    IL_000d:  stfld      ""int Test.<G>d__0.<x>5__2""
    IL_0012:  nop
    .try
    {
      IL_0013:  ldloc.0
      IL_0014:  ldc.i4.5
      IL_0015:  pop
      IL_0016:  pop
      IL_0017:  nop
      .try
      {
        IL_0018:  ldloc.0
        IL_0019:  ldc.i4.5
        IL_001a:  pop
        IL_001b:  pop
        IL_001c:  nop
        .try
        {
          IL_001d:  ldloc.0
          IL_001e:  switch    (
        IL_0075,
        IL_00e0,
        IL_014b,
        IL_01b6,
        IL_0221,
        IL_028c)
          IL_003b:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_0040:  stloc.3
          IL_0041:  ldloca.s   V_3
          IL_0043:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_0048:  stloc.2
          IL_0049:  ldloca.s   V_2
          IL_004b:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_0050:  brtrue.s   IL_0091
          IL_0052:  ldarg.0
          IL_0053:  ldc.i4.0
          IL_0054:  dup
          IL_0055:  stloc.0
          IL_0056:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_005b:  ldarg.0
          IL_005c:  ldloc.2
          IL_005d:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0062:  ldarg.0
          IL_0063:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_0068:  ldloca.s   V_2
          IL_006a:  ldarg.0
          IL_006b:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_0070:  leave      IL_0332
          IL_0075:  ldarg.0
          IL_0076:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_007b:  stloc.2
          IL_007c:  ldarg.0
          IL_007d:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0082:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_0088:  ldarg.0
          IL_0089:  ldc.i4.m1
          IL_008a:  dup
          IL_008b:  stloc.0
          IL_008c:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_0091:  ldloca.s   V_2
          IL_0093:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_0098:  ldarg.0
          IL_0099:  ldarg.0
          IL_009a:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_009f:  ldc.i4.1
          IL_00a0:  add
          IL_00a1:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_00a6:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_00ab:  stloc.3
          IL_00ac:  ldloca.s   V_3
          IL_00ae:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_00b3:  stloc.2
          IL_00b4:  ldloca.s   V_2
          IL_00b6:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_00bb:  brtrue.s   IL_00fc
          IL_00bd:  ldarg.0
          IL_00be:  ldc.i4.1
          IL_00bf:  dup
          IL_00c0:  stloc.0
          IL_00c1:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_00c6:  ldarg.0
          IL_00c7:  ldloc.2
          IL_00c8:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_00cd:  ldarg.0
          IL_00ce:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_00d3:  ldloca.s   V_2
          IL_00d5:  ldarg.0
          IL_00d6:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_00db:  leave      IL_0332
          IL_00e0:  ldarg.0
          IL_00e1:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_00e6:  stloc.2
          IL_00e7:  ldarg.0
          IL_00e8:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_00ed:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_00f3:  ldarg.0
          IL_00f4:  ldc.i4.m1
          IL_00f5:  dup
          IL_00f6:  stloc.0
          IL_00f7:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_00fc:  ldloca.s   V_2
          IL_00fe:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_0103:  ldarg.0
          IL_0104:  ldarg.0
          IL_0105:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_010a:  ldc.i4.1
          IL_010b:  add
          IL_010c:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_0111:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_0116:  stloc.3
          IL_0117:  ldloca.s   V_3
          IL_0119:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_011e:  stloc.2
          IL_011f:  ldloca.s   V_2
          IL_0121:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_0126:  brtrue.s   IL_0167
          IL_0128:  ldarg.0
          IL_0129:  ldc.i4.2
          IL_012a:  dup
          IL_012b:  stloc.0
          IL_012c:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_0131:  ldarg.0
          IL_0132:  ldloc.2
          IL_0133:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0138:  ldarg.0
          IL_0139:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_013e:  ldloca.s   V_2
          IL_0140:  ldarg.0
          IL_0141:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_0146:  leave      IL_0332
          IL_014b:  ldarg.0
          IL_014c:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0151:  stloc.2
          IL_0152:  ldarg.0
          IL_0153:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0158:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_015e:  ldarg.0
          IL_015f:  ldc.i4.m1
          IL_0160:  dup
          IL_0161:  stloc.0
          IL_0162:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_0167:  ldloca.s   V_2
          IL_0169:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_016e:  ldarg.0
          IL_016f:  ldarg.0
          IL_0170:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_0175:  ldc.i4.1
          IL_0176:  add
          IL_0177:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_017c:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_0181:  stloc.3
          IL_0182:  ldloca.s   V_3
          IL_0184:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_0189:  stloc.2
          IL_018a:  ldloca.s   V_2
          IL_018c:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_0191:  brtrue.s   IL_01d2
          IL_0193:  ldarg.0
          IL_0194:  ldc.i4.3
          IL_0195:  dup
          IL_0196:  stloc.0
          IL_0197:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_019c:  ldarg.0
          IL_019d:  ldloc.2
          IL_019e:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_01a3:  ldarg.0
          IL_01a4:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_01a9:  ldloca.s   V_2
          IL_01ab:  ldarg.0
          IL_01ac:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_01b1:  leave      IL_0332
          IL_01b6:  ldarg.0
          IL_01b7:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_01bc:  stloc.2
          IL_01bd:  ldarg.0
          IL_01be:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_01c3:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_01c9:  ldarg.0
          IL_01ca:  ldc.i4.m1
          IL_01cb:  dup
          IL_01cc:  stloc.0
          IL_01cd:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_01d2:  ldloca.s   V_2
          IL_01d4:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_01d9:  ldarg.0
          IL_01da:  ldarg.0
          IL_01db:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_01e0:  ldc.i4.1
          IL_01e1:  add
          IL_01e2:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_01e7:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_01ec:  stloc.3
          IL_01ed:  ldloca.s   V_3
          IL_01ef:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_01f4:  stloc.2
          IL_01f5:  ldloca.s   V_2
          IL_01f7:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_01fc:  brtrue.s   IL_023d
          IL_01fe:  ldarg.0
          IL_01ff:  ldc.i4.4
          IL_0200:  dup
          IL_0201:  stloc.0
          IL_0202:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_0207:  ldarg.0
          IL_0208:  ldloc.2
          IL_0209:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_020e:  ldarg.0
          IL_020f:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_0214:  ldloca.s   V_2
          IL_0216:  ldarg.0
          IL_0217:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_021c:  leave      IL_0332
          IL_0221:  ldarg.0
          IL_0222:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0227:  stloc.2
          IL_0228:  ldarg.0
          IL_0229:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_022e:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_0234:  ldarg.0
          IL_0235:  ldc.i4.m1
          IL_0236:  dup
          IL_0237:  stloc.0
          IL_0238:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_023d:  ldloca.s   V_2
          IL_023f:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_0244:  ldarg.0
          IL_0245:  ldarg.0
          IL_0246:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_024b:  ldc.i4.1
          IL_024c:  add
          IL_024d:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_0252:  call       ""System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()""
          IL_0257:  stloc.3
          IL_0258:  ldloca.s   V_3
          IL_025a:  call       ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()""
          IL_025f:  stloc.2
          IL_0260:  ldloca.s   V_2
          IL_0262:  call       ""bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get""
          IL_0267:  brtrue.s   IL_02a8
          IL_0269:  ldarg.0
          IL_026a:  ldc.i4.5
          IL_026b:  dup
          IL_026c:  stloc.0
          IL_026d:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_0272:  ldarg.0
          IL_0273:  ldloc.2
          IL_0274:  stfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0279:  ldarg.0
          IL_027a:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
          IL_027f:  ldloca.s   V_2
          IL_0281:  ldarg.0
          IL_0282:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, Test.<G>d__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Test.<G>d__0)""
          IL_0287:  leave      IL_0332
          IL_028c:  ldarg.0
          IL_028d:  ldfld      ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0292:  stloc.2
          IL_0293:  ldarg.0
          IL_0294:  ldflda     ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Test.<G>d__0.<>u__1""
          IL_0299:  initobj    ""System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter""
          IL_029f:  ldarg.0
          IL_02a0:  ldc.i4.m1
          IL_02a1:  dup
          IL_02a2:  stloc.0
          IL_02a3:  stfld      ""int Test.<G>d__0.<>1__state""
          IL_02a8:  ldloca.s   V_2
          IL_02aa:  call       ""void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()""
          IL_02af:  ldarg.0
          IL_02b0:  ldarg.0
          IL_02b1:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_02b6:  ldc.i4.1
          IL_02b7:  add
          IL_02b8:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_02bd:  leave.s    IL_02d2
        }
        finally
        {
          IL_02bf:  ldloc.0
          IL_02c0:  ldc.i4.0
          IL_02c1:  bge.s      IL_02d1
          IL_02c3:  ldarg.0
          IL_02c4:  ldarg.0
          IL_02c5:  ldfld      ""int Test.<G>d__0.<x>5__2""
          IL_02ca:  ldc.i4.1
          IL_02cb:  add
          IL_02cc:  stfld      ""int Test.<G>d__0.<x>5__2""
          IL_02d1:  endfinally
        }
        IL_02d2:  leave.s    IL_02e7
      }
      finally
      {
        IL_02d4:  ldloc.0
        IL_02d5:  ldc.i4.0
        IL_02d6:  bge.s      IL_02e6
        IL_02d8:  ldarg.0
        IL_02d9:  ldarg.0
        IL_02da:  ldfld      ""int Test.<G>d__0.<x>5__2""
        IL_02df:  ldc.i4.1
        IL_02e0:  add
        IL_02e1:  stfld      ""int Test.<G>d__0.<x>5__2""
        IL_02e6:  endfinally
      }
      IL_02e7:  leave.s    IL_02fc
    }
    finally
    {
      IL_02e9:  ldloc.0
      IL_02ea:  ldc.i4.0
      IL_02eb:  bge.s      IL_02fb
      IL_02ed:  ldarg.0
      IL_02ee:  ldarg.0
      IL_02ef:  ldfld      ""int Test.<G>d__0.<x>5__2""
      IL_02f4:  ldc.i4.1
      IL_02f5:  add
      IL_02f6:  stfld      ""int Test.<G>d__0.<x>5__2""
      IL_02fb:  endfinally
    }
    IL_02fc:  ldarg.0
    IL_02fd:  ldfld      ""int Test.<G>d__0.<x>5__2""
    IL_0302:  stloc.1
    IL_0303:  leave.s    IL_031e
  }
  catch System.Exception
  {
    IL_0305:  stloc.s    V_4
    IL_0307:  ldarg.0
    IL_0308:  ldc.i4.s   -2
    IL_030a:  stfld      ""int Test.<G>d__0.<>1__state""
    IL_030f:  ldarg.0
    IL_0310:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
    IL_0315:  ldloc.s    V_4
    IL_0317:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
    IL_031c:  leave.s    IL_0332
  }
  IL_031e:  ldarg.0
  IL_031f:  ldc.i4.s   -2
  IL_0321:  stfld      ""int Test.<G>d__0.<>1__state""
  IL_0326:  ldarg.0
  IL_0327:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__0.<>t__builder""
  IL_032c:  ldloc.1
  IL_032d:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
  IL_0332:  ret
}
");
        }
 
        [Fact, WorkItem(855080, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/855080")]
        public void GenericCatchVariableInAsyncMethod()
        {
            var source = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Bar().Result);
        }
        static async Task<int> Bar()
        {
            NotImplementedException ex = await Goo<NotImplementedException>();
            return 3;
        }
        public static async Task<T> Goo<T>() where T : Exception
        {
            Task<int> task = null;
            if (task != null) await task;
            T result = null;
            try
            {
            }
            catch (T ex)
            {
                result = ex;
            }
            return result;
        }
    }
}
";
            CompileAndVerify(source, expectedOutput: "3");
        }
 
        [Fact]
        public void AsyncWithException1()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        throw new Exception();
    }
 
    static async Task<int> G()
    {
        try
        {
            return await F();
        }
        catch(Exception)
        {
            return -1;
        }
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
-1
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncWithException2()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        throw new Exception();
    }
 
    static async Task<int> H()
    {
        return await F();
    }
 
    public static void Main()
    {
        Task<int> t1 = H();
        try
        {
            t1.Wait(1000 * 60);
        }
        catch (AggregateException)
        {
            Console.WriteLine(""exception"");
        }
    }
}";
            var expected = @"
exception
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInFinally001()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 42;
 
        try
        {
        }
        finally
        {
            x = await F();
        }
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
2
";
            CompileAndVerify(source, expectedOutput: expected).
VerifyIL("Test.<G>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      210 (0xd2)
  .maxstack  3
  .locals init (int V_0,
                int V_1,
                object V_2,
                System.Runtime.CompilerServices.TaskAwaiter<int> V_3,
                System.Exception V_4)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int Test.<G>d__1.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_0058
    IL_000a:  ldarg.0
    IL_000b:  ldnull
    IL_000c:  stfld      ""object Test.<G>d__1.<>7__wrap1""
    IL_0011:  ldarg.0
    IL_0012:  ldc.i4.0
    IL_0013:  stfld      ""int Test.<G>d__1.<>7__wrap2""
    .try
    {
      IL_0018:  leave.s    IL_0024
    }
    catch object
    {
      IL_001a:  stloc.2
      IL_001b:  ldarg.0
      IL_001c:  ldloc.2
      IL_001d:  stfld      ""object Test.<G>d__1.<>7__wrap1""
      IL_0022:  leave.s    IL_0024
    }
    IL_0024:  call       ""System.Threading.Tasks.Task<int> Test.F()""
    IL_0029:  callvirt   ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
    IL_002e:  stloc.3
    IL_002f:  ldloca.s   V_3
    IL_0031:  call       ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
    IL_0036:  brtrue.s   IL_0074
    IL_0038:  ldarg.0
    IL_0039:  ldc.i4.0
    IL_003a:  dup
    IL_003b:  stloc.0
    IL_003c:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_0041:  ldarg.0
    IL_0042:  ldloc.3
    IL_0043:  stfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0048:  ldarg.0
    IL_0049:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_004e:  ldloca.s   V_3
    IL_0050:  ldarg.0
    IL_0051:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
    IL_0056:  leave.s    IL_00d1
    IL_0058:  ldarg.0
    IL_0059:  ldfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_005e:  stloc.3
    IL_005f:  ldarg.0
    IL_0060:  ldflda     ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0065:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter<int>""
    IL_006b:  ldarg.0
    IL_006c:  ldc.i4.m1
    IL_006d:  dup
    IL_006e:  stloc.0
    IL_006f:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_0074:  ldloca.s   V_3
    IL_0076:  call       ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
    IL_007b:  ldarg.0
    IL_007c:  ldfld      ""object Test.<G>d__1.<>7__wrap1""
    IL_0081:  stloc.2
    IL_0082:  ldloc.2
    IL_0083:  brfalse.s  IL_009a
    IL_0085:  ldloc.2
    IL_0086:  isinst     ""System.Exception""
    IL_008b:  dup
    IL_008c:  brtrue.s   IL_0090
    IL_008e:  ldloc.2
    IL_008f:  throw
    IL_0090:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_0095:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_009a:  ldarg.0
    IL_009b:  ldnull
    IL_009c:  stfld      ""object Test.<G>d__1.<>7__wrap1""
    IL_00a1:  stloc.1
    IL_00a2:  leave.s    IL_00bd
  }
  catch System.Exception
  {
    IL_00a4:  stloc.s    V_4
    IL_00a6:  ldarg.0
    IL_00a7:  ldc.i4.s   -2
    IL_00a9:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_00ae:  ldarg.0
    IL_00af:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_00b4:  ldloc.s    V_4
    IL_00b6:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
    IL_00bb:  leave.s    IL_00d1
  }
  IL_00bd:  ldarg.0
  IL_00be:  ldc.i4.s   -2
  IL_00c0:  stfld      ""int Test.<G>d__1.<>1__state""
  IL_00c5:  ldarg.0
  IL_00c6:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
  IL_00cb:  ldloc.1
  IL_00cc:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
  IL_00d1:  ret
}
");
        }
 
        [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsWindowsTypes)]
        public void AsyncInFinally002()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        System.Console.Write(""F"");
        return 2;
    }
 
    static async Task G()
    {
        int x = 0;
 
        try
        {
            throw new Exception(""hello"");
        }
        finally
        {
            x += await F();
        }
    }
 
    public static void Main()
    {
        System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
 
        try
        {
            Task t2 = G();
            try
            {
                t2.Wait(1000 * 60);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        finally
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
        }
    }
}";
            var expected = @"FOne or more errors occurred.
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)]
        public void AsyncInFinally003()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            x = await F();
            return x;
        }
        finally
        {
            x += await F();
        }
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
2
";
            var v = CompileAndVerify(source, s_asyncRefs, targetFramework: TargetFramework.Empty, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: expected, symbolValidator: module =>
            {
                Assert.Equal(new[]
                {
                    "<>1__state",
                    "<>t__builder",
                    "<x>5__1",
                    "<>s__2", // pending exception
                    "<>s__3", // pending branch
                    "<>s__4", // return value
                    "<>s__5", // spill
                    "<>s__6", // spill
                    "<>s__7", // spill
                    "<>u__1", // awaiter
                }, module.GetFieldNames("Test.<G>d__1"));
            });
 
            v.VerifyPdb("Test.G", @"
<symbols>
  <files>
    <file id=""1"" name="""" language=""C#"" />
  </files>
  <entryPoint declaringType=""Test"" methodName=""Main"" />
  <methods>
    <method containingType=""Test"" name=""G"">
      <customDebugInfo>
        <forwardIterator name=""&lt;G&gt;d__1"" />
        <encLocalSlotMap>
          <slot kind=""0"" offset=""15"" />
          <slot kind=""22"" offset=""33"" />
          <slot kind=""23"" offset=""33"" />
          <slot kind=""20"" offset=""33"" />
          <slot kind=""28"" offset=""65"" />
          <slot kind=""28"" offset=""156"" />
          <slot kind=""28"" offset=""156"" ordinal=""1"" />
        </encLocalSlotMap>
        <encStateMachineStateMap>
          <state number=""0"" offset=""65"" />
          <state number=""1"" offset=""156"" />
        </encStateMachineStateMap>
      </customDebugInfo>
    </method>
  </methods>
</symbols>
");
 
            v.VerifyIL("Test.<G>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext",
@"{
  // Code size      461 (0x1cd)
  .maxstack  3
  .locals init (int V_0,
                int V_1,
                System.Runtime.CompilerServices.TaskAwaiter<int> V_2,
                Test.<G>d__1 V_3,
                object V_4,
                System.Runtime.CompilerServices.TaskAwaiter<int> V_5,
                System.Exception V_6,
                int V_7)
 ~IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int Test.<G>d__1.<>1__state""
  IL_0006:  stloc.0
  .try
  {
   ~IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_0012
    IL_000a:  br.s       IL_000c
    IL_000c:  ldloc.0
    IL_000d:  ldc.i4.1
    IL_000e:  beq.s      IL_0014
    IL_0010:  br.s       IL_0019
    IL_0012:  br.s       IL_002f
    IL_0014:  br         IL_0115
   -IL_0019:  nop
   -IL_001a:  ldarg.0
    IL_001b:  ldc.i4.0
    IL_001c:  stfld      ""int Test.<G>d__1.<x>5__1""
   ~IL_0021:  ldarg.0
    IL_0022:  ldnull
    IL_0023:  stfld      ""object Test.<G>d__1.<>s__2""
    IL_0028:  ldarg.0
    IL_0029:  ldc.i4.0
    IL_002a:  stfld      ""int Test.<G>d__1.<>s__3""
   ~IL_002f:  nop
    .try
    {
     ~IL_0030:  ldloc.0
      IL_0031:  brfalse.s  IL_0035
      IL_0033:  br.s       IL_0037
      IL_0035:  br.s       IL_0073
     -IL_0037:  nop
     -IL_0038:  call       ""System.Threading.Tasks.Task<int> Test.F()""
      IL_003d:  callvirt   ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
      IL_0042:  stloc.2
     ~IL_0043:  ldloca.s   V_2
      IL_0045:  call       ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
      IL_004a:  brtrue.s   IL_008f
      IL_004c:  ldarg.0
      IL_004d:  ldc.i4.0
      IL_004e:  dup
      IL_004f:  stloc.0
      IL_0050:  stfld      ""int Test.<G>d__1.<>1__state""
     <IL_0055:  ldarg.0
      IL_0056:  ldloc.2
      IL_0057:  stfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
      IL_005c:  ldarg.0
      IL_005d:  stloc.3
      IL_005e:  ldarg.0
      IL_005f:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
      IL_0064:  ldloca.s   V_2
      IL_0066:  ldloca.s   V_3
      IL_0068:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
      IL_006d:  nop
      IL_006e:  leave      IL_01cc
     >IL_0073:  ldarg.0
      IL_0074:  ldfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
      IL_0079:  stloc.2
      IL_007a:  ldarg.0
      IL_007b:  ldflda     ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
      IL_0080:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter<int>""
      IL_0086:  ldarg.0
      IL_0087:  ldc.i4.m1
      IL_0088:  dup
      IL_0089:  stloc.0
      IL_008a:  stfld      ""int Test.<G>d__1.<>1__state""
      IL_008f:  ldarg.0
      IL_0090:  ldloca.s   V_2
      IL_0092:  call       ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
      IL_0097:  stfld      ""int Test.<G>d__1.<>s__5""
      IL_009c:  ldarg.0
      IL_009d:  ldarg.0
      IL_009e:  ldfld      ""int Test.<G>d__1.<>s__5""
      IL_00a3:  stfld      ""int Test.<G>d__1.<x>5__1""
     -IL_00a8:  ldarg.0
      IL_00a9:  ldarg.0
      IL_00aa:  ldfld      ""int Test.<G>d__1.<x>5__1""
      IL_00af:  stfld      ""int Test.<G>d__1.<>s__4""
      IL_00b4:  br.s       IL_00b6
      IL_00b6:  ldarg.0
      IL_00b7:  ldc.i4.1
      IL_00b8:  stfld      ""int Test.<G>d__1.<>s__3""
      IL_00bd:  leave.s    IL_00cb
    }
    catch object
    {
     ~IL_00bf:  stloc.s    V_4
      IL_00c1:  ldarg.0
      IL_00c2:  ldloc.s    V_4
      IL_00c4:  stfld      ""object Test.<G>d__1.<>s__2""
      IL_00c9:  leave.s    IL_00cb
    }
   -IL_00cb:  nop
   -IL_00cc:  ldarg.0
    IL_00cd:  ldarg.0
    IL_00ce:  ldfld      ""int Test.<G>d__1.<x>5__1""
    IL_00d3:  stfld      ""int Test.<G>d__1.<>s__6""
    IL_00d8:  call       ""System.Threading.Tasks.Task<int> Test.F()""
    IL_00dd:  callvirt   ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
    IL_00e2:  stloc.s    V_5
   ~IL_00e4:  ldloca.s   V_5
    IL_00e6:  call       ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
    IL_00eb:  brtrue.s   IL_0132
    IL_00ed:  ldarg.0
    IL_00ee:  ldc.i4.1
    IL_00ef:  dup
    IL_00f0:  stloc.0
    IL_00f1:  stfld      ""int Test.<G>d__1.<>1__state""
   <IL_00f6:  ldarg.0
    IL_00f7:  ldloc.s    V_5
    IL_00f9:  stfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_00fe:  ldarg.0
    IL_00ff:  stloc.3
    IL_0100:  ldarg.0
    IL_0101:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_0106:  ldloca.s   V_5
    IL_0108:  ldloca.s   V_3
    IL_010a:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
    IL_010f:  nop
    IL_0110:  leave      IL_01cc
   >IL_0115:  ldarg.0
    IL_0116:  ldfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_011b:  stloc.s    V_5
    IL_011d:  ldarg.0
    IL_011e:  ldflda     ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0123:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter<int>""
    IL_0129:  ldarg.0
    IL_012a:  ldc.i4.m1
    IL_012b:  dup
    IL_012c:  stloc.0
    IL_012d:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_0132:  ldarg.0
    IL_0133:  ldloca.s   V_5
    IL_0135:  call       ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
    IL_013a:  stfld      ""int Test.<G>d__1.<>s__7""
    IL_013f:  ldarg.0
    IL_0140:  ldarg.0
    IL_0141:  ldfld      ""int Test.<G>d__1.<>s__6""
    IL_0146:  ldarg.0
    IL_0147:  ldfld      ""int Test.<G>d__1.<>s__7""
    IL_014c:  add
    IL_014d:  stfld      ""int Test.<G>d__1.<x>5__1""
   -IL_0152:  nop
   ~IL_0153:  ldarg.0
    IL_0154:  ldfld      ""object Test.<G>d__1.<>s__2""
    IL_0159:  stloc.s    V_4
    IL_015b:  ldloc.s    V_4
    IL_015d:  brfalse.s  IL_017c
    IL_015f:  ldloc.s    V_4
    IL_0161:  isinst     ""System.Exception""
    IL_0166:  stloc.s    V_6
    IL_0168:  ldloc.s    V_6
    IL_016a:  brtrue.s   IL_016f
    IL_016c:  ldloc.s    V_4
    IL_016e:  throw
    IL_016f:  ldloc.s    V_6
    IL_0171:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_0176:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_017b:  nop
    IL_017c:  ldarg.0
    IL_017d:  ldfld      ""int Test.<G>d__1.<>s__3""
    IL_0182:  stloc.s    V_7
    IL_0184:  ldloc.s    V_7
    IL_0186:  ldc.i4.1
    IL_0187:  beq.s      IL_018b
    IL_0189:  br.s       IL_0194
    IL_018b:  ldarg.0
    IL_018c:  ldfld      ""int Test.<G>d__1.<>s__4""
    IL_0191:  stloc.1
    IL_0192:  leave.s    IL_01b7
    IL_0194:  ldarg.0
    IL_0195:  ldnull
    IL_0196:  stfld      ""object Test.<G>d__1.<>s__2""
    IL_019b:  leave.s    IL_01b7
  }
  catch System.Exception
  {
   ~IL_019d:  stloc.s    V_6
    IL_019f:  ldarg.0
    IL_01a0:  ldc.i4.s   -2
    IL_01a2:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_01a7:  ldarg.0
    IL_01a8:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_01ad:  ldloc.s    V_6
    IL_01af:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
    IL_01b4:  nop
    IL_01b5:  leave.s    IL_01cc
  }
 -IL_01b7:  ldarg.0
  IL_01b8:  ldc.i4.s   -2
  IL_01ba:  stfld      ""int Test.<G>d__1.<>1__state""
 ~IL_01bf:  ldarg.0
  IL_01c0:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
  IL_01c5:  ldloc.1
  IL_01c6:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
  IL_01cb:  nop
  IL_01cc:  ret
}", sequencePoints: "Test+<G>d__1.MoveNext");
        }
 
        [Fact]
        public void AsyncInFinally004()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                throw new Exception();
            }
            finally
            {
                x += await F();
            }
        }
        catch
        {
            return x;
        }
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
2
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInFinallyNested001()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F(int a)
    {
        await Task.Yield();
        return a;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                x = await F(1);
                goto L1;
                System.Console.WriteLine(""FAIL"");
            }
            finally
            {
                x += await F(2);
            }
        }
        finally
        {
            try
            {
                x += await F(4);
            }
            finally
            {
                x += await F(8);
            }
        }
 
        System.Console.WriteLine(""FAIL"");
 
        L1:
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"15";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInFinallyNested002()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F(int a)
    {
        await Task.Yield();
        return a;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                try
                {
                    x = await F(1);
                    throw new Exception(""hello"");
                    System.Console.WriteLine(""FAIL"");
                }
                finally
                {
                    x += await F(2);
                }
 
                System.Console.WriteLine(""FAIL"");
            }
            finally
            {
                try
                {
                    x += await F(4);
                }
                finally
                {
                    x += await F(8);
                }
            }
 
            System.Console.WriteLine(""FAIL"");
        }
        catch(Exception ex)
        {
            System.Console.WriteLine(ex.Message);
        }      
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"hello
15";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInFinallyNested003()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F(int a)
    {
        await Task.Yield();
        return a;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                try
                {
                    x = await F(1);
                    throw new Exception(""hello"");
                    System.Console.WriteLine(""FAIL"");
                }
                finally
                {
                    x += await F(2);
                }
 
                System.Console.WriteLine(""FAIL"");
            }
            finally
            {
                try
                {
                    x += await F(4);
                }
                finally
                {
                    x += await F(8);
                    throw new Exception(""bye"");
                }
            }
 
            System.Console.WriteLine(""FAIL"");
        }
        catch(Exception ex)
        {
            System.Console.WriteLine(ex.Message);
        }      
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"bye
15";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInCatch001()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            x = x / x;
        }
        catch
        {
            x = await F();
        }
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
2
";
            CompileAndVerify(source, expectedOutput: expected).
VerifyIL("Test.<G>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      170 (0xaa)
  .maxstack  3
  .locals init (int V_0,
                int V_1,
                int V_2, //x
                int V_3,
                System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
                System.Exception V_5)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int Test.<G>d__1.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_0053
    IL_000a:  ldc.i4.0
    IL_000b:  stloc.2
    IL_000c:  ldc.i4.0
    IL_000d:  stloc.3
    .try
    {
      IL_000e:  ldloc.2
      IL_000f:  ldloc.2
      IL_0010:  div
      IL_0011:  stloc.2
      IL_0012:  leave.s    IL_0019
    }
    catch object
    {
      IL_0014:  pop
      IL_0015:  ldc.i4.1
      IL_0016:  stloc.3
      IL_0017:  leave.s    IL_0019
    }
    IL_0019:  ldloc.3
    IL_001a:  ldc.i4.1
    IL_001b:  bne.un.s   IL_0078
    IL_001d:  call       ""System.Threading.Tasks.Task<int> Test.F()""
    IL_0022:  callvirt   ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
    IL_0027:  stloc.s    V_4
    IL_0029:  ldloca.s   V_4
    IL_002b:  call       ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
    IL_0030:  brtrue.s   IL_0070
    IL_0032:  ldarg.0
    IL_0033:  ldc.i4.0
    IL_0034:  dup
    IL_0035:  stloc.0
    IL_0036:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_003b:  ldarg.0
    IL_003c:  ldloc.s    V_4
    IL_003e:  stfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0043:  ldarg.0
    IL_0044:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_0049:  ldloca.s   V_4
    IL_004b:  ldarg.0
    IL_004c:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
    IL_0051:  leave.s    IL_00a9
    IL_0053:  ldarg.0
    IL_0054:  ldfld      ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0059:  stloc.s    V_4
    IL_005b:  ldarg.0
    IL_005c:  ldflda     ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__1""
    IL_0061:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter<int>""
    IL_0067:  ldarg.0
    IL_0068:  ldc.i4.m1
    IL_0069:  dup
    IL_006a:  stloc.0
    IL_006b:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_0070:  ldloca.s   V_4
    IL_0072:  call       ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
    IL_0077:  stloc.2
    IL_0078:  ldloc.2
    IL_0079:  stloc.1
    IL_007a:  leave.s    IL_0095
  }
  catch System.Exception
  {
    IL_007c:  stloc.s    V_5
    IL_007e:  ldarg.0
    IL_007f:  ldc.i4.s   -2
    IL_0081:  stfld      ""int Test.<G>d__1.<>1__state""
    IL_0086:  ldarg.0
    IL_0087:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
    IL_008c:  ldloc.s    V_5
    IL_008e:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
    IL_0093:  leave.s    IL_00a9
  }
  IL_0095:  ldarg.0
  IL_0096:  ldc.i4.s   -2
  IL_0098:  stfld      ""int Test.<G>d__1.<>1__state""
  IL_009d:  ldarg.0
  IL_009e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
  IL_00a3:  ldloc.1
  IL_00a4:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
  IL_00a9:  ret
}
");
        }
 
        [Fact]
        public void AsyncInCatchRethrow()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        await Task.Yield();
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                x = x / x;
            }
            catch
            {
                x = await F();
                throw;
            }
        }
        catch(DivideByZeroException ex)
        {
            x = await F();
            System.Console.WriteLine(ex.Message);
        }
 
        return x;
    }
 
    public static void Main()
    {
        System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
 
        try
        {
            Task<int> t2 = G();
            t2.Wait(1000 * 60);
            Console.WriteLine(t2.Result);
        }
        finally
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
        }
    }
}";
            var expected = @"
Attempted to divide by zero.
2
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [WorkItem(74, "https://github.com/dotnet/roslyn/issues/1334")]
        [Fact]
        public void AsyncInCatchRethrow01()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        await Task.Yield();
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                x = x / x;
            }
            catch (ArgumentNullException)
            {
                x = await F();
            }
            catch
            {
                Console.WriteLine(""rethrowing"");
                throw;
            }
        }
        catch(DivideByZeroException ex)
        {
            x += await F();
            System.Console.WriteLine(ex.Message);
        }
 
        return x;
    }
 
    public static void Main()
    {
        System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
 
        try
        {
            Task<int> t2 = G();
            t2.Wait(1000 * 60);
            Console.WriteLine(t2.Result);
        }
        finally
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
        }
    }
}";
            var expected = @"rethrowing
Attempted to divide by zero.
2
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [WorkItem(74, "https://github.com/dotnet/roslyn/issues/1334")]
        [Fact]
        public void AsyncInCatchRethrow02()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        await Task.Yield();
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                x = x / x;
            }
            catch (ArgumentNullException)
            {
                Console.WriteLine(""should not get here"");
            }
            catch (Exception ex) when (ex == null)
            {
                Console.WriteLine(""should not get here"");
            }
            catch
            {
                x = await F();
                Console.WriteLine(""rethrowing"");
                throw;
            }
        }
        catch(DivideByZeroException ex)
        {
            x += await F();
            System.Console.WriteLine(ex.Message);
        }
 
        return x;
    }
 
    public static void Main()
    {
        System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
 
        try
        {
            Task<int> t2 = G();
            t2.Wait(1000 * 60);
            Console.WriteLine(t2.Result);
        }
        finally
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
        }
    }
}";
            var expected = @"rethrowing
Attempted to divide by zero.
4
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInCatchFilter()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        await Task.Yield();
        return 2;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                x = x / x;
            }
            catch when(x != 0)
            {
                x = await F();
                throw;
            }
        }
        catch(Exception ex) when(x == 0 && ((ex = new Exception(""hello"")) != null))
        {
            x = await F();
            System.Console.WriteLine(ex.Message);
        }
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
hello
2
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInCatchFilterLifted()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F()
    {
        await Task.Yield();
        return 2;
    }
 
    static bool T(Func<bool> f, ref Exception ex)
    {
        var result = f();
        ex = new Exception(result.ToString());
        return result;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            x = x / x;
        }
        catch(Exception ex) when(T(()=>ex.Message == null, ref ex))
        {
            x = await F();
            System.Console.WriteLine(ex.Message);
        }
        catch(Exception ex) when(T(()=>ex.Message != null, ref ex))
        {
            x = await F();
            System.Console.WriteLine(ex.Message);
        }
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"True
2
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInCatchFinallyMixed()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F(int x)
    {
        await Task.Yield();
        return x;
    }
 
    static async Task<int> G()
    {
        int x = 0;
 
        try
        {
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    try
                    {
                        try
                        {
                            x = x / await F(0);
                        }
                        catch (DivideByZeroException) when (i < 3)
                        {
                            await Task.Yield();
                            continue;
                        }
                        catch (DivideByZeroException)
                        {
                            x = 2 + await F(x);
                            throw;
                        }
                        System.Console.WriteLine(""FAIL"");
                    }
                    finally
                    {
                        x = await F(x) + 3;
                        if (i >= 3)
                        {
                            throw new Exception(""hello"");
                        }
                    }
                }
            }
            finally
            {
                x = 11 + await F(x);
            }
        }
        catch (Exception ex)
        {
            x = await F(x) + 17;
            System.Console.WriteLine(ex.Message);
        }
 
        return x;
    }
 
    public static void Main()
    {
        Task<int> t2 = G();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
hello
42
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void AsyncInCatchFinallyMixed_InAsyncLambda()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    static async Task<int> F(int x)
    {
        await Task.Yield();
        return x;
    }
 
    static Func<Task<int>> G()
    {
        int x = 0;
 
        return async () =>
        {
            try
            {
                try
                {
                    for (int i = 0; i < 5; i++)
                    {
                        try
                        {
                            try
                            {
                                x = x / await F(0);
                            }
                            catch (DivideByZeroException) when (i < 3)
                            {
                                await Task.Yield();
                                continue;
                            }
                            catch (DivideByZeroException)
                            {
                                x = 2 + await F(x);
                                throw;
                            }
                            System.Console.WriteLine(""FAIL"");
                        }
                        finally
                        {
                            x = await F(x) + 3;
                            if (i >= 3)
                            {
                                throw new Exception(""hello"");
                            }
                        }
                    }
                }
                finally
                {
                    x = 11 + await F(x);
                }
            }
            catch (Exception ex)
            {
                x = await F(x) + 17;
                System.Console.WriteLine(ex.Message);
            }
 
            return x;
        };
    }
 
    public static void Main()
    {
        Task<int> t2 = G()();
        t2.Wait(1000 * 60);
        Console.WriteLine(t2.Result);
    }
}";
            var expected = @"
hello
42
";
            CompileAndVerify(source, expectedOutput: expected);
        }
 
        [Fact]
        public void DoFinallyBodies()
        {
            var source = @"
using System.Threading.Tasks;
using System;
 
class Driver
{
    public static int finally_count = 0;
 
    static async Task F()
    {
        try
        {
            await Task.Factory.StartNew(() => { });
        }
        finally
        {
            Driver.finally_count++;
        }
    }
    
    static void Main()
    {
        var t = F();
        t.Wait();
        Console.WriteLine(Driver.finally_count);
    }
}";
            var expected = @"
1
";
            CompileAndVerify(source, expected);
        }
 
        [Fact, WorkItem(67091, "https://github.com/dotnet/roslyn/issues/67091")]
        public void NestedCatch_DuplicateLocal()
        {
            var source = """
                using System;
                using System.Threading.Tasks;
                using static System.Console;
 
                class C
                {
                    static async Task Main()
                    {
                        await new C().M1(catchFirst: false);
                        WriteLine("--- catch first ---");
                        await new C().M1(catchFirst: true);
                    }
 
                    bool F(string caller, Exception ex, bool result)
                    {
                        WriteLine($"F: {caller} {ex.Message}");
                        return result;
                    }
 
                    async Task M1(bool catchFirst)
                    {
                        try
                        {
                            throw new Exception("M1");
                        }
                        catch (Exception ex) when (F("M1-catch1", ex, catchFirst))
                        {
                            await M2("M1-catch1", ex);
                        }
                        catch (Exception ex) when (F("M1-catch2", ex, true))
                        {
                            try
                            {
                                throw new Exception("M1-catch2");
                            }
                            catch 
                            {
                                await M2("M1-catch2-catch", ex);
                            }
                        }
                    }
 
                    async Task M2(string caller, Exception ex)
                    {
                        WriteLine($"M2: {caller} {ex.Message}");
                        await Task.Yield();
                    }
                }
                """;
            var expectedOutput = """
                F: M1-catch1 M1
                F: M1-catch2 M1
                M2: M1-catch2-catch M1
                --- catch first ---
                F: M1-catch1 M1
                M2: M1-catch1 M1
                """;
 
            CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact, WorkItem(67091, "https://github.com/dotnet/roslyn/issues/67091")]
        public void NestedCatch_DuplicateLocal_Level2()
        {
            var source = """
                using System;
                using System.Threading.Tasks;
                using static System.Console;
 
                class C
                {
                    static async Task Main()
                    {
                        foreach (var catchFirst1 in new[] { false, true })
                        {
                            foreach (var catchFirst2 in new[] { false, true })
                            {
                                WriteLine($"--- catchFirst1={catchFirst1}, catchFirst2={catchFirst2} ---");
                                await new C().M1(catchFirst1: catchFirst1, catchFirst2: catchFirst2);
                            }
                        }
                    }
 
                    bool F(string caller, Exception ex, bool result)
                    {
                        WriteLine($"F: {caller} {ex.Message}");
                        return result;
                    }
 
                    async Task M1(bool catchFirst1, bool catchFirst2)
                    {
                        try
                        {
                            throw new Exception("M1-try");
                        }
                        catch (Exception ex) when (F("M1-catch1", ex, catchFirst1))
                        {
                            await M2("M1-catch1", ex);
                        }
                        catch (Exception ex) when (F("M1-catch2", ex, true))
                        {
                            try
                            {
                                throw new Exception("M1-catch2");
                            }
                            catch (Exception ex2) when (F("M1-catch2-catch1", ex2, catchFirst2))
                            {
                                await M2("M1-catch2-catch1-ex", ex);
                                await M2("M1-catch2-catch1-ex2", ex2);
                            }
                            catch (Exception ex2) when (F("M1-catch2-catch2", ex2, true))
                            {
                                try
                                {
                                    throw new Exception("M1-catch2-catch1");
                                }
                                catch
                                {
                                    await M2("M1-catch2-catch2-catch-ex", ex);
                                    await M2("M1-catch2-catch2-catch-ex2", ex2);
                                }
                            }
                        }
                    }
 
                    async Task M2(string caller, Exception ex)
                    {
                        await Task.Yield();
                        WriteLine($"M2: {caller} {ex.Message}");
                    }
                }
                """;
            var expectedOutput = """
                --- catchFirst1=False, catchFirst2=False ---
                F: M1-catch1 M1-try
                F: M1-catch2 M1-try
                F: M1-catch2-catch1 M1-catch2
                F: M1-catch2-catch2 M1-catch2
                M2: M1-catch2-catch2-catch-ex M1-try
                M2: M1-catch2-catch2-catch-ex2 M1-catch2
                --- catchFirst1=False, catchFirst2=True ---
                F: M1-catch1 M1-try
                F: M1-catch2 M1-try
                F: M1-catch2-catch1 M1-catch2
                M2: M1-catch2-catch1-ex M1-try
                M2: M1-catch2-catch1-ex2 M1-catch2
                --- catchFirst1=True, catchFirst2=False ---
                F: M1-catch1 M1-try
                M2: M1-catch1 M1-try
                --- catchFirst1=True, catchFirst2=True ---
                F: M1-catch1 M1-try
                M2: M1-catch1 M1-try
                """;
 
            CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/70483")]
        public void NestedCatch_DuplicateLocal_NoAwaitInNestedCatch(bool awaitInTry2)
        {
            var source = $$"""
                using System;
                using System.Threading.Tasks;
                using static System.Console;
                
                class C
                {
                    static async Task Main()
                    {
                        await new C().M1(catchFirst: false);
                        WriteLine("--- catch first ---");
                        await new C().M1(catchFirst: true);
                    }
                
                    bool F(string caller, bool result)
                    {
                        WriteLine($"F: {caller}");
                        return result;
                    }
                
                    async Task M1(bool catchFirst)
                    {
                        try
                        {
                            throw new Exception("M1");
                        }
                        catch (Exception ex) when (F("M1-catch1", catchFirst))
                        {
                            await M2("M1-catch1", ex);
                        }
                        catch (Exception ex) when (F("M1-catch2", true))
                        {
                            try
                            {
                                {{(awaitInTry2 ? "await Task.Yield();" : "")}}
                                throw new Exception("M1-catch2");
                            }
                            catch 
                            {
                                _ = M2("M1-catch2-catch", ex);
                            }
                        }
                    }
                
                    async Task M2(string caller, Exception ex)
                    {
                        WriteLine($"M2: {caller} {ex.Message}");
                        await Task.Yield();
                    }
                }
                """;
 
            var expectedOutput = """
                F: M1-catch1
                F: M1-catch2
                M2: M1-catch2-catch M1
                --- catch first ---
                F: M1-catch1
                M2: M1-catch1 M1
                """;
 
            CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71569")]
        public void NestedRethrow(bool await1, bool await2)
        {
            var source = $$"""
                using System;
                using System.Threading.Tasks;
 
                try
                {
                    await Test1();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.GetType().Name);
                }
 
                try
                {
                    await Test2();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.GetType().Name);
                }
 
                static async Task Test1()
                {
                    try
                    {
                        throw new Exception1();
                    }
                    catch (Exception1)
                    {
                        try
                        {
                            await Task.FromException(new Exception2());
                        }
                        catch (Exception2)
                        {
                            {{(await1 ? "await Task.Yield();" : "")}}
                            throw;
                        }
                    }
                }
 
                static async Task Test2()
                {
                    try
                    {
                        throw new Exception1();
                    }
                    catch (Exception1)
                    {
                        try
                        {
                            await Task.FromException(new Exception2());
                        }
                        catch (Exception2 ex)
                        {
                            {{(await2 ? "await Task.Yield();" : "")}}
                            throw ex;
                        }
                    }
                }
 
                class Exception1 : Exception { }
                class Exception2 : Exception { }
                """;
 
            var expectedOutput = """
                Exception2
                Exception2
                """;
 
            CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput,
                targetFramework: TargetFramework.Mscorlib46).VerifyDiagnostics();
            CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: expectedOutput,
                targetFramework: TargetFramework.Mscorlib46).VerifyDiagnostics();
        }
 
        [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71569")]
        public void NestedRethrow_02(bool await1, bool await2, bool await3)
        {
            var source = $$"""
                #pragma warning disable 1998 // async method lacks 'await' operators
                using System;
                using System.Threading.Tasks;
 
                try
                {
                    await Run();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.GetType().Name);
                }
 
                static async Task Run()
                {
                    try
                    {
                        throw new Exception1();
                    }
                    catch (Exception1)
                    {
                        try
                        {
                            {{(await1 ? "await Task.Yield();" : "")}}
                            throw new Exception2();
                        }
                        catch (Exception2)
                        {
                            try
                            {
                                {{(await2 ? "await Task.Yield();" : "")}}
                                throw new Exception3();
                            }
                            catch (Exception3)
                            {
                                {{(await3 ? "await Task.Yield();" : "")}}
                                throw;
                            }
                        }
                    }
                }
 
                class Exception1 : Exception { }
                class Exception2 : Exception { }
                class Exception3 : Exception { }
                """;
 
            var expectedOutput = "Exception3";
 
            CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/71569")]
        [InlineData("await Task.Yield();")]
        [InlineData("await using var c = new C();")]
        [InlineData("await foreach (var x in new C()) { }")]
        public void NestedRethrow_03(string statement)
        {
            var source = $$"""
                using System;
                using System.Collections.Generic;
                using System.Threading;
                using System.Threading.Tasks;
 
                try
                {
                    await Run();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.GetType().Name);
                }
 
                static async Task Run()
                {
                    try
                    {
                        throw new Exception1();
                    }
                    catch (Exception1)
                    {
                        {{statement}}
                        try
                        {
                            throw new Exception2();
                        }
                        catch (Exception2)
                        {
                            try
                            {
                                throw new Exception3();
                            }
                            catch (Exception3)
                            {
                                throw;
                            }
                        }
                    }
                }
 
                class Exception1 : Exception { }
                class Exception2 : Exception { }
                class Exception3 : Exception { }
 
                class C : IAsyncDisposable, IAsyncEnumerable<int>
                {
                    public async ValueTask DisposeAsync() => await Task.Yield();
                    public async IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken ct)
                    {
                        await Task.Yield();
                        yield return 1;
                    }
                }
                """;
 
            CSharpTestSource sources = [source, AsyncStreamsTypes];
 
            var expectedOutput = "Exception3";
 
            CompileAndVerify(CreateCompilationWithTasksExtensions(sources, options: TestOptions.DebugExe), expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(CreateCompilationWithTasksExtensions(sources, options: TestOptions.ReleaseExe), expectedOutput: expectedOutput).VerifyDiagnostics();
        }
    }
}