Browse Source

Fix some type inference issues with pointer types.

pull/2150/head
Daniel Grunwald 6 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 @@
using System; using System;
using System.Text;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
@ -25,6 +26,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return (delegate*<int, void>)(&Overloaded); 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 internal class FunctionPointersWithDynamicTypes
@ -94,4 +117,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// public delegate* unmanaged[Cdecl]<void> cdecl; // 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
CollectNamespacesForTypeReference(elementType); CollectNamespacesForTypeReference(elementType);
} }
break; break;
case FunctionPointerType fnPtrType:
CollectNamespacesForTypeReference(fnPtrType.ReturnType);
foreach (var paramType in fnPtrType.ParameterTypes)
{
CollectNamespacesForTypeReference(paramType);
}
break;
default: default:
namespaces.Add(type.Namespace); namespaces.Add(type.Namespace);
break; break;

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

@ -874,6 +874,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return true; return true;
if (fromType.Kind == TypeKind.Null && toType.Kind.IsAnyPointer()) if (fromType.Kind == TypeKind.Null && toType.Kind.IsAnyPointer())
return true; 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; return false;
} }

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

@ -676,6 +676,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i)); MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i));
} }
Log.Unindent(); 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
} }
} }
Log.Unindent(); 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
} }
} }
Log.Unindent(); 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 #endregion

4
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

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

Loading…
Cancel
Save