Browse Source

Fix #979: Unrecognized foreach loop in unsafe code

pull/987/head
Siegfried Pammer 8 years ago
parent
commit
5cd6299191
  1. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs
  2. 311
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.il
  3. 218
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.il
  4. 205
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.roslyn.il
  5. 263
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.roslyn.il
  6. 163
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

33
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs

@ -495,7 +495,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -495,7 +495,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
item.TestCall();
}
}
#endregion
public void ForEachOverMultiDimArray(int[,] items)
{
foreach (int value in items) {
Console.WriteLine(value);
Console.WriteLine(value);
}
}
public void ForEachOverMultiDimArray2(int[,,] items)
{
foreach (int value in items) {
Console.WriteLine(value);
Console.WriteLine(value);
}
}
public unsafe void ForEachOverMultiDimArray3(int*[,] items)
{
#if ROSLYN && OPT
foreach (int* intPtr in items) {
Console.WriteLine(*intPtr);
Console.WriteLine(*intPtr);
}
#else
foreach (int* ptr in items) {
Console.WriteLine(*ptr);
Console.WriteLine(*ptr);
}
#endif
}
#endregion
public void ForOverArray(string[] array)
{

311
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly gc5hv5wh
.assembly '50bjvac5'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module gc5hv5wh.dll
// MVID: {062C7BAF-1AEF-4973-83C5-A0DC279703B8}
.module '50bjvac5.dll'
// MVID: {7EA9F0A8-B896-4F84-BCD8-AC7B4D44BBC0}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x038E0000
// Image base: 0x03450000
// =============== CLASS MEMBERS DECLARATION ===================
@ -1901,6 +1901,272 @@ @@ -1901,6 +1901,272 @@
IL_003a: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForEachOverMultiDimArray(int32[0...,0...] items) cil managed
{
// Code size 110 (0x6e)
.maxstack 3
.locals init (int32 V_0,
int32[0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
bool V_6)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.1
IL_0004: ldloc.1
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.2
IL_000c: ldloc.1
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.3
IL_0014: ldloc.1
IL_0015: ldc.i4.0
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_001b: stloc.s V_4
IL_001d: br.s IL_005f
IL_001f: ldloc.1
IL_0020: ldc.i4.1
IL_0021: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0026: stloc.s V_5
IL_0028: br.s IL_004b
IL_002a: ldloc.1
IL_002b: ldloc.s V_4
IL_002d: ldloc.s V_5
IL_002f: call instance int32 int32[0...,0...]::Get(int32,
int32)
IL_0034: stloc.0
IL_0035: nop
IL_0036: ldloc.0
IL_0037: call void [mscorlib]System.Console::WriteLine(int32)
IL_003c: nop
IL_003d: ldloc.0
IL_003e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0043: nop
IL_0044: nop
IL_0045: ldloc.s V_5
IL_0047: ldc.i4.1
IL_0048: add
IL_0049: stloc.s V_5
IL_004b: ldloc.s V_5
IL_004d: ldloc.3
IL_004e: cgt
IL_0050: ldc.i4.0
IL_0051: ceq
IL_0053: stloc.s V_6
IL_0055: ldloc.s V_6
IL_0057: brtrue.s IL_002a
IL_0059: ldloc.s V_4
IL_005b: ldc.i4.1
IL_005c: add
IL_005d: stloc.s V_4
IL_005f: ldloc.s V_4
IL_0061: ldloc.2
IL_0062: cgt
IL_0064: ldc.i4.0
IL_0065: ceq
IL_0067: stloc.s V_6
IL_0069: ldloc.s V_6
IL_006b: brtrue.s IL_001f
IL_006d: ret
} // end of method Loops::ForEachOverMultiDimArray
.method public hidebysig instance void
ForEachOverMultiDimArray2(int32[0...,0...,0...] items) cil managed
{
// Code size 153 (0x99)
.maxstack 4
.locals init (int32 V_0,
int32[0...,0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
int32 V_6,
int32 V_7,
bool V_8)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.1
IL_0004: ldloc.1
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.2
IL_000c: ldloc.1
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.3
IL_0014: ldloc.1
IL_0015: ldc.i4.2
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_001b: stloc.s V_4
IL_001d: ldloc.1
IL_001e: ldc.i4.0
IL_001f: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0024: stloc.s V_5
IL_0026: br.s IL_008a
IL_0028: ldloc.1
IL_0029: ldc.i4.1
IL_002a: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_002f: stloc.s V_6
IL_0031: br.s IL_0076
IL_0033: ldloc.1
IL_0034: ldc.i4.2
IL_0035: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_003a: stloc.s V_7
IL_003c: br.s IL_0061
IL_003e: ldloc.1
IL_003f: ldloc.s V_5
IL_0041: ldloc.s V_6
IL_0043: ldloc.s V_7
IL_0045: call instance int32 int32[0...,0...,0...]::Get(int32,
int32,
int32)
IL_004a: stloc.0
IL_004b: nop
IL_004c: ldloc.0
IL_004d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0052: nop
IL_0053: ldloc.0
IL_0054: call void [mscorlib]System.Console::WriteLine(int32)
IL_0059: nop
IL_005a: nop
IL_005b: ldloc.s V_7
IL_005d: ldc.i4.1
IL_005e: add
IL_005f: stloc.s V_7
IL_0061: ldloc.s V_7
IL_0063: ldloc.s V_4
IL_0065: cgt
IL_0067: ldc.i4.0
IL_0068: ceq
IL_006a: stloc.s V_8
IL_006c: ldloc.s V_8
IL_006e: brtrue.s IL_003e
IL_0070: ldloc.s V_6
IL_0072: ldc.i4.1
IL_0073: add
IL_0074: stloc.s V_6
IL_0076: ldloc.s V_6
IL_0078: ldloc.3
IL_0079: cgt
IL_007b: ldc.i4.0
IL_007c: ceq
IL_007e: stloc.s V_8
IL_0080: ldloc.s V_8
IL_0082: brtrue.s IL_0033
IL_0084: ldloc.s V_5
IL_0086: ldc.i4.1
IL_0087: add
IL_0088: stloc.s V_5
IL_008a: ldloc.s V_5
IL_008c: ldloc.2
IL_008d: cgt
IL_008f: ldc.i4.0
IL_0090: ceq
IL_0092: stloc.s V_8
IL_0094: ldloc.s V_8
IL_0096: brtrue.s IL_0028
IL_0098: ret
} // end of method Loops::ForEachOverMultiDimArray2
.method public hidebysig instance void
ForEachOverMultiDimArray3(int32*[0...,0...] items) cil managed
{
// Code size 112 (0x70)
.maxstack 3
.locals init (int32* V_0,
int32*[0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
bool V_6)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.1
IL_0004: ldloc.1
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.2
IL_000c: ldloc.1
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.3
IL_0014: ldloc.1
IL_0015: ldc.i4.0
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_001b: stloc.s V_4
IL_001d: br.s IL_0061
IL_001f: ldloc.1
IL_0020: ldc.i4.1
IL_0021: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0026: stloc.s V_5
IL_0028: br.s IL_004d
IL_002a: ldloc.1
IL_002b: ldloc.s V_4
IL_002d: ldloc.s V_5
IL_002f: call instance int32* int32*[0...,0...]::Get(int32,
int32)
IL_0034: stloc.0
IL_0035: nop
IL_0036: ldloc.0
IL_0037: ldind.i4
IL_0038: call void [mscorlib]System.Console::WriteLine(int32)
IL_003d: nop
IL_003e: ldloc.0
IL_003f: ldind.i4
IL_0040: call void [mscorlib]System.Console::WriteLine(int32)
IL_0045: nop
IL_0046: nop
IL_0047: ldloc.s V_5
IL_0049: ldc.i4.1
IL_004a: add
IL_004b: stloc.s V_5
IL_004d: ldloc.s V_5
IL_004f: ldloc.3
IL_0050: cgt
IL_0052: ldc.i4.0
IL_0053: ceq
IL_0055: stloc.s V_6
IL_0057: ldloc.s V_6
IL_0059: brtrue.s IL_002a
IL_005b: ldloc.s V_4
IL_005d: ldc.i4.1
IL_005e: add
IL_005f: stloc.s V_4
IL_0061: ldloc.s V_4
IL_0063: ldloc.2
IL_0064: cgt
IL_0066: ldc.i4.0
IL_0067: ceq
IL_0069: stloc.s V_6
IL_006b: ldloc.s V_6
IL_006d: brtrue.s IL_001f
IL_006f: ret
} // end of method Loops::ForEachOverMultiDimArray3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{
@ -2352,7 +2618,7 @@ @@ -2352,7 +2618,7 @@
.method public hidebysig instance void
ForeachLoopWithEarlyReturn(class [mscorlib]System.Collections.Generic.List`1<object> items) cil managed
{
// Code size 73 (0x49)
// Code size 74 (0x4a)
.maxstack 3
.locals init (object V_0,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_1,
@ -2365,7 +2631,7 @@ @@ -2365,7 +2631,7 @@
IL_0008: stloc.1
.try
{
IL_0009: br.s IL_002b
IL_0009: br.s IL_002c
IL_000b: ldloca.s V_1
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
@ -2383,30 +2649,31 @@ @@ -2383,30 +2649,31 @@
IL_0022: ceq
IL_0024: stloc.3
IL_0025: ldloc.3
IL_0026: brtrue.s IL_002a
IL_0026: brtrue.s IL_002b
IL_0028: br.s IL_0036
IL_0028: nop
IL_0029: br.s IL_0037
IL_002a: nop
IL_002b: ldloca.s V_1
IL_002d: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0032: stloc.3
IL_0033: ldloc.3
IL_0034: brtrue.s IL_000b
IL_002b: nop
IL_002c: ldloca.s V_1
IL_002e: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0033: stloc.3
IL_0034: ldloc.3
IL_0035: brtrue.s IL_000b
IL_0036: leave.s IL_0047
IL_0037: leave.s IL_0048
} // end .try
finally
{
IL_0038: ldloca.s V_1
IL_003a: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_0040: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0045: nop
IL_0046: endfinally
IL_0039: ldloca.s V_1
IL_003b: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_0041: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0046: nop
IL_0047: endfinally
} // end handler
IL_0047: nop
IL_0048: ret
IL_0048: nop
IL_0049: ret
} // end of method Loops::ForeachLoopWithEarlyReturn
.method public hidebysig specialname rtspecialname

218
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly iyvgltxy
.assembly ca3webe1
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module iyvgltxy.dll
// MVID: {29F6B869-DC6A-4F23-A073-750A25BF2F78}
.module ca3webe1.dll
// MVID: {3674B35A-51F1-4E0A-A67E-D7FEBA11373B}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x01130000
// Image base: 0x02DA0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -1528,6 +1528,216 @@ @@ -1528,6 +1528,216 @@
IL_0031: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForEachOverMultiDimArray(int32[0...,0...] items) cil managed
{
// Code size 86 (0x56)
.maxstack 3
.locals init (int32 V_0,
int32[0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5)
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.2
IL_000a: ldloc.1
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.3
IL_0012: ldloc.1
IL_0013: ldc.i4.0
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0019: stloc.s V_4
IL_001b: br.s IL_0050
IL_001d: ldloc.1
IL_001e: ldc.i4.1
IL_001f: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0024: stloc.s V_5
IL_0026: br.s IL_0045
IL_0028: ldloc.1
IL_0029: ldloc.s V_4
IL_002b: ldloc.s V_5
IL_002d: call instance int32 int32[0...,0...]::Get(int32,
int32)
IL_0032: stloc.0
IL_0033: ldloc.0
IL_0034: call void [mscorlib]System.Console::WriteLine(int32)
IL_0039: ldloc.0
IL_003a: call void [mscorlib]System.Console::WriteLine(int32)
IL_003f: ldloc.s V_5
IL_0041: ldc.i4.1
IL_0042: add
IL_0043: stloc.s V_5
IL_0045: ldloc.s V_5
IL_0047: ldloc.3
IL_0048: ble.s IL_0028
IL_004a: ldloc.s V_4
IL_004c: ldc.i4.1
IL_004d: add
IL_004e: stloc.s V_4
IL_0050: ldloc.s V_4
IL_0052: ldloc.2
IL_0053: ble.s IL_001d
IL_0055: ret
} // end of method Loops::ForEachOverMultiDimArray
.method public hidebysig instance void
ForEachOverMultiDimArray2(int32[0...,0...,0...] items) cil managed
{
// Code size 120 (0x78)
.maxstack 4
.locals init (int32 V_0,
int32[0...,0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
int32 V_6,
int32 V_7)
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.2
IL_000a: ldloc.1
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.3
IL_0012: ldloc.1
IL_0013: ldc.i4.2
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0019: stloc.s V_4
IL_001b: ldloc.1
IL_001c: ldc.i4.0
IL_001d: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0022: stloc.s V_5
IL_0024: br.s IL_0072
IL_0026: ldloc.1
IL_0027: ldc.i4.1
IL_0028: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_002d: stloc.s V_6
IL_002f: br.s IL_0067
IL_0031: ldloc.1
IL_0032: ldc.i4.2
IL_0033: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0038: stloc.s V_7
IL_003a: br.s IL_005b
IL_003c: ldloc.1
IL_003d: ldloc.s V_5
IL_003f: ldloc.s V_6
IL_0041: ldloc.s V_7
IL_0043: call instance int32 int32[0...,0...,0...]::Get(int32,
int32,
int32)
IL_0048: stloc.0
IL_0049: ldloc.0
IL_004a: call void [mscorlib]System.Console::WriteLine(int32)
IL_004f: ldloc.0
IL_0050: call void [mscorlib]System.Console::WriteLine(int32)
IL_0055: ldloc.s V_7
IL_0057: ldc.i4.1
IL_0058: add
IL_0059: stloc.s V_7
IL_005b: ldloc.s V_7
IL_005d: ldloc.s V_4
IL_005f: ble.s IL_003c
IL_0061: ldloc.s V_6
IL_0063: ldc.i4.1
IL_0064: add
IL_0065: stloc.s V_6
IL_0067: ldloc.s V_6
IL_0069: ldloc.3
IL_006a: ble.s IL_0031
IL_006c: ldloc.s V_5
IL_006e: ldc.i4.1
IL_006f: add
IL_0070: stloc.s V_5
IL_0072: ldloc.s V_5
IL_0074: ldloc.2
IL_0075: ble.s IL_0026
IL_0077: ret
} // end of method Loops::ForEachOverMultiDimArray2
.method public hidebysig instance void
ForEachOverMultiDimArray3(int32*[0...,0...] items) cil managed
{
// Code size 88 (0x58)
.maxstack 3
.locals init (int32* V_0,
int32*[0...,0...] V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5)
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.2
IL_000a: ldloc.1
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.3
IL_0012: ldloc.1
IL_0013: ldc.i4.0
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0019: stloc.s V_4
IL_001b: br.s IL_0052
IL_001d: ldloc.1
IL_001e: ldc.i4.1
IL_001f: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0024: stloc.s V_5
IL_0026: br.s IL_0047
IL_0028: ldloc.1
IL_0029: ldloc.s V_4
IL_002b: ldloc.s V_5
IL_002d: call instance int32* int32*[0...,0...]::Get(int32,
int32)
IL_0032: stloc.0
IL_0033: ldloc.0
IL_0034: ldind.i4
IL_0035: call void [mscorlib]System.Console::WriteLine(int32)
IL_003a: ldloc.0
IL_003b: ldind.i4
IL_003c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0041: ldloc.s V_5
IL_0043: ldc.i4.1
IL_0044: add
IL_0045: stloc.s V_5
IL_0047: ldloc.s V_5
IL_0049: ldloc.3
IL_004a: ble.s IL_0028
IL_004c: ldloc.s V_4
IL_004e: ldc.i4.1
IL_004f: add
IL_0050: stloc.s V_4
IL_0052: ldloc.s V_4
IL_0054: ldloc.2
IL_0055: ble.s IL_001d
IL_0057: ret
} // end of method Loops::ForEachOverMultiDimArray3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{

205
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module Loops.dll
// MVID: {781CB7F6-E31A-4804-B6CA-CB8C7FDF34DA}
// MVID: {F07742D5-57A8-4CEC-B130-8CFD8D8E0AFC}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x03730000
// Image base: 0x04780000
// =============== CLASS MEMBERS DECLARATION ===================
@ -1481,6 +1481,207 @@ @@ -1481,6 +1481,207 @@
IL_0031: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForEachOverMultiDimArray(int32[0...,0...] items) cil managed
{
// Code size 79 (0x4f)
.maxstack 3
.locals init (int32[0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.1
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.2
IL_0012: ldloc.0
IL_0013: ldc.i4.0
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0019: stloc.3
IL_001a: br.s IL_004a
IL_001c: ldloc.0
IL_001d: ldc.i4.1
IL_001e: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0023: stloc.s V_4
IL_0025: br.s IL_0041
IL_0027: ldloc.0
IL_0028: ldloc.3
IL_0029: ldloc.s V_4
IL_002b: call instance int32 int32[0...,0...]::Get(int32,
int32)
IL_0030: dup
IL_0031: call void [mscorlib]System.Console::WriteLine(int32)
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: ldloc.s V_4
IL_003d: ldc.i4.1
IL_003e: add
IL_003f: stloc.s V_4
IL_0041: ldloc.s V_4
IL_0043: ldloc.2
IL_0044: ble.s IL_0027
IL_0046: ldloc.3
IL_0047: ldc.i4.1
IL_0048: add
IL_0049: stloc.3
IL_004a: ldloc.3
IL_004b: ldloc.1
IL_004c: ble.s IL_001c
IL_004e: ret
} // end of method Loops::ForEachOverMultiDimArray
.method public hidebysig instance void
ForEachOverMultiDimArray2(int32[0...,0...,0...] items) cil managed
{
// Code size 116 (0x74)
.maxstack 4
.locals init (int32[0...,0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
int32 V_6)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.1
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.2
IL_0012: ldloc.0
IL_0013: ldc.i4.2
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0019: stloc.3
IL_001a: ldloc.0
IL_001b: ldc.i4.0
IL_001c: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0021: stloc.s V_4
IL_0023: br.s IL_006e
IL_0025: ldloc.0
IL_0026: ldc.i4.1
IL_0027: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_002c: stloc.s V_5
IL_002e: br.s IL_0063
IL_0030: ldloc.0
IL_0031: ldc.i4.2
IL_0032: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0037: stloc.s V_6
IL_0039: br.s IL_0058
IL_003b: ldloc.0
IL_003c: ldloc.s V_4
IL_003e: ldloc.s V_5
IL_0040: ldloc.s V_6
IL_0042: call instance int32 int32[0...,0...,0...]::Get(int32,
int32,
int32)
IL_0047: dup
IL_0048: call void [mscorlib]System.Console::WriteLine(int32)
IL_004d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0052: ldloc.s V_6
IL_0054: ldc.i4.1
IL_0055: add
IL_0056: stloc.s V_6
IL_0058: ldloc.s V_6
IL_005a: ldloc.3
IL_005b: ble.s IL_003b
IL_005d: ldloc.s V_5
IL_005f: ldc.i4.1
IL_0060: add
IL_0061: stloc.s V_5
IL_0063: ldloc.s V_5
IL_0065: ldloc.2
IL_0066: ble.s IL_0030
IL_0068: ldloc.s V_4
IL_006a: ldc.i4.1
IL_006b: add
IL_006c: stloc.s V_4
IL_006e: ldloc.s V_4
IL_0070: ldloc.1
IL_0071: ble.s IL_0025
IL_0073: ret
} // end of method Loops::ForEachOverMultiDimArray2
.method public hidebysig instance void
ForEachOverMultiDimArray3(int32*[0...,0...] items) cil managed
{
// Code size 81 (0x51)
.maxstack 3
.locals init (int32*[0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0009: stloc.1
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0011: stloc.2
IL_0012: ldloc.0
IL_0013: ldc.i4.0
IL_0014: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0019: stloc.3
IL_001a: br.s IL_004c
IL_001c: ldloc.0
IL_001d: ldc.i4.1
IL_001e: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0023: stloc.s V_4
IL_0025: br.s IL_0043
IL_0027: ldloc.0
IL_0028: ldloc.3
IL_0029: ldloc.s V_4
IL_002b: call instance int32* int32*[0...,0...]::Get(int32,
int32)
IL_0030: dup
IL_0031: ldind.i4
IL_0032: call void [mscorlib]System.Console::WriteLine(int32)
IL_0037: ldind.i4
IL_0038: call void [mscorlib]System.Console::WriteLine(int32)
IL_003d: ldloc.s V_4
IL_003f: ldc.i4.1
IL_0040: add
IL_0041: stloc.s V_4
IL_0043: ldloc.s V_4
IL_0045: ldloc.2
IL_0046: ble.s IL_0027
IL_0048: ldloc.3
IL_0049: ldc.i4.1
IL_004a: add
IL_004b: stloc.3
IL_004c: ldloc.3
IL_004d: ldloc.1
IL_004e: ble.s IL_001c
IL_0050: ret
} // end of method Loops::ForEachOverMultiDimArray3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{

263
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module Loops.dll
// MVID: {673E7ABD-594F-4CEA-B653-2C92D7588EE4}
// MVID: {FFD462DB-4ADF-4242-B780-E01C783B2038}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x033F0000
// Image base: 0x04F90000
// =============== CLASS MEMBERS DECLARATION ===================
@ -1771,6 +1771,234 @@ @@ -1771,6 +1771,234 @@
IL_0037: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForEachOverMultiDimArray(int32[0...,0...] items) cil managed
{
// Code size 90 (0x5a)
.maxstack 3
.locals init (int32[0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.1
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.2
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_001b: stloc.3
IL_001c: br.s IL_0055
IL_001e: ldloc.0
IL_001f: ldc.i4.1
IL_0020: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0025: stloc.s V_4
IL_0027: br.s IL_004c
IL_0029: ldloc.0
IL_002a: ldloc.3
IL_002b: ldloc.s V_4
IL_002d: call instance int32 int32[0...,0...]::Get(int32,
int32)
IL_0032: stloc.s V_5
IL_0034: nop
IL_0035: ldloc.s V_5
IL_0037: call void [mscorlib]System.Console::WriteLine(int32)
IL_003c: nop
IL_003d: ldloc.s V_5
IL_003f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0044: nop
IL_0045: nop
IL_0046: ldloc.s V_4
IL_0048: ldc.i4.1
IL_0049: add
IL_004a: stloc.s V_4
IL_004c: ldloc.s V_4
IL_004e: ldloc.2
IL_004f: ble.s IL_0029
IL_0051: ldloc.3
IL_0052: ldc.i4.1
IL_0053: add
IL_0054: stloc.3
IL_0055: ldloc.3
IL_0056: ldloc.1
IL_0057: ble.s IL_001e
IL_0059: ret
} // end of method Loops::ForEachOverMultiDimArray
.method public hidebysig instance void
ForEachOverMultiDimArray2(int32[0...,0...,0...] items) cil managed
{
// Code size 127 (0x7f)
.maxstack 4
.locals init (int32[0...,0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32 V_5,
int32 V_6,
int32 V_7)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.1
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.2
IL_0014: ldloc.0
IL_0015: ldc.i4.2
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_001b: stloc.3
IL_001c: ldloc.0
IL_001d: ldc.i4.0
IL_001e: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0023: stloc.s V_4
IL_0025: br.s IL_0079
IL_0027: ldloc.0
IL_0028: ldc.i4.1
IL_0029: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_002e: stloc.s V_5
IL_0030: br.s IL_006e
IL_0032: ldloc.0
IL_0033: ldc.i4.2
IL_0034: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0039: stloc.s V_6
IL_003b: br.s IL_0063
IL_003d: ldloc.0
IL_003e: ldloc.s V_4
IL_0040: ldloc.s V_5
IL_0042: ldloc.s V_6
IL_0044: call instance int32 int32[0...,0...,0...]::Get(int32,
int32,
int32)
IL_0049: stloc.s V_7
IL_004b: nop
IL_004c: ldloc.s V_7
IL_004e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0053: nop
IL_0054: ldloc.s V_7
IL_0056: call void [mscorlib]System.Console::WriteLine(int32)
IL_005b: nop
IL_005c: nop
IL_005d: ldloc.s V_6
IL_005f: ldc.i4.1
IL_0060: add
IL_0061: stloc.s V_6
IL_0063: ldloc.s V_6
IL_0065: ldloc.3
IL_0066: ble.s IL_003d
IL_0068: ldloc.s V_5
IL_006a: ldc.i4.1
IL_006b: add
IL_006c: stloc.s V_5
IL_006e: ldloc.s V_5
IL_0070: ldloc.2
IL_0071: ble.s IL_0032
IL_0073: ldloc.s V_4
IL_0075: ldc.i4.1
IL_0076: add
IL_0077: stloc.s V_4
IL_0079: ldloc.s V_4
IL_007b: ldloc.1
IL_007c: ble.s IL_0027
IL_007e: ret
} // end of method Loops::ForEachOverMultiDimArray2
.method public hidebysig instance void
ForEachOverMultiDimArray3(int32*[0...,0...] items) cil managed
{
// Code size 92 (0x5c)
.maxstack 3
.locals init (int32*[0...,0...] V_0,
int32 V_1,
int32 V_2,
int32 V_3,
int32 V_4,
int32* V_5)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_000b: stloc.1
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: callvirt instance int32 [mscorlib]System.Array::GetUpperBound(int32)
IL_0013: stloc.2
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_001b: stloc.3
IL_001c: br.s IL_0057
IL_001e: ldloc.0
IL_001f: ldc.i4.1
IL_0020: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
IL_0025: stloc.s V_4
IL_0027: br.s IL_004e
IL_0029: ldloc.0
IL_002a: ldloc.3
IL_002b: ldloc.s V_4
IL_002d: call instance int32* int32*[0...,0...]::Get(int32,
int32)
IL_0032: stloc.s V_5
IL_0034: nop
IL_0035: ldloc.s V_5
IL_0037: ldind.i4
IL_0038: call void [mscorlib]System.Console::WriteLine(int32)
IL_003d: nop
IL_003e: ldloc.s V_5
IL_0040: ldind.i4
IL_0041: call void [mscorlib]System.Console::WriteLine(int32)
IL_0046: nop
IL_0047: nop
IL_0048: ldloc.s V_4
IL_004a: ldc.i4.1
IL_004b: add
IL_004c: stloc.s V_4
IL_004e: ldloc.s V_4
IL_0050: ldloc.2
IL_0051: ble.s IL_0029
IL_0053: ldloc.3
IL_0054: ldc.i4.1
IL_0055: add
IL_0056: stloc.3
IL_0057: ldloc.3
IL_0058: ldloc.1
IL_0059: ble.s IL_001e
IL_005b: ret
} // end of method Loops::ForEachOverMultiDimArray3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{
@ -2217,7 +2445,7 @@ @@ -2217,7 +2445,7 @@
.method public hidebysig instance void
ForeachLoopWithEarlyReturn(class [mscorlib]System.Collections.Generic.List`1<object> items) cil managed
{
// Code size 67 (0x43)
// Code size 68 (0x44)
.maxstack 3
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_0,
object V_1,
@ -2230,7 +2458,7 @@ @@ -2230,7 +2458,7 @@
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_0028
IL_0009: br.s IL_0029
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
@ -2246,27 +2474,28 @@ @@ -2246,27 +2474,28 @@
IL_001f: ceq
IL_0021: stloc.2
IL_0022: ldloc.2
IL_0023: brfalse.s IL_0027
IL_0023: brfalse.s IL_0028
IL_0025: br.s IL_0031
IL_0025: nop
IL_0026: br.s IL_0032
IL_0027: nop
IL_0028: ldloca.s V_0
IL_002a: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_002f: brtrue.s IL_000b
IL_0028: nop
IL_0029: ldloca.s V_0
IL_002b: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
IL_0030: brtrue.s IL_000b
IL_0031: leave.s IL_0042
IL_0032: leave.s IL_0043
} // end .try
finally
{
IL_0033: ldloca.s V_0
IL_0035: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_003b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0040: nop
IL_0041: endfinally
IL_0034: ldloca.s V_0
IL_0036: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
IL_003c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0041: nop
IL_0042: endfinally
} // end handler
IL_0042: ret
IL_0043: ret
} // end of method Loops::ForeachLoopWithEarlyReturn
.method public hidebysig specialname rtspecialname

163
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -72,7 +72,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -72,7 +72,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement)
{
AstNode result = TransformFor(expressionStatement);
AstNode result = TransformForeachOnMultiDimArray(expressionStatement);
if (result != null)
return result;
result = TransformFor(expressionStatement);
if (result != null)
return result;
if (context.Settings.AutomaticProperties) {
@ -269,6 +272,164 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -269,6 +272,164 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return foreachStmt;
}
static readonly ForStatement forOnArrayMultiDimPattern = new ForStatement {
Initializers = { },
Condition = new BinaryOperatorExpression(
new NamedNode("indexVariable", new IdentifierExpression(Pattern.AnyString)),
BinaryOperatorType.LessThanOrEqual,
new NamedNode("upperBoundVariable", new IdentifierExpression(Pattern.AnyString))
),
Iterators = {
new ExpressionStatement(
new AssignmentExpression(
new IdentifierExpressionBackreference("indexVariable"),
new BinaryOperatorExpression(new IdentifierExpressionBackreference("indexVariable"), BinaryOperatorType.Add, new PrimitiveExpression(1))
))
},
EmbeddedStatement = new BlockStatement { Statements = { new AnyNode("lowerBoundAssign"), new Repeat(new AnyNode("statements")) } }
};
/// <summary>
/// $variable = $collection.GetUpperBound($index);
/// </summary>
static readonly AstNode variableAssignUpperBoundPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new InvocationExpression(
new MemberReferenceExpression(
new NamedNode("collection", new IdentifierExpression(Pattern.AnyString)),
"GetUpperBound"
),
new NamedNode("index", new PrimitiveExpression(PrimitiveExpression.AnyValue))
)));
/// <summary>
/// $variable = $collection.GetLowerBound($index);
/// </summary>
static readonly ExpressionStatement variableAssignLowerBoundPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new InvocationExpression(
new MemberReferenceExpression(
new NamedNode("collection", new IdentifierExpression(Pattern.AnyString)),
"GetLowerBound"
),
new NamedNode("index", new PrimitiveExpression(PrimitiveExpression.AnyValue))
)));
/// <summary>
/// $variable = $collection[$index1, $index2, ...];
/// </summary>
static readonly ExpressionStatement foreachVariableOnMultArrayAssignPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new IndexerExpression(
new NamedNode("collection", new IdentifierExpression(Pattern.AnyString)),
new Repeat(new NamedNode("index", new IdentifierExpression(Pattern.AnyString))
)
)));
bool MatchLowerBound(int indexNum, out IL.ILVariable index, IL.ILVariable collection, Statement statement)
{
index = null;
var m = variableAssignLowerBoundPattern.Match(statement);
if (!m.Success) return false;
if (!int.TryParse(m.Get<PrimitiveExpression>("index").Single().Value.ToString(), out int i) || indexNum != i)
return false;
index = m.Get<IdentifierExpression>("variable").Single().GetILVariable();
return m.Get<IdentifierExpression>("collection").Single().GetILVariable() == collection;
}
bool MatchForeachOnMultiDimArray(IL.ILVariable[] upperBounds, IL.ILVariable collection, Statement firstInitializerStatement, out IdentifierExpression foreachVariable, out IList<Statement> statements, out IL.ILVariable[] lowerBounds)
{
int i = 0;
foreachVariable = null;
statements = null;
lowerBounds = new IL.ILVariable[upperBounds.Length];
Statement stmt = firstInitializerStatement;
Match m = default(Match);
while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable indexVariable, collection, stmt)) {
m = forOnArrayMultiDimPattern.Match(stmt.GetNextStatement());
if (!m.Success) return false;
var upperBound = m.Get<IdentifierExpression>("upperBoundVariable").Single().GetILVariable();
if (upperBounds[i] != upperBound)
return false;
stmt = m.Get<Statement>("lowerBoundAssign").Single();
lowerBounds[i] = indexVariable;
i++;
}
var m2 = foreachVariableOnMultArrayAssignPattern.Match(stmt);
if (!m2.Success)
return false;
var collection2 = m2.Get<IdentifierExpression>("collection").Single().GetILVariable();
if (collection2 != collection)
return false;
foreachVariable = m2.Get<IdentifierExpression>("variable").Single();
statements = m.Get<Statement>("statements").ToList();
return true;
}
Statement TransformForeachOnMultiDimArray(ExpressionStatement expressionStatement)
{
Match m;
Statement stmt = expressionStatement;
IL.ILVariable collection = null;
IL.ILVariable[] upperBounds = null;
List<Statement> statementsToDelete = new List<Statement>();
int i = 0;
// first we look for all the upper bound initializations
do {
m = variableAssignUpperBoundPattern.Match(stmt);
if (!m.Success) break;
if (upperBounds == null) {
collection = m.Get<IdentifierExpression>("collection").Single().GetILVariable();
if (!(collection.Type is Decompiler.TypeSystem.ArrayType arrayType))
break;
upperBounds = new IL.ILVariable[arrayType.Dimensions];
} else {
statementsToDelete.Add(stmt);
}
var nextCollection = m.Get<IdentifierExpression>("collection").Single().GetILVariable();
if (nextCollection != collection)
break;
if (!int.TryParse(m.Get<PrimitiveExpression>("index").Single().Value?.ToString() ?? "", out int index) || index != i)
break;
upperBounds[i] = m.Get<IdentifierExpression>("variable").Single().GetILVariable();
stmt = stmt.GetNextStatement();
i++;
} while (stmt != null && i < upperBounds.Length);
if (upperBounds?.LastOrDefault() == null || collection == null)
return null;
if (!MatchForeachOnMultiDimArray(upperBounds, collection, stmt, out var foreachVariable, out var statements, out var lowerBounds))
return null;
statementsToDelete.Add(stmt);
statementsToDelete.Add(stmt.GetNextStatement());
var itemVariable = foreachVariable.GetILVariable();
if (!itemVariable.IsSingleDefinition
|| !upperBounds.All(ub => ub.IsSingleDefinition && ub.LoadCount == 1)
|| !lowerBounds.All(lb => lb.StoreCount == 2 && lb.LoadCount == 3 && lb.AddressCount == 0))
return null;
var body = new BlockStatement();
foreach (var statement in statements)
body.Statements.Add(statement.Detach());
var foreachStmt = new ForeachStatement {
VariableType = context.Settings.AnonymousTypes && itemVariable.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVariable.Type),
VariableName = itemVariable.Name,
InExpression = m.Get<IdentifierExpression>("collection").Single().Detach(),
EmbeddedStatement = body
};
foreach (var statement in statementsToDelete)
statement.Detach();
//foreachStmt.CopyAnnotationsFrom(forStatement);
itemVariable.Kind = IL.VariableKind.ForeachLocal;
// Add the variable annotation for highlighting (TokenTextWriter expects it directly on the ForeachStatement).
foreachStmt.AddAnnotation(new ILVariableResolveResult(itemVariable, itemVariable.Type));
// TODO : add ForeachAnnotation
expressionStatement.ReplaceWith(foreachStmt);
return foreachStmt;
}
#endregion
#region Automatic Properties

Loading…
Cancel
Save