Browse Source

Fix invalid variable inlining in foreach (fixes #889)

pull/976/head
Siegfried Pammer 8 years ago
parent
commit
d424d93dce
  1. 45
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs
  2. 345
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.il
  3. 172
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.il
  4. 178
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.opt.roslyn.il
  5. 341
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.roslyn.il
  6. 68
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

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

@ -252,6 +252,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -252,6 +252,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public struct DataItem
{
public int Property {
get;
set;
}
public void TestCall()
{
}
}
private IEnumerable<string> alternatives;
private static void Operation(ref int item)
@ -390,7 +402,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -390,7 +402,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
foreach (int item in items) {
#if ROSLYN && OPT
// The variable names differs based on whether roslyn optimizes out the 'item' variable
// The variable name differs based on whether roslyn optimizes out the 'item' variable
int current = item;
Loops.Operation(ref current);
#else
@ -441,6 +453,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -441,6 +453,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
}
public void ForEachOverListOfStruct(List<DataItem> items, int value)
{
foreach (DataItem item in items) {
DataItem dataItem = item;
dataItem.Property = value;
}
}
public void ForEachOverListOfStruct2(List<DataItem> items, int value)
{
foreach (DataItem item in items) {
#if ROSLYN && OPT
// The variable name differs based on whether roslyn optimizes out the 'item' variable
DataItem current = item;
current.TestCall();
current.Property = value;
#else
DataItem dataItem = item;
dataItem.TestCall();
dataItem.Property = value;
#endif
}
}
public void ForEachOverListOfStruct3(List<DataItem> items, int value)
{
foreach (DataItem item in items) {
item.TestCall();
}
}
#endregion
public void ForOverArray(string[] array)

345
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 n3qdq2uj
.assembly dky1g03y
{
.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 n3qdq2uj.dll
// MVID: {98B4F05B-5E30-48EB-AAF5-A90EA42A94A2}
.module dky1g03y.dll
// MVID: {4ADF70C5-8EC0-41AF-A9B1-6DF95B943C1A}
.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: 0x02AD0000
// Image base: 0x03580000
// =============== CLASS MEMBERS DECLARATION ===================
@ -584,6 +584,55 @@ @@ -584,6 +584,55 @@
} // end of property CustomStructEnumeratorWithIDisposable`1::Current
} // end of class CustomStructEnumeratorWithIDisposable`1
.class sequential ansi sealed nested public beforefieldinit DataItem
extends [mscorlib]System.ValueType
{
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname
instance int32 get_Property() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 11 (0xb)
.maxstack 1
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method DataItem::get_Property
.method public hidebysig specialname
instance void set_Property(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0007: ret
} // end of method DataItem::set_Property
.method public hidebysig instance void
TestCall() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method DataItem::TestCall
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
} // end of property DataItem::Property
} // end of class DataItem
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass1'
extends [mscorlib]System.Object
{
@ -1269,7 +1318,7 @@ @@ -1269,7 +1318,7 @@
.method public hidebysig static void NonGenericForeachWithReturnFallbackTest(class [mscorlib]System.Collections.IEnumerable e) cil managed
{
// Code size 111 (0x6f)
// Code size 113 (0x71)
.maxstack 2
.locals init (class [mscorlib]System.Collections.IEnumerator V_0,
object V_1,
@ -1308,7 +1357,7 @@ @@ -1308,7 +1357,7 @@
IL_0044: nop
IL_0045: nop
IL_0046: nop
IL_0047: leave.s IL_0062
IL_0047: leave.s IL_0064
} // end .try
finally
@ -1322,19 +1371,21 @@ @@ -1322,19 +1371,21 @@
IL_0053: ceq
IL_0055: stloc.3
IL_0056: ldloc.3
IL_0057: brtrue.s IL_0060
IL_0057: brtrue.s IL_0062
IL_0059: ldloc.2
IL_005a: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_005f: nop
IL_0059: nop
IL_005a: ldloc.2
IL_005b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0060: nop
IL_0061: endfinally
IL_0061: nop
IL_0062: nop
IL_0063: endfinally
} // end handler
IL_0062: nop
IL_0063: ldstr "After finally!"
IL_0068: call void [mscorlib]System.Console::WriteLine(string)
IL_006d: nop
IL_006e: ret
IL_0064: nop
IL_0065: ldstr "After finally!"
IL_006a: call void [mscorlib]System.Console::WriteLine(string)
IL_006f: nop
IL_0070: ret
} // end of method Loops::NonGenericForeachWithReturnFallbackTest
.method public hidebysig static void ForeachWithRefUsage(class [mscorlib]System.Collections.Generic.List`1<int32> items) cil managed
@ -1669,6 +1720,158 @@ @@ -1669,6 +1720,158 @@
IL_0069: ret
} // end of method Loops::ForEachBreakWhenFound
.method public hidebysig instance void
ForEachOverListOfStruct(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 62 (0x3e)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_2,
bool V_3)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.2
.try
{
IL_0009: br.s IL_0020
IL_000b: ldloca.s V_2
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.0
IL_0013: nop
IL_0014: ldloc.0
IL_0015: stloc.1
IL_0016: ldloca.s V_1
IL_0018: ldarg.2
IL_0019: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_001e: nop
IL_001f: nop
IL_0020: ldloca.s V_2
IL_0022: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0027: stloc.3
IL_0028: ldloc.3
IL_0029: brtrue.s IL_000b
IL_002b: leave.s IL_003c
} // end .try
finally
{
IL_002d: ldloca.s V_2
IL_002f: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0035: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003a: nop
IL_003b: endfinally
} // end handler
IL_003c: nop
IL_003d: ret
} // end of method Loops::ForEachOverListOfStruct
.method public hidebysig instance void
ForEachOverListOfStruct2(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 70 (0x46)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_2,
bool V_3)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.2
.try
{
IL_0009: br.s IL_0028
IL_000b: ldloca.s V_2
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.0
IL_0013: nop
IL_0014: ldloc.0
IL_0015: stloc.1
IL_0016: ldloca.s V_1
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_001d: nop
IL_001e: ldloca.s V_1
IL_0020: ldarg.2
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_0026: nop
IL_0027: nop
IL_0028: ldloca.s V_2
IL_002a: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_002f: stloc.3
IL_0030: ldloc.3
IL_0031: brtrue.s IL_000b
IL_0033: leave.s IL_0044
} // end .try
finally
{
IL_0035: ldloca.s V_2
IL_0037: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_003d: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0042: nop
IL_0043: endfinally
} // end handler
IL_0044: nop
IL_0045: ret
} // end of method Loops::ForEachOverListOfStruct2
.method public hidebysig instance void
ForEachOverListOfStruct3(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 59 (0x3b)
.maxstack 1
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_1,
bool V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.1
.try
{
IL_0009: br.s IL_001d
IL_000b: ldloca.s V_1
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.0
IL_0013: nop
IL_0014: ldloca.s V_0
IL_0016: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_001b: nop
IL_001c: nop
IL_001d: ldloca.s V_1
IL_001f: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0024: stloc.2
IL_0025: ldloc.2
IL_0026: brtrue.s IL_000b
IL_0028: leave.s IL_0039
} // end .try
finally
{
IL_002a: ldloca.s V_1
IL_002c: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0032: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0037: nop
IL_0038: endfinally
} // end handler
IL_0039: nop
IL_003a: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{
@ -1848,7 +2051,7 @@ @@ -1848,7 +2051,7 @@
.method public hidebysig instance void
WhileLoop() cil managed
{
// Code size 154 (0x9a)
// Code size 155 (0x9b)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
@ -1862,10 +2065,10 @@ @@ -1862,10 +2065,10 @@
IL_0018: ceq
IL_001a: stloc.0
IL_001b: ldloc.0
IL_001c: brtrue.s IL_008e
IL_001c: brtrue.s IL_008f
IL_001e: nop
IL_001f: br.s IL_0073
IL_001f: br.s IL_0074
IL_0021: nop
IL_0022: ldstr "Loop Body"
@ -1878,7 +2081,7 @@ @@ -1878,7 +2081,7 @@
IL_0039: ceq
IL_003b: stloc.0
IL_003c: ldloc.0
IL_003d: brtrue.s IL_0067
IL_003d: brtrue.s IL_0068
IL_003f: nop
IL_0040: ldarg.0
@ -1891,43 +2094,44 @@ @@ -1891,43 +2094,44 @@
IL_0050: brtrue.s IL_0055
IL_0052: nop
IL_0053: br.s IL_0073
IL_0053: br.s IL_0074
IL_0055: ldarg.0
IL_0056: ldstr "break"
IL_005b: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0060: stloc.0
IL_0061: ldloc.0
IL_0062: brtrue.s IL_0066
IL_0062: brtrue.s IL_0067
IL_0064: br.s IL_0082
IL_0064: nop
IL_0065: br.s IL_0083
IL_0066: nop
IL_0067: ldstr "End of loop body"
IL_006c: call void [mscorlib]System.Console::WriteLine(string)
IL_0071: nop
IL_0067: nop
IL_0068: ldstr "End of loop body"
IL_006d: call void [mscorlib]System.Console::WriteLine(string)
IL_0072: nop
IL_0073: ldarg.0
IL_0074: ldstr "while"
IL_0079: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_007e: stloc.0
IL_007f: ldloc.0
IL_0080: brtrue.s IL_0021
IL_0082: ldstr "After loop"
IL_0087: call void [mscorlib]System.Console::WriteLine(string)
IL_008c: nop
IL_0073: nop
IL_0074: ldarg.0
IL_0075: ldstr "while"
IL_007a: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_007f: stloc.0
IL_0080: ldloc.0
IL_0081: brtrue.s IL_0021
IL_0083: ldstr "After loop"
IL_0088: call void [mscorlib]System.Console::WriteLine(string)
IL_008d: nop
IL_008e: ldstr "End of method"
IL_0093: call void [mscorlib]System.Console::WriteLine(string)
IL_0098: nop
IL_0099: ret
IL_008e: nop
IL_008f: ldstr "End of method"
IL_0094: call void [mscorlib]System.Console::WriteLine(string)
IL_0099: nop
IL_009a: ret
} // end of method Loops::WhileLoop
.method public hidebysig instance void
ForLoop() cil managed
{
// Code size 160 (0xa0)
// Code size 161 (0xa1)
.maxstack 2
.locals init (int32 V_0,
bool V_1)
@ -1942,12 +2146,12 @@ @@ -1942,12 +2146,12 @@
IL_0018: ceq
IL_001a: stloc.1
IL_001b: ldloc.1
IL_001c: brtrue.s IL_0094
IL_001c: brtrue.s IL_0095
IL_001e: nop
IL_001f: ldc.i4.0
IL_0020: stloc.0
IL_0021: br.s IL_0079
IL_0021: br.s IL_007a
IL_0023: nop
IL_0024: ldstr "Loop Body"
@ -1960,7 +2164,7 @@ @@ -1960,7 +2164,7 @@
IL_003b: ceq
IL_003d: stloc.1
IL_003e: ldloc.1
IL_003f: brtrue.s IL_0069
IL_003f: brtrue.s IL_006a
IL_0041: nop
IL_0042: ldarg.0
@ -1973,41 +2177,42 @@ @@ -1973,41 +2177,42 @@
IL_0052: brtrue.s IL_0057
IL_0054: nop
IL_0055: br.s IL_0075
IL_0055: br.s IL_0076
IL_0057: ldarg.0
IL_0058: ldstr "not-break"
IL_005d: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0062: stloc.1
IL_0063: ldloc.1
IL_0064: brtrue.s IL_0068
IL_0064: brtrue.s IL_0069
IL_0066: br.s IL_0088
IL_0066: nop
IL_0067: br.s IL_0089
IL_0068: nop
IL_0069: ldstr "End of loop body"
IL_006e: call void [mscorlib]System.Console::WriteLine(string)
IL_0073: nop
IL_0069: nop
IL_006a: ldstr "End of loop body"
IL_006f: call void [mscorlib]System.Console::WriteLine(string)
IL_0074: nop
IL_0075: ldloc.0
IL_0076: ldc.i4.1
IL_0077: add
IL_0078: stloc.0
IL_0079: ldarg.0
IL_007a: ldstr "for"
IL_007f: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0084: stloc.1
IL_0085: ldloc.1
IL_0086: brtrue.s IL_0023
IL_0088: ldstr "After loop"
IL_008d: call void [mscorlib]System.Console::WriteLine(string)
IL_0092: nop
IL_0075: nop
IL_0076: ldloc.0
IL_0077: ldc.i4.1
IL_0078: add
IL_0079: stloc.0
IL_007a: ldarg.0
IL_007b: ldstr "for"
IL_0080: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0085: stloc.1
IL_0086: ldloc.1
IL_0087: brtrue.s IL_0023
IL_0089: ldstr "After loop"
IL_008e: call void [mscorlib]System.Console::WriteLine(string)
IL_0093: nop
IL_0094: ldstr "End of method"
IL_0099: call void [mscorlib]System.Console::WriteLine(string)
IL_009e: nop
IL_009f: ret
IL_0094: nop
IL_0095: ldstr "End of method"
IL_009a: call void [mscorlib]System.Console::WriteLine(string)
IL_009f: nop
IL_00a0: ret
} // end of method Loops::ForLoop
.method public hidebysig specialname rtspecialname

172
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 spdzj2hg
.assembly trg3dx5v
{
.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 spdzj2hg.dll
// MVID: {D8CD3A33-FD06-4791-A4E6-AC836DA34D06}
.module trg3dx5v.dll
// MVID: {39502A20-4431-466D-88D2-F47B21FB8C58}
.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: 0x002F0000
// Image base: 0x00B30000
// =============== CLASS MEMBERS DECLARATION ===================
@ -506,6 +506,49 @@ @@ -506,6 +506,49 @@
} // end of property CustomStructEnumeratorWithIDisposable`1::Current
} // end of class CustomStructEnumeratorWithIDisposable`1
.class sequential ansi sealed nested public beforefieldinit DataItem
extends [mscorlib]System.ValueType
{
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname
instance int32 get_Property() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0006: ret
} // end of method DataItem::get_Property
.method public hidebysig specialname
instance void set_Property(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0007: ret
} // end of method DataItem::set_Property
.method public hidebysig instance void
TestCall() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method DataItem::TestCall
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
} // end of property DataItem::Property
} // end of class DataItem
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass1'
extends [mscorlib]System.Object
{
@ -1336,6 +1379,127 @@ @@ -1336,6 +1379,127 @@
IL_0056: ret
} // end of method Loops::ForEachBreakWhenFound
.method public hidebysig instance void
ForEachOverListOfStruct(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 53 (0x35)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_2)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.2
.try
{
IL_0007: br.s IL_001b
IL_0009: ldloca.s V_2
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: stloc.1
IL_0013: ldloca.s V_1
IL_0015: ldarg.2
IL_0016: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_001b: ldloca.s V_2
IL_001d: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0022: brtrue.s IL_0009
IL_0024: leave.s IL_0034
} // end .try
finally
{
IL_0026: ldloca.s V_2
IL_0028: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_002e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0033: endfinally
} // end handler
IL_0034: ret
} // end of method Loops::ForEachOverListOfStruct
.method public hidebysig instance void
ForEachOverListOfStruct2(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 60 (0x3c)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_2)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.2
.try
{
IL_0007: br.s IL_0022
IL_0009: ldloca.s V_2
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: stloc.1
IL_0013: ldloca.s V_1
IL_0015: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_001a: ldloca.s V_1
IL_001c: ldarg.2
IL_001d: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_0022: ldloca.s V_2
IL_0024: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0029: brtrue.s IL_0009
IL_002b: leave.s IL_003b
} // end .try
finally
{
IL_002d: ldloca.s V_2
IL_002f: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0035: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003a: endfinally
} // end handler
IL_003b: ret
} // end of method Loops::ForEachOverListOfStruct2
.method public hidebysig instance void
ForEachOverListOfStruct3(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 50 (0x32)
.maxstack 1
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_0,
valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_1)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.1
.try
{
IL_0007: br.s IL_0018
IL_0009: ldloca.s V_1
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.0
IL_0011: ldloca.s V_0
IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_0018: ldloca.s V_1
IL_001a: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_001f: brtrue.s IL_0009
IL_0021: leave.s IL_0031
} // end .try
finally
{
IL_0023: ldloca.s V_1
IL_0025: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: endfinally
} // end handler
IL_0031: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{

178
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: {B3F85A6A-79B4-41C0-9146-2088985BFC34}
// MVID: {F193AB7E-127F-4EFE-9BF9-ADF41756C267}
.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: 0x02550000
// Image base: 0x03460000
// =============== CLASS MEMBERS DECLARATION ===================
@ -510,7 +510,50 @@ @@ -510,7 +510,50 @@
} // end of property CustomStructEnumeratorWithIDisposable`1::Current
} // end of class CustomStructEnumeratorWithIDisposable`1
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass25_0'
.class sequential ansi sealed nested public beforefieldinit DataItem
extends [mscorlib]System.ValueType
{
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname
instance int32 get_Property() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0006: ret
} // end of method DataItem::get_Property
.method public hidebysig specialname
instance void set_Property(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0007: ret
} // end of method DataItem::set_Property
.method public hidebysig instance void
TestCall() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method DataItem::TestCall
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
} // end of property DataItem::Property
} // end of class DataItem
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass26_0'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
@ -523,7 +566,7 @@ @@ -523,7 +566,7 @@
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method '<>c__DisplayClass25_0'::.ctor
} // end of method '<>c__DisplayClass26_0'::.ctor
.method assembly hidebysig instance bool
'<ForeachWithCapturedVariable>b__0'() cil managed
@ -531,13 +574,13 @@ @@ -531,13 +574,13 @@
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::c
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::c
IL_0006: ldc.i4.5
IL_0007: ceq
IL_0009: ret
} // end of method '<>c__DisplayClass25_0'::'<ForeachWithCapturedVariable>b__0'
} // end of method '<>c__DisplayClass26_0'::'<ForeachWithCapturedVariable>b__0'
} // end of class '<>c__DisplayClass25_0'
} // end of class '<>c__DisplayClass26_0'
.field private class [mscorlib]System.Collections.Generic.IEnumerable`1<string> alternatives
.method private hidebysig static void Operation(int32& item) cil managed
@ -1101,11 +1144,11 @@ @@ -1101,11 +1144,11 @@
IL_0009: ldloca.s V_0
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
IL_0010: stloc.1
IL_0011: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::.ctor()
IL_0011: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::.ctor()
IL_0016: dup
IL_0017: ldloc.1
IL_0018: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::c
IL_001d: ldftn instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::'<ForeachWithCapturedVariable>b__0'()
IL_0018: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::c
IL_001d: ldftn instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::'<ForeachWithCapturedVariable>b__0'()
IL_0023: newobj instance void class [mscorlib]System.Func`1<bool>::.ctor(object,
native int)
IL_0028: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Operation(class [mscorlib]System.Func`1<bool>)
@ -1295,6 +1338,121 @@ @@ -1295,6 +1338,121 @@
IL_0058: ret
} // end of method Loops::ForEachBreakWhenFound
.method public hidebysig instance void
ForEachOverListOfStruct(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 51 (0x33)
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.0
.try
{
IL_0007: br.s IL_0019
IL_0009: ldloca.s V_0
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.1
IL_0011: ldloca.s V_1
IL_0013: ldarg.2
IL_0014: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_0019: ldloca.s V_0
IL_001b: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0020: brtrue.s IL_0009
IL_0022: leave.s IL_0032
} // end .try
finally
{
IL_0024: ldloca.s V_0
IL_0026: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_002c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0031: endfinally
} // end handler
IL_0032: ret
} // end of method Loops::ForEachOverListOfStruct
.method public hidebysig instance void
ForEachOverListOfStruct2(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 58 (0x3a)
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.0
.try
{
IL_0007: br.s IL_0020
IL_0009: ldloca.s V_0
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.1
IL_0011: ldloca.s V_1
IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_0018: ldloca.s V_1
IL_001a: ldarg.2
IL_001b: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_0020: ldloca.s V_0
IL_0022: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0027: brtrue.s IL_0009
IL_0029: leave.s IL_0039
} // end .try
finally
{
IL_002b: ldloca.s V_0
IL_002d: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0033: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0038: endfinally
} // end handler
IL_0039: ret
} // end of method Loops::ForEachOverListOfStruct2
.method public hidebysig instance void
ForEachOverListOfStruct3(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 50 (0x32)
.maxstack 1
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1)
IL_0000: ldarg.1
IL_0001: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0006: stloc.0
.try
{
IL_0007: br.s IL_0018
IL_0009: ldloca.s V_0
IL_000b: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0010: stloc.1
IL_0011: ldloca.s V_1
IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_0018: ldloca.s V_0
IL_001a: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_001f: brtrue.s IL_0009
IL_0021: leave.s IL_0031
} // end .try
finally
{
IL_0023: ldloca.s V_0
IL_0025: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: endfinally
} // end handler
IL_0031: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{

341
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: {8261F08F-23F6-43C1-9650-C5B6A10A0F30}
// MVID: {8F6E41CD-7AE5-437C-BACB-4A672A0014D0}
.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: 0x00720000
// Image base: 0x00C80000
// =============== CLASS MEMBERS DECLARATION ===================
@ -592,7 +592,52 @@ @@ -592,7 +592,52 @@
} // end of property CustomStructEnumeratorWithIDisposable`1::Current
} // end of class CustomStructEnumeratorWithIDisposable`1
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass25_0'
.class sequential ansi sealed nested public beforefieldinit DataItem
extends [mscorlib]System.ValueType
{
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.method public hidebysig specialname
instance int32 get_Property() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0006: ret
} // end of method DataItem::get_Property
.method public hidebysig specialname
instance void set_Property(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::'<Property>k__BackingField'
IL_0007: ret
} // end of method DataItem::set_Property
.method public hidebysig instance void
TestCall() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method DataItem::TestCall
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
} // end of property DataItem::Property
} // end of class DataItem
.class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass26_0'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
@ -606,7 +651,7 @@ @@ -606,7 +651,7 @@
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method '<>c__DisplayClass25_0'::.ctor
} // end of method '<>c__DisplayClass26_0'::.ctor
.method assembly hidebysig instance bool
'<ForeachWithCapturedVariable>b__0'() cil managed
@ -614,13 +659,13 @@ @@ -614,13 +659,13 @@
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::c
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::c
IL_0006: ldc.i4.5
IL_0007: ceq
IL_0009: ret
} // end of method '<>c__DisplayClass25_0'::'<ForeachWithCapturedVariable>b__0'
} // end of method '<>c__DisplayClass26_0'::'<ForeachWithCapturedVariable>b__0'
} // end of class '<>c__DisplayClass25_0'
} // end of class '<>c__DisplayClass26_0'
.field private class [mscorlib]System.Collections.Generic.IEnumerable`1<string> alternatives
.method private hidebysig static void Operation(int32& item) cil managed
@ -1189,7 +1234,7 @@ @@ -1189,7 +1234,7 @@
.method public hidebysig static void NonGenericForeachWithReturnFallbackTest(class [mscorlib]System.Collections.IEnumerable e) cil managed
{
// Code size 109 (0x6d)
// Code size 111 (0x6f)
.maxstack 2
.locals init (class [mscorlib]System.Collections.IEnumerator V_0,
bool V_1,
@ -1227,7 +1272,7 @@ @@ -1227,7 +1272,7 @@
IL_0041: nop
IL_0042: nop
IL_0043: nop
IL_0044: leave.s IL_0061
IL_0044: leave.s IL_0063
} // end .try
finally
@ -1241,18 +1286,20 @@ @@ -1241,18 +1286,20 @@
IL_0050: cgt.un
IL_0052: stloc.s V_4
IL_0054: ldloc.s V_4
IL_0056: brfalse.s IL_005f
IL_0056: brfalse.s IL_0061
IL_0058: ldloc.3
IL_0059: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_005e: nop
IL_0058: nop
IL_0059: ldloc.3
IL_005a: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_005f: nop
IL_0060: endfinally
IL_0060: nop
IL_0061: nop
IL_0062: endfinally
} // end handler
IL_0061: ldstr "After finally!"
IL_0066: call void [mscorlib]System.Console::WriteLine(string)
IL_006b: nop
IL_006c: ret
IL_0063: ldstr "After finally!"
IL_0068: call void [mscorlib]System.Console::WriteLine(string)
IL_006d: nop
IL_006e: ret
} // end of method Loops::NonGenericForeachWithReturnFallbackTest
.method public hidebysig static void ForeachWithRefUsage(class [mscorlib]System.Collections.Generic.List`1<int32> items) cil managed
@ -1305,7 +1352,7 @@ @@ -1305,7 +1352,7 @@
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32> V_0,
int32 V_1,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0' V_2)
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0' V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.0
@ -1318,14 +1365,14 @@ @@ -1318,14 +1365,14 @@
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
IL_0012: stloc.1
IL_0013: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::.ctor()
IL_0013: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::.ctor()
IL_0018: stloc.2
IL_0019: nop
IL_001a: ldloc.2
IL_001b: ldloc.1
IL_001c: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::c
IL_001c: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::c
IL_0021: ldloc.2
IL_0022: ldftn instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass25_0'::'<ForeachWithCapturedVariable>b__0'()
IL_0022: ldftn instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/'<>c__DisplayClass26_0'::'<ForeachWithCapturedVariable>b__0'()
IL_0028: newobj instance void class [mscorlib]System.Func`1<bool>::.ctor(object,
native int)
IL_002d: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Operation(class [mscorlib]System.Func`1<bool>)
@ -1554,6 +1601,146 @@ @@ -1554,6 +1601,146 @@
IL_0060: ret
} // end of method Loops::ForEachBreakWhenFound
.method public hidebysig instance void
ForEachOverListOfStruct(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 59 (0x3b)
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_0020
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.1
IL_0013: nop
IL_0014: ldloc.1
IL_0015: stloc.2
IL_0016: ldloca.s V_2
IL_0018: ldarg.2
IL_0019: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_001e: nop
IL_001f: nop
IL_0020: ldloca.s V_0
IL_0022: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0027: brtrue.s IL_000b
IL_0029: leave.s IL_003a
} // end .try
finally
{
IL_002b: ldloca.s V_0
IL_002d: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0033: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0038: nop
IL_0039: endfinally
} // end handler
IL_003a: ret
} // end of method Loops::ForEachOverListOfStruct
.method public hidebysig instance void
ForEachOverListOfStruct2(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 67 (0x43)
.maxstack 2
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_0028
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.1
IL_0013: nop
IL_0014: ldloc.1
IL_0015: stloc.2
IL_0016: ldloca.s V_2
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_001d: nop
IL_001e: ldloca.s V_2
IL_0020: ldarg.2
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::set_Property(int32)
IL_0026: nop
IL_0027: nop
IL_0028: ldloca.s V_0
IL_002a: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_002f: brtrue.s IL_000b
IL_0031: leave.s IL_0042
} // end .try
finally
{
IL_0033: ldloca.s V_0
IL_0035: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_003b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0040: nop
IL_0041: endfinally
} // end handler
IL_0042: ret
} // end of method Loops::ForEachOverListOfStruct2
.method public hidebysig instance void
ForEachOverListOfStruct3(class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> items,
int32 'value') cil managed
{
// Code size 56 (0x38)
.maxstack 1
.locals init (valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem> V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem V_1)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::GetEnumerator()
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_001d
IL_000b: ldloca.s V_0
IL_000d: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::get_Current()
IL_0012: stloc.1
IL_0013: nop
IL_0014: ldloca.s V_1
IL_0016: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem::TestCall()
IL_001b: nop
IL_001c: nop
IL_001d: ldloca.s V_0
IL_001f: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>::MoveNext()
IL_0024: brtrue.s IL_000b
IL_0026: leave.s IL_0037
} // end .try
finally
{
IL_0028: ldloca.s V_0
IL_002a: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops/DataItem>
IL_0030: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0035: nop
IL_0036: endfinally
} // end handler
IL_0037: ret
} // end of method Loops::ForEachOverListOfStruct3
.method public hidebysig instance void
ForOverArray(string[] 'array') cil managed
{
@ -1732,7 +1919,7 @@ @@ -1732,7 +1919,7 @@
.method public hidebysig instance void
WhileLoop() cil managed
{
// Code size 150 (0x96)
// Code size 151 (0x97)
.maxstack 2
.locals init (bool V_0,
bool V_1,
@ -1748,10 +1935,10 @@ @@ -1748,10 +1935,10 @@
IL_0012: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: brfalse.s IL_008a
IL_0019: brfalse.s IL_008b
IL_001b: nop
IL_001c: br.s IL_006d
IL_001c: br.s IL_006e
IL_001e: nop
IL_001f: ldstr "Loop Body"
@ -1762,7 +1949,7 @@ @@ -1762,7 +1949,7 @@
IL_0030: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0035: stloc.1
IL_0036: ldloc.1
IL_0037: brfalse.s IL_0061
IL_0037: brfalse.s IL_0062
IL_0039: nop
IL_003a: ldarg.0
@ -1773,7 +1960,7 @@ @@ -1773,7 +1960,7 @@
IL_0047: brfalse.s IL_004c
IL_0049: nop
IL_004a: br.s IL_006d
IL_004a: br.s IL_006e
IL_004c: ldarg.0
IL_004d: ldstr "break"
@ -1782,36 +1969,37 @@ @@ -1782,36 +1969,37 @@
IL_0058: ceq
IL_005a: stloc.3
IL_005b: ldloc.3
IL_005c: brfalse.s IL_0060
IL_005c: brfalse.s IL_0061
IL_005e: br.s IL_007e
IL_005e: nop
IL_005f: br.s IL_007f
IL_0060: nop
IL_0061: ldstr "End of loop body"
IL_0066: call void [mscorlib]System.Console::WriteLine(string)
IL_006b: nop
IL_0061: nop
IL_0062: ldstr "End of loop body"
IL_0067: call void [mscorlib]System.Console::WriteLine(string)
IL_006c: nop
IL_006d: ldarg.0
IL_006e: ldstr "while"
IL_0073: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0078: stloc.s V_4
IL_007a: ldloc.s V_4
IL_007c: brtrue.s IL_001e
IL_007e: ldstr "After loop"
IL_0083: call void [mscorlib]System.Console::WriteLine(string)
IL_0088: nop
IL_006d: nop
IL_006e: ldarg.0
IL_006f: ldstr "while"
IL_0074: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0079: stloc.s V_4
IL_007b: ldloc.s V_4
IL_007d: brtrue.s IL_001e
IL_007f: ldstr "After loop"
IL_0084: call void [mscorlib]System.Console::WriteLine(string)
IL_0089: nop
IL_008a: ldstr "End of method"
IL_008f: call void [mscorlib]System.Console::WriteLine(string)
IL_0094: nop
IL_0095: ret
IL_008a: nop
IL_008b: ldstr "End of method"
IL_0090: call void [mscorlib]System.Console::WriteLine(string)
IL_0095: nop
IL_0096: ret
} // end of method Loops::WhileLoop
.method public hidebysig instance void
ForLoop() cil managed
{
// Code size 158 (0x9e)
// Code size 159 (0x9f)
.maxstack 2
.locals init (bool V_0,
int32 V_1,
@ -1828,12 +2016,12 @@ @@ -1828,12 +2016,12 @@
IL_0012: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: brfalse.s IL_0092
IL_0019: brfalse.s IL_0093
IL_001b: nop
IL_001c: ldc.i4.0
IL_001d: stloc.1
IL_001e: br.s IL_0075
IL_001e: br.s IL_0076
IL_0020: nop
IL_0021: ldstr "Loop Body"
@ -1844,7 +2032,7 @@ @@ -1844,7 +2032,7 @@
IL_0032: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0037: stloc.2
IL_0038: ldloc.2
IL_0039: brfalse.s IL_0065
IL_0039: brfalse.s IL_0066
IL_003b: nop
IL_003c: ldarg.0
@ -1855,7 +2043,7 @@ @@ -1855,7 +2043,7 @@
IL_0049: brfalse.s IL_004e
IL_004b: nop
IL_004c: br.s IL_0071
IL_004c: br.s IL_0072
IL_004e: ldarg.0
IL_004f: ldstr "not-break"
@ -1864,34 +2052,35 @@ @@ -1864,34 +2052,35 @@
IL_005a: ceq
IL_005c: stloc.s V_4
IL_005e: ldloc.s V_4
IL_0060: brfalse.s IL_0064
IL_0060: brfalse.s IL_0065
IL_0062: br.s IL_0086
IL_0062: nop
IL_0063: br.s IL_0087
IL_0064: nop
IL_0065: ldstr "End of loop body"
IL_006a: call void [mscorlib]System.Console::WriteLine(string)
IL_006f: nop
IL_0065: nop
IL_0066: ldstr "End of loop body"
IL_006b: call void [mscorlib]System.Console::WriteLine(string)
IL_0070: nop
IL_0071: ldloc.1
IL_0072: ldc.i4.1
IL_0073: add
IL_0074: stloc.1
IL_0075: ldarg.0
IL_0076: ldstr "for"
IL_007b: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0080: stloc.s V_5
IL_0082: ldloc.s V_5
IL_0084: brtrue.s IL_0020
IL_0086: ldstr "After loop"
IL_008b: call void [mscorlib]System.Console::WriteLine(string)
IL_0090: nop
IL_0071: nop
IL_0072: ldloc.1
IL_0073: ldc.i4.1
IL_0074: add
IL_0075: stloc.1
IL_0076: ldarg.0
IL_0077: ldstr "for"
IL_007c: call instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.Loops::Condition(string)
IL_0081: stloc.s V_5
IL_0083: ldloc.s V_5
IL_0085: brtrue.s IL_0020
IL_0087: ldstr "After loop"
IL_008c: call void [mscorlib]System.Console::WriteLine(string)
IL_0091: nop
IL_0092: ldstr "End of method"
IL_0097: call void [mscorlib]System.Console::WriteLine(string)
IL_009c: nop
IL_009d: ret
IL_0092: nop
IL_0093: ldstr "End of method"
IL_0098: call void [mscorlib]System.Console::WriteLine(string)
IL_009d: nop
IL_009e: ret
} // end of method Loops::ForLoop
.method public hidebysig specialname rtspecialname

68
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -471,6 +471,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -471,6 +471,19 @@ namespace ICSharpCode.Decompiler.CSharp
instToReplace.ReplaceWith(new LdLoc(foreachVariable));
body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace));
break;
case RequiredGetCurrentTransformation.IntroduceNewVariableAndLocalCopy:
foreachVariable = currentFunction.RegisterVariable(
VariableKind.ForeachLocal, type,
AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>())
);
var localCopyVariable = currentFunction.RegisterVariable(
VariableKind.Local, type,
AssignVariableNames.GenerateVariableName(currentFunction, type)
);
instToReplace.Parent.ReplaceWith(new LdLoca(localCopyVariable));
body.Instructions.Insert(0, new StLoc(localCopyVariable, new LdLoc(foreachVariable)));
body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace));
break;
}
// Convert the modified body to C# AST:
var whileLoop = (WhileStatement)ConvertAsBlock(container).First();
@ -563,7 +576,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -563,7 +576,20 @@ namespace ICSharpCode.Decompiler.CSharp
/// ... (ldloc foreachVar) ...
/// </code>
/// </summary>
IntroduceNewVariable
IntroduceNewVariable,
/// <summary>
/// No store was found, thus create a new variable and use it as foreach variable.
/// Additionally it is necessary to copy the value of the foreach variable to another local
/// to allow safe modification of its value.
/// <code>
/// ... addressof(call get_Current()) ...
/// =>
/// stloc foreachVar(call get_Current())
/// stloc copy(ldloc foreachVar)
/// ... (ldloca copy) ...
/// </code>
/// </summary>
IntroduceNewVariableAndLocalCopy
}
/// <summary>
@ -603,6 +629,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -603,6 +629,11 @@ namespace ICSharpCode.Decompiler.CSharp
return RequiredGetCurrentTransformation.UseExistingVariable;
}
}
// In optimized Roslyn code it can happen that the foreach variable is referenced via addressof
// We only do this unwrapping if where dealing with a custom struct type.
if (CurrentIsStructSetterTarget(inst, singleGetter)) {
return RequiredGetCurrentTransformation.IntroduceNewVariableAndLocalCopy;
}
// No suitable variable was found: we need a new one.
return RequiredGetCurrentTransformation.IntroduceNewVariable;
}
@ -616,13 +647,46 @@ namespace ICSharpCode.Decompiler.CSharp @@ -616,13 +647,46 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (storeInst.Variable.LoadInstructions.Any(ld => !ld.IsDescendantOf(usingContainer)))
return false;
if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(usingContainer) || !ILInlining.IsUsedAsThisPointerInCall(la)))
if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(usingContainer) || !ILInlining.IsUsedAsThisPointerInCall(la) || IsTargetOfSetterCall(la, la.Variable.Type)))
return false;
if (storeInst.Variable.StoreInstructions.OfType<ILInstruction>().Any(st => st != storeInst))
return false;
return true;
}
/// <summary>
/// Returns true if singleGetter is a value type and its address is used as setter target.
/// </summary>
bool CurrentIsStructSetterTarget(ILInstruction inst, CallInstruction singleGetter)
{
if (!(inst.Parent is AddressOf addr))
return false;
return IsTargetOfSetterCall(addr, singleGetter.Method.ReturnType);
}
bool IsTargetOfSetterCall(ILInstruction inst, IType targetType)
{
if (inst.ChildIndex != 0)
return false;
if (targetType.IsReferenceType ?? false)
return false;
switch (inst.Parent.OpCode) {
case OpCode.Call:
case OpCode.CallVirt:
var targetMethod = ((CallInstruction)inst.Parent).Method;
if (!targetMethod.IsAccessor || targetMethod.IsStatic)
return false;
switch (targetMethod.AccessorOwner) {
case IProperty p:
return p.Setter == targetMethod;
default:
return true;
}
default:
return false;
}
}
bool ParentIsCurrentGetter(ILInstruction inst)
{
return inst.Parent is CallInstruction cv && cv.Method.IsAccessor &&

Loading…
Cancel
Save