Browse Source

Merge branch '5.0.x' of https://github.com/icsharpcode/ILSpy

pull/1790/head
Siegfried Pammer 7 years ago
parent
commit
e52ac90cfc
  1. 32
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  2. 34
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  3. 3
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  4. 21
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

32
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
ConstructorTest(); ConstructorTest();
TestIndexer(); TestIndexer();
Issue1281(); Issue1281();
Issue1747();
} }
#region ConstructorTest #region ConstructorTest
@ -203,6 +204,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
} }
#endregion #endregion
#region NullableValueTypes
private static void Issue1747()
{
Console.WriteLine("Issue1747:");
M1747(null);
M1747(true);
M1747(false);
M1747((bool?)true);
M1747((bool?)false);
Console.WriteLine("Issue1747, non-constant:");
bool b = Get<bool>();
M1747(b);
M1747((bool?)b);
}
private static void M1747(bool b)
{
Console.WriteLine("bool=" + b);
}
private static void M1747(bool? b)
{
Console.WriteLine("bool?=" + b);
}
static T Get<T>()
{
return default(T);
}
#endregion
#region IndexerTests #region IndexerTests
static void TestIndexer() static void TestIndexer()
{ {

34
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -151,6 +151,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
void M3(); void M3();
} }
public class BaseClass : IM3 public class BaseClass : IM3
{ {
protected virtual void M1() protected virtual void M1()
@ -163,6 +164,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
} }
} }
public class SubClass : BaseClass public class SubClass : BaseClass
{ {
protected override void M2() protected override void M2()
@ -193,6 +195,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Noop("M3", M3); Noop("M3", M3);
#endif #endif
} }
public void Test2() public void Test2()
{ {
Noop("M3.new", new BaseClass().M3); Noop("M3.new", new BaseClass().M3);
@ -204,6 +207,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
} }
public class GenericTest<TNonCaptured, TCaptured>
{
public Func<TCaptured> GetFunc(Func<TNonCaptured, TCaptured> f)
{
TCaptured captured = f(default(TNonCaptured));
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
public Func<TNonCaptured, TNonCapturedMP, TCaptured> GetFunc<TNonCapturedMP>(Func<TCaptured> f)
{
TCaptured captured = f();
return delegate(TNonCaptured a, TNonCapturedMP d) {
Console.WriteLine(a.GetHashCode());
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
}
public static Func<string, string, bool> test0 = (string a, string b) => string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b); public static Func<string, string, bool> test0 = (string a, string b) => string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b);
public static Func<string, string, bool> test1 = (string a, string b) => string.IsNullOrEmpty(a) || !string.IsNullOrEmpty(b); public static Func<string, string, bool> test1 = (string a, string b) => string.IsNullOrEmpty(a) || !string.IsNullOrEmpty(b);
public static Func<string, string, bool> test2 = (string a, string b) => !string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b); public static Func<string, string, bool> test2 = (string a, string b) => !string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b);
@ -342,5 +367,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return (int b) => (int c) => (int d) => a + b + c + d; return (int b) => (int c) => (int d) => a + b + c + d;
} }
public static Func<TCaptured> CapturedTypeParameter1<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, TCaptured> f)
{
TCaptured captured = f(a);
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
} }
} }

3
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -285,7 +285,8 @@ namespace ICSharpCode.Decompiler.CSharp
} }
IType utype = NullableType.GetUnderlyingType(type); IType utype = NullableType.GetUnderlyingType(type);
IType targetUType = NullableType.GetUnderlyingType(targetType); IType targetUType = NullableType.GetUnderlyingType(targetType);
if (type.IsKnownType(KnownTypeCode.Boolean) && targetUType.GetStackType().IsIntegerType()) { if (type.IsKnownType(KnownTypeCode.Boolean) && !targetUType.IsKnownType(KnownTypeCode.Boolean)
&& targetUType.GetStackType().IsIntegerType()) {
// convert from boolean to integer (or enum) // convert from boolean to integer (or enum)
return new ConditionalExpression( return new ConditionalExpression(
this.Expression, this.Expression,

21
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -57,9 +57,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Inner functions are transformed before outer functions // Inner functions are transformed before outer functions
foreach (var f in function.Descendants.OfType<ILFunction>()) { foreach (var f in function.Descendants.OfType<ILFunction>()) {
foreach (var v in f.Variables.ToArray()) { foreach (var v in f.Variables.ToArray()) {
if (HandleMonoStateMachine(function, v, decompilationContext, f)) if (context.Settings.YieldReturn && HandleMonoStateMachine(function, v, decompilationContext, f))
continue; continue;
if (IsClosure(v, out ITypeDefinition closureType, out var inst)) { if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(v, out ITypeDefinition closureType, out var inst)) {
AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false); AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false);
} }
if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) { if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) {
@ -354,7 +354,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.Step($"Introduce captured variable for {field.FullName}", inst); context.Step($"Introduce captured variable for {field.FullName}", inst);
// Introduce a fresh variable for the display class field. // Introduce a fresh variable for the display class field.
Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition); Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition);
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, field.Type, field.Name); v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name);
v.HasInitialValue = true; v.HasInitialValue = true;
v.CaptureScope = displayClass.CaptureScope; v.CaptureScope = displayClass.CaptureScope;
inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
@ -364,5 +364,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
} }
} }
private IType GetVariableTypeFromClosureField(IField field)
{
if (!(field.Type is ITypeParameter typeParameter))
return field.Type;
var rootMethod = context.Function.Method;
if (typeParameter.Owner != field.DeclaringTypeDefinition)
return field.Type;
if (typeParameter.Index >= rootMethod.TypeParameters.Count) {
Debug.Assert(false, "Cannot map display-class type parameter to method type parameter");
return field.Type;
}
return rootMethod.TypeParameters[typeParameter.Index];
}
} }
} }

Loading…
Cancel
Save