mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Repair private virtual member output
Metadata can contain private virtual members that C# cannot declare directly. Adjusting the emitted accessibility in the decompiler keeps such members compilable without pushing the policy into the general AST builder. Assisted-by: OpenCode:openai/gpt-5.5:OpenCode
This commit is contained in:
@@ -117,6 +117,12 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await Run();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Issue3136()
|
||||
{
|
||||
await Run();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Issue1918()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public class MyClass
|
||||
{
|
||||
private object _MyValue;
|
||||
|
||||
protected virtual object MyValue {
|
||||
get {
|
||||
return _MyValue;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
set {
|
||||
_MyValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
.class public auto ansi beforefieldinit MyClass extends [mscorlib]System.Object
|
||||
{
|
||||
.field private object _MyValue
|
||||
|
||||
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
|
||||
{
|
||||
.maxstack 8
|
||||
ldarg.0
|
||||
call instance void [mscorlib]System.Object::.ctor()
|
||||
ret
|
||||
} // end of method MyClass::.ctor
|
||||
|
||||
.method private specialname newslot strict virtual instance object get_MyValue () cil managed
|
||||
{
|
||||
.maxstack 8
|
||||
ldarg.0
|
||||
ldfld object MyClass::_MyValue
|
||||
ret
|
||||
} // end of method MyClass::get_MyValue
|
||||
|
||||
.method private specialname newslot strict virtual instance void set_MyValue (object 'value') cil managed synchronized
|
||||
{
|
||||
.maxstack 8
|
||||
ldarg.0
|
||||
ldarg.1
|
||||
stfld object MyClass::_MyValue
|
||||
ret
|
||||
} // end of method MyClass::set_MyValue
|
||||
|
||||
.property instance object MyValue()
|
||||
{
|
||||
.get instance object MyClass::get_MyValue()
|
||||
.set instance void MyClass::set_MyValue(object)
|
||||
} // end of property MyClass::MyValue
|
||||
}
|
||||
@@ -2245,6 +2245,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
// without this the decompiled program does not compile (CS5001).
|
||||
methodDecl.Name = "Main";
|
||||
}
|
||||
FixPrivateVirtualMemberModifiers(methodDecl, method);
|
||||
FixParameterNames(methodDecl);
|
||||
var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
|
||||
if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule!.MetadataFile, (MethodDefinitionHandle)method.MetadataToken))
|
||||
@@ -2824,6 +2825,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
int lastDot = property.Name.LastIndexOf('.');
|
||||
propertyDecl.Name = property.Name.Substring(lastDot + 1);
|
||||
}
|
||||
FixPrivateVirtualMemberModifiers(propertyDecl, property);
|
||||
FixParameterNames(propertyDecl);
|
||||
Accessor? getter, setter;
|
||||
if (propertyDecl is PropertyDeclaration)
|
||||
@@ -2905,6 +2907,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
{
|
||||
eventDecl.Name = ev.Name.Substring(lastDot + 1);
|
||||
}
|
||||
FixPrivateVirtualMemberModifiers(eventDecl, ev);
|
||||
if (isAutomaticEvent)
|
||||
{
|
||||
AutoEventDecompiler.AddFieldLikeEventAttributes((EventDeclaration)eventDecl, typeSystemAstBuilder, ev, backingField!);
|
||||
@@ -2941,6 +2944,16 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
static void FixPrivateVirtualMemberModifiers(EntityDeclaration declaration, IMember member)
|
||||
{
|
||||
if (member.Accessibility != Accessibility.Private || member.DeclaringType.Kind == TypeKind.Interface)
|
||||
return;
|
||||
if (!member.IsVirtual && !member.IsAbstract && !member.IsOverride)
|
||||
return;
|
||||
declaration.Modifiers &= ~Modifiers.Private;
|
||||
declaration.Modifiers |= Modifiers.Protected;
|
||||
}
|
||||
|
||||
#region Sequence Points
|
||||
/// <summary>
|
||||
/// Creates sequence points for the given syntax tree.
|
||||
|
||||
Reference in New Issue
Block a user