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
10 changes: 2 additions & 8 deletions src/coreclr/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,14 +806,8 @@ FCIMPL1(INT32, RuntimeTypeHandle::GetAttributes, ReflectClassBaseObject *pTypeUN

TypeHandle typeHandle = refType->GetType();

if (typeHandle.IsTypeDesc()) {

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

return 0;
}
if (typeHandle.IsTypeDesc())
return typeHandle.GetElementTypeAttributes();

#ifdef FEATURE_COMINTEROP
// __ComObject types are always public.
Expand Down
21 changes: 21 additions & 0 deletions src/coreclr/vm/typehandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,27 @@ TypeHandle TypeHandle::GetTypeParam() const
return TypeHandle();
}

// Obtain attributes of the element type from a byref or pointer type, returns tdPublic for generic type variables, 0 otherwise
INT32 TypeHandle::GetElementTypeAttributes() const
{
LIMITED_METHOD_DAC_CONTRACT;

if (IsGenericVariable())
return tdPublic;

if (IsPointer() || IsByRef()) {
_ASSERTE(HasTypeParam());
TypeHandle elementType = GetTypeParam();
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved

if (elementType.IsTypeDesc())
return elementType.GetElementTypeAttributes();

return (INT32)elementType.GetMethodTable()->GetAttrClass();
}

return 0;
}

#ifndef DACCESS_COMPILE
TypeHandle TypeHandle::Instantiate(Instantiation inst) const
{
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/typehandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ class TypeHandle
// Obtain element type for an array, byref or pointer, returning NULL otherwise
TypeHandle GetTypeParam() const;

// Obtain attributes of the element type from a byref or pointer type, returns tdPublic for generic type variables, 0 otherwise
INT32 GetElementTypeAttributes() const;

// Obtain instantiation from an instantiated type
// NULL if not instantiated
Instantiation GetInstantiation() const;
Expand Down
55 changes: 55 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,60 @@ public void MakePointerType(Type type)
Assert.True(pointerType.IsPointer);
}

public static IEnumerable<object[]> TypeDescTypesIsPublic_TestData()
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
yield return new object[] { typeof(int).MakeByRefType(), true };
yield return new object[] { typeof(int).MakePointerType(), true };
yield return new object[] { typeof(int).MakeArrayType(), true };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass).MakeByRefType(), false };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass).MakePointerType(), false };
yield return new object[] { typeof(TI_BaseClass.InternalNestedClass).MakeArrayType(), true };
yield return new object[] { typeof(TI_BaseClass.InternalNestedGenericClass<>).MakeGenericType(typeof(string)), false };
yield return new object[] { typeof(TI_BaseClass).MakeByRefType(), true };
yield return new object[] { typeof(TI_BaseClass).MakePointerType(), true };
yield return new object[] { typeof(TI_BaseClass).MakeArrayType(), true };
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}

[Theory]
[MemberData(nameof(TypeDescTypesIsPublic_TestData))]
public void TypeDescTypesIsPublic(Type type, bool expected)
{
Assert.Equal(expected, type.IsPublic);
Assert.Equal(!expected, type.IsNestedAssembly);
}

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.True(typeof(InternalDelegate).MakePointerType().IsNestedAssembly);
Assert.False(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 NestedPointerIsPublic()
{
Type pointerType = typeof(int***);
Assert.True(pointerType.IsPointer);
Assert.True(pointerType.IsPublic);
}

[Fact]
public void MakePointerType_TypeAlreadyByRef_ThrowsTypeLoadException()
{
Expand Down Expand Up @@ -1828,6 +1882,7 @@ public class PublicNestedClass1 { }
public class PublicNestedClass2 { }
private class PrivateNestedClass { } // Private, so not inherited
internal class InternalNestedClass { } // Internal members are not inherited
internal class InternalNestedGenericClass<T>{ }
protected class ProtectedNestedClass { }

public string StringProperty1 { get { return ""; } set { } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,8 @@ public class IntPointerTests : TypePropertyTestBase
{
public override Type CreateType() => typeof(int).MakePointerType();

public override TypeAttributes Attributes => TypeAttributes.Class;
public override TypeAttributes Attributes => PlatformDetection.IsMonoRuntime ? TypeAttributes.Public :
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.Serializable | TypeAttributes.BeforeFieldInit;

public override Type BaseType => null;

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

public override TypeAttributes Attributes => TypeAttributes.Class;
public override TypeAttributes Attributes => TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.Serializable | TypeAttributes.BeforeFieldInit;

public override Type BaseType => null;

Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1802,8 +1802,8 @@ 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;
if (type->type == MONO_TYPE_FNPTR)
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