/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/ForLoopsTests.cs
1 936 строк
41 KB
Jared Parsons
generated move
28 сен 2020, 19:36
28 сен 2020, 19:36
1cca63b
Код
Авторство
О чём код?
// 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.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UnitTests.Emit; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen { public class ForLoopsTests : EmitMetadataTestBase { [Fact] public void ForLoop() { string source = @"class C { static void Main() { int x = 3; for (int i = 0; i < 3; i = i + 1) { x = x * 3; } System.Console.Write(""{0}"", x); } }"; var compilation = CompileAndVerify(source, expectedOutput: "81"); compilation.VerifyIL("C.Main", @"{ // Code size 35 (0x23) .maxstack 2 .locals init (int V_0, //x int V_1) //i IL_0000: ldc.i4.3 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: br.s IL_000e IL_0006: ldloc.0 IL_0007: ldc.i4.3 IL_0008: mul IL_0009: stloc.0 IL_000a: ldloc.1 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.1 IL_000e: ldloc.1 IL_000f: ldc.i4.3 IL_0010: blt.s IL_0006 IL_0012: ldstr ""{0}"" IL_0017: ldloc.0 IL_0018: box ""int"" IL_001d: call ""void System.Console.Write(string, object)"" IL_0022: ret } "); } [Fact] public void ForLoopExecuteOnce() { string source = @"class C { static void Main() { int i = 0; int j; bool loop = true; for (j = 0; loop; j = j + 1) { loop = false; i = i + 1; } System.Console.Write(""{0}, {1}"", i, j); } }"; var compilation = CompileAndVerify(source, expectedOutput: "1, 1"); compilation.VerifyIL("C.Main", @"{ // Code size 44 (0x2c) .maxstack 3 .locals init (int V_0, //i int V_1, //j bool V_2) //loop IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.1 IL_0003: stloc.2 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_0012 IL_0008: ldc.i4.0 IL_0009: stloc.2 IL_000a: ldloc.0 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.0 IL_000e: ldloc.1 IL_000f: ldc.i4.1 IL_0010: add IL_0011: stloc.1 IL_0012: ldloc.2 IL_0013: brtrue.s IL_0008 IL_0015: ldstr ""{0}, {1}"" IL_001a: ldloc.0 IL_001b: box ""int"" IL_0020: ldloc.1 IL_0021: box ""int"" IL_0026: call ""void System.Console.Write(string, object, object)"" IL_002b: ret } "); } [Fact] public void ForLoopTrue() { string source = @"class C { static void Main() { int i = 0; int j; for (j = 0; true; j = j + 1) { i = i + 1; break; } System.Console.Write(""{0}, {1}"", i, j); } }"; var compilation = CompileAndVerify(source, expectedOutput: "1, 0"); compilation.VerifyIL("C.Main", @"{ // Code size 31 (0x1f) .maxstack 3 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldstr ""{0}, {1}"" IL_000d: ldloc.0 IL_000e: box ""int"" IL_0013: ldloc.1 IL_0014: box ""int"" IL_0019: call ""void System.Console.Write(string, object, object)"" IL_001e: ret } "); } [Fact] public void ForLoopFalse() { string source = @"class C { static void Main() { int i = 0; int j; for (j = 0; false; j = j + 1) { i = i + 1; } System.Console.Write(""{0}, {1}"", i, j); } }"; var compilation = CompileAndVerify(source, expectedOutput: "0, 0"); compilation.VerifyIL("C.Main", @"{ // Code size 27 (0x1b) .maxstack 3 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: ldstr ""{0}, {1}"" IL_0009: ldloc.0 IL_000a: box ""int"" IL_000f: ldloc.1 IL_0010: box ""int"" IL_0015: call ""void System.Console.Write(string, object, object)"" IL_001a: ret } "); } [Fact] public void ForLoopBreakContinue() { string source = @"class C { static void Main() { int i; int j; for (i = 0, j = 0; i < 5; i = i + 1) { if (i > 2) continue; j = j + 1; } System.Console.Write(""{0}, {1}, "", i, j); for (i = 0, j = 0; i < 5; i = i + 1) { if (i > 3) break; j = j + 1; } System.Console.Write(""{0}, {1}"", i, j); } }"; var compilation = CompileAndVerify(source, expectedOutput: "5, 3, 4, 4"); compilation.VerifyIL("C.Main", @"{ // Code size 89 (0x59) .maxstack 3 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: br.s IL_0012 IL_0006: ldloc.0 IL_0007: ldc.i4.2 IL_0008: bgt.s IL_000e IL_000a: ldloc.1 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.1 IL_000e: ldloc.0 IL_000f: ldc.i4.1 IL_0010: add IL_0011: stloc.0 IL_0012: ldloc.0 IL_0013: ldc.i4.5 IL_0014: blt.s IL_0006 IL_0016: ldstr ""{0}, {1}, "" IL_001b: ldloc.0 IL_001c: box ""int"" IL_0021: ldloc.1 IL_0022: box ""int"" IL_0027: call ""void System.Console.Write(string, object, object)"" IL_002c: ldc.i4.0 IL_002d: stloc.0 IL_002e: ldc.i4.0 IL_002f: stloc.1 IL_0030: br.s IL_003e IL_0032: ldloc.0 IL_0033: ldc.i4.3 IL_0034: bgt.s IL_0042 IL_0036: ldloc.1 IL_0037: ldc.i4.1 IL_0038: add IL_0039: stloc.1 IL_003a: ldloc.0 IL_003b: ldc.i4.1 IL_003c: add IL_003d: stloc.0 IL_003e: ldloc.0 IL_003f: ldc.i4.5 IL_0040: blt.s IL_0032 IL_0042: ldstr ""{0}, {1}"" IL_0047: ldloc.0 IL_0048: box ""int"" IL_004d: ldloc.1 IL_004e: box ""int"" IL_0053: call ""void System.Console.Write(string, object, object)"" IL_0058: ret } "); } /// <summary> /// No statements in for loop parts. /// </summary> [Fact] public void ForLoopNoStatements() { string source = @"class C { static void Main() { int i = 0; for (; ; ) { if (i > 4) break; i = i + 2; } System.Console.Write(""{0}"", i); } }"; var compilation = CompileAndVerify(source, expectedOutput: "6"); compilation.VerifyIL("C.Main", @"{ // Code size 29 (0x1d) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: ldc.i4.4 IL_0004: bgt.s IL_000c IL_0006: ldloc.0 IL_0007: ldc.i4.2 IL_0008: add IL_0009: stloc.0 IL_000a: br.s IL_0002 IL_000c: ldstr ""{0}"" IL_0011: ldloc.0 IL_0012: box ""int"" IL_0017: call ""void System.Console.Write(string, object)"" IL_001c: ret } "); } /// <summary> /// Statement expression list in initializer. /// </summary> [Fact] public void ForLoopStatementExpressionListInitializer() { string source = @"class C { static void Main() { int i = 0; int j = 0; for (i = i + 1, i = i + 1; j < 2; i = i + 2, j = j + 1) { } System.Console.Write(""{0}"", i); } }"; var compilation = CompileAndVerify(source, expectedOutput: "6"); compilation.VerifyIL("C.Main", @"{ // Code size 43 (0x2b) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.0 IL_000c: br.s IL_0016 IL_000e: ldloc.0 IL_000f: ldc.i4.2 IL_0010: add IL_0011: stloc.0 IL_0012: ldloc.1 IL_0013: ldc.i4.1 IL_0014: add IL_0015: stloc.1 IL_0016: ldloc.1 IL_0017: ldc.i4.2 IL_0018: blt.s IL_000e IL_001a: ldstr ""{0}"" IL_001f: ldloc.0 IL_0020: box ""int"" IL_0025: call ""void System.Console.Write(string, object)"" IL_002a: ret } "); } // The initializer list is a comma separated list of expressions [Fact] public void InitializerList() { var text = @" class C { static void Main(string[] args) { int i = 1; for (; i < 10; i = i + 1) { } } } "; string expectedIL = @"{ // Code size 14 (0xe) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: br.s IL_0008 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.s 10 IL_000b: blt.s IL_0004 IL_000d: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // The value of Iterator expression could be decreasing [Fact] public void DecreasingForIterator() { var text = @" class C { static void Main(string[] args) { for (int k = 200 ; k > 100; k = k - 1) { } } } "; string expectedIL = @"{ // Code size 18 (0x12) .maxstack 2 .locals init (int V_0) //k IL_0000: ldc.i4 0xc8 IL_0005: stloc.0 IL_0006: br.s IL_000c IL_0008: ldloc.0 IL_0009: ldc.i4.1 IL_000a: sub IL_000b: stloc.0 IL_000c: ldloc.0 IL_000d: ldc.i4.s 100 IL_000f: bgt.s IL_0008 IL_0011: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Method calls work fine in all for loop areas [Fact] public void MethodCall() { var text = @" class C { static void Main(string[] args) { for (Initializer(); Conditional(); Iterator()) { } } public static int Initializer() { return 1; } public static bool Conditional() { return true; } public static int Iterator() { return 1; } } "; string expectedIL = @"{ // Code size 22 (0x16) .maxstack 1 IL_0000: call ""int C.Initializer()"" IL_0005: pop IL_0006: br.s IL_000e IL_0008: call ""int C.Iterator()"" IL_000d: pop IL_000e: call ""bool C.Conditional()"" IL_0013: brtrue.s IL_0008 IL_0015: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } [Fact] public void EmptyForBody() { var text = @" class C { static void Main(string[] args) { for (int i = 10; i < 100; i = i + 1) ; } } "; CompileAndVerify(text).VerifyIL("C.Main", @"{ // Code size 15 (0xf) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.s 10 IL_0002: stloc.0 IL_0003: br.s IL_0009 IL_0005: ldloc.0 IL_0006: ldc.i4.1 IL_0007: add IL_0008: stloc.0 IL_0009: ldloc.0 IL_000a: ldc.i4.s 100 IL_000c: blt.s IL_0005 IL_000e: ret } "); } // Nested for Loops [Fact] public void NestedForLoop() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 100; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { } } } } "; string expectedIL = @"{ // Code size 27 (0x1b) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0015 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_000c IL_0008: ldloc.1 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.1 IL_000c: ldloc.1 IL_000d: ldc.i4.s 10 IL_000f: blt.s IL_0008 IL_0011: ldloc.0 IL_0012: ldc.i4.1 IL_0013: add IL_0014: stloc.0 IL_0015: ldloc.0 IL_0016: ldc.i4.s 100 IL_0018: blt.s IL_0004 IL_001a: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Change outer variable in inner for Loops [Fact] public void ChangeOuterInInnerForLoop() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { i = 1; } } } } "; string expectedIL = @"{ // Code size 29 (0x1d) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0017 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_000e IL_0008: ldc.i4.1 IL_0009: stloc.0 IL_000a: ldloc.1 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.1 IL_000e: ldloc.1 IL_000f: ldc.i4.s 10 IL_0011: blt.s IL_0008 IL_0013: ldloc.0 IL_0014: ldc.i4.1 IL_0015: add IL_0016: stloc.0 IL_0017: ldloc.0 IL_0018: ldc.i4.s 10 IL_001a: blt.s IL_0004 IL_001c: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Inner for loop referencing the outer for loop iteration variable [Fact] public void InnerRefOuterIteration() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 5; i = i + 1) { for (int j = i + 1; i < j; j = j - 1) { } } } } "; string expectedIL = @"{ // Code size 27 (0x1b) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0016 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.1 IL_0008: br.s IL_000e IL_000a: ldloc.1 IL_000b: ldc.i4.1 IL_000c: sub IL_000d: stloc.1 IL_000e: ldloc.0 IL_000f: ldloc.1 IL_0010: blt.s IL_000a IL_0012: ldloc.0 IL_0013: ldc.i4.1 IL_0014: add IL_0015: stloc.0 IL_0016: ldloc.0 IL_0017: ldc.i4.5 IL_0018: blt.s IL_0004 IL_001a: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Breaking from nested Loops [Fact, WorkItem(527952, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527952")] public void BreakFromNestedLoop() { var source = @" class C { static void Main(string[] args) { for (int i = 0; i < 5; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { if (j == 5) break; } } } } "; var c = CompileAndVerify(source, options: TestOptions.ReleaseDll); c.VerifyIL("C.Main", @" { // Code size 30 (0x1e) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0019 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_0010 IL_0008: ldloc.1 IL_0009: ldc.i4.5 IL_000a: beq.s IL_0015 IL_000c: ldloc.1 IL_000d: ldc.i4.1 IL_000e: add IL_000f: stloc.1 IL_0010: ldloc.1 IL_0011: ldc.i4.s 10 IL_0013: blt.s IL_0008 IL_0015: ldloc.0 IL_0016: ldc.i4.1 IL_0017: add IL_0018: stloc.0 IL_0019: ldloc.0 IL_001a: ldc.i4.5 IL_001b: blt.s IL_0004 IL_001d: ret } "); } [WorkItem(539555, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539555")] // Continuing for nested Loops [Fact] public void ContinueForNestedLoop() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 5; i = i + 1) { for (int j = 1; j < 10; j = j + 1) { if ((j % 2) != 0) continue; i = i + 1; System.Console.Write(i); } } } } "; string expectedIL = @"{ // Code size 41 (0x29) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0024 IL_0004: ldc.i4.1 IL_0005: stloc.1 IL_0006: br.s IL_001b IL_0008: ldloc.1 IL_0009: ldc.i4.2 IL_000a: rem IL_000b: brtrue.s IL_0017 IL_000d: ldloc.0 IL_000e: ldc.i4.1 IL_000f: add IL_0010: stloc.0 IL_0011: ldloc.0 IL_0012: call ""void System.Console.Write(int)"" IL_0017: ldloc.1 IL_0018: ldc.i4.1 IL_0019: add IL_001a: stloc.1 IL_001b: ldloc.1 IL_001c: ldc.i4.s 10 IL_001e: blt.s IL_0008 IL_0020: ldloc.0 IL_0021: ldc.i4.1 IL_0022: add IL_0023: stloc.0 IL_0024: ldloc.0 IL_0025: ldc.i4.5 IL_0026: blt.s IL_0004 IL_0028: ret } "; CompileAndVerify(text, expectedOutput: "1234"). VerifyIL("C.Main", expectedIL); } // Goto in for Loops [Fact] public void GotoForNestedLoop_1() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 5; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { goto stop; stop: j = j + 1; } } } } "; string expectedIL = @"{ // Code size 30 (0x1e) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0019 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_0010 IL_0008: ldloc.1 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.1 IL_000c: ldloc.1 IL_000d: ldc.i4.1 IL_000e: add IL_000f: stloc.1 IL_0010: ldloc.1 IL_0011: ldc.i4.s 10 IL_0013: blt.s IL_0008 IL_0015: ldloc.0 IL_0016: ldc.i4.1 IL_0017: add IL_0018: stloc.0 IL_0019: ldloc.0 IL_001a: ldc.i4.5 IL_001b: blt.s IL_0004 IL_001d: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Goto in for Loops [Fact, WorkItem(527952, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527952")] public void GotoForNestedLoop_2() { var source = @" class C { static void Main(string[] args) { for (int i = 0; i < 5; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { goto stop; } stop: i = i + 1; } } } "; var c = CompileAndVerify(source, options: TestOptions.ReleaseDll); c.VerifyIL("C.Main", @" { // Code size 24 (0x18) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0013 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: ldloc.1 IL_0007: ldc.i4.s 10 IL_0009: pop IL_000a: pop IL_000b: ldloc.0 IL_000c: ldc.i4.1 IL_000d: add IL_000e: stloc.0 IL_000f: ldloc.0 IL_0010: ldc.i4.1 IL_0011: add IL_0012: stloc.0 IL_0013: ldloc.0 IL_0014: ldc.i4.5 IL_0015: blt.s IL_0004 IL_0017: ret } "); } // Goto in for Loops [Fact, WorkItem(527952, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527952")] public void GotoForNestedLoop_3() { var source = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { goto outerLoop; } outerLoop: i = i + 2; } } } "; var c = CompileAndVerify(source, options: TestOptions.ReleaseDll); c.VerifyIL("C.Main", @" { // Code size 25 (0x19) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0013 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: ldloc.1 IL_0007: ldc.i4.s 10 IL_0009: pop IL_000a: pop IL_000b: ldloc.0 IL_000c: ldc.i4.2 IL_000d: add IL_000e: stloc.0 IL_000f: ldloc.0 IL_0010: ldc.i4.1 IL_0011: add IL_0012: stloc.0 IL_0013: ldloc.0 IL_0014: ldc.i4.s 10 IL_0016: blt.s IL_0004 IL_0018: ret } "); } // Throw exception in for [Fact] public void ThrowException() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i = i + 1) { for (int j = 0; j < 10;) { throw new System.Exception(); } } } } "; string expectedIL = @"{ // Code size 29 (0x1d) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0017 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_000e IL_0008: newobj ""System.Exception..ctor()"" IL_000d: throw IL_000e: ldloc.1 IL_000f: ldc.i4.s 10 IL_0011: blt.s IL_0008 IL_0013: ldloc.0 IL_0014: ldc.i4.1 IL_0015: add IL_0016: stloc.0 IL_0017: ldloc.0 IL_0018: ldc.i4.s 10 IL_001a: blt.s IL_0004 IL_001c: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Return in for [Fact] public void ReturnInFor() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; ) { for (int j = 0; j < 5; ) { return; } } } } "; string expectedIL = @"{ // Code size 19 (0x13) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_000d IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_0009 IL_0008: ret IL_0009: ldloc.1 IL_000a: ldc.i4.5 IL_000b: blt.s IL_0008 IL_000d: ldloc.0 IL_000e: ldc.i4.s 10 IL_0010: blt.s IL_0004 IL_0012: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // The value of initializer expressions [Fact] public void ValueOfInit() { var text = @" class C { static void Main(string[] args) { for (int i = 0, j = 1; i < 5; i = i + 1) { j = 2; } } } "; string expectedIL = @"{ // Code size 13 (0xd) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0008 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.5 IL_000a: blt.s IL_0004 IL_000c: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // The value of condition expression [Fact] public void ValueOfCondition() { var text = @" class C { static void Main(string[] args) { int c = 0, x = 0; for (int i = 0; i < 50 - x; i = i + 1) { x = x + 1; c = c + 1; } } } "; string expectedIL = @"{ // Code size 28 (0x1c) .maxstack 3 .locals init (int V_0, //c int V_1, //x int V_2) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldc.i4.0 IL_0003: stloc.1 IL_0004: ldc.i4.0 IL_0005: stloc.2 IL_0006: br.s IL_0014 IL_0008: ldloc.1 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.1 IL_000c: ldloc.0 IL_000d: ldc.i4.1 IL_000e: add IL_000f: stloc.0 IL_0010: ldloc.2 IL_0011: ldc.i4.1 IL_0012: add IL_0013: stloc.2 IL_0014: ldloc.2 IL_0015: ldc.i4.s 50 IL_0017: ldloc.1 IL_0018: sub IL_0019: blt.s IL_0008 IL_001b: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // The evaluation of condition expression take place before execution of loop [Fact] public void ValueOfConditionBeforeLoop() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 0; i = i + 1) { i = i + 1; } } } "; string expectedIL = @"{ // Code size 17 (0x11) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_000c IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.0 IL_000c: ldloc.0 IL_000d: ldc.i4.0 IL_000e: blt.s IL_0004 IL_0010: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Unreachable code [Fact] public void CS0162WRN_UnreachableCode_1() { var text = @" class C { static void Main(string[] args) { for (; false; ) { System.Console.WriteLine(""hello""); //unreachable } } } "; string expectedIL = @"{ // Code size 1 (0x1) .maxstack 1 IL_0000: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL). VerifyDiagnostics(Diagnostic(ErrorCode.WRN_UnreachableCode, "System")); } [Fact, WorkItem(527952, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527952")] public void CS0162WRN_UnreachableCode_2() { var source = @" class C { static void Main(string[] args) { for (; ; ) { } System.Console.WriteLine(""hello""); //unreachable } } "; var c = CompileAndVerify(source, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(Diagnostic(ErrorCode.WRN_UnreachableCode, "System")); c.VerifyIL("C.Main", @" { // Code size 2 (0x2) .maxstack 1 IL_0000: br.s IL_0000 } "); } [Fact, WorkItem(528275, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528275")] public void CS0162WRN_UnreachableCode_3() { var text = @" class C { static void Main(string[] args) { for (uint i = 0; true || f(); i = i + 1) // f() is unreachable expression { } } static bool f() { return true; } } "; string expectedIL = @"{ // Code size 8 (0x8) .maxstack 2 .locals init (uint V_0) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: ldc.i4.1 IL_0004: add IL_0005: stloc.0 IL_0006: br.s IL_0002 } "; // Roslyn no unreachable warning CS0429 (for expr) CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Unreachable code [Fact] public void CS0162WRN_UnreachableCode_4() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i = i + 1) { for (int j = 0; j < 10; j = j + 1) { goto stop; goto outerLoop; } outerLoop: return; } stop: return; } } "; string expectedIL = @" { // Code size 18 (0x12) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_000c IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: ldloc.1 IL_0007: ldc.i4.s 10 IL_0009: pop IL_000a: pop IL_000b: ret IL_000c: ldloc.0 IL_000d: ldc.i4.s 10 IL_000f: blt.s IL_0004 IL_0011: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL). VerifyDiagnostics( Diagnostic(ErrorCode.WRN_UnreachableCode, "goto"), Diagnostic(ErrorCode.WRN_UnreachableCode, "i") ); } // Unreachable code [Fact] public void CS0162WRN_UnreachableCode_5() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i = i + 1) { for (int j = 0; j < 10; j = j + 1) // j++ is unreachable { throw new System.Exception(); } } } } "; string expectedIL = @"{ // Code size 29 (0x1d) .maxstack 2 .locals init (int V_0, //i int V_1) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0017 IL_0004: ldc.i4.0 IL_0005: stloc.1 IL_0006: br.s IL_000e IL_0008: newobj ""System.Exception..ctor()"" IL_000d: throw IL_000e: ldloc.1 IL_000f: ldc.i4.s 10 IL_0011: blt.s IL_0008 IL_0013: ldloc.0 IL_0014: ldc.i4.1 IL_0015: add IL_0016: stloc.0 IL_0017: ldloc.0 IL_0018: ldc.i4.s 10 IL_001a: blt.s IL_0004 IL_001c: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL). VerifyDiagnostics(Diagnostic(ErrorCode.WRN_UnreachableCode, "j")); } // Unreachable code [Fact] public void CS0162WRN_UnreachableCode_6() { var text = @" class C { static void Main(string[] args) { for (int i = 0; i < 10; i = i + 1) { return; } } } "; string expectedIL = @" { // Code size 8 (0x8) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: ldc.i4.s 10 IL_0005: pop IL_0006: pop IL_0007: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL). VerifyDiagnostics(Diagnostic(ErrorCode.WRN_UnreachableCode, "i")); } // Object initializer as iteration variable of for loop [Fact] public void ObjectInitAsInitializer() { var text = @" class C { static void Main(string[] args) { for (Goo f = new Goo { i = 0, s = ""abc"" }; f.i < 5; f.i = f.i + 1) { } } } public class Goo { public int i; public string s; } "; string expectedIL = @" { // Code size 50 (0x32) .maxstack 3 .locals init (Goo V_0) //f IL_0000: newobj ""Goo..ctor()"" IL_0005: dup IL_0006: ldc.i4.0 IL_0007: stfld ""int Goo.i"" IL_000c: dup IL_000d: ldstr ""abc"" IL_0012: stfld ""string Goo.s"" IL_0017: stloc.0 IL_0018: br.s IL_0028 IL_001a: ldloc.0 IL_001b: ldloc.0 IL_001c: ldfld ""int Goo.i"" IL_0021: ldc.i4.1 IL_0022: add IL_0023: stfld ""int Goo.i"" IL_0028: ldloc.0 IL_0029: ldfld ""int Goo.i"" IL_002e: ldc.i4.5 IL_002f: blt.s IL_001a IL_0031: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Dynamic works in for loop [Fact] public void DynamicInFor() { var text = @"class C { static void Main(string[] args) { dynamic d = new myFor(); for (d.Initialize(5); d.Done; d.Next()) { } } } public class myFor { int index; int max; public void Initialize(int max) { index = 0; this.max = max; System.Console.WriteLine(""Initialize""); } public bool Done { get { System.Console.WriteLine(""Done""); return index < max; } } public void Next() { index = index + 1; System.Console.WriteLine(""Next""); } } "; CompileAndVerify(text, references: new MetadataReference[] { CSharpRef }, expectedOutput: @"Initialize Done Next Done Next Done Next Done Next Done Next Done"); } // Var works in for loop [Fact] public void VarInFor() { var text = @" class C { static void Main(string[] args) { for (var i = 1; i < 5; i = i + 1) ; } } "; string expectedIL = @"{ // Code size 13 (0xd) .maxstack 2 .locals init (int V_0) //i IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: br.s IL_0008 IL_0004: ldloc.0 IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.5 IL_000a: blt.s IL_0004 IL_000c: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // Query expression in initializer list [Fact] public void QueryInInit() { var text = @" using System.Linq; using System.Collections.Generic; class C { static void Main(string[] args) { for (IEnumerable<string> str = from x in ""123"" let z = x.ToString() select z into w select w; ; ) { foreach (var item in str) { System.Console.WriteLine(item); } return; } } } "; var comp = CompileAndVerify(text, expectedOutput: @"1 2 3"); } // Query expression in for body [Fact] public void QueryInBody() { var text = @" using System.Linq; using System.Collections.Generic; class C { static void Main(string[] args) { foreach (var item in fun()) { System.Console.WriteLine(item); } } private static IEnumerable<string> fun() { for (int i = 0; i < 5; ) { return from x in ""123"" let z = x.ToString() select z into w select w; } return null; } } "; var comp = CompileAndVerify(text, expectedOutput: @"1 2 3"); } // Expression tree in for initializer of for statement [Fact] public void ExpressiontreeInInit() { var text = @" class C { static void Main(string[] args) { System.Linq.Expressions.Expression<System.Func<int, int>> e = x => x % 6; int i = 1; for (e = x => x * x; i < 5; i++) { var lambda = e.Compile(); System.Console.WriteLine(lambda(i)); } } } "; CompileAndVerify(text, expectedOutput: @"1 4 9 16"); } // Expression tree in for iterator of for statement [Fact] public void ExpressiontreeInIterator() { var text = @" class C { static void Main(string[] args) { System.Linq.Expressions.Expression<System.Func<int, int>> e = x => x % 6; for (int i = 1; i < 5; e = x => x * x, i = i + 1) { var lambda = e.Compile(); System.Console.WriteLine(lambda(i)); } } } "; var comp = CompileAndVerify(text, expectedOutput: @"1 4 9 16"); } // Custom type in for loop [Fact] public void CustomerTypeInFor() { var text = @" class C { static void Main(string[] args) { for (C1 i = new C1(); i == null; i++) { } } } public class C1 { public static C1 operator ++(C1 obj) { return obj; } } "; string expectedIL = @"{ // Code size 19 (0x13) .maxstack 1 .locals init (C1 V_0) //i IL_0000: newobj ""C1..ctor()"" IL_0005: stloc.0 IL_0006: br.s IL_000f IL_0008: ldloc.0 IL_0009: call ""C1 C1.op_Increment(C1)"" IL_000e: stloc.0 IL_000f: ldloc.0 IL_0010: brfalse.s IL_0008 IL_0012: ret } "; CompileAndVerify(text). VerifyIL("C.Main", expectedIL); } // PostFix Increment In For [Fact, WorkItem(539759, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539759")] public void PostFixIncrementInFor() { var text = @" class Program { static void Main(string[] args) { int i = 0; for (int j = i++; j < 5; ++j) { System.Console.WriteLine(j); } } } "; string expectedIL = @"{ // Code size 19 (0x13) .maxstack 2 .locals init (int V_0) //j IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_000e IL_0004: ldloc.0 IL_0005: call ""void System.Console.WriteLine(int)"" IL_000a: ldloc.0 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.0 IL_000e: ldloc.0 IL_000f: ldc.i4.5 IL_0010: blt.s IL_0004 IL_0012: ret } "; CompileAndVerify(text). VerifyIL("Program.Main", expectedIL); } // PreFix Increment In For [Fact] public void PreFixIncrementInFor() { var text = @" class Program { static void Main(string[] args) { int i = 0; for (int j = ++i; j < 5; ++j) { System.Console.WriteLine(j); } } } "; var comp = CompileAndVerify(text, expectedOutput: @"1 2 3 4"); } // PreFix Increment In Condition [Fact] public void PreFixIncrementInCondition() { var text = @" class Program { static void Main(string[] args) { for (int i = 0; ++i < 5; ) { System.Console.WriteLine(i); } } } "; var comp = CompileAndVerify(text, expectedOutput: @"1 2 3 4"); } // PostFix Increment In Condition [Fact] public void PostFixDecrementInCondition() { var text = @" class Program { static void Main(string[] args) { for (int i = 0; goo(i--) > -5;) { System.Console.WriteLine(i); } } static int goo(int x) { return x; } } "; var comp = CompileAndVerify(text, expectedOutput: @"-1 -2 -3 -4 -5"); } [Fact, WorkItem(992882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/992882")] public void InfiniteLoopVerify() { var text = @" class Program { static void Main(string[] args) { for (;true;) { System.Console.WriteLine(""z""); } } } "; string expectedIL = @" { // Code size 12 (0xc) .maxstack 1 IL_0000: ldstr ""z"" IL_0005: call ""void System.Console.WriteLine(string)"" IL_000a: br.s IL_0000 }"; CompileAndVerify(text). VerifyIL("Program.Main", expectedIL); } [Fact, WorkItem(992882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/992882")] public void InfiniteLoopVerify01() { var text = @" class Program { static void Main(string[] args) { for (;true;) { System.Console.WriteLine(""z""); } } } "; var c = CompileAndVerify(text, options: TestOptions.DebugExe); c.VerifyIL("Program.Main", @" { // Code size 20 (0x14) .maxstack 1 .locals init (bool V_0) IL_0000: nop IL_0001: br.s IL_0010 IL_0003: nop IL_0004: ldstr ""z"" IL_0009: call ""void System.Console.WriteLine(string)"" IL_000e: nop IL_000f: nop IL_0010: ldc.i4.1 IL_0011: stloc.0 IL_0012: br.s IL_0003 }"); } } }