Browse Source

Fix #926: missing explicit casts for implicit operators

pull/960/head
Daniel Grunwald 8 years ago
parent
commit
dd1c509651
  1. 36
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs
  2. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  3. 40
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il
  4. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il
  5. 24
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il
  6. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il
  7. 17
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  8. 4
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  9. 3
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

36
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
TypeCode.UInt64,
TypeCode.Single,
TypeCode.Double,
//TypeCode.Decimal
TypeCode.Decimal
};
static object[] inputValues = {
@ -109,6 +109,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -109,6 +109,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
RunTest(checkForOverflow: true);
Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length));
C1.Test();
}
static void RunTest(bool checkForOverflow)
@ -156,4 +157,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -156,4 +157,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
return System.Text.Encoding.ASCII.GetBytes("Hello World!");
}
}
class C1
{
public static implicit operator Type(C1 c)
{
return c.GetType();
}
public static void Test()
{
Console.WriteLine("op_Implicit tests");
ExplicitUseOfImplicitConversion(new C1());
Console.WriteLine(ChainedImplicitConversions(new C2()).Name);
}
static void ExplicitUseOfImplicitConversion(C1 c)
{
Console.WriteLine(((Type)c).Name);
}
static Type ChainedImplicitConversions(C2 c)
{
return (C1)c;
}
}
class C2
{
public static implicit operator C1(C2 c)
{
return new C1();
}
}
}

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -214,5 +214,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -214,5 +214,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return a == null;
}
public decimal ImplicitConversionToDecimal(byte v)
{
return v;
}
public decimal ImplicitConversionToDecimal(ulong v)
{
return v;
}
}
}

40
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il

@ -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 ph2u0axx
.assembly t2movxx2
{
.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 ph2u0axx.dll
// MVID: {8F821F70-8053-4F18-BDF7-88A43880B754}
.module t2movxx2.dll
// MVID: {F28F6C6C-94AA-4D5E-B9EE-907881B3E7E4}
.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: 0x00D70000
// Image base: 0x00690000
// =============== CLASS MEMBERS DECLARATION ===================
@ -735,6 +735,38 @@ @@ -735,6 +735,38 @@
IL_0009: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (valuetype [mscorlib]System.Decimal V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint8)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint64 v) cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (valuetype [mscorlib]System.Decimal V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint64)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il

@ -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 frnxitb5
.assembly '0nmkvdgs'
{
.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 frnxitb5.dll
// MVID: {DC6B1392-D29F-44A5-97D6-0C026DCD3A00}
.module '0nmkvdgs.dll'
// MVID: {E543BCF9-C441-4A6D-A25F-19C170B765C0}
.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: 0x00D50000
// Image base: 0x00C50000
// =============== CLASS MEMBERS DECLARATION ===================
@ -510,6 +510,26 @@ @@ -510,6 +510,26 @@
IL_0004: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint8)
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint64 v) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint64)
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

24
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module TypeAnalysisTests.dll
// MVID: {B6659F2C-8CAA-447B-9D1D-D59D8C40C6D7}
// MVID: {7D2FE161-359E-42EC-B423-26BEB23F890D}
.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: 0x003E0000
// Image base: 0x01730000
// =============== CLASS MEMBERS DECLARATION ===================
@ -512,6 +512,26 @@ @@ -512,6 +512,26 @@
IL_0004: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint8)
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint64 v) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint64)
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module TypeAnalysisTests.dll
// MVID: {E25A3961-A07D-4220-AB6C-FE5B1624514C}
// MVID: {6A008C4E-2BC5-45CA-93FB-93A12CD0BC69}
.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: 0x00D80000
// Image base: 0x01320000
// =============== CLASS MEMBERS DECLARATION ===================
@ -734,6 +734,38 @@ @@ -734,6 +734,38 @@
IL_0009: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (valuetype [mscorlib]System.Decimal V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint8)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint64 v) cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (valuetype [mscorlib]System.Decimal V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(uint64)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

17
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -167,6 +167,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -167,6 +167,8 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (IsDelegateEqualityComparison(method, arguments)) {
return HandleDelegateEqualityComparison(method, arguments)
.WithILInstruction(inst).WithRR(rr);
} else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) {
return HandleImplicitConversion(inst, arguments[0]);
} else {
bool requireTypeArguments = false;
bool targetCasted = false;
@ -269,6 +271,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -269,6 +271,21 @@ namespace ICSharpCode.Decompiler.CSharp
);
}
private TranslatedExpression HandleImplicitConversion(CallInstruction call, TranslatedExpression argument)
{
var conversions = CSharpConversions.Get(expressionBuilder.compilation);
IType targetType = call.Method.ReturnType;
var conv = conversions.ImplicitConversion(argument.Type, targetType);
if (!(conv.IsUserDefined && conv.Method.Equals(call.Method))) {
// implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type
argument = argument.ConvertTo(call.Method.Parameters[0].Type, expressionBuilder);
conv = conversions.ImplicitConversion(argument.Type, targetType);
}
return new CastExpression(expressionBuilder.ConvertType(targetType), argument.Expression)
.WithILInstruction(call)
.WithRR(new ConversionResolveResult(targetType, argument.ResolveResult, conv));
}
OverloadResolutionErrors IsUnambiguousCall(ILInstruction inst, TranslatedExpression target, IMethod method, IType[] typeArguments, IList<TranslatedExpression> arguments)
{
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);

4
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -131,10 +131,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -131,10 +131,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
);
return;
}
if (method.Name == "op_Implicit" && arguments.Length == 1) {
invocationExpression.ReplaceWith(arguments[0]);
return;
}
if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) {
invocationExpression.ReplaceWith(arguments[0]);
return;

3
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -179,7 +179,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -179,7 +179,8 @@ namespace ICSharpCode.Decompiler.CSharp
if (Expression is CastExpression cast
&& (type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion
|| type.Kind == TypeKind.Delegate && conversion.Conversion.IsAnonymousFunctionConversion
)) {
|| (conversion.Conversion.IsImplicit && (conversion.Conversion.IsUserDefined || targetType.IsKnownType(KnownTypeCode.Decimal)))
)) {
return this.UnwrapChild(cast.Expression);
} else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion
&& oce.Arguments.Count == 1 && expressionBuilder.settings.UseImplicitMethodGroupConversion) {

Loading…
Cancel
Save