Browse Source

Fix reference comparisons on strings.

pull/987/head
Daniel Grunwald 9 years ago
parent
commit
73420102a6
  1. 15
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  2. 62
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il
  3. 44
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il
  4. 40
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il
  5. 58
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il
  6. 23
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

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

@ -215,6 +215,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -215,6 +215,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return a == null;
}
public bool CompareStringsByValue(string a, string b)
{
return a == b;
}
public bool CompareStringsByReference(string a, string b)
{
return (object)a == b;
}
public bool CompareStringWithNull(string a)
{
return a == null;
}
public decimal ImplicitConversionToDecimal(byte v)
{
return v;

62
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 t2movxx2
.assembly fpugcpej
{
.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 t2movxx2.dll
// MVID: {F28F6C6C-94AA-4D5E-B9EE-907881B3E7E4}
.module fpugcpej.dll
// MVID: {F42443CE-6C18-4149-B04E-77437B350B2C}
.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: 0x00690000
// Image base: 0x01650000
// =============== CLASS MEMBERS DECLARATION ===================
@ -735,6 +735,60 @@ @@ -735,6 +735,60 @@
IL_0009: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance bool
CompareStringsByValue(string a,
string b) cil managed
{
// Code size 13 (0xd)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0008: stloc.0
IL_0009: br.s IL_000b
IL_000b: ldloc.0
IL_000c: ret
} // end of method TypeAnalysisTests::CompareStringsByValue
.method public hidebysig instance bool
CompareStringsByReference(string a,
string b) cil managed
{
// Code size 10 (0xa)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ceq
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
} // end of method TypeAnalysisTests::CompareStringsByReference
.method public hidebysig instance bool
CompareStringWithNull(string a) cil managed
{
// Code size 10 (0xa)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldnull
IL_0003: ceq
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
} // end of method TypeAnalysisTests::CompareStringWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{

44
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 '0nmkvdgs'
.assembly '31uigzt1'
{
.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 '0nmkvdgs.dll'
// MVID: {E543BCF9-C441-4A6D-A25F-19C170B765C0}
.module '31uigzt1.dll'
// MVID: {77B7D9D4-A6DF-4CC8-B1E3-7B3B553633FF}
.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: 0x00C50000
// Image base: 0x01360000
// =============== CLASS MEMBERS DECLARATION ===================
@ -510,6 +510,42 @@ @@ -510,6 +510,42 @@
IL_0004: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance bool
CompareStringsByValue(string a,
string b) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0007: ret
} // end of method TypeAnalysisTests::CompareStringsByValue
.method public hidebysig instance bool
CompareStringsByReference(string a,
string b) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: ret
} // end of method TypeAnalysisTests::CompareStringsByReference
.method public hidebysig instance bool
CompareStringWithNull(string a) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldnull
IL_0002: ceq
IL_0004: ret
} // end of method TypeAnalysisTests::CompareStringWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{

40
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: {7D2FE161-359E-42EC-B423-26BEB23F890D}
// MVID: {6215C6B8-0FF3-4C9E-999F-BE9720986F05}
.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: 0x01730000
// Image base: 0x03030000
// =============== CLASS MEMBERS DECLARATION ===================
@ -512,6 +512,42 @@ @@ -512,6 +512,42 @@
IL_0004: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance bool
CompareStringsByValue(string a,
string b) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0007: ret
} // end of method TypeAnalysisTests::CompareStringsByValue
.method public hidebysig instance bool
CompareStringsByReference(string a,
string b) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: ret
} // end of method TypeAnalysisTests::CompareStringsByReference
.method public hidebysig instance bool
CompareStringWithNull(string a) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldnull
IL_0002: ceq
IL_0004: ret
} // end of method TypeAnalysisTests::CompareStringWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{

58
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: {6A008C4E-2BC5-45CA-93FB-93A12CD0BC69}
// MVID: {3A10F4E7-88B8-4945-8775-A3643132F64B}
.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: 0x01320000
// Image base: 0x01720000
// =============== CLASS MEMBERS DECLARATION ===================
@ -734,6 +734,60 @@ @@ -734,6 +734,60 @@
IL_0009: ret
} // end of method TypeAnalysisTests::CompareDelegateWithNull
.method public hidebysig instance bool
CompareStringsByValue(string a,
string b) cil managed
{
// Code size 13 (0xd)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0008: stloc.0
IL_0009: br.s IL_000b
IL_000b: ldloc.0
IL_000c: ret
} // end of method TypeAnalysisTests::CompareStringsByValue
.method public hidebysig instance bool
CompareStringsByReference(string a,
string b) cil managed
{
// Code size 10 (0xa)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ceq
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
} // end of method TypeAnalysisTests::CompareStringsByReference
.method public hidebysig instance bool
CompareStringWithNull(string a) cil managed
{
// Code size 10 (0xa)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldnull
IL_0003: ceq
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
} // end of method TypeAnalysisTests::CompareStringWithNull
.method public hidebysig instance valuetype [mscorlib]System.Decimal
ImplicitConversionToDecimal(uint8 v) cil managed
{

23
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -527,17 +527,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -527,17 +527,20 @@ namespace ICSharpCode.Decompiler.CSharp
left = AdjustConstantExpressionToType(left, right.Type);
right = AdjustConstantExpressionToType(right, left.Type);
if (left.Type.Kind == TypeKind.Delegate && right.Type.Kind == TypeKind.Null
|| left.Type.Kind == TypeKind.Null && right.Type.Kind == TypeKind.Delegate)
{
// When comparing a delegate with null, the C# compiler generates a reference comparison.
if (IsSpecialCasedReferenceComparisonWithNull(left, right)) {
// When comparing a string/delegate with null, the C# compiler generates a reference comparison.
negateOutput = false;
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
}
var rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult)
as OperatorResolveResult;
OperatorResolveResult rr;
if (left.Type.IsKnownType(KnownTypeCode.String) && right.Type.IsKnownType(KnownTypeCode.String)) {
rr = null; // it's a string comparison by-value, which is not a reference comparison
} else {
rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult)
as OperatorResolveResult;
}
if (rr == null || rr.IsError || rr.UserDefinedOperatorMethod != null
|| NullableType.GetUnderlyingType(rr.Operands[0].Type).GetStackType() != inst.InputType)
{
@ -583,6 +586,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -583,6 +586,14 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(rr);
}
bool IsSpecialCasedReferenceComparisonWithNull(TranslatedExpression lhs, TranslatedExpression rhs)
{
if (lhs.Type.Kind == TypeKind.Null)
ExtensionMethods.Swap(ref lhs, ref rhs);
return rhs.Type.Kind == TypeKind.Null
&& (lhs.Type.Kind == TypeKind.Delegate || lhs.Type.IsKnownType(KnownTypeCode.String));
}
ExpressionWithResolveResult CreateBuiltinBinaryOperator(
TranslatedExpression left, BinaryOperatorType type, TranslatedExpression right,
bool checkForOverflow = false)

Loading…
Cancel
Save