Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 59 additions & 2 deletions src/libraries/Common/tests/System/FunctionPointerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,55 @@ public static unsafe void GenericFunctionPointer()
Assert.True(fcnPtr2.ContainsGenericParameters);
}

[Fact]
public static unsafe void FunctionPointerVisibility()
{
Type t = typeof(FunctionPointerHolder).Project();

// A function pointer with public return type should be visible
Type fnPtrPublicReturn = t.GetField(nameof(FunctionPointerHolder.Field_Int), Bindings)!.FieldType;
Assert.True(fnPtrPublicReturn.IsFunctionPointer);
Assert.True(fnPtrPublicReturn.IsVisible);

// A function pointer with public parameter types should be visible
Type fnPtrPublicParams = t.GetField(nameof(FunctionPointerHolder.Field_PublicParam), Bindings)!.FieldType;
Assert.True(fnPtrPublicParams.IsFunctionPointer);
Assert.True(fnPtrPublicParams.IsVisible);

// A function pointer with private return type should not be visible
Type fnPtrPrivateReturn = t.GetField("Field_PrivateReturn", Bindings)!.FieldType;
Assert.True(fnPtrPrivateReturn.IsFunctionPointer);
Assert.False(fnPtrPrivateReturn.IsVisible);

// A function pointer with private parameter type should not be visible
Type fnPtrPrivateParam = t.GetField("Field_PrivateParam", Bindings)!.FieldType;
Assert.True(fnPtrPrivateParam.IsFunctionPointer);
Assert.False(fnPtrPrivateParam.IsVisible);
}

[Fact]
public static unsafe void FunctionPointerContainsGenericParameters()
{
Type t = typeof(FunctionPointerHolder).Project();

// A function pointer with non-generic return type should not contain generic parameters
Type fnPtrNonGeneric = t.GetField(nameof(FunctionPointerHolder.Field_Int), Bindings)!.FieldType;
Assert.True(fnPtrNonGeneric.IsFunctionPointer);
Assert.False(fnPtrNonGeneric.ContainsGenericParameters);

// A function pointer with generic return type should contain generic parameters
MethodInfo m1 = t.GetMethod(nameof(FunctionPointerHolder.GenericReturnValue), Bindings)!;
Type fnPtrGenericReturn = m1.ReturnType;
Assert.True(fnPtrGenericReturn.IsFunctionPointer);
Assert.True(fnPtrGenericReturn.ContainsGenericParameters);

// A function pointer with generic parameter type should contain generic parameters
MethodInfo m2 = t.GetMethod(nameof(FunctionPointerHolder.GenericArgument), Bindings)!;
Type fnPtrGenericParam = m2.GetParameters()[1].ParameterType;
Assert.True(fnPtrGenericParam.IsFunctionPointer);
Assert.True(fnPtrGenericParam.ContainsGenericParameters);
}

[Theory]
[InlineData(nameof(FunctionPointerHolder.MethodReturnValue1),
"MethodReturnValue1()",
Expand Down Expand Up @@ -270,7 +319,9 @@ private static void VerifyFieldOrProperty(Type fnPtrType)

private unsafe class FunctionPointerHolder
{
#pragma warning disable 0649
// CS0649: Field is never assigned to (fields are used via reflection)
// CS0169: Field is never used (private fields are accessed via reflection)
#pragma warning disable 0649, 0169
public delegate*<void> ToString_1;
public delegate*unmanaged<void> ToString_2;
public delegate*<int> ToString_3;
Expand All @@ -283,7 +334,12 @@ private unsafe class FunctionPointerHolder

public delegate* managed<int> Field_Int;
public delegate* managed<MyClass> Field_MyClass;
#pragma warning restore 0649

// Fields for visibility tests
public delegate* managed<int, void> Field_PublicParam;
private delegate* managed<PrivateClass> Field_PrivateReturn;
private delegate* managed<PrivateClass, void> Field_PrivateParam;
#pragma warning restore 0649, 0169

public delegate* managed<int> Prop_Int { get; }
public delegate* managed<MyClass> Prop_MyClass { get; }
Expand All @@ -299,6 +355,7 @@ private unsafe class FunctionPointerHolder

public class MyClass { }
public struct MyStruct { }
private class PrivateClass { }
}
}
}
28 changes: 28 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Type.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public virtual bool ContainsGenericParameters
if (IsGenericParameter)
return true;

if (IsFunctionPointer)
{
if (GetFunctionPointerReturnType().ContainsGenericParameters)
return true;

foreach (Type parameterType in GetFunctionPointerParameterTypes())
{
if (parameterType.ContainsGenericParameters)
return true;
}

return false;
}

if (!IsGenericType)
return false;

Expand Down Expand Up @@ -88,6 +102,20 @@ public bool IsVisible
if (HasElementType)
return GetElementType()!.IsVisible;

if (IsFunctionPointer)
{
if (!GetFunctionPointerReturnType().IsVisible)
return false;

foreach (Type parameterType in GetFunctionPointerParameterTypes())
{
if (!parameterType.IsVisible)
return false;
}

return true;
}

Type type = this;
while (type.IsNested)
{
Expand Down
Loading