Browse Source

Fix #1083: add pattern for mcs auto events (version 4)

pull/1051/head
Siegfried Pammer 8 years ago
parent
commit
659b12bdb8
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  3. 10
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1038.cs
  4. 125
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1038.il
  5. 55
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -62,6 +62,8 @@ @@ -62,6 +62,8 @@
<Compile Include="TestCases\Correctness\LINQRaytracer.cs" />
<Compile Include="TestCases\Correctness\MiniJSON.cs" />
<Compile Include="TestCases\Correctness\FloatingPointArithmetic.cs" />
<Compile Include="TestCases\ILPretty\Issue1038.cs" />
<None Include="TestCases\ILPretty\Issue1038.il" />
<None Include="TestCases\ILPretty\Issue1047.cs" />
<Compile Include="TestCases\ILPretty\Issue982.cs" />
<Compile Include="TestCases\Pretty\AsyncMain.cs" />

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -54,6 +54,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -54,6 +54,12 @@ namespace ICSharpCode.Decompiler.Tests
Run();
}
[Test]
public void Issue1038()
{
Run();
}
[Test]
public void Issue1047()
{

10
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1038.cs

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
{
public class Issue1038<TK, TR> where TR : class, new()
{
public event Action<TK, TR> TestEvent = delegate {
};
}
}

125
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1038.il

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern System
{
.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 ConsoleApp11
{
.ver 1:0:0:0
}
.module ConsoleApp11.exe
// MVID: {B973FCD6-A9C4-48A9-8291-26DDC248E208}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00020003 // ILONLY 32BITPREFERRED
// Image base: 0x000001C4B6C90000
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<TK, class .ctor TR>
{
// Fields
.field private class [System.Core]System.Action`2<!TK, !TR> TestEvent
.field private static class [System.Core]System.Action`2<!TK, !TR> '<>f__am$cache0'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Methods
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
.maxstack 8
ldarg.0
ldsfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::'<>f__am$cache0'
brtrue.s IL_0019
ldnull
ldftn void class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::'<TestEvent>m__0'(!0, !1)
newobj instance void class [System.Core]System.Action`2<!TK, !TR>::.ctor(object, native int)
stsfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::'<>f__am$cache0'
IL_0019: ldsfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::'<>f__am$cache0'
stfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::TestEvent
ret
}
.method public hidebysig specialname instance void add_TestEvent (class [System.Core]System.Action`2<!TK, !TR> 'value') cil managed
{
.maxstack 3
.locals init (
[0] class [System.Core]System.Action`2<!TK, !TR>,
[1] class [System.Core]System.Action`2<!TK, !TR>
)
ldarg.0
ldfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::TestEvent
stloc.0
IL_0007: ldloc.0
stloc.1
ldarg.0
ldflda class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::TestEvent
ldloc.1
ldarg.1
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass class [System.Core]System.Action`2<!TK, !TR>
ldloc.0
call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [System.Core]System.Action`2<!TK, !TR>>(!!0&, !!0, !!0)
stloc.0
ldloc.0
ldloc.1
bne.un IL_0007
ret
}
.method public hidebysig specialname instance void remove_TestEvent (class [System.Core]System.Action`2<!TK, !TR> 'value') cil managed
{
.maxstack 3
.locals init (
[0] class [System.Core]System.Action`2<!TK, !TR>,
[1] class [System.Core]System.Action`2<!TK, !TR>
)
ldarg.0
ldfld class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::TestEvent
stloc.0
IL_0007: ldloc.0
stloc.1
ldarg.0
ldflda class [System.Core]System.Action`2<!0, !1> class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2<!TK, !TR>::TestEvent
ldloc.1
ldarg.1
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass class [System.Core]System.Action`2<!TK, !TR>
ldloc.0
call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [System.Core]System.Action`2<!TK, !TR>>(!!0&, !!0, !!0)
stloc.0
ldloc.0
ldloc.1
bne.un IL_0007
ret
}
.method private hidebysig static void '<TestEvent>m__0' (!TK '', !TR '') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
ret
}
// Events
.event class [System.Core]System.Action`2<!TK, !TR> TestEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2::add_TestEvent(class [System.Core]System.Action`2<!0, !1>)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1038`2::remove_TestEvent(class [System.Core]System.Action`2<!0, !1>)
}
}

55
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -633,7 +633,46 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -633,7 +633,46 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
};
static readonly Accessor automaticEventPatternV4MCS = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Body = new BlockStatement {
new AssignmentExpression {
Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
Right = new NamedNode(
"field",
new MemberReferenceExpression {
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
MemberName = Pattern.AnyString
}
)
},
new DoWhileStatement {
EmbeddedStatement = new BlockStatement {
new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")),
new AssignmentExpression {
Left = new IdentifierExpressionBackreference("var1"),
Right = new InvocationExpression(new MemberReferenceExpression(new TypeReferenceExpression(new TypePattern(typeof(System.Threading.Interlocked)).ToType()),
"CompareExchange",
new AstType[] { new AnyNode("type") }), // type argument+
new Expression[] { // arguments
new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") },
new CastExpression(new Backreference("type"), new InvocationExpression(new AnyNode("delegateCombine").ToExpression(), new IdentifierExpressionBackreference("var2"), new IdentifierExpression("value"))),
new IdentifierExpressionBackreference("var1")
}
)
}
},
Condition = new BinaryOperatorExpression {
Left = new CastExpression(new TypePattern(typeof(object)), new IdentifierExpressionBackreference("var1")),
Operator = BinaryOperatorType.InEquality,
Right = new IdentifierExpressionBackreference("var2")
},
}
}
};
bool CheckAutomaticEventMatch(Match m, CustomEventDeclaration ev, bool isAddAccessor)
{
if (!m.Success)
@ -678,10 +717,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -678,10 +717,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return true;
}
bool CheckAutomaticEventV4MCS(CustomEventDeclaration ev, out Match addMatch, out Match removeMatch)
{
addMatch = removeMatch = default(Match);
addMatch = automaticEventPatternV4MCS.Match(ev.AddAccessor);
if (!CheckAutomaticEventMatch(addMatch, ev, true))
return false;
removeMatch = automaticEventPatternV4MCS.Match(ev.RemoveAccessor);
if (!CheckAutomaticEventMatch(removeMatch, ev, false))
return false;
return true;
}
EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
{
Match m1, m2;
if (!CheckAutomaticEventV4(ev, out m1, out m2) && !CheckAutomaticEventV2(ev, out m1, out m2))
if (!CheckAutomaticEventV4(ev, out m1, out m2) && !CheckAutomaticEventV2(ev, out m1, out m2) && !CheckAutomaticEventV4MCS(ev, out m1, out m2))
return null;
RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes, attributeTypesToRemoveFromAutoEvents);
EventDeclaration ed = new EventDeclaration();

Loading…
Cancel
Save