diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 816c0fb31..888df6e51 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -81,6 +81,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs new file mode 100644 index 000000000..a6dcc9f0e --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs @@ -0,0 +1,75 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly +{ + public sealed class Handle + { + private readonly Func _func; + public Handle(Func func) + { + _func = func; + } + } + + public static class NoLocalFunctions + { + [StructLayout(LayoutKind.Auto)] + [CompilerGenerated] + private struct _003C_003Ec__DisplayClass1_0 + { + public int x; + } + + [CompilerGenerated] + private sealed class _003C_003Ec__DisplayClass2_0 + { + public int x; + + internal int _003CSimpleCaptureWithRef_003Eg__F_007C0() + { + return 42 + x; + } + } + + private static void UseLocalFunctionReference() + { +#if OPT + new Handle(new Func(_003CUseLocalFunctionReference_003Eg__F_007C0_0)); +#else + Handle handle = new Handle(new Func(_003CUseLocalFunctionReference_003Eg__F_007C0_0)); +#endif + } + + private static void SimpleCapture() + { + _003C_003Ec__DisplayClass1_0 A_ = default(_003C_003Ec__DisplayClass1_0); + A_.x = 1; + _003CSimpleCapture_003Eg__F_007C1_0(ref A_); + } + + private static void SimpleCaptureWithRef() + { + _003C_003Ec__DisplayClass2_0 _003C_003Ec__DisplayClass2_ = new _003C_003Ec__DisplayClass2_0(); + _003C_003Ec__DisplayClass2_.x = 1; +#if OPT + new Handle(new Func(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0)); +#else + Handle handle = new Handle(new Func(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0)); +#endif + } + + [CompilerGenerated] + internal static int _003CUseLocalFunctionReference_003Eg__F_007C0_0() + { + return 42; + } + + [CompilerGenerated] + private static int _003CSimpleCapture_003Eg__F_007C1_0(ref _003C_003Ec__DisplayClass1_0 A_0) + { + return 42 + A_0.x; + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.cs new file mode 100644 index 000000000..b72df11b3 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly +{ + public sealed class Handle + { + private readonly Func _func; + public Handle(Func func) + { + _func = func; + } + } + + public static class NoLocalFunctions + { + private static void UseLocalFunctionReference() + { + int F() => 42; + var handle = new Handle(F); + } + private static void SimpleCapture() + { + int x = 1; + int F() => 42 + x; + F(); + } + private static void SimpleCaptureWithRef() + { + int x = 1; + int F() => 42 + x; + var handle = new Handle(F); + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.opt.roslyn.il new file mode 100644 index 000000000..605a92362 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.opt.roslyn.il @@ -0,0 +1,165 @@ + + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly NoLocalFunctions +{ + .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 + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 ) + + .permissionset reqmin + = {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}} + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module NoLocalFunctions.dll +.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 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle + extends [mscorlib]System.Object +{ + .field private initonly class [mscorlib]System.Func`1 _func + .method public hidebysig specialname rtspecialname + instance void .ctor(class [mscorlib]System.Func`1 func) cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [mscorlib]System.Func`1 ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::_func + IL_000d: ret + } // end of method Handle::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle + +.class public abstract auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass1_0' + extends [mscorlib]System.ValueType + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 x + } // end of class '<>c__DisplayClass1_0' + + .class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass2_0' + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 x + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method '<>c__DisplayClass2_0'::.ctor + + .method assembly hidebysig instance int32 + 'g__F|0'() cil managed + { + // Code size 10 (0xa) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ldarg.0 + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::x + IL_0008: add + IL_0009: ret + } // end of method '<>c__DisplayClass2_0'::'g__F|0' + + } // end of class '<>c__DisplayClass2_0' + + .method private hidebysig static void UseLocalFunctionReference() cil managed + { + // Code size 19 (0x13) + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions::'g__F|0_0'() + IL_0007: newobj instance void class [mscorlib]System.Func`1::.ctor(object, + native int) + IL_000c: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::.ctor(class [mscorlib]System.Func`1) + IL_0011: pop + IL_0012: ret + } // end of method NoLocalFunctions::UseLocalFunctionReference + + .method private hidebysig static void SimpleCapture() cil managed + { + // Code size 17 (0x11) + .maxstack 2 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0' V_0) + IL_0000: ldloca.s V_0 + IL_0002: ldc.i4.1 + IL_0003: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'::x + IL_0008: ldloca.s V_0 + IL_000a: call int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions::'g__F|1_0'(valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'&) + IL_000f: pop + IL_0010: ret + } // end of method NoLocalFunctions::SimpleCapture + + .method private hidebysig static void SimpleCaptureWithRef() cil managed + { + // Code size 30 (0x1e) + .maxstack 8 + IL_0000: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::.ctor() + IL_0005: dup + IL_0006: ldc.i4.1 + IL_0007: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::x + IL_000c: ldftn instance int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::'g__F|0'() + IL_0012: newobj instance void class [mscorlib]System.Func`1::.ctor(object, + native int) + IL_0017: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::.ctor(class [mscorlib]System.Func`1) + IL_001c: pop + IL_001d: ret + } // end of method NoLocalFunctions::SimpleCaptureWithRef + + .method assembly hidebysig static int32 + 'g__F|0_0'() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 3 (0x3) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ret + } // end of method NoLocalFunctions::'g__F|0_0' + + .method assembly hidebysig static int32 + 'g__F|1_0'(valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'& A_0) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 10 (0xa) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ldarg.0 + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'::x + IL_0008: add + IL_0009: ret + } // end of method NoLocalFunctions::'g__F|1_0' + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.roslyn.il new file mode 100644 index 000000000..ac6ecbb93 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.roslyn.il @@ -0,0 +1,179 @@ + + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly NoLocalFunctions +{ + .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 + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .permissionset reqmin + = {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}} + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module NoLocalFunctions.dll +.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 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle + extends [mscorlib]System.Object +{ + .field private initonly class [mscorlib]System.Func`1 _func + .method public hidebysig specialname rtspecialname + instance void .ctor(class [mscorlib]System.Func`1 func) cil managed + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld class [mscorlib]System.Func`1 ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::_func + IL_000f: ret + } // end of method Handle::.ctor + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle + +.class public abstract auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions + extends [mscorlib]System.Object +{ + .class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass1_0' + extends [mscorlib]System.ValueType + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 x + } // end of class '<>c__DisplayClass1_0' + + .class auto ansi sealed nested private beforefieldinit '<>c__DisplayClass2_0' + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 x + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method '<>c__DisplayClass2_0'::.ctor + + .method assembly hidebysig instance int32 + 'g__F|0'() cil managed + { + // Code size 10 (0xa) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ldarg.0 + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::x + IL_0008: add + IL_0009: ret + } // end of method '<>c__DisplayClass2_0'::'g__F|0' + + } // end of class '<>c__DisplayClass2_0' + + .method private hidebysig static void UseLocalFunctionReference() cil managed + { + // Code size 21 (0x15) + .maxstack 2 + .locals init (class ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle V_0) + IL_0000: nop + IL_0001: nop + IL_0002: ldnull + IL_0003: ldftn int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions::'g__F|0_0'() + IL_0009: newobj instance void class [mscorlib]System.Func`1::.ctor(object, + native int) + IL_000e: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::.ctor(class [mscorlib]System.Func`1) + IL_0013: stloc.0 + IL_0014: ret + } // end of method NoLocalFunctions::UseLocalFunctionReference + + .method private hidebysig static void SimpleCapture() cil managed + { + // Code size 19 (0x13) + .maxstack 2 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0' V_0) + IL_0000: nop + IL_0001: ldloca.s V_0 + IL_0003: ldc.i4.1 + IL_0004: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'::x + IL_0009: nop + IL_000a: ldloca.s V_0 + IL_000c: call int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions::'g__F|1_0'(valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'&) + IL_0011: pop + IL_0012: ret + } // end of method NoLocalFunctions::SimpleCapture + + .method private hidebysig static void SimpleCaptureWithRef() cil managed + { + // Code size 34 (0x22) + .maxstack 2 + .locals init (class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0' V_0, + class ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle V_1) + IL_0000: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::.ctor() + IL_0005: stloc.0 + IL_0006: nop + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::x + IL_000e: nop + IL_000f: ldloc.0 + IL_0010: ldftn instance int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass2_0'::'g__F|0'() + IL_0016: newobj instance void class [mscorlib]System.Func`1::.ctor(object, + native int) + IL_001b: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Ugly.Handle::.ctor(class [mscorlib]System.Func`1) + IL_0020: stloc.1 + IL_0021: ret + } // end of method NoLocalFunctions::SimpleCaptureWithRef + + .method assembly hidebysig static int32 + 'g__F|0_0'() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 3 (0x3) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ret + } // end of method NoLocalFunctions::'g__F|0_0' + + .method assembly hidebysig static int32 + 'g__F|1_0'(valuetype ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'& A_0) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 10 (0xa) + .maxstack 8 + IL_0000: ldc.i4.s 42 + IL_0002: ldarg.0 + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions/'<>c__DisplayClass1_0'::x + IL_0008: add + IL_0009: ret + } // end of method NoLocalFunctions::'g__F|1_0' + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoLocalFunctions + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs index e0e2b7aeb..b69e33bae 100644 --- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs @@ -99,6 +99,12 @@ namespace ICSharpCode.Decompiler.Tests }); } + [Test] + public void NoLocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) + { + RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1)); + } + void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) { Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 525f3bea8..b4e5cf77b 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1247,7 +1247,7 @@ namespace ICSharpCode.Decompiler.CSharp } FixParameterNames(methodDecl); var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - if (!settings.LocalFunctions && LocalFunctionDecompiler.IsLocalFunctionMethod(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) { + if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) { // if local functions are not active and we're dealing with a local function, // reduce the visibility of the method to private, // otherwise this leads to compile errors because the display classes have lesser accessibility. diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index 5adbdf4e0..e79d30e86 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -333,6 +333,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + public static bool LocalFunctionNeedsAccessibilityChange(PEFile module, MethodDefinitionHandle methodHandle) + { + if (!IsLocalFunctionMethod(module, methodHandle)) + return false; + + var metadata = module.Metadata; + var method = metadata.GetMethodDefinition(methodHandle); + + FindRefStructParameters visitor = new FindRefStructParameters(); + method.DecodeSignature(visitor, default); + + foreach (var h in visitor.RefStructTypes) { + var td = metadata.GetTypeDefinition(h); + if (td.IsCompilerGenerated(metadata) && td.IsValueType(metadata)) + return true; + } + + return false; + } + public static bool IsLocalFunctionDisplayClass(PEFile module, TypeDefinitionHandle typeHandle, ILTransformContext context = null) { if (context != null && context.PEFile != module) @@ -414,5 +434,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); } } + + class FindRefStructParameters : ISignatureTypeProvider + { + public readonly List RefStructTypes = new List(); + + public TypeDefinitionHandle GetArrayType(TypeDefinitionHandle elementType, ArrayShape shape) => default; + public TypeDefinitionHandle GetFunctionPointerType(MethodSignature signature) => default; + public TypeDefinitionHandle GetGenericInstantiation(TypeDefinitionHandle genericType, ImmutableArray typeArguments) => default; + public TypeDefinitionHandle GetGenericMethodParameter(Unit genericContext, int index) => default; + public TypeDefinitionHandle GetGenericTypeParameter(Unit genericContext, int index) => default; + public TypeDefinitionHandle GetModifiedType(TypeDefinitionHandle modifier, TypeDefinitionHandle unmodifiedType, bool isRequired) => default; + public TypeDefinitionHandle GetPinnedType(TypeDefinitionHandle elementType) => default; + public TypeDefinitionHandle GetPointerType(TypeDefinitionHandle elementType) => default; + public TypeDefinitionHandle GetPrimitiveType(PrimitiveTypeCode typeCode) => default; + public TypeDefinitionHandle GetSZArrayType(TypeDefinitionHandle elementType) => default; + + public TypeDefinitionHandle GetByReferenceType(TypeDefinitionHandle elementType) + { + if (!elementType.IsNil) + RefStructTypes.Add(elementType); + return elementType; + } + + public TypeDefinitionHandle GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) => default; + public TypeDefinitionHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => handle; + public TypeDefinitionHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => default; + } } }