Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Type.IsPublic for pointer and byref types #65156

Merged
merged 11 commits into from
Feb 21, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public sealed override int MetadataToken
protected override TypeAttributes GetAttributeFlagsImpl()
{
Debug.Assert(IsByRef || IsPointer);
return TypeAttributes.AnsiClass;
return TypeAttributes.Public;
}

protected sealed override int InternalGetHashCode()
Expand Down
7 changes: 1 addition & 6 deletions src/coreclr/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,12 +807,7 @@ FCIMPL1(INT32, RuntimeTypeHandle::GetAttributes, ReflectClassBaseObject *pTypeUN
TypeHandle typeHandle = refType->GetType();

if (typeHandle.IsTypeDesc()) {

if (typeHandle.IsGenericVariable()) {
return tdPublic;
}

return 0;
return tdPublic;
}

#ifdef FEATURE_COMINTEROP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal RoByRefType(RoType elementType)

public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);

protected sealed override TypeAttributes ComputeAttributeFlags() => TypeAttributes.AnsiClass;
protected sealed override TypeAttributes ComputeAttributeFlags() => TypeAttributes.Public;
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved

protected sealed override string Suffix => "&";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal RoPointerType(RoType elementType)

public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);

protected sealed override TypeAttributes ComputeAttributeFlags() => TypeAttributes.AnsiClass;
protected sealed override TypeAttributes ComputeAttributeFlags() => TypeAttributes.Public;

protected sealed override string Suffix => "*";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,4 +553,9 @@ public class ClassWithDefaultMember1<T> where T : ClassWithDefaultMember1<T>
{
public int Yes;
}

public class PublicClass
{
internal class InternalNestedClass { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,36 @@ public static void TestIsValueType()
return;
}

public static IEnumerable<object[]> ByRefPonterTypes_IsPublicIsVisible_TestData()
{
yield return new object[] { typeof(int).Project().MakeByRefType(), true, true };
yield return new object[] { typeof(int).Project().MakePointerType(), true, true };
yield return new object[] { typeof(int).Project(), true, true };
yield return new object[] { typeof(SampleMetadata.PublicClass.InternalNestedClass).Project().MakeByRefType(), true, false };
yield return new object[] { typeof(SampleMetadata.PublicClass.InternalNestedClass).Project().MakePointerType(), true, false };
yield return new object[] { typeof(SampleMetadata.PublicClass.InternalNestedClass).Project(), false, false };
yield return new object[] { typeof(SampleMetadata.PublicClass).Project().MakeByRefType(), true, true };
yield return new object[] { typeof(SampleMetadata.PublicClass).Project().MakePointerType(), true, true };
yield return new object[] { typeof(SampleMetadata.PublicClass).Project(), true, true };
}

[Theory]
[MemberData(nameof(ByRefPonterTypes_IsPublicIsVisible_TestData))]
public static void ByRefPonterTypes_IsPublicIsVisible(Type type, bool isPublic, bool isVisible)
{
Assert.Equal(isPublic, type.IsPublic);
Assert.Equal(!isPublic, type.IsNestedAssembly);
Assert.Equal(isVisible, type.IsVisible);
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/11354")]
public static void FunctionPointerTypeIsPublic()
{
Assert.True(typeof(delegate*<string, int>).Project().IsPublic);
Assert.True(typeof(delegate*<string, int>).Project().MakePointerType().IsPublic);
}

[Fact]
public static void TestMethodSelection1()
{
Expand Down
48 changes: 48 additions & 0 deletions src/libraries/System.Reflection/tests/TypeInfoTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,54 @@ public void MakePointerType(Type type)
Assert.True(pointerType.IsPointer);
}

public static IEnumerable<object[]> ByRefPonterTypes_IsPublicIsVisible_TestData()
{
yield return new object[] { typeof(int).MakeByRefType(), true, true };
yield return new object[] { typeof(int).MakePointerType(), true, true };
yield return new object[] { typeof(List<int>), true, true };
yield return new object[] { typeof(int), true, true };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass).MakeByRefType(), true, false };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass).MakePointerType(), true, false };
yield return new object[] { typeof(List<TI_BaseClass.InternalNestedClass>), true, false };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass), false, false };
yield return new object[] { typeof(TI_BaseClass).MakeByRefType(), true, true };
yield return new object[] { typeof(TI_BaseClass).MakePointerType(), true, true };
yield return new object[] { typeof(List<TI_BaseClass>), true, true };
}

[Theory]
[MemberData(nameof(ByRefPonterTypes_IsPublicIsVisible_TestData))]
public void ByRefPonterTypesTypes_IsPublicIsVisible(Type type, bool isPublic, bool isVisible)
{
Assert.Equal(isPublic, type.IsPublic);
Assert.Equal(!isPublic, type.IsNestedAssembly);
Assert.Equal(isVisible, type.IsVisible);
}

public delegate void PublicDelegate(string str);
internal delegate void InternalDelegate(string str);

[Fact]
public void DelegateTypesIsPublic()
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
Assert.True(typeof(Delegate).IsPublic);
Assert.False(typeof(Delegate).IsNotPublic);
Assert.True(typeof(PublicDelegate).IsNestedPublic);
Assert.True(typeof(InternalDelegate).IsNestedAssembly);
Assert.False(typeof(InternalDelegate).IsPublic);
Assert.False(typeof(InternalDelegate).MakePointerType().IsNestedAssembly);
Assert.True(typeof(InternalDelegate).MakePointerType().IsPublic);
Assert.True(typeof(Delegate).MakePointerType().IsPublic);
Assert.False(typeof(Delegate).MakePointerType().IsNotPublic);
}

[Fact]
public void FunctionPointerTypeIsPublic()
{
Assert.True(typeof(delegate*<string, int>).IsPublic);
Assert.True(typeof(delegate*<string, int>).MakePointerType().IsPublic);
}

[Fact]
public void MakePointerType_TypeAlreadyByRef_ThrowsTypeLoadException()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ public class IntPointerTests : TypePropertyTestBase
{
public override Type CreateType() => typeof(int).MakePointerType();

public override TypeAttributes Attributes => TypeAttributes.Class;
public override TypeAttributes Attributes => TypeAttributes.Public;

public override Type BaseType => null;

Expand All @@ -689,7 +689,7 @@ public class IntRefTests : TypePropertyTestBase
{
public override Type CreateType() => typeof(int).MakeByRefType();

public override TypeAttributes Attributes => TypeAttributes.Class;
public override TypeAttributes Attributes => TypeAttributes.Public;

public override Type BaseType => null;

Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1803,7 +1803,7 @@ ves_icall_RuntimeTypeHandle_GetAttributes (MonoQCallTypeHandle type_handle)
MonoType *type = type_handle.type;

if (m_type_is_byref (type) || type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR)
return TYPE_ATTRIBUTE_NOT_PUBLIC;
return TYPE_ATTRIBUTE_PUBLIC;
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved

MonoClass *klass = mono_class_from_mono_type_internal (type);
return mono_class_get_flags (klass);
Expand Down