From 8b0c7fbe85a53779dd437a1e40f0cf2fc1ff6d7d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 4 Apr 2023 20:19:14 +0200 Subject: [PATCH] Fix #2921: struct type definition contains duplicate default constructor. --- .../TypeSystem/TypeSystemLoaderTests.cs | 10 ++++++++++ .../TypeSystem/TypeSystemTestCase.cs | 5 +++++ .../Implementation/MetadataTypeDefinition.cs | 12 +++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index 38435f1d0a..b6346f0fde 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -616,6 +616,16 @@ public void DefaultConstructorAddedToStruct() Assert.IsTrue(ctors.All(c => c.Accessibility == Accessibility.Public)); } + [Test] + public void NoDefaultConstructorAddedToStruct() + { + var ctors = compilation.FindType(typeof(MyStructWithDefaultCtor)).GetConstructors(); + Assert.AreEqual(1, ctors.Count()); + Assert.IsFalse(ctors.Any(c => c.IsStatic)); + Assert.IsTrue(ctors.All(c => c.ReturnType.Kind == TypeKind.Void)); + Assert.IsTrue(ctors.All(c => c.Accessibility == Accessibility.Public)); + } + [Test] public void NoDefaultConstructorAddedToClass() { diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs index 1a55b5cce5..a526c793ff 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs @@ -140,6 +140,11 @@ public struct MyStructWithCtor public MyStructWithCtor(int a) { } } + public struct MyStructWithDefaultCtor + { + public MyStructWithDefaultCtor() { } + } + public class MyClassWithCtor { private MyClassWithCtor(int a) { } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index 4fe5a35867..1cb4c5954b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -259,17 +259,23 @@ public IEnumerable Methods { var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods(); var methodsList = new List(methodsCollection.Count); var methodSemantics = module.PEFile.MethodSemanticsLookup; + bool hasDefaultCtor = false; foreach (MethodDefinitionHandle h in methodsCollection) { var md = metadata.GetMethodDefinition(h); if (methodSemantics.GetSemantics(h).Item2 == 0 && module.IsVisible(md.Attributes)) { - methodsList.Add(module.GetDefinition(h)); + IMethod method = module.GetDefinition(h); + if (method.SymbolKind == SymbolKind.Constructor && !method.IsStatic && method.Parameters.Count == 0) + { + hasDefaultCtor = true; + } + methodsList.Add(method); } } - if (this.Kind == TypeKind.Struct || this.Kind == TypeKind.Enum) + if (!hasDefaultCtor && (this.Kind == TypeKind.Struct || this.Kind == TypeKind.Enum)) { - methodsList.Add(FakeMethod.CreateDummyConstructor(Compilation, this, IsAbstract ? Accessibility.Protected : Accessibility.Public)); + methodsList.Add(FakeMethod.CreateDummyConstructor(Compilation, this, Accessibility.Public)); } if ((module.TypeSystemOptions & TypeSystemOptions.Uncached) != 0) return methodsList;