/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTryFinally.cs
4 314 строк
91 KB
Copilot
Remove CS1998 warning entirely and remove dependent C# code fix providers (#80144)
19 сен 2025, 20:17
Не верифицирован
19 сен 2025, 20:17
84133cc
Код
Авторство
О чём код?
// 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 Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen { public class CodeGenTryFinallyTests : CSharpTestBase { [Fact] public void EmptyTryFinally() { var source = @"class C { static void EmptyTryFinally() { try { } finally { } } static void EmptyTryFinallyInTry() { try { try { } finally { } } finally { } } static void EmptyTryFinallyInFinally() { try { } finally { try { } finally { } } } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.EmptyTryFinally", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); compilation.VerifyIL("C.EmptyTryFinallyInTry", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); compilation.VerifyIL("C.EmptyTryFinallyInFinally", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); } [Theory, WorkItem(4729, "https://github.com/dotnet/roslyn/issues/4729")] [InlineData("")] [InlineData(";")] public void NopInTryCatchFinally(string doNothingStatements) { var source = $@"class C {{ static void M1() {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ {doNothingStatements} }} }} static void M2() {{ try {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ {doNothingStatements} }} }} catch (System.Exception) {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ {doNothingStatements} }} }} finally {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ {doNothingStatements} }} }} }} static void M3() {{ try {{ System.Console.WriteLine(1); }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ {doNothingStatements} }} }} static void M4() {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ System.Console.WriteLine(1); }} finally {{ {doNothingStatements} }} }} static void M5() {{ try {{ {doNothingStatements} }} catch (System.Exception) {{ {doNothingStatements} }} finally {{ System.Console.WriteLine(1); }} }} }}"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.M1", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); compilation.VerifyIL("C.M2", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); compilation.VerifyIL("C.M3", @"{ // Code size 12 (0xc) .maxstack 1 .try { IL_0000: ldc.i4.1 IL_0001: call ""void System.Console.WriteLine(int)"" IL_0006: leave.s IL_000b } catch System.Exception { IL_0008: pop IL_0009: leave.s IL_000b } IL_000b: ret }"); compilation.VerifyIL("C.M4", @"{ // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); compilation.VerifyIL("C.M5", @"{ // Code size 10 (0xa) .maxstack 1 .try { IL_0000: leave.s IL_0009 } finally { IL_0002: ldc.i4.1 IL_0003: call ""void System.Console.WriteLine(int)"" IL_0008: endfinally } IL_0009: ret }"); } [Fact] public void TryFinally() { var source = @"class C { static void Main() { M(1); M(0); } static void M(int f) { try { System.Console.Write(""1, ""); if (f > 0) goto End; System.Console.Write(""2, ""); return; } finally { System.Console.Write(""3, ""); } End: System.Console.Write(""4, ""); } }"; var compilation = CompileAndVerify(source, expectedOutput: "1, 3, 4, 1, 2, 3, "); compilation.VerifyIL("C.M", @"{ // Code size 50 (0x32) .maxstack 2 .try { IL_0000: ldstr ""1, "" IL_0005: call ""void System.Console.Write(string)"" IL_000a: ldarg.0 IL_000b: ldc.i4.0 IL_000c: ble.s IL_0010 IL_000e: leave.s IL_0027 IL_0010: ldstr ""2, "" IL_0015: call ""void System.Console.Write(string)"" IL_001a: leave.s IL_0031 } finally { IL_001c: ldstr ""3, "" IL_0021: call ""void System.Console.Write(string)"" IL_0026: endfinally } IL_0027: ldstr ""4, "" IL_002c: call ""void System.Console.Write(string)"" IL_0031: ret }"); } [Fact] public void TryCatch() { var source = @"using System; class C { static void Main() { M(1); M(0); } static void M(int f) { try { Console.Write(""before, ""); N(f); Console.Write(""after, ""); } catch (Exception) { Console.Write(""catch, ""); } } static void N(int f) { if (f > 0) throw new Exception(); } }"; var compilation = CompileAndVerify(source, expectedOutput: "before, catch, before, after,"); compilation.VerifyIL("C.M", @"{ // Code size 42 (0x2a) .maxstack 1 .try { IL_0000: ldstr ""before, "" IL_0005: call ""void System.Console.Write(string)"" IL_000a: ldarg.0 IL_000b: call ""void C.N(int)"" IL_0010: ldstr ""after, "" IL_0015: call ""void System.Console.Write(string)"" IL_001a: leave.s IL_0029 } catch System.Exception { IL_001c: pop IL_001d: ldstr ""catch, "" IL_0022: call ""void System.Console.Write(string)"" IL_0027: leave.s IL_0029 } IL_0029: ret }"); } [Fact] public void TryCatch001() { var source = @"using System; class C { static void Main() { } static void M() { try { System.Object o = null; o.ToString();//null Exception throw } catch (System.NullReferenceException NullException)//null Exception caught { try { throw new System.ApplicationException();//app Exception throw } catch (System.ApplicationException AppException)//app Exception caught { throw new System.DivideByZeroException();//Zero Exception throw } } } }"; var compilation = CompileAndVerify(source, expectedOutput: ""); compilation.VerifyIL("C.M", @"{ // Code size 24 (0x18) .maxstack 1 .try { IL_0000: ldnull IL_0001: callvirt ""string object.ToString()"" IL_0006: pop IL_0007: leave.s IL_0017 } catch System.NullReferenceException { IL_0009: pop .try { IL_000a: newobj ""System.ApplicationException..ctor()"" IL_000f: throw } catch System.ApplicationException { IL_0010: pop IL_0011: newobj ""System.DivideByZeroException..ctor()"" IL_0016: throw } } IL_0017: ret }"); } [Fact] public void TryCatch002() { var source = @"using System; class C { static void Main() { } static void M() { try { System.Object o = null; o.ToString();//null Exception throw goto l1; } catch (System.NullReferenceException NullException)//null Exception caught { try { throw new System.ApplicationException();//app Exception throw } catch (System.ApplicationException AppException)//app Exception caught { throw new System.DivideByZeroException();//Zero Exception throw } } l1: ; ; ; } }"; var compilation = CompileAndVerify(source, expectedOutput: ""); compilation.VerifyIL("C.M", @" { // Code size 24 (0x18) .maxstack 1 .try { IL_0000: ldnull IL_0001: callvirt ""string object.ToString()"" IL_0006: pop IL_0007: leave.s IL_0017 } catch System.NullReferenceException { IL_0009: pop .try { IL_000a: newobj ""System.ApplicationException..ctor()"" IL_000f: throw } catch System.ApplicationException { IL_0010: pop IL_0011: newobj ""System.DivideByZeroException..ctor()"" IL_0016: throw } } IL_0017: ret }"); } [WorkItem(813428, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/813428")] [Fact] public void TryCatchOptimized001() { var source = @" using System; using System.Diagnostics; class Program { static void Main() { try { throw new Exception(""debug only""); } catch (Exception ex) { Debug.Write(ex.Message); } try { throw new Exception(""hello""); } catch (Exception ex) { Console.Write(ex.Message); } try { throw new Exception(""bye""); } catch (Exception ex) { Console.Write(ex.Message); Console.Write(ex.Message); } } } "; var compilation = CompileAndVerify(source, expectedOutput: "hellobyebye"); compilation.VerifyIL("Program.Main", @" { // Code size 74 (0x4a) .maxstack 2 .try { IL_0000: ldstr ""debug only"" IL_0005: newobj ""System.Exception..ctor(string)"" IL_000a: throw } catch System.Exception { IL_000b: pop IL_000c: leave.s IL_000e } IL_000e: nop .try { IL_000f: ldstr ""hello"" IL_0014: newobj ""System.Exception..ctor(string)"" IL_0019: throw } catch System.Exception { IL_001a: callvirt ""string System.Exception.Message.get"" IL_001f: call ""void System.Console.Write(string)"" IL_0024: leave.s IL_0026 } IL_0026: nop .try { IL_0027: ldstr ""bye"" IL_002c: newobj ""System.Exception..ctor(string)"" IL_0031: throw } catch System.Exception { IL_0032: dup IL_0033: callvirt ""string System.Exception.Message.get"" IL_0038: call ""void System.Console.Write(string)"" IL_003d: callvirt ""string System.Exception.Message.get"" IL_0042: call ""void System.Console.Write(string)"" IL_0047: leave.s IL_0049 } IL_0049: ret } "); } [Fact] public void TryFilterOptimized001() { var source = @" using System; class Program { static void Main() { try { throw new Exception(""hello""); } catch (Exception ex1) when (ex1.Message == null) { } try { throw new Exception(""bye""); } catch (Exception ex2) when (F(ex2, ex2)) { } } private static bool F(Exception e1, Exception e2) { return false; } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("Program.Main", @" { // Code size 78 (0x4e) .maxstack 2 .try { IL_0000: ldstr ""hello"" IL_0005: newobj ""System.Exception..ctor(string)"" IL_000a: throw } filter { IL_000b: isinst ""System.Exception"" IL_0010: dup IL_0011: brtrue.s IL_0017 IL_0013: pop IL_0014: ldc.i4.0 IL_0015: br.s IL_0022 IL_0017: callvirt ""string System.Exception.Message.get"" IL_001c: ldnull IL_001d: ceq IL_001f: ldc.i4.0 IL_0020: cgt.un IL_0022: endfilter } // end filter { // handler IL_0024: pop IL_0025: leave.s IL_0027 } IL_0027: nop .try { IL_0028: ldstr ""bye"" IL_002d: newobj ""System.Exception..ctor(string)"" IL_0032: throw } filter { IL_0033: isinst ""System.Exception"" IL_0038: dup IL_0039: brtrue.s IL_003f IL_003b: pop IL_003c: ldc.i4.0 IL_003d: br.s IL_0048 IL_003f: dup IL_0040: call ""bool Program.F(System.Exception, System.Exception)"" IL_0045: ldc.i4.0 IL_0046: cgt.un IL_0048: endfilter } // end filter { // handler IL_004a: pop IL_004b: leave.s IL_004d } IL_004d: ret } "); } [Fact] public void TryFilterOptimized002() { var source = @" using System; class Program { static void Main() { try { throw new Exception(""bye""); } catch (Exception ex) when (F(ex, ex)) { Console.WriteLine(ex); } } private static bool F(Exception e1, Exception e2) { return false; } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("Program.Main", @" { // Code size 46 (0x2e) .maxstack 2 .locals init (System.Exception V_0) //ex .try { IL_0000: ldstr ""bye"" IL_0005: newobj ""System.Exception..ctor(string)"" IL_000a: throw } filter { IL_000b: isinst ""System.Exception"" IL_0010: dup IL_0011: brtrue.s IL_0017 IL_0013: pop IL_0014: ldc.i4.0 IL_0015: br.s IL_0022 IL_0017: stloc.0 IL_0018: ldloc.0 IL_0019: ldloc.0 IL_001a: call ""bool Program.F(System.Exception, System.Exception)"" IL_001f: ldc.i4.0 IL_0020: cgt.un IL_0022: endfilter } // end filter { // handler IL_0024: pop IL_0025: ldloc.0 IL_0026: call ""void System.Console.WriteLine(object)"" IL_002b: leave.s IL_002d } IL_002d: ret } "); } [Fact] public void TryFilterOptimized003() { var source = @" using System; class Program { static void Main() { try { throw new Exception(""bye""); } catch (Exception ex) when (F(ref ex)) { Console.WriteLine(ex); } } private static bool F(ref Exception e) { e = null; return true; } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("Program.Main", @" { // Code size 46 (0x2e) .maxstack 2 .locals init (System.Exception V_0) //ex .try { IL_0000: ldstr ""bye"" IL_0005: newobj ""System.Exception..ctor(string)"" IL_000a: throw } filter { IL_000b: isinst ""System.Exception"" IL_0010: dup IL_0011: brtrue.s IL_0017 IL_0013: pop IL_0014: ldc.i4.0 IL_0015: br.s IL_0022 IL_0017: stloc.0 IL_0018: ldloca.s V_0 IL_001a: call ""bool Program.F(ref System.Exception)"" IL_001f: ldc.i4.0 IL_0020: cgt.un IL_0022: endfilter } // end filter { // handler IL_0024: pop IL_0025: ldloc.0 IL_0026: call ""void System.Console.WriteLine(object)"" IL_002b: leave.s IL_002d } IL_002d: ret }"); } [Fact] public void TryFilterOptimized004() { var source = @" using System; class Program { static void F<T>() where T : Exception { try { throw new Exception(""bye""); } catch (T ex) when (F(ex, ex)) { Console.WriteLine(ex); } } private static bool F<S>(S e1, S e2) { return false; } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("Program.F<T>", @" { // Code size 56 (0x38) .maxstack 2 .locals init (T V_0) //ex .try { IL_0000: ldstr ""bye"" IL_0005: newobj ""System.Exception..ctor(string)"" IL_000a: throw } filter { IL_000b: isinst ""T"" IL_0010: dup IL_0011: brtrue.s IL_0017 IL_0013: pop IL_0014: ldc.i4.0 IL_0015: br.s IL_0027 IL_0017: unbox.any ""T"" IL_001c: stloc.0 IL_001d: ldloc.0 IL_001e: ldloc.0 IL_001f: call ""bool Program.F<T>(T, T)"" IL_0024: ldc.i4.0 IL_0025: cgt.un IL_0027: endfilter } // end filter { // handler IL_0029: pop IL_002a: ldloc.0 IL_002b: box ""T"" IL_0030: call ""void System.Console.WriteLine(object)"" IL_0035: leave.s IL_0037 } IL_0037: ret } "); } [Fact, WorkItem(854935, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854935")] public void LiftedExceptionVariableInGenericIterator() { var source = @" using System; using System.IO; using System.Collections.Generic; class C { public IEnumerable<int> Iter2<T>() { try { throw new IOException(""Hi""); } catch (Exception e) { ( (Action) delegate { Console.WriteLine(e.Message); })(); } yield return 1; } static void Main() { foreach (var x in new C().Iter2<object>()) { } } }"; CompileAndVerify(source, expectedOutput: "Hi"); } [Fact, WorkItem(854935, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854935")] public void GenericLiftedExceptionVariableInGenericIterator() { var source = @" using System; using System.IO; using System.Collections.Generic; class C { public IEnumerable<int> Iter2<T, E>() where E : Exception { try { throw new IOException(""Hi""); } catch (E e) when (new Func<bool>(() => e.Message != null)()) { ( (Action) delegate { Console.WriteLine(e.Message); })(); } yield return 1; } static void Main() { foreach (var x in new C().Iter2<object, IOException>()) { } } }"; CompileAndVerify(source, expectedOutput: "Hi"); } [WorkItem(579778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/579778")] [Fact] public void Regression579778() { var source = @" using System; using System.Security; [assembly: SecurityTransparent()] class C { static void nop() {} static void Main() { try { throw null; } catch (Exception) { } finally { try { nop(); } catch { } } } }"; var compilation = CompileAndVerify(source, expectedOutput: ""); compilation.VerifyIL("C.Main", @" { // Code size 18 (0x12) .maxstack 1 .try { .try { IL_0000: ldnull IL_0001: throw } catch System.Exception { IL_0002: pop IL_0003: leave.s IL_0011 } } finally { IL_0005: nop .try { IL_0006: call ""void C.nop()"" IL_000b: leave.s IL_0010 } catch object { IL_000d: pop IL_000e: leave.s IL_0010 } IL_0010: endfinally } IL_0011: ret } "); } [Fact] public void NestedExceptionHandlers() { var source = @"using System; class C { static void F(int i) { if (i == 0) { throw new Exception(""i == 0""); } throw new InvalidOperationException(""i != 0""); } static void M(int i) { try { try { F(i); } catch (InvalidOperationException e) { Console.WriteLine(""InvalidOperationException: {0}"", e.Message); F(i + 1); } } catch (Exception e) { Console.WriteLine(""Exception: {0}"", e.Message); } } static void Main() { M(0); M(1); } }"; var compilation = CompileAndVerify(source, expectedOutput: @"Exception: i == 0 InvalidOperationException: i != 0 Exception: i != 0"); compilation.VerifyIL("C.M", @" { // Code size 57 (0x39) .maxstack 2 .locals init (System.InvalidOperationException V_0, //e System.Exception V_1) //e .try { .try { IL_0000: ldarg.0 IL_0001: call ""void C.F(int)"" IL_0006: leave.s IL_0023 } catch System.InvalidOperationException { IL_0008: stloc.0 IL_0009: ldstr ""InvalidOperationException: {0}"" IL_000e: ldloc.0 IL_000f: callvirt ""string System.Exception.Message.get"" IL_0014: call ""void System.Console.WriteLine(string, object)"" IL_0019: ldarg.0 IL_001a: ldc.i4.1 IL_001b: add IL_001c: call ""void C.F(int)"" IL_0021: leave.s IL_0023 } IL_0023: leave.s IL_0038 } catch System.Exception { IL_0025: stloc.1 IL_0026: ldstr ""Exception: {0}"" IL_002b: ldloc.1 IL_002c: callvirt ""string System.Exception.Message.get"" IL_0031: call ""void System.Console.WriteLine(string, object)"" IL_0036: leave.s IL_0038 } IL_0038: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort01() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { s.Set(); for (; ;) ; } catch (Exception ex) { Console.WriteLine(""catch1""); } } catch (Exception ex) { Console.WriteLine(""catch2""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 catch2 "); compilation.VerifyIL("Program.Test", @" { // Code size 41 (0x29) .maxstack 1 .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: br.s IL_000a } catch System.Exception { IL_000c: pop IL_000d: ldstr ""catch1"" IL_0012: call ""void System.Console.WriteLine(string)"" IL_0017: leave.s IL_0019 } IL_0019: leave.s IL_0028 } catch System.Exception { IL_001b: pop IL_001c: ldstr ""catch2"" IL_0021: call ""void System.Console.WriteLine(string)"" IL_0026: leave.s IL_0028 } IL_0028: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort02() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { try { s.Set(); for (; ;) ; } catch (Exception ex) { Console.WriteLine(""catch1""); } } finally { Console.WriteLine(""finally""); } } catch (Exception ex) { Console.WriteLine(""catch2""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 finally catch2 "); compilation.VerifyIL("Program.Test", @" { // Code size 54 (0x36) .maxstack 1 .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: br.s IL_000a } catch System.Exception { IL_000c: pop IL_000d: ldstr ""catch1"" IL_0012: call ""void System.Console.WriteLine(string)"" IL_0017: leave.s IL_0019 } IL_0019: leave.s IL_0026 } finally { IL_001b: ldstr ""finally"" IL_0020: call ""void System.Console.WriteLine(string)"" IL_0025: endfinally } IL_0026: leave.s IL_0035 } catch System.Exception { IL_0028: pop IL_0029: ldstr ""catch2"" IL_002e: call ""void System.Console.WriteLine(string)"" IL_0033: leave.s IL_0035 } IL_0035: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort03() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { try { try { s.Set(); while (s != null) {}; } catch (Exception ex) { Console.WriteLine(""catch1""); } } finally { Console.WriteLine(""finally1""); } } catch (Exception ex) { Console.WriteLine(""catch2""); } } finally { Console.WriteLine(""finally2""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 finally1 catch2 finally2 "); compilation.VerifyIL("Program.Test", @" { // Code size 72 (0x48) .maxstack 1 .try { .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_000f: brtrue.s IL_000a IL_0011: leave.s IL_0020 } catch System.Exception { IL_0013: pop IL_0014: ldstr ""catch1"" IL_0019: call ""void System.Console.WriteLine(string)"" IL_001e: leave.s IL_0020 } IL_0020: leave.s IL_002d } finally { IL_0022: ldstr ""finally1"" IL_0027: call ""void System.Console.WriteLine(string)"" IL_002c: endfinally } IL_002d: leave.s IL_0047 } catch System.Exception { IL_002f: pop IL_0030: ldstr ""catch2"" IL_0035: call ""void System.Console.WriteLine(string)"" IL_003a: leave.s IL_0047 } } finally { IL_003c: ldstr ""finally2"" IL_0041: call ""void System.Console.WriteLine(string)"" IL_0046: endfinally } IL_0047: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort04() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { try { try { s.Set(); while (s != null) {}; } catch (Exception ex) { Console.WriteLine(""catch1""); } } finally { Console.WriteLine(""finally1""); } } catch (Exception ex) when (ex != null) { Console.WriteLine(""catch2""); } } finally { Console.WriteLine(""finally2""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 finally1 catch2 finally2 "); compilation.VerifyIL("Program.Test", @" { // Code size 92 (0x5c) .maxstack 2 .try { .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_000f: brtrue.s IL_000a IL_0011: leave.s IL_0020 } catch System.Exception { IL_0013: pop IL_0014: ldstr ""catch1"" IL_0019: call ""void System.Console.WriteLine(string)"" IL_001e: leave.s IL_0020 } IL_0020: leave.s IL_002d } finally { IL_0022: ldstr ""finally1"" IL_0027: call ""void System.Console.WriteLine(string)"" IL_002c: endfinally } IL_002d: leave.s IL_005b } filter { IL_002f: isinst ""System.Exception"" IL_0034: dup IL_0035: brtrue.s IL_003b IL_0037: pop IL_0038: ldc.i4.0 IL_0039: br.s IL_0041 IL_003b: ldnull IL_003c: cgt.un IL_003e: ldc.i4.0 IL_003f: cgt.un IL_0041: endfilter } // end filter { // handler IL_0043: pop IL_0044: ldstr ""catch2"" IL_0049: call ""void System.Console.WriteLine(string)"" IL_004e: leave.s IL_005b } } finally { IL_0050: ldstr ""finally2"" IL_0055: call ""void System.Console.WriteLine(string)"" IL_005a: endfinally } IL_005b: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsDesktopTypes)] public void NestedExceptionHandlersThreadAbort05() { var source = @" using System; using System.Threading; class Program { static void nop() { } static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { s.Set(); while (s != null) {}; } catch { try { nop(); } catch { Console.WriteLine(""catch1""); } } finally { try { Console.WriteLine(""try2""); } catch { Console.WriteLine(""catch2""); } } } catch { Console.WriteLine(""catch3""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" try2 catch3 "); compilation.VerifyIL("Program.Test", @"{ // Code size 87 (0x57) .maxstack 1 .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_000f: brtrue.s IL_000a IL_0011: leave.s IL_002a } catch object { IL_0013: pop .try { IL_0014: call ""void Program.nop()"" IL_0019: leave.s IL_0028 } catch object { IL_001b: pop IL_001c: ldstr ""catch1"" IL_0021: call ""void System.Console.WriteLine(string)"" IL_0026: leave.s IL_0028 } IL_0028: leave.s IL_002a } IL_002a: leave.s IL_0047 } finally { IL_002c: nop .try { IL_002d: ldstr ""try2"" IL_0032: call ""void System.Console.WriteLine(string)"" IL_0037: leave.s IL_0046 } catch object { IL_0039: pop IL_003a: ldstr ""catch2"" IL_003f: call ""void System.Console.WriteLine(string)"" IL_0044: leave.s IL_0046 } IL_0046: endfinally } IL_0047: leave.s IL_0056 } catch object { IL_0049: pop IL_004a: ldstr ""catch3"" IL_004f: call ""void System.Console.WriteLine(string)"" IL_0054: leave.s IL_0056 } IL_0056: ret }"); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort06() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { s.Set(); while (s != null) {}; } catch { try { int i = 0; i = i / i; } catch { Console.WriteLine(""catch1""); } } finally { try { Console.WriteLine(""try2""); } catch { Console.WriteLine(""catch2""); } } } catch { Console.WriteLine(""catch3""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 try2 catch3 "); compilation.VerifyIL("Program.Test", @" { // Code size 86 (0x56) .maxstack 2 .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_000f: brtrue.s IL_000a IL_0011: leave.s IL_0029 } catch object { IL_0013: pop .try { IL_0014: ldc.i4.0 IL_0015: dup IL_0016: div IL_0017: pop IL_0018: leave.s IL_0027 } catch object { IL_001a: pop IL_001b: ldstr ""catch1"" IL_0020: call ""void System.Console.WriteLine(string)"" IL_0025: leave.s IL_0027 } IL_0027: leave.s IL_0029 } IL_0029: leave.s IL_0046 } finally { IL_002b: nop .try { IL_002c: ldstr ""try2"" IL_0031: call ""void System.Console.WriteLine(string)"" IL_0036: leave.s IL_0045 } catch object { IL_0038: pop IL_0039: ldstr ""catch2"" IL_003e: call ""void System.Console.WriteLine(string)"" IL_0043: leave.s IL_0045 } IL_0045: endfinally } IL_0046: leave.s IL_0055 } catch object { IL_0048: pop IL_0049: ldstr ""catch3"" IL_004e: call ""void System.Console.WriteLine(string)"" IL_0053: leave.s IL_0055 } IL_0055: ret } "); } [ConditionalFact(typeof(WindowsDesktopOnly))] public void NestedExceptionHandlersThreadAbort07() { var source = @" using System; using System.Threading; class Program { static ManualResetEventSlim s = new ManualResetEventSlim(false); static void Main(string[] args) { var ts = new ThreadStart(Test); var t = new Thread(ts); t.Start(); s.Wait(); t.Abort(); t.Join(); } public static void Test() { try { try { try { try { s.Set(); while (s != null) {}; } catch (Exception ex) { Console.WriteLine(""catch1""); } } finally { Console.WriteLine(""finally1""); } } finally { Console.WriteLine(""finally2""); } } catch (Exception ex) { Console.WriteLine(""catch2""); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @" catch1 finally1 finally2 catch2 "); compilation.VerifyIL("Program.Test", @" { // Code size 74 (0x4a) .maxstack 1 .try { .try { .try { .try { IL_0000: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_0005: callvirt ""void System.Threading.ManualResetEventSlim.Set()"" IL_000a: ldsfld ""System.Threading.ManualResetEventSlim Program.s"" IL_000f: brtrue.s IL_000a IL_0011: leave.s IL_0020 } catch System.Exception { IL_0013: pop IL_0014: ldstr ""catch1"" IL_0019: call ""void System.Console.WriteLine(string)"" IL_001e: leave.s IL_0020 } IL_0020: leave.s IL_002d } finally { IL_0022: ldstr ""finally1"" IL_0027: call ""void System.Console.WriteLine(string)"" IL_002c: endfinally } IL_002d: leave.s IL_003a } finally { IL_002f: ldstr ""finally2"" IL_0034: call ""void System.Console.WriteLine(string)"" IL_0039: endfinally } IL_003a: leave.s IL_0049 } catch System.Exception { IL_003c: pop IL_003d: ldstr ""catch2"" IL_0042: call ""void System.Console.WriteLine(string)"" IL_0047: leave.s IL_0049 } IL_0049: ret } "); } [Fact] public void ThrowInTry() { var source = @"using System; class C { static void nop() { } static void ThrowInTry() { try { throw new Exception(); } finally { } } static void ThrowInTryInTry() { try { try { throw new Exception(); } finally { } } finally { } } static void ThrowInTryInFinally() { try { } finally { try { throw new Exception(); } finally { } } } } class D { static void nop() { } static void ThrowInTry() { try { throw new Exception(); } catch { } finally { } } static void ThrowInTryInTry() { try { try { throw new Exception(); } catch { } finally { } } finally { } } static void ThrowInTryInFinally() { try { nop(); } catch { } finally { try { throw new Exception(); } catch { } finally { } } } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.ThrowInTry", @"{ // Code size 6 (0x6) .maxstack 1 IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw }"); compilation.VerifyIL("C.ThrowInTryInTry", @"{ // Code size 6 (0x6) .maxstack 1 IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw }"); compilation.VerifyIL("C.ThrowInTryInFinally", @"{ // Code size 10 (0xa) .maxstack 1 .try { IL_0000: leave.s IL_0008 } finally { IL_0002: newobj ""System.Exception..ctor()"" IL_0007: throw } IL_0008: br.s IL_0008 }"); compilation.VerifyIL("D.ThrowInTry", @"{ // Code size 10 (0xa) .maxstack 1 .try { IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw } catch object { IL_0006: pop IL_0007: leave.s IL_0009 } IL_0009: ret }"); compilation.VerifyIL("D.ThrowInTryInTry", @"{ // Code size 10 (0xa) .maxstack 1 .try { IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw } catch object { IL_0006: pop IL_0007: leave.s IL_0009 } IL_0009: ret }"); compilation.VerifyIL("D.ThrowInTryInFinally", @"{ // Code size 22 (0x16) .maxstack 1 .try { .try { IL_0000: call ""void D.nop()"" IL_0005: leave.s IL_0015 } catch object { IL_0007: pop IL_0008: leave.s IL_0015 } } finally { IL_000a: nop .try { IL_000b: newobj ""System.Exception..ctor()"" IL_0010: throw } catch object { IL_0011: pop IL_0012: leave.s IL_0014 } IL_0014: endfinally } IL_0015: ret }"); } [WorkItem(540716, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540716")] [Fact] public void ThrowInFinally() { var source = @"using System; class C { static void nop() { } static void ThrowInFinally() { try { } finally { throw new Exception(); } } static void ThrowInFinallyInTry() { try { try { } finally { throw new Exception(); } } finally { nop(); } } static int ThrowInFinallyInFinally() { try { } finally { try { } finally { throw new Exception(); } } // unreachable and has no return System.Console.WriteLine(); } } class D { static void nop() { } static void ThrowInFinally() { try { nop(); } catch { } finally { throw new Exception(); } } static void ThrowInFinallyInTry() { try { try { nop(); } catch { } finally { throw new Exception(); } } catch { } finally { nop(); } } static void ThrowInFinallyInFinally() { try { nop(); } catch { } finally { try { nop(); } catch { } finally { throw new Exception(); } } } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.ThrowInFinally", @"{ // Code size 10 (0xa) .maxstack 1 .try { IL_0000: leave.s IL_0008 } finally { IL_0002: newobj ""System.Exception..ctor()"" IL_0007: throw } IL_0008: br.s IL_0008 }"); compilation.VerifyIL("C.ThrowInFinallyInTry", @"{ // Code size 16 (0x10) .maxstack 1 .try { .try { IL_0000: leave.s IL_0008 } finally { IL_0002: newobj ""System.Exception..ctor()"" IL_0007: throw } IL_0008: br.s IL_0008 } finally { IL_000a: call ""void C.nop()"" IL_000f: endfinally } }"); // The nop below is to work around a verifier bug. // See DevDiv 563799. compilation.VerifyIL("C.ThrowInFinallyInFinally", @"{ // Code size 15 (0xf) .maxstack 1 .try { IL_0000: leave.s IL_000d } finally { IL_0002: nop .try { IL_0003: leave.s IL_000b } finally { IL_0005: newobj ""System.Exception..ctor()"" IL_000a: throw } IL_000b: br.s IL_000b } IL_000d: br.s IL_000d }"); compilation.VerifyIL("D.ThrowInFinally", @"{ // Code size 18 (0x12) .maxstack 1 .try { .try { IL_0000: call ""void D.nop()"" IL_0005: leave.s IL_0010 } catch object { IL_0007: pop IL_0008: leave.s IL_0010 } } finally { IL_000a: newobj ""System.Exception..ctor()"" IL_000f: throw } IL_0010: br.s IL_0010 }"); compilation.VerifyIL("D.ThrowInFinallyInTry", @"{ // Code size 30 (0x1e) .maxstack 1 .try { .try { .try { .try { IL_0000: call ""void D.nop()"" IL_0005: leave.s IL_000a } catch object { IL_0007: pop IL_0008: leave.s IL_000a } IL_000a: leave.s IL_0012 } finally { IL_000c: newobj ""System.Exception..ctor()"" IL_0011: throw } IL_0012: br.s IL_0012 } catch object { IL_0014: pop IL_0015: leave.s IL_001d } } finally { IL_0017: call ""void D.nop()"" IL_001c: endfinally } IL_001d: ret }"); compilation.VerifyIL("D.ThrowInFinallyInFinally", @"{ // Code size 31 (0x1f) .maxstack 1 .try { .try { IL_0000: call ""void D.nop()"" IL_0005: leave.s IL_001d } catch object { IL_0007: pop IL_0008: leave.s IL_001d } } finally { IL_000a: nop .try { .try { IL_000b: call ""void D.nop()"" IL_0010: leave.s IL_001b } catch object { IL_0012: pop IL_0013: leave.s IL_001b } } finally { IL_0015: newobj ""System.Exception..ctor()"" IL_001a: throw } IL_001b: br.s IL_001b } IL_001d: br.s IL_001d }"); } [Fact] public void TryFilterSimple() { var src = @" using System; class C { static bool Filter() { Console.Write(""Filter""); return true; } static void Main() { int x = 0; try { Console.Write(""Try""); x = x / x; } catch when (Filter()) { Console.Write(""Catch""); } finally { Console.Write(""Finally""); } } }"; var comp = CompileAndVerify(src, expectedOutput: "TryFilterCatchFinally"); comp.VerifyIL("C.Main", @" { // Code size 54 (0x36) .maxstack 2 .locals init (int V_0) //x IL_0000: ldc.i4.0 IL_0001: stloc.0 .try { .try { IL_0002: ldstr ""Try"" IL_0007: call ""void System.Console.Write(string)"" IL_000c: ldloc.0 IL_000d: ldloc.0 IL_000e: div IL_000f: stloc.0 IL_0010: leave.s IL_0035 } filter { IL_0012: pop IL_0013: call ""bool C.Filter()"" IL_0018: ldc.i4.0 IL_0019: cgt.un IL_001b: endfilter } // end filter { // handler IL_001d: pop IL_001e: ldstr ""Catch"" IL_0023: call ""void System.Console.Write(string)"" IL_0028: leave.s IL_0035 } } finally { IL_002a: ldstr ""Finally"" IL_002f: call ""void System.Console.Write(string)"" IL_0034: endfinally } IL_0035: ret } "); } [Fact] public void TryFilterUseException() { var src = @" using System; class C { static void Main() { System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; try { Test(); } finally { System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture; } } static void Test() { int x = 0; try { Console.Write(""Try""); x = x / x; } catch (DivideByZeroException e) when (e.Message == null) { Console.Write(""Catch1""); } catch (DivideByZeroException e) when (e.Message != null) { Console.Write(""Catch2"" + e.Message.Length); } finally { Console.Write(""Finally""); } } }"; CompileAndVerify(src, expectedOutput: "TryCatch228Finally"). VerifyIL("C.Test", @" { // Code size 132 (0x84) .maxstack 2 .locals init (int V_0, //x System.DivideByZeroException V_1, //e int V_2) IL_0000: ldc.i4.0 IL_0001: stloc.0 .try { .try { IL_0002: ldstr ""Try"" IL_0007: call ""void System.Console.Write(string)"" IL_000c: ldloc.0 IL_000d: ldloc.0 IL_000e: div IL_000f: stloc.0 IL_0010: leave.s IL_0083 } filter { IL_0012: isinst ""System.DivideByZeroException"" IL_0017: dup IL_0018: brtrue.s IL_001e IL_001a: pop IL_001b: ldc.i4.0 IL_001c: br.s IL_0029 IL_001e: callvirt ""string System.Exception.Message.get"" IL_0023: ldnull IL_0024: ceq IL_0026: ldc.i4.0 IL_0027: cgt.un IL_0029: endfilter } // end filter { // handler IL_002b: pop IL_002c: ldstr ""Catch1"" IL_0031: call ""void System.Console.Write(string)"" IL_0036: leave.s IL_0083 } filter { IL_0038: isinst ""System.DivideByZeroException"" IL_003d: dup IL_003e: brtrue.s IL_0044 IL_0040: pop IL_0041: ldc.i4.0 IL_0042: br.s IL_0051 IL_0044: stloc.1 IL_0045: ldloc.1 IL_0046: callvirt ""string System.Exception.Message.get"" IL_004b: ldnull IL_004c: cgt.un IL_004e: ldc.i4.0 IL_004f: cgt.un IL_0051: endfilter } // end filter { // handler IL_0053: pop IL_0054: ldstr ""Catch2"" IL_0059: ldloc.1 IL_005a: callvirt ""string System.Exception.Message.get"" IL_005f: callvirt ""int string.Length.get"" IL_0064: stloc.2 IL_0065: ldloca.s V_2 IL_0067: call ""string int.ToString()"" IL_006c: call ""string string.Concat(string, string)"" IL_0071: call ""void System.Console.Write(string)"" IL_0076: leave.s IL_0083 } } finally { IL_0078: ldstr ""Finally"" IL_007d: call ""void System.Console.Write(string)"" IL_0082: endfinally } IL_0083: ret }"); } [Fact] public void TryFilterScoping() { var src = @" using System; class C { private static string str = ""S1""; static void Main() { int x = 0; try { Console.Write(""Try""); x = x / x; } catch when (new Func<bool>(() => str.Length == 2)()) { Console.Write(""Catch"" + str); } finally { Console.Write(""Finally""); } } }"; var comp = CompileAndVerify(src, expectedOutput: "TryCatchS1Finally"); comp.VerifyIL("C.Main", @" { // Code size 95 (0x5f) .maxstack 2 .locals init (int V_0) //x IL_0000: ldc.i4.0 IL_0001: stloc.0 .try { .try { IL_0002: ldstr ""Try"" IL_0007: call ""void System.Console.Write(string)"" IL_000c: ldloc.0 IL_000d: ldloc.0 IL_000e: div IL_000f: stloc.0 IL_0010: leave.s IL_005e } filter { IL_0012: pop IL_0013: ldsfld ""System.Func<bool> C.<>c.<>9__1_0"" IL_0018: dup IL_0019: brtrue.s IL_0032 IL_001b: pop IL_001c: ldsfld ""C.<>c C.<>c.<>9"" IL_0021: ldftn ""bool C.<>c.<Main>b__1_0()"" IL_0027: newobj ""System.Func<bool>..ctor(object, System.IntPtr)"" IL_002c: dup IL_002d: stsfld ""System.Func<bool> C.<>c.<>9__1_0"" IL_0032: callvirt ""bool System.Func<bool>.Invoke()"" IL_0037: ldc.i4.0 IL_0038: cgt.un IL_003a: endfilter } // end filter { // handler IL_003c: pop IL_003d: ldstr ""Catch"" IL_0042: ldsfld ""string C.str"" IL_0047: call ""string string.Concat(string, string)"" IL_004c: call ""void System.Console.Write(string)"" IL_0051: leave.s IL_005e } } finally { IL_0053: ldstr ""Finally"" IL_0058: call ""void System.Console.Write(string)"" IL_005d: endfinally } IL_005e: ret } "); } [WorkItem(18678, "https://github.com/dotnet/roslyn/issues/18678")] [Fact] public void TryCatchConstantFalseFilter1() { var src = @" using System; class C { static void Main() { try { throw new Exception(); } catch (Exception) when (false) { Console.Write(""Catch""); } } }"; var comp = CompileAndVerify(src); comp.VerifyIL("C.Main", @" { // Code size 6 (0x6) .maxstack 1 IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw }"); } [WorkItem(18678, "https://github.com/dotnet/roslyn/issues/18678")] [Fact] public void TryCatchConstantFalseFilter2() { var src = @" using System; class C { static void Main() { try { throw new Exception(); } catch (NullReferenceException) when (false) { Console.Write(""Catch1""); } catch (Exception) when (false) { Console.Write(""Catch2""); } catch when (false) { Console.Write(""Catch""); } } }"; var comp = CompileAndVerify(src); comp.VerifyIL("C.Main", @" { // Code size 6 (0x6) .maxstack 1 IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw }"); } [WorkItem(18678, "https://github.com/dotnet/roslyn/issues/18678")] [Fact] public void TryCatchConstantFalseFilter3() { var src = @" using System; class C { static void Main() { try { throw new Exception(); } catch (NullReferenceException) when ((1+1) == 2) { Console.Write(""Catch1""); } catch (Exception) when (true == false) { Console.Write(""Catch2""); } catch when ((1+1) != 2) { Console.Write(""Catch""); } } }"; var comp = CompileAndVerify(src); comp.VerifyIL("C.Main", @" { // Code size 39 (0x27) .maxstack 2 .try { IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw } filter { IL_0006: isinst ""System.NullReferenceException"" IL_000b: dup IL_000c: brtrue.s IL_0012 IL_000e: pop IL_000f: ldc.i4.0 IL_0010: br.s IL_0017 IL_0012: pop IL_0013: ldc.i4.1 IL_0014: ldc.i4.0 IL_0015: cgt.un IL_0017: endfilter } // end filter { // handler IL_0019: pop IL_001a: ldstr ""Catch1"" IL_001f: call ""void System.Console.Write(string)"" IL_0024: leave.s IL_0026 } IL_0026: ret }"); } [WorkItem(18678, "https://github.com/dotnet/roslyn/issues/18678")] [Fact] public void TryCatchConstantFalseFilterCombined() { var src = @" using System; class C { static void Main() { var message = ""ExceptionMessage""; try { throw new Exception(message); } catch (NullReferenceException) when (false) { Console.Write(""NullReferenceCatch""); } catch (Exception e) when (e.Message == message) { Console.Write(""ExceptionFilter""); } catch (Exception) { Console.Write(""ExceptionCatch""); } catch when (false) { Console.Write(""Catch""); } } }"; var comp = CompileAndVerify(src, expectedOutput: "ExceptionFilter"); comp.VerifyIL("C.Main", @" { // Code size 68 (0x44) .maxstack 2 .locals init (string V_0) //message IL_0000: ldstr ""ExceptionMessage"" IL_0005: stloc.0 .try { IL_0006: ldloc.0 IL_0007: newobj ""System.Exception..ctor(string)"" IL_000c: throw } filter { IL_000d: isinst ""System.Exception"" IL_0012: dup IL_0013: brtrue.s IL_0019 IL_0015: pop IL_0016: ldc.i4.0 IL_0017: br.s IL_0027 IL_0019: callvirt ""string System.Exception.Message.get"" IL_001e: ldloc.0 IL_001f: call ""bool string.op_Equality(string, string)"" IL_0024: ldc.i4.0 IL_0025: cgt.un IL_0027: endfilter } // end filter { // handler IL_0029: pop IL_002a: ldstr ""ExceptionFilter"" IL_002f: call ""void System.Console.Write(string)"" IL_0034: leave.s IL_0043 } catch System.Exception { IL_0036: pop IL_0037: ldstr ""ExceptionCatch"" IL_003c: call ""void System.Console.Write(string)"" IL_0041: leave.s IL_0043 } IL_0043: ret }"); } [WorkItem(18678, "https://github.com/dotnet/roslyn/issues/18678")] [Fact] public void TryCatchFinallyConstantFalseFilter() { var src = @" using System; class C { static void Main() { try { try { throw new Exception(); } catch (NullReferenceException) when (false) { Console.Write(""Catch1""); } catch (Exception) when (false) { Console.Write(""Catch2""); } finally { Console.Write(""Finally""); } } catch { Console.Write(""OuterCatch""); } } }"; var comp = CompileAndVerify(src, expectedOutput: "FinallyOuterCatch"); comp.VerifyIL("C.Main", @" { // Code size 31 (0x1f) .maxstack 1 .try { .try { IL_0000: newobj ""System.Exception..ctor()"" IL_0005: throw } finally { IL_0006: ldstr ""Finally"" IL_000b: call ""void System.Console.Write(string)"" IL_0010: endfinally } } catch object { IL_0011: pop IL_0012: ldstr ""OuterCatch"" IL_0017: call ""void System.Console.Write(string)"" IL_001c: leave.s IL_001e } IL_001e: ret }"); } [Fact] public void TryCatchWithReturnValue() { var source = @"using System; class C { static int F(int i) { if (i == 0) { throw new InvalidOperationException(); } else if (i == 1) { throw new InvalidCastException(); } return i; } static int M(int i) { try { return F(i) * 3; } catch (InvalidOperationException) { return (i - 1) * 4; } catch { } finally { i = i + 10; } return i; } static void Main() { Console.WriteLine(""M(0)={0}, M(1)={1}, M(2)={2}"", M(0), M(1), M(2)); } }"; var compilation = CompileAndVerify(source, expectedOutput: "M(0)=-4, M(1)=11, M(2)=6"); compilation.VerifyIL("C.M", @"{ // Code size 34 (0x22) .maxstack 2 .locals init (int V_0) .try { .try { IL_0000: ldarg.0 IL_0001: call ""int C.F(int)"" IL_0006: ldc.i4.3 IL_0007: mul IL_0008: stloc.0 IL_0009: leave.s IL_0020 } catch System.InvalidOperationException { IL_000b: pop IL_000c: ldarg.0 IL_000d: ldc.i4.1 IL_000e: sub IL_000f: ldc.i4.4 IL_0010: mul IL_0011: stloc.0 IL_0012: leave.s IL_0020 } catch object { IL_0014: pop IL_0015: leave.s IL_001e } } finally { IL_0017: ldarg.0 IL_0018: ldc.i4.s 10 IL_001a: add IL_001b: starg.s V_0 IL_001d: endfinally } IL_001e: ldarg.0 IL_001f: ret IL_0020: ldloc.0 IL_0021: ret }"); } [Fact] public void Rethrow() { var source = @"using System.IO; class C { static void nop() { } static int F = 0; static void M() { try { nop(); } catch (FileNotFoundException e) { if (F > 0) { throw; } else { throw e; } } catch (IOException) { throw; } catch { throw; } } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.M", @"{ // Code size 27 (0x1b) .maxstack 2 .locals init (System.IO.FileNotFoundException V_0) //e .try { IL_0000: call ""void C.nop()"" IL_0005: leave.s IL_001a } catch System.IO.FileNotFoundException { IL_0007: stloc.0 IL_0008: ldsfld ""int C.F"" IL_000d: ldc.i4.0 IL_000e: ble.s IL_0012 IL_0010: rethrow IL_0012: ldloc.0 IL_0013: throw } catch System.IO.IOException { IL_0014: pop IL_0015: rethrow } catch object { IL_0017: pop IL_0018: rethrow } IL_001a: ret }"); } [WorkItem(541494, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541494")] [Fact] public void CatchT() { var source = @"using System; class C { internal static void TryCatch<T>() where T : Exception { try { Throw(); } catch (T t) { Catch(t); } } static void Throw() { throw new NotImplementedException(); } static void Catch(Exception e) { Console.WriteLine(""Handled""); } static void Main() { try { TryCatch<NotImplementedException>(); TryCatch<InvalidOperationException>(); } catch (Exception) { Console.WriteLine(""Unhandled""); } } }"; var compilation = CompileAndVerify(source, expectedOutput: @"Handled Unhandled"); compilation.VerifyIL("C.TryCatch<T>()", @" { // Code size 25 (0x19) .maxstack 1 .try { IL_0000: call ""void C.Throw()"" IL_0005: leave.s IL_0018 } catch T { IL_0007: unbox.any ""T"" IL_000c: box ""T"" IL_0011: call ""void C.Catch(System.Exception)"" IL_0016: leave.s IL_0018 } IL_0018: ret } "); } [WorkItem(540664, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540664")] [Fact] public void ExceptionAlreadyCaught1() { var source = @"class C { static void M() { try { } catch (System.Exception) { } catch { } } }"; CompileAndVerify(source).VerifyDiagnostics( Diagnostic(ErrorCode.WRN_UnreachableGeneralCatch, "catch").WithLocation(7, 9)); } [Fact] public void ExceptionAlreadyCaught2() { var text = @" class Program { static void M() { int a = 1; try { } catch (System.Exception) { } catch when (a == 1) { } } } "; CreateCompilation(text).VerifyDiagnostics( // (9,9): warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException. // catch when (a == 1) { } Diagnostic(ErrorCode.WRN_UnreachableGeneralCatch, "catch").WithLocation(9, 9)); } [Fact] public void ExceptionAlreadyCaught3() { var text = @" class Program { static void M() { int a = 1; try { } catch when (a == 2) { } catch (System.Exception) when (a == 3) { } catch { } } } "; CreateCompilation(text).VerifyDiagnostics(); } [WorkItem(540666, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540666")] [Fact] public void EmptyTryFinally_Simple() { var source = @"class C { static void M() { try { } finally { } } }"; CompileAndVerify(source); } [WorkItem(542002, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542002")] [Fact] public void ConditionInTry() { var source = @"using System; class Program { static void Main() { int a = 10; try { if (a == 3) { } } catch (System.Exception) { } } }"; var compilation = CompileAndVerify(source, expectedOutput: ""); compilation.VerifyIL("Program.Main", @" { // Code size 13 (0xd) .maxstack 2 .locals init (int V_0) //a IL_0000: ldc.i4.s 10 IL_0002: stloc.0 .try { IL_0003: ldloc.0 IL_0004: ldc.i4.3 IL_0005: pop IL_0006: pop IL_0007: leave.s IL_000c } catch System.Exception { IL_0009: pop IL_000a: leave.s IL_000c } IL_000c: ret } "); } [Fact(), WorkItem(544911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544911")] public void UnreachableAfterTryFinally() { var source = @" using System; class Program { static int Result = 0; static void F() { Result = 1; } static void T1() { try { goto L; } finally { for (; ; ) { } } L: F(); //unreachable } static void Main() { Console.Write(Result); } } "; var compilation = CompileAndVerify(source, expectedOutput: "0"); compilation.VerifyIL("Program.T1", @" { // Code size 6 (0x6) .maxstack 0 .try { IL_0000: leave.s IL_0004 } finally { IL_0002: br.s IL_0002 } IL_0004: br.s IL_0004 } "); } [Fact(), WorkItem(544911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544911")] public void ReachableAfterBlockingCatch() { var source = @"using System; class Program { static void nop() { } static void F() { Console.WriteLine(""hello""); } static void T1() { try { nop(); } catch { for (; ; ) { } } F(); //reachable } static void Main() { T1(); } } "; var compilation = CompileAndVerify(source, expectedOutput: "hello"); compilation.VerifyIL("Program.T1", @"{ // Code size 16 (0x10) .maxstack 1 .try { IL_0000: call ""void Program.nop()"" IL_0005: leave.s IL_000a } catch object { IL_0007: pop IL_0008: br.s IL_0008 } IL_000a: call ""void Program.F()"" IL_000f: ret }"); } [Fact(), WorkItem(544911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544911")] public void UnreachableAfterTryFinallyConditional() { var source = @" using System; class Program { static int Result = 0; static void F() { Result = 1; } static void T1() { try { if (Result == 0) goto L; } finally { for (; ; ) { } } L: F(); //unreachable } static void Main() { Console.Write(Result); } } "; var compilation = CompileAndVerify(source, expectedOutput: "0"); compilation.VerifyIL("Program.T1", @" { // Code size 12 (0xc) .maxstack 1 .try { IL_0000: ldsfld ""int Program.Result"" IL_0005: pop IL_0006: leave.s IL_000a } finally { IL_0008: br.s IL_0008 } IL_000a: br.s IL_000a } "); } [Fact()] public void ReachableAfterFinallyButNotFromTryConditional01() { var source = @" using System; class Program { static int Result = 0; static void F() { Result = 1; } static void T1() { if (Result == 1) goto L; try { try { if (Result == 0) goto L; goto L; } finally { for (; ; ) { } } if (Result == 0) goto L; } finally { for (; ; ) { } } L: F(); //reachable but not from the try } static void Main() { Console.Write(Result); } } "; var compilation = CompileAndVerify(source, expectedOutput: "0"); compilation.VerifyIL("Program.T1", @" { // Code size 29 (0x1d) .maxstack 2 IL_0000: ldsfld ""int Program.Result"" IL_0005: ldc.i4.1 IL_0006: beq.s IL_0017 IL_0008: nop .try { .try { IL_0009: ldsfld ""int Program.Result"" IL_000e: pop IL_000f: leave.s IL_0013 } finally { IL_0011: br.s IL_0011 } IL_0013: br.s IL_0013 } finally { IL_0015: br.s IL_0015 } IL_0017: call ""void Program.F()"" IL_001c: ret } "); } [Fact(), WorkItem(544911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544911")] public void ReachableAfterFinallyButNotFromTryConditional() { var source = @" using System; class Program { static int Result = 0; static void F() { Result = 1; } static void T1() { if (Result == 1) goto L; try { try { if (Result == 0) goto L; } finally { for (; ; ) { } } if (Result == 0) goto L; } finally { for (; ; ) { } } L: F(); //reachable but not from the try } static void Main() { Console.Write(Result); } } "; var compilation = CompileAndVerify(source, expectedOutput: "0"); compilation.VerifyIL("Program.T1", @" { // Code size 29 (0x1d) .maxstack 2 IL_0000: ldsfld ""int Program.Result"" IL_0005: ldc.i4.1 IL_0006: beq.s IL_0017 IL_0008: nop .try { .try { IL_0009: ldsfld ""int Program.Result"" IL_000e: pop IL_000f: leave.s IL_0013 } finally { IL_0011: br.s IL_0011 } IL_0013: br.s IL_0013 } finally { IL_0015: br.s IL_0015 } IL_0017: call ""void Program.F()"" IL_001c: ret } "); } [Fact(), WorkItem(713418, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713418")] public void ConditionalUnconditionalBranches() { var source = @" using System; class Program { private static int x = 123; static void Main(string[] args) { try { if (x == 10) { goto l2;; } if (x != 0) { Console.WriteLine(""2""); } goto l1; l2: Console.WriteLine(""l2""); l1: goto lOut; } finally { Console.WriteLine(""Finally""); } lOut: Console.WriteLine(""Out""); } } "; var compilation = CompileAndVerify(source, expectedOutput: @"2 Finally Out"); compilation.VerifyIL("Program.Main", @" { // Code size 62 (0x3e) .maxstack 2 .try { IL_0000: ldsfld ""int Program.x"" IL_0005: ldc.i4.s 10 IL_0007: beq.s IL_001c IL_0009: ldsfld ""int Program.x"" IL_000e: brfalse.s IL_0026 IL_0010: ldstr ""2"" IL_0015: call ""void System.Console.WriteLine(string)"" IL_001a: leave.s IL_0033 IL_001c: ldstr ""l2"" IL_0021: call ""void System.Console.WriteLine(string)"" IL_0026: leave.s IL_0033 } finally { IL_0028: ldstr ""Finally"" IL_002d: call ""void System.Console.WriteLine(string)"" IL_0032: endfinally } IL_0033: ldstr ""Out"" IL_0038: call ""void System.Console.WriteLine(string)"" IL_003d: ret } "); } [Fact(), WorkItem(713418, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713418")] public void ConditionalUnconditionalBranches001() { var source = @" using System; class Program { private static int x = 123; static void Main(string[] args) { try { if (x == 10) { goto l2;; } if (x != 0) { Console.WriteLine(""2""); } goto l1; l2: // Console.WriteLine(""l2""); l1: goto lOut; } finally { Console.WriteLine(""Finally""); } lOut: Console.WriteLine(""Out""); } } "; var compilation = CompileAndVerify(source, expectedOutput: @"2 Finally Out"); compilation.VerifyIL("Program.Main", @" { // Code size 52 (0x34) .maxstack 2 .try { IL_0000: ldsfld ""int Program.x"" IL_0005: ldc.i4.s 10 IL_0007: bne.un.s IL_000b IL_0009: leave.s IL_0029 IL_000b: ldsfld ""int Program.x"" IL_0010: brfalse.s IL_001c IL_0012: ldstr ""2"" IL_0017: call ""void System.Console.WriteLine(string)"" IL_001c: leave.s IL_0029 } finally { IL_001e: ldstr ""Finally"" IL_0023: call ""void System.Console.WriteLine(string)"" IL_0028: endfinally } IL_0029: ldstr ""Out"" IL_002e: call ""void System.Console.WriteLine(string)"" IL_0033: ret } "); } [Fact(), WorkItem(2443, "https://github.com/dotnet/roslyn/issues/2443")] public void OptimizeEmptyTryBlock() { var source = @" using System; class Program { public static void Main(string[] args) { try { } catch (Exception ex) { Console.WriteLine(ex); } } } "; var compilation = CompileAndVerify(source, expectedOutput: @""); compilation.VerifyIL("Program.Main", @" { // Code size 1 (0x1) .maxstack 0 IL_0000: ret } "); } [Fact] [WorkItem(29481, "https://github.com/dotnet/roslyn/issues/29481")] public void Issue29481() { var source = @" using System; public class Program { public static void Main() { try { bool b = false; if (b) { try { return; } finally { Console.WriteLine(""Prints""); } } else { return; } } finally { GC.KeepAlive(null); } } }"; CompileAndVerify(source, expectedOutput: "", options: TestOptions.DebugExe); CompileAndVerify(source, expectedOutput: "", options: TestOptions.ReleaseExe).VerifyIL("Program.Main", @" { // Code size 26 (0x1a) .maxstack 1 .try { IL_0000: ldc.i4.0 IL_0001: brfalse.s IL_0010 .try { IL_0003: leave.s IL_0019 } finally { IL_0005: ldstr ""Prints"" IL_000a: call ""void System.Console.WriteLine(string)"" IL_000f: endfinally } IL_0010: leave.s IL_0019 } finally { IL_0012: ldnull IL_0013: call ""void System.GC.KeepAlive(object)"" IL_0018: endfinally } IL_0019: ret } "); } [ConditionalFact(typeof(IsEnglishLocal))] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void WhenWithAlwaysThrowingExpression_01() { var source = """ class C { static bool _throw; static void Main() { M(); _throw = true; try { M(); } catch (System.NullReferenceException) { System.Console.Write("Catch"); } } static void M() { try { M1(); } catch when (true ? throw M2() : true) { M3(); } M4(); } static void M1() { System.Console.Write("M1"); if (_throw) throw null; } static System.Exception M2() { System.Console.Write("M2"); return new System.NotSupportedException(); } static void M3() { System.Console.Write("M3"); } static void M4() { System.Console.Write("M4"); } } """; var verifier = CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: "M1M4M1M2Catch", // False PEVerify failure: verify: Verification.FailsPEVerify with { PEVerifyMessage = "[ : C::M][offset 0x0000000E] Stack not empty when leaving an exception filter." }).VerifyDiagnostics(); verifier.VerifyIL("C.M", """ { // Code size 30 (0x1e) .maxstack 2 .try { IL_0000: call "void C.M1()" IL_0005: leave.s IL_0018 } filter { IL_0007: pop IL_0008: call "System.Exception C.M2()" IL_000d: throw IL_000e: endfilter } // end filter { // handler IL_0010: pop IL_0011: call "void C.M3()" IL_0016: leave.s IL_0018 } IL_0018: call "void C.M4()" IL_001d: ret } """); verifier = CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: "M1M4M1M2Catch", // False PEVerify failure: verify: Verification.FailsPEVerify with { PEVerifyMessage = "[ : C::M][offset 0x00000012] Stack not empty when leaving an exception filter." }).VerifyDiagnostics(); verifier.VerifyIL("C.M", """ { // Code size 38 (0x26) .maxstack 2 .locals init (bool V_0) IL_0000: nop .try { IL_0001: nop IL_0002: call "void C.M1()" IL_0007: nop IL_0008: nop IL_0009: leave.s IL_001f } filter { IL_000b: pop IL_000c: call "System.Exception C.M2()" IL_0011: throw IL_0012: endfilter } // end filter { // handler IL_0014: pop IL_0015: nop IL_0016: call "void C.M3()" IL_001b: nop IL_001c: nop IL_001d: leave.s IL_001f } IL_001f: call "void C.M4()" IL_0024: nop IL_0025: ret } """); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void WhenWithAlwaysThrowingExpression_02() { var source = """ class C { static void M() { try { M1(); } catch (System.ArgumentException) when (true ? throw null : true) { M2(); } } static void M1(){} static void M2(){} } """; var verifier = CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics(); verifier.VerifyIL("C.M", """ { // Code size 33 (0x21) .maxstack 2 .try { IL_0000: call "void C.M1()" IL_0005: leave.s IL_0020 } filter { IL_0007: isinst "System.ArgumentException" IL_000c: dup IL_000d: brtrue.s IL_0013 IL_000f: pop IL_0010: ldc.i4.0 IL_0011: br.s IL_0016 IL_0013: pop IL_0014: ldnull IL_0015: throw IL_0016: endfilter } // end filter { // handler IL_0018: pop IL_0019: call "void C.M2()" IL_001e: leave.s IL_0020 } IL_0020: ret } """); verifier = CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics(); verifier.VerifyIL("C.M", """ { // Code size 40 (0x28) .maxstack 2 .locals init (bool V_0) IL_0000: nop .try { IL_0001: nop IL_0002: call "void C.M1()" IL_0007: nop IL_0008: nop IL_0009: leave.s IL_0027 } filter { IL_000b: isinst "System.ArgumentException" IL_0010: dup IL_0011: brtrue.s IL_0017 IL_0013: pop IL_0014: ldc.i4.0 IL_0015: br.s IL_001a IL_0017: pop IL_0018: ldnull IL_0019: throw IL_001a: endfilter } // end filter { // handler IL_001c: pop IL_001d: nop IL_001e: call "void C.M2()" IL_0023: nop IL_0024: nop IL_0025: leave.s IL_0027 } IL_0027: ret } """); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void WhenWithAlwaysThrowingExpression_03() { var source = """ class C { static void M() { try { M1(); } catch when (throw null) { M2(); } } static void M1(){} static void M2(){} } """; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics( // (9,21): error CS8115: A throw expression is not allowed in this context. // catch when (throw null) Diagnostic(ErrorCode.ERR_ThrowMisplaced, "throw").WithLocation(9, 21) ); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void WhenWithAlwaysThrowingExpression_04() { var source = """ class C { static void M() { try { M1(); } catch (System.ArgumentException) when (throw null) { M2(); } } static void M1(){} static void M2(){} } """; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics( // (9,48): error CS8115: A throw expression is not allowed in this context. // catch (System.ArgumentException) when (throw null) Diagnostic(ErrorCode.ERR_ThrowMisplaced, "throw").WithLocation(9, 48) ); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void UnreachableCatch_01() { var source = """ class C { static void M() { try { M1(); } catch when (false) { M2(); } } static void M1(){} static void M2(){} } """; var verifier = CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics( // (9,21): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch when (false) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(9, 21), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 6 (0x6) .maxstack 0 IL_0000: call "void C.M1()" IL_0005: ret } """); verifier = CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics( // (9,21): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch when (false) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(9, 21), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 10 (0xa) .maxstack 0 IL_0000: nop IL_0001: nop IL_0002: call "void C.M1()" IL_0007: nop IL_0008: nop IL_0009: ret } """); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void UnreachableCatch_02() { var source = """ class C { static void M() { try { M1(); } catch (System.ArgumentException) when (false) { M2(); } } static void M1(){} static void M2(){} } """; var verifier = CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics( // (9,48): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch (System.ArgumentException) when (false) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(9, 48), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 6 (0x6) .maxstack 0 IL_0000: call "void C.M1()" IL_0005: ret } """); verifier = CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics( // (9,48): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch (System.ArgumentException) when (false) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(9, 48), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 10 (0xa) .maxstack 0 IL_0000: nop IL_0001: nop IL_0002: call "void C.M1()" IL_0007: nop IL_0008: nop IL_0009: ret } """); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/67494")] public void UnreachableCatch_03() { var source = """ class C { static void M() { try { M1(); } catch when (true ? false : true) { M2(); } } static void M1(){} static void M2(){} } """; var verifier = CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics( // (9,21): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch when (true ? false : true) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "true ? false : true").WithLocation(9, 21), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 6 (0x6) .maxstack 0 IL_0000: call "void C.M1()" IL_0005: ret } """); verifier = CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics( // (9,21): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch when (true ? false : true) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "true ? false : true").WithLocation(9, 21), // (11,13): warning CS0162: Unreachable code detected // M2(); Diagnostic(ErrorCode.WRN_UnreachableCode, "M2").WithLocation(11, 13) ); verifier.VerifyIL("C.M", """ { // Code size 10 (0xa) .maxstack 0 IL_0000: nop IL_0001: nop IL_0002: call "void C.M1()" IL_0007: nop IL_0008: nop IL_0009: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70200")] public void Repro70200() { var source = """ using System; using System.Threading.Tasks; class C { async Task M() { return; try { Console.WriteLine(string.Empty); } catch (Exception e1) when (e1.InnerException is Exception { InnerException: { } e2 }) { Console.WriteLine(e2.Message); } } } """; var expectedDiagnostics = new[] { // (10,9): warning CS0162: Unreachable code detected // try Diagnostic(ErrorCode.WRN_UnreachableCode, "try").WithLocation(10, 9) }; CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics(expectedDiagnostics); CompileAndVerify(source, options: TestOptions.DebugDll).VerifyDiagnostics(expectedDiagnostics); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70200")] public void Repro70200_WithoutReturn() { var source = """ using System; using System.Threading.Tasks; class C { async Task M() { try { Console.WriteLine(string.Empty); } catch (Exception e1) when (e1.InnerException is Exception { InnerException: { } e2 }) { Console.WriteLine(e2.Message); } } } """; CompileAndVerify(source, options: TestOptions.ReleaseDll).VerifyDiagnostics(); } } }