Browse Source

Fix deactivated Generics pretty tests: remove redundant boxing conversion from is-expressions.

pull/1440/head
Siegfried Pammer 7 years ago
parent
commit
54ff546221
  1. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs
  2. 54
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.il
  3. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.il
  4. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il
  5. 54
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il
  6. 5
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  7. 4
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

8
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs

@ -198,12 +198,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -198,12 +198,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return d.Keys.GetEnumerator();
}
#if false
public static bool IsString<T>(T input)
{
return input is string;
}
#endif
public static string AsString<T>(T input)
{
@ -220,12 +218,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -220,12 +218,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return (T)(object)input;
}
#if false
public static bool IsInt<T>(T input)
{
return input is int;
}
#endif
public static int CastToInt<T>(T input)
{
@ -236,12 +232,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -236,12 +232,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return (T)(object)input;
}
#if false
public static bool IsNullableInt<T>(T input)
{
return input is int?;
}
#endif
public static int? AsNullableInt<T>(T input)
{
return input as int?;

54
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.il

@ -581,6 +581,24 @@ @@ -581,6 +581,24 @@
IL_0010: ret
} // end of method Generics::GetEnumerator
.method public hidebysig static bool IsString<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst [mscorlib]System.String
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsString
.method public hidebysig static string
AsString<T>(!!T input) cil managed
{
@ -630,6 +648,24 @@ @@ -630,6 +648,24 @@
IL_000b: ret
} // end of method Generics::CastFromString
.method public hidebysig static bool IsInt<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst [mscorlib]System.Int32
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsInt
.method public hidebysig static int32 CastToInt<T>(!!T input) cil managed
{
// Code size 17 (0x11)
@ -662,6 +698,24 @@ @@ -662,6 +698,24 @@
IL_0010: ret
} // end of method Generics::CastFromInt
.method public hidebysig static bool IsNullableInt<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst valuetype [mscorlib]System.Nullable`1<int32>
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsNullableInt
.method public hidebysig static valuetype [mscorlib]System.Nullable`1<int32>
AsNullableInt<T>(!!T input) cil managed
{

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.il

@ -478,6 +478,18 @@ @@ -478,6 +478,18 @@
IL_000b: ret
} // end of method Generics::GetEnumerator
.method public hidebysig static bool IsString<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst [mscorlib]System.String
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsString
.method public hidebysig static string
AsString<T>(!!T input) cil managed
{
@ -509,6 +521,18 @@ @@ -509,6 +521,18 @@
IL_0006: ret
} // end of method Generics::CastFromString
.method public hidebysig static bool IsInt<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst [mscorlib]System.Int32
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsInt
.method public hidebysig static int32 CastToInt<T>(!!T input) cil managed
{
// Code size 12 (0xc)
@ -529,6 +553,18 @@ @@ -529,6 +553,18 @@
IL_000b: ret
} // end of method Generics::CastFromInt
.method public hidebysig static bool IsNullableInt<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst valuetype [mscorlib]System.Nullable`1<int32>
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsNullableInt
.method public hidebysig static valuetype [mscorlib]System.Nullable`1<int32>
AsNullableInt<T>(!!T input) cil managed
{

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il

@ -466,6 +466,18 @@ @@ -466,6 +466,18 @@
IL_000b: ret
} // end of method Generics::GetEnumerator
.method public hidebysig static bool IsString<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst [mscorlib]System.String
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsString
.method public hidebysig static string
AsString<T>(!!T input) cil managed
{
@ -497,6 +509,18 @@ @@ -497,6 +509,18 @@
IL_0006: ret
} // end of method Generics::CastFromString
.method public hidebysig static bool IsInt<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst [mscorlib]System.Int32
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsInt
.method public hidebysig static int32 CastToInt<T>(!!T input) cil managed
{
// Code size 12 (0xc)
@ -517,6 +541,18 @@ @@ -517,6 +541,18 @@
IL_000b: ret
} // end of method Generics::CastFromInt
.method public hidebysig static bool IsNullableInt<T>(!!T input) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: isinst valuetype [mscorlib]System.Nullable`1<int32>
IL_000b: ldnull
IL_000c: cgt.un
IL_000e: ret
} // end of method Generics::IsNullableInt
.method public hidebysig static valuetype [mscorlib]System.Nullable`1<int32>
AsNullableInt<T>(!!T input) cil managed
{

54
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il

@ -576,6 +576,24 @@ @@ -576,6 +576,24 @@
IL_0010: ret
} // end of method Generics::GetEnumerator
.method public hidebysig static bool IsString<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst [mscorlib]System.String
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsString
.method public hidebysig static string
AsString<T>(!!T input) cil managed
{
@ -625,6 +643,24 @@ @@ -625,6 +643,24 @@
IL_000b: ret
} // end of method Generics::CastFromString
.method public hidebysig static bool IsInt<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst [mscorlib]System.Int32
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsInt
.method public hidebysig static int32 CastToInt<T>(!!T input) cil managed
{
// Code size 17 (0x11)
@ -657,6 +693,24 @@ @@ -657,6 +693,24 @@
IL_0010: ret
} // end of method Generics::CastFromInt
.method public hidebysig static bool IsNullableInt<T>(!!T input) cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: isinst valuetype [mscorlib]System.Nullable`1<int32>
IL_000c: ldnull
IL_000d: cgt.un
IL_000f: stloc.0
IL_0010: br.s IL_0012
IL_0012: ldloc.0
IL_0013: ret
} // end of method Generics::IsNullableInt
.method public hidebysig static valuetype [mscorlib]System.Nullable`1<int32>
AsNullableInt<T>(!!T input) cil managed
{

5
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -257,6 +257,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -257,6 +257,7 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression IsType(IsInst inst)
{
var arg = Translate(inst.Argument);
arg = UnwrapBoxingConversion(arg);
return new IsExpression(arg.Expression, ConvertType(inst.Type))
.WithILInstruction(inst)
.WithRR(new TypeIsResolveResult(arg.ResolveResult, inst.Type, compilation.FindType(TypeCode.Boolean)));
@ -265,6 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -265,6 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitIsInst(IsInst inst, TranslationContext context)
{
var arg = Translate(inst.Argument);
arg = UnwrapBoxingConversion(arg);
if (inst.Type.IsReferenceType == false) {
// isinst with a value type results in an expression of "boxed value type",
// which is not supported in C#.
@ -284,7 +286,6 @@ namespace ICSharpCode.Decompiler.CSharp @@ -284,7 +286,6 @@ namespace ICSharpCode.Decompiler.CSharp
return ErrorExpression("isinst with value type is only supported in some contexts");
}
}
arg = UnwrapBoxingConversion(arg);
return new AsExpression(arg.Expression, ConvertType(inst.Type))
.WithILInstruction(inst)
.WithRR(new ConversionResolveResult(inst.Type, arg.ResolveResult, Conversion.TryCast));
@ -296,7 +297,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -296,7 +297,7 @@ namespace ICSharpCode.Decompiler.CSharp
&& arg.Type.IsKnownType(KnownTypeCode.Object)
&& arg.ResolveResult is ConversionResolveResult crr
&& crr.Conversion.IsBoxingConversion) {
// When 'as' used with value type or type parameter,
// When 'is' or 'as' is used with a value type or type parameter,
// the C# compiler implicitly boxes the input.
arg = arg.UnwrapChild(cast.Expression);
}

4
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -72,9 +72,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -72,9 +72,11 @@ namespace ICSharpCode.Decompiler.CSharp
// (even for value types) by using "is" instead of "as"
// This can happen when the result of "expr is T" is unused
// and the C# compiler optimizes away the null check portion of the "is" operator.
var arg = exprBuilder.Translate(inst.Argument);
arg = ExpressionBuilder.UnwrapBoxingConversion(arg);
return new ExpressionStatement(
new IsExpression(
exprBuilder.Translate(inst.Argument),
arg,
exprBuilder.ConvertType(inst.Type)
)
.WithRR(new ResolveResult(exprBuilder.compilation.FindType(KnownTypeCode.Boolean)))

Loading…
Cancel
Save