diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 971979b70..d34cd96d3 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -154,6 +154,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index f34b96b5b..562beb8f2 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -133,6 +133,14 @@ namespace ICSharpCode.Decompiler.Tests CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, }; + static readonly CompilerOptions[] roslyn4OrNewerWithNet40Options = + { + CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, + CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, + CompilerOptions.UseRoslynLatest, + CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, + }; + static readonly CompilerOptions[] roslyn4OrNewerOptions = { CompilerOptions.UseRoslynLatest, @@ -664,6 +672,12 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions | CompilerOptions.CheckForOverflowUnderflow, configureDecompiler: settings => settings.CheckForOverflowUnderflow = true); } + [Test] + public async Task Issue3541([ValueSource(nameof(roslyn4OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs new file mode 100644 index 000000000..c1df03b60 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs @@ -0,0 +1,15 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal class Issue3541 + { + private void Test(string format) + { + TestLocal(); + + void TestLocal(int a = 0) + { + a.ToString(format); + } + } + } +} diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index a5d01d8f0..1d93b677a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -566,13 +566,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms } internal static bool IsClosureParameter(IParameter parameter, ITypeResolveContext context) + { + return IsClosureParameter(parameter, context.CurrentTypeDefinition); + } + + internal static bool IsClosureParameter(IParameter parameter, ITypeDefinition currentTypeDefinition) { if (parameter.Type is not ByReferenceType brt) return false; var type = brt.ElementType.GetDefinition(); return type != null && type.Kind == TypeKind.Struct - && TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type); + && TransformDisplayClassUsage.IsPotentialClosure(currentTypeDefinition, type); } LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove) diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 1a4b11501..b89e2d10b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; +using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -681,6 +682,9 @@ namespace ICSharpCode.Decompiler.TypeSystem if (otherParameter == parameter) break; + if (LocalFunctionDecompiler.IsClosureParameter(otherParameter, otherParameter.Owner.DeclaringTypeDefinition)) + continue; + if (DefaultValueAssignmentAllowedIndividual(otherParameter) || otherParameter.IsParams) continue;