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
20 changes: 20 additions & 0 deletions src/coreclr/vm/typehandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,26 @@ 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()) {
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
31 changes: 31 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,36 @@ 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);
}

[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 +1858,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