Browse Source

Fix generic using patterns.

pull/877/head
Siegfried Pammer 8 years ago
parent
commit
e2dab8699f
  1. 14
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs
  2. 83
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.il
  3. 66
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.opt.il
  4. 62
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.opt.roslyn.il
  5. 72
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.roslyn.il
  6. 19
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  7. 3
      ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs
  8. 8
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

14
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs

@ -108,6 +108,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -108,6 +108,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public void GenericStructUsing<T>(T t) where T : struct, IDisposable
{
using (t) {
Console.WriteLine(t);
}
}
public void GenericClassUsing<T>(T t) where T : class, IDisposable
{
using (t) {
Console.WriteLine(t);
}
}
public void NoUsing()
{
PrintOnDispose printOnDispose = new PrintOnDispose("Wrong");

83
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly l2hk2gwn
.assembly vu3cz5gg
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module l2hk2gwn.dll
// MVID: {657FEAFC-6D05-4375-B9FF-DE1D3DB20A85}
.module vu3cz5gg.dll
// MVID: {FD1D14F2-B901-4ADC-A6BA-6844964F643A}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x02BA0000
// Image base: 0x00F10000
// =============== CLASS MEMBERS DECLARATION ===================
@ -379,6 +379,79 @@ @@ -379,6 +379,79 @@
IL_0030: ret
} // end of method Using::GenericUsing
.method public hidebysig instance void
GenericStructUsing<valuetype .ctor ([mscorlib]System.ValueType, [mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 36 (0x24)
.maxstack 1
.locals init (!!T V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldarg.1
IL_0005: box !!T
IL_000a: call void [mscorlib]System.Console::WriteLine(object)
IL_000f: nop
IL_0010: nop
IL_0011: leave.s IL_0022
} // end .try
finally
{
IL_0013: ldloca.s V_0
IL_0015: constrained. !!T
IL_001b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0020: nop
IL_0021: endfinally
} // end handler
IL_0022: nop
IL_0023: ret
} // end of method Using::GenericStructUsing
.method public hidebysig instance void
GenericClassUsing<class ([mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 49 (0x31)
.maxstack 2
.locals init (!!T V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldarg.1
IL_0005: box !!T
IL_000a: call void [mscorlib]System.Console::WriteLine(object)
IL_000f: nop
IL_0010: nop
IL_0011: leave.s IL_002f
} // end .try
finally
{
IL_0013: ldloc.0
IL_0014: box !!T
IL_0019: ldnull
IL_001a: ceq
IL_001c: stloc.1
IL_001d: ldloc.1
IL_001e: brtrue.s IL_002e
IL_0020: ldloca.s V_0
IL_0022: constrained. !!T
IL_0028: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_002d: nop
IL_002e: endfinally
} // end handler
IL_002f: nop
IL_0030: ret
} // end of method Using::GenericClassUsing
.method public hidebysig instance void
NoUsing() cil managed
{

66
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.opt.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly lseglqv2
.assembly vexl0swc
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module lseglqv2.dll
// MVID: {57E840D4-DC5F-44E8-80CB-5FE3F73EAEF2}
.module vexl0swc.dll
// MVID: {EB6E7617-FC1E-4784-86CC-81DA71679C35}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x02770000
// Image base: 0x00BE0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -302,6 +302,62 @@ @@ -302,6 +302,62 @@
IL_0025: ret
} // end of method Using::GenericUsing
.method public hidebysig instance void
GenericStructUsing<valuetype .ctor ([mscorlib]System.ValueType, [mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 30 (0x1e)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
.try
{
IL_0002: ldarg.1
IL_0003: box !!T
IL_0008: call void [mscorlib]System.Console::WriteLine(object)
IL_000d: leave.s IL_001d
} // end .try
finally
{
IL_000f: ldloca.s V_0
IL_0011: constrained. !!T
IL_0017: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_001c: endfinally
} // end handler
IL_001d: ret
} // end of method Using::GenericStructUsing
.method public hidebysig instance void
GenericClassUsing<class ([mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 38 (0x26)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
.try
{
IL_0002: ldarg.1
IL_0003: box !!T
IL_0008: call void [mscorlib]System.Console::WriteLine(object)
IL_000d: leave.s IL_0025
} // end .try
finally
{
IL_000f: ldloc.0
IL_0010: box !!T
IL_0015: brfalse.s IL_0024
IL_0017: ldloca.s V_0
IL_0019: constrained. !!T
IL_001f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0024: endfinally
} // end handler
IL_0025: ret
} // end of method Using::GenericClassUsing
.method public hidebysig instance void
NoUsing() cil managed
{

62
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.opt.roslyn.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module Using.dll
// MVID: {81DAF28D-BA8B-49CF-9CAC-D5C7BE5BE2AC}
// MVID: {6ACE0D07-2500-4E79-B8A5-908F446B5708}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x010E0000
// Image base: 0x01950000
// =============== CLASS MEMBERS DECLARATION ===================
@ -279,6 +279,62 @@ @@ -279,6 +279,62 @@
IL_0025: ret
} // end of method Using::GenericUsing
.method public hidebysig instance void
GenericStructUsing<valuetype .ctor ([mscorlib]System.IDisposable, [mscorlib]System.ValueType) T>(!!T t) cil managed
{
// Code size 30 (0x1e)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
.try
{
IL_0002: ldarg.1
IL_0003: box !!T
IL_0008: call void [mscorlib]System.Console::WriteLine(object)
IL_000d: leave.s IL_001d
} // end .try
finally
{
IL_000f: ldloca.s V_0
IL_0011: constrained. !!T
IL_0017: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_001c: endfinally
} // end handler
IL_001d: ret
} // end of method Using::GenericStructUsing
.method public hidebysig instance void
GenericClassUsing<class ([mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 36 (0x24)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
.try
{
IL_0002: ldarg.1
IL_0003: box !!T
IL_0008: call void [mscorlib]System.Console::WriteLine(object)
IL_000d: leave.s IL_0023
} // end .try
finally
{
IL_000f: ldloc.0
IL_0010: box !!T
IL_0015: brfalse.s IL_0022
IL_0017: ldloc.0
IL_0018: box !!T
IL_001d: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0022: endfinally
} // end handler
IL_0023: ret
} // end of method Using::GenericClassUsing
.method public hidebysig instance void
NoUsing() cil managed
{

72
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.roslyn.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module Using.dll
// MVID: {75250624-2DF6-4B63-B8BF-A82776556583}
// MVID: {01A69772-54AF-4C5E-875F-47130AC714FC}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x02BA0000
// Image base: 0x02BE0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -317,6 +317,72 @@ @@ -317,6 +317,72 @@
IL_002a: ret
} // end of method Using::GenericUsing
.method public hidebysig instance void
GenericStructUsing<valuetype .ctor ([mscorlib]System.IDisposable, [mscorlib]System.ValueType) T>(!!T t) cil managed
{
// Code size 35 (0x23)
.maxstack 1
.locals init (!!T V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldarg.1
IL_0005: box !!T
IL_000a: call void [mscorlib]System.Console::WriteLine(object)
IL_000f: nop
IL_0010: nop
IL_0011: leave.s IL_0022
} // end .try
finally
{
IL_0013: ldloca.s V_0
IL_0015: constrained. !!T
IL_001b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0020: nop
IL_0021: endfinally
} // end handler
IL_0022: ret
} // end of method Using::GenericStructUsing
.method public hidebysig instance void
GenericClassUsing<class ([mscorlib]System.IDisposable) T>(!!T t) cil managed
{
// Code size 41 (0x29)
.maxstack 1
.locals init (!!T V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldarg.1
IL_0005: box !!T
IL_000a: call void [mscorlib]System.Console::WriteLine(object)
IL_000f: nop
IL_0010: nop
IL_0011: leave.s IL_0028
} // end .try
finally
{
IL_0013: ldloc.0
IL_0014: box !!T
IL_0019: brfalse.s IL_0027
IL_001b: ldloc.0
IL_001c: box !!T
IL_0021: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0026: nop
IL_0027: endfinally
} // end handler
IL_0028: ret
} // end of method Using::GenericClassUsing
.method public hidebysig instance void
NoUsing() cil managed
{

19
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -257,7 +257,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -257,7 +257,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
#region foreach construction
static readonly AssignmentExpression getEnumeratorPattern = new AssignmentExpression(new NamedNode("enumerator", new IdentifierExpression(Pattern.AnyString)), new InvocationExpression(new MemberReferenceExpression(new AnyNode("collection").ToExpression(), "GetEnumerator")));
static readonly InvocationExpression getEnumeratorPattern = new InvocationExpression(new MemberReferenceExpression(new AnyNode("collection").ToExpression(), "GetEnumerator"));
static readonly InvocationExpression moveNextConditionPattern = new InvocationExpression(new MemberReferenceExpression(new NamedNode("enumerator", new IdentifierExpression(Pattern.AnyString)), "MoveNext"));
protected internal override Statement VisitUsingInstruction(UsingInstruction inst)
@ -265,19 +265,28 @@ namespace ICSharpCode.Decompiler.CSharp @@ -265,19 +265,28 @@ namespace ICSharpCode.Decompiler.CSharp
var transformed = TransformToForeach(inst, out var resource);
if (transformed != null)
return transformed;
AstNode usingInit = resource;
var var = inst.Variable;
if (var.LoadCount > 0 || var.AddressCount > 0) {
var.Kind = VariableKind.UsingLocal;
var type = settings.AnonymousTypes && var.Type.ContainsAnonymousType() ? new SimpleType("var") : exprBuilder.ConvertType(var.Type);
var vds = new VariableDeclarationStatement(type, var.Name, resource);
vds.Variables.Single().AddAnnotation(new ILVariableResolveResult(var, var.Type));
usingInit = vds;
}
return new UsingStatement {
ResourceAcquisition = resource,
ResourceAcquisition = usingInit,
EmbeddedStatement = ConvertAsBlock(inst.Body)
};
}
Statement TransformToForeach(UsingInstruction inst, out TranslatedExpression resource)
Statement TransformToForeach(UsingInstruction inst, out Expression resource)
{
resource = exprBuilder.Translate(inst.ResourceExpression);
var m = getEnumeratorPattern.Match(resource.Expression);
var m = getEnumeratorPattern.Match(resource);
if (!(inst.Body is BlockContainer container) || !m.Success)
return null;
var enumeratorVar = m.Get<IdentifierExpression>("enumerator").Single().GetILVariable();
var enumeratorVar = inst.Variable;
var loopContainer = UnwrapNestedContainerIfPossible(container, out var optionalReturnAfterLoop);
var loop = DetectedLoop.DetectLoop(loopContainer);
if (loop.Kind != LoopKind.While || !(loop.Body is Block body))

3
ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs

@ -51,6 +51,9 @@ namespace ICSharpCode.Decompiler.IL @@ -51,6 +51,9 @@ namespace ICSharpCode.Decompiler.IL
/// }
/// </code>
/// </summary>
/// <remarks>
/// The value of v is undefined after the end of the body block.
/// </remarks>
partial class UsingInstruction
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)

8
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -120,17 +120,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -120,17 +120,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
callVirt = cv;
}
if (callVirt.Method.Name != "Dispose" || callVirt.Method.DeclaringType.FullName != "System.IDisposable")
if (callVirt.Method.FullName != "System.IDisposable.Dispose")
return false;
if (callVirt.Method.Parameters.Count > 0)
return false;
if (callVirt.Arguments.Count != 1)
return false;
if (objVar.Type.IsReferenceType != false) {
return callVirt.Arguments[0].MatchLdLoc(objVar) || (usingNull && callVirt.Arguments[0].MatchLdNull());
} else {
return callVirt.Arguments[0].MatchLdLoca(objVar);
}
return callVirt.Arguments[0].MatchLdLocRef(objVar) || (usingNull && callVirt.Arguments[0].MatchLdNull());
}
}
}

Loading…
Cancel
Save