From 2a887cc5fd3442ef08aeef48d8fc1928ce80fce6 Mon Sep 17 00:00:00 2001 From: sonyps5201314 Date: Sat, 1 Nov 2025 03:06:30 +0800 Subject: [PATCH] When a constructor starts with a NOP instruction, the primary constructor check is skipped to allow some unit tests to pass. --- .../CSharp/RecordDecompiler.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs index c52fea6bc..d6cff9416 100644 --- a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs @@ -249,10 +249,11 @@ namespace ICSharpCode.Decompiler.CSharp var unspecializedMethod = instanceCtors[i]; var method = unspecializedMethod.Specialize(subst); Block body = null; + bool? bodyHasLeadingNop = false; if (mustFindChainingWithThis_Or_IsPrimaryConstructor) { - body = DecompileBody(method); + body = DecompileBody(method, ref bodyHasLeadingNop); if (body != null) { var first = body.Instructions.FirstOrDefault(); @@ -286,7 +287,7 @@ namespace ICSharpCode.Decompiler.CSharp } } - if (!CheckForInitPrimaryConstructor(method, unspecializedMethod, body)) + if (bodyHasLeadingNop == true || !CheckForInitPrimaryConstructor(method, unspecializedMethod, body)) { primaryConstructor = null; primaryCtorParameterToAutoPropertyOrBackingField.Clear(); @@ -313,7 +314,12 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (body == null) - body = DecompileBody(method); + { + bool? bodyHasLeadingNop = false; + body = DecompileBody(method, ref bodyHasLeadingNop); + if (bodyHasLeadingNop == true) + return false; + } if (body == null) return false; @@ -1290,6 +1296,11 @@ namespace ICSharpCode.Decompiler.CSharp } Block DecompileBody(IMethod method) + { + bool? bodyHasLeadingNop = null; + return DecompileBody(method, ref bodyHasLeadingNop); + } + Block DecompileBody(IMethod method, ref bool? bodyHasLeadingNop) { if (method == null || method.MetadataToken.IsNil) return null; @@ -1306,6 +1317,11 @@ namespace ICSharpCode.Decompiler.CSharp var body = typeSystem.MainModule.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); var ilReader = new ILReader(typeSystem.MainModule); var il = ilReader.ReadIL(methodDefHandle, body, genericContext, ILFunctionKind.TopLevelFunction, cancellationToken); + if (bodyHasLeadingNop != null) + { + var preBody = il.Body is BlockContainer bc ? bc.EntryPoint ?? il.Body as Block : null; + bodyHasLeadingNop = preBody != null ? preBody.Instructions.FirstOrDefault() is Nop : false; + } var settings = new DecompilerSettings(LanguageVersion.CSharp1); var transforms = CSharpDecompiler.GetILTransforms(); // Remove the last couple transforms -- we don't need variable names etc. here