Browse Source

Fix some type inference issues with pointer types.

pull/2150/head
Daniel Grunwald 5 years ago
parent
commit
b8796908f6
  1. 43
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
  2. 7
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  4. 48
      ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs
  5. 4
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

43
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using System.Text;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
@ -25,6 +26,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -25,6 +26,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return (delegate*<int, void>)(&Overloaded);
}
public static string VarianceTest(object o)
{
return null;
}
public unsafe delegate*<StringBuilder, object> Variance()
{
return (delegate*<object, string>)(&VarianceTest);
}
#if TODO
public unsafe delegate*<void> AddressOfLocalFunction()
{
return &LocalFunction;
static void LocalFunction()
{
}
}
#endif
}
internal class FunctionPointersWithDynamicTypes
@ -94,4 +117,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -94,4 +117,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// public delegate* unmanaged[Cdecl]<void> cdecl;
//}
internal class FunctionPointerTypeInference
{
private static char Test(int i)
{
return (char)i;
}
public unsafe R GenericMethod<T, R>(delegate*<T, R> f, T arg)
{
return f(arg);
}
public unsafe void Call()
{
delegate*<int, char> f = &Test;
GenericMethod(f, 0);
GenericMethod((delegate*<int, char>)(&Test), 1);
GenericMethod<int, char>(null, 2);
}
}
}

7
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -180,6 +180,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -180,6 +180,13 @@ namespace ICSharpCode.Decompiler.CSharp
CollectNamespacesForTypeReference(elementType);
}
break;
case FunctionPointerType fnPtrType:
CollectNamespacesForTypeReference(fnPtrType.ReturnType);
foreach (var paramType in fnPtrType.ParameterTypes)
{
CollectNamespacesForTypeReference(paramType);
}
break;
default:
namespaces.Add(type.Namespace);
break;

21
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -874,6 +874,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -874,6 +874,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return true;
if (fromType.Kind == TypeKind.Null && toType.Kind.IsAnyPointer())
return true;
if (fromType is FunctionPointerType fromFnPtr && toType is FunctionPointerType toFnPtr
&& fromFnPtr.CallingConvention == toFnPtr.CallingConvention
&& fromFnPtr.ParameterTypes.Length == toFnPtr.ParameterTypes.Length)
{
// Variance applies to function pointer types
const int nestingDepth = 0;
if (!(IdentityConversion(fromFnPtr.ReturnType, toFnPtr.ReturnType)
|| ImplicitReferenceConversion(fromFnPtr.ReturnType, toFnPtr.ReturnType, nestingDepth)))
{
return false;
}
foreach (var (fromPT, toPT) in fromFnPtr.ParameterTypes.Zip(toFnPtr.ParameterTypes))
{
if (!(IdentityConversion(toPT, fromPT)
|| ImplicitReferenceConversion(toPT, fromPT, nestingDepth)))
{
return false;
}
}
return true;
}
return false;
}

48
ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs

@ -676,6 +676,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -676,6 +676,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i));
}
Log.Unindent();
return;
}
// Handle pointer types:
if (U is PointerType ptrU && V is PointerType ptrV)
{
MakeExactInference(ptrU.ElementType, ptrV.ElementType);
return;
}
if (U is FunctionPointerType fnPtrU && V is FunctionPointerType fnPtrV)
{
MakeExactInference(fnPtrU.ReturnType, fnPtrV.ReturnType);
foreach (var (ptU, ptV) in fnPtrU.ParameterTypes.Zip(fnPtrV.ParameterTypes))
{
MakeExactInference(ptU, ptV);
}
return;
}
}
@ -792,6 +808,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -792,6 +808,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
Log.Unindent();
return;
}
// Handle pointer types:
if (U is PointerType ptrU && V is PointerType ptrV)
{
MakeExactInference(ptrU.ElementType, ptrV.ElementType);
return;
}
if (U is FunctionPointerType fnPtrU && V is FunctionPointerType fnPtrV)
{
MakeLowerBoundInference(fnPtrU.ReturnType, fnPtrV.ReturnType);
foreach (var (ptU, ptV) in fnPtrU.ParameterTypes.Zip(fnPtrV.ParameterTypes))
{
MakeUpperBoundInference(ptU, ptV);
}
return;
}
}
@ -897,6 +929,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -897,6 +929,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
Log.Unindent();
return;
}
// Handle pointer types:
if (U is PointerType ptrU && V is PointerType ptrV)
{
MakeExactInference(ptrU.ElementType, ptrV.ElementType);
return;
}
if (U is FunctionPointerType fnPtrU && V is FunctionPointerType fnPtrV)
{
MakeUpperBoundInference(fnPtrU.ReturnType, fnPtrV.ReturnType);
foreach (var (ptU, ptV) in fnPtrU.ParameterTypes.Zip(fnPtrV.ParameterTypes))
{
MakeLowerBoundInference(ptU, ptV);
}
return;
}
}
#endregion

4
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -535,11 +535,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -535,11 +535,11 @@ namespace ICSharpCode.Decompiler.CSharp
{
return new NullReferenceExpression()
.WithILInstruction(this.ILInstructions)
.WithRR(new ConstantResolveResult(targetType, null));
.WithRR(new ConstantResolveResult(SpecialType.NullType, null));
}
return new CastExpression(expressionBuilder.ConvertType(targetType), new NullReferenceExpression())
.WithILInstruction(this.ILInstructions)
.WithRR(new ConstantResolveResult(targetType, null));
.WithRR(new ConstantResolveResult(SpecialType.NullType, null));
}
if (allowImplicitConversion)
{

Loading…
Cancel
Save