diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 29015d86a..f112879f5 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -105,6 +105,7 @@
+
@@ -209,6 +210,8 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
index 117f54bef..ea17c49f8 100644
--- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
@@ -359,6 +359,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
+ [Test]
+ public async Task InaccessibleParameterTypes()
+ {
+ await Run();
+ }
+
[Test]
public async Task EmptyBodies()
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.cs
new file mode 100644
index 000000000..e1dcd80b3
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
+{
+ public class InaccessibleParameterTypes
+ {
+ private class Hidden
+ {
+ }
+
+ public delegate void Handler(Hidden h);
+
+ public static void Register(Action callback)
+ {
+ }
+ }
+ public class InaccessibleParameterTypesConsumer
+ {
+ public InaccessibleParameterTypes.Handler Create()
+ {
+ return delegate {
+ };
+ }
+
+ public void Run()
+ {
+ InaccessibleParameterTypes.Register(delegate {
+ });
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.il
new file mode 100644
index 000000000..968ca4264
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/InaccessibleParameterTypes.il
@@ -0,0 +1,138 @@
+// Anonymous methods whose delegate signature contains a type the use site cannot name.
+// IL (unlike C#) permits a public delegate with a less-accessible parameter type, so the
+// parameter-list-less "delegate {}" form is the only C# syntax the consumer class below
+// could legally have used - the decompiler must not expand it to a lambda parameter list.
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly extern System.Core
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly InaccessibleParameterTypes
+{
+ .ver 1:0:0:0
+}
+.module InaccessibleParameterTypes.dll
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00020003 // ILONLY 32BITPREFERRED
+
+.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes
+ extends [mscorlib]System.Object
+{
+ .class nested private auto ansi beforefieldinit Hidden
+ extends [mscorlib]System.Object
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ ldarg.0
+ call instance void [mscorlib]System.Object::.ctor()
+ ret
+ }
+ }
+
+ .class nested public auto ansi sealed Handler
+ extends [mscorlib]System.MulticastDelegate
+ {
+ .method public hidebysig specialname rtspecialname instance void .ctor (object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig newslot virtual instance void Invoke (class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Hidden h) runtime managed
+ {
+ }
+ }
+
+ .method public hidebysig static void Register (class [System.Core]System.Action`1 callback) cil managed
+ {
+ .maxstack 8
+
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ ldarg.0
+ call instance void [mscorlib]System.Object::.ctor()
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer
+ extends [mscorlib]System.Object
+{
+ // Fields
+ .field private static class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler '<>f__am$cache0'
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .field private static class [System.Core]System.Action`1 '<>f__am$cache1'
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+
+ // Methods
+ .method public hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler Create () cil managed
+ {
+ .maxstack 8
+
+ ldsfld class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache0'
+ brtrue.s IL_0016
+
+ ldnull
+ ldftn void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'m__0'(class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Hidden)
+ newobj instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler::.ctor(object, native int)
+ stsfld class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache0'
+
+ IL_0016: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Handler ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache0'
+ ret
+ }
+
+ .method public hidebysig instance void Run () cil managed
+ {
+ .maxstack 8
+
+ ldsfld class [System.Core]System.Action`1 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache1'
+ brtrue.s IL_0016
+
+ ldnull
+ ldftn void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'m__1'(class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Hidden)
+ newobj instance void class [System.Core]System.Action`1::.ctor(object, native int)
+ stsfld class [System.Core]System.Action`1 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache1'
+
+ IL_0016: ldsfld class [System.Core]System.Action`1 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypesConsumer::'<>f__am$cache1'
+ call void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes::Register(class [System.Core]System.Action`1)
+ ret
+ }
+
+ .method private hidebysig static void 'm__0' (class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Hidden '') cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .maxstack 8
+
+ ret
+ }
+
+ .method private hidebysig static void 'm__1' (class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.InaccessibleParameterTypes/Hidden '') cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .maxstack 8
+
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname instance void .ctor () cil managed
+ {
+ .maxstack 8
+
+ ldarg.0
+ call instance void [mscorlib]System.Object::.ctor()
+ ret
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
index f1a8b708e..01a0ed57e 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
@@ -163,11 +163,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
return (int x) => this.x;
}
+#if ROSLYN
+ // Roslyn names the parameters of an anonymous method declared without a parameter
+ // list "", which no lambda parameter list can spell, so the delegate form is
+ // kept. Legacy csc names them "param0" - a perfectly good identifier that does
+ // become a lambda - hence the Roslyn-only guard.
public Action