Skip to content

Commit

Permalink
Add tests for UnsafeAccessor on fields on generic types (#92657)
Browse files Browse the repository at this point in the history
* Add tests for field access on generics

The tests are currently disabled.

* Fix ILC to compile UnsafeAccessorsTests

UnsafeAccessorsTests passes on NAOT.
  • Loading branch information
AaronRobinsonMSFT committed Sep 27, 2023
1 parent d6c28d4 commit 3db080c
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 11 deletions.
18 changes: 8 additions & 10 deletions src/coreclr/tools/Common/TypeSystem/IL/UnsafeAccessors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,12 @@ public static MethodIL TryGetIL(EcmaMethod method)
return GenerateAccessorBadImageFailure(method);
}

const string ctorName = ".ctor";
context.TargetType = ValidateTargetType(retType);
if (context.TargetType == null)
if (!ValidateTargetType(retType, out context.TargetType))
{
return GenerateAccessorBadImageFailure(method);
}

const string ctorName = ".ctor";
if (!TrySetTargetMethod(ref context, ctorName, out isAmbiguous))
{
return GenerateAccessorSpecificFailure(ref context, ctorName, isAmbiguous);
Expand All @@ -100,8 +99,7 @@ public static MethodIL TryGetIL(EcmaMethod method)
return GenerateAccessorBadImageFailure(method);
}

context.TargetType = ValidateTargetType(firstArgType);
if (context.TargetType == null)
if (!ValidateTargetType(firstArgType, out context.TargetType))
{
return GenerateAccessorBadImageFailure(method);
}
Expand Down Expand Up @@ -132,8 +130,7 @@ public static MethodIL TryGetIL(EcmaMethod method)
return GenerateAccessorBadImageFailure(method);
}

context.TargetType = ValidateTargetType(firstArgType);
if (context.TargetType == null)
if (!ValidateTargetType(firstArgType, out context.TargetType))
{
return GenerateAccessorBadImageFailure(method);
}
Expand Down Expand Up @@ -221,7 +218,7 @@ private struct GenerationContext
public FieldDesc TargetField;
}

private static TypeDesc ValidateTargetType(TypeDesc targetTypeMaybe)
private static bool ValidateTargetType(TypeDesc targetTypeMaybe, out TypeDesc validated)
{
TypeDesc targetType = targetTypeMaybe.IsByRef
? ((ParameterizedType)targetTypeMaybe).ParameterType
Expand All @@ -232,10 +229,11 @@ private static TypeDesc ValidateTargetType(TypeDesc targetTypeMaybe)
if ((targetType.IsParameterizedType && !targetType.IsArray)
|| targetType.IsFunctionPointer)
{
ThrowHelper.ThrowBadImageFormatException();
targetType = null;
}

return targetType;
validated = targetType;
return validated != null;
}

private static bool DoesMethodMatchUnsafeAccessorDeclaration(ref GenerationContext context, MethodDesc method, bool ignoreCustomModifiers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private static void _MVV() {}
private void _mvv() {}

// The "init" is important to have here - custom modifier test.
// The signature of set_Prop is
// The signature of set_Prop is
// instance void modreq([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) set_Prop ( string 'value')
private string Prop { get; init; }

Expand Down Expand Up @@ -85,6 +85,33 @@ struct UserDataValue
public string GetFieldValue() => _f;
}

class UserDataGenericClass<T>
{
public const string StaticGenericFieldName = nameof(_GF);
public const string GenericFieldName = nameof(_gf);
public const string StaticGenericMethodName = nameof(_GM);
public const string GenericMethodName = nameof(_gm);

public const string StaticFieldName = nameof(_F);
public const string FieldName = nameof(_f);
public const string StaticMethodName = nameof(_M);
public const string MethodName = nameof(_m);

private static T _GF;
private T _gf;

private static string _F = PrivateStatic;
private string _f;

public UserDataGenericClass() { _f = Private; }

private static string _GM(T s, ref T sr, in T si) => typeof(T).ToString();
private string _gm(T s, ref T sr, in T si) => typeof(T).ToString();

private static string _M(string s, ref string sr, in string si) => s;
private string _m(string s, ref string sr, in string si) => s;
}

[UnsafeAccessor(UnsafeAccessorKind.Constructor)]
extern static UserDataClass CallPrivateConstructorClass();

Expand Down Expand Up @@ -188,6 +215,23 @@ public static void Verify_AccessFieldClass()
extern static ref string GetPrivateField(UserDataClass d);
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/92633")]
public static void Verify_AccessStaticFieldGenericClass()
{
Console.WriteLine($"Running {nameof(Verify_AccessStaticFieldGenericClass)}");

Assert.Equal(PrivateStatic, GetPrivateStaticFieldInt((UserDataGenericClass<int>)null));

Assert.Equal(PrivateStatic, GetPrivateStaticFieldString((UserDataGenericClass<string>)null));

[UnsafeAccessor(UnsafeAccessorKind.StaticField, Name=UserDataGenericClass<int>.StaticFieldName)]
extern static ref string GetPrivateStaticFieldInt(UserDataGenericClass<int> d);

[UnsafeAccessor(UnsafeAccessorKind.StaticField, Name=UserDataGenericClass<string>.StaticFieldName)]
extern static ref string GetPrivateStaticFieldString(UserDataGenericClass<string> d);
}

[Fact]
public static void Verify_AccessStaticFieldValue()
{
Expand Down Expand Up @@ -215,6 +259,23 @@ public static void Verify_AccessFieldValue()
extern static ref string GetPrivateField(ref UserDataValue d);
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/92633")]
public static void Verify_AccessFieldGenericClass()
{
Console.WriteLine($"Running {nameof(Verify_AccessFieldGenericClass)}");

Assert.Equal(Private, GetPrivateFieldInt(new UserDataGenericClass<int>()));

Assert.Equal(Private, GetPrivateFieldString(new UserDataGenericClass<string>()));

[UnsafeAccessor(UnsafeAccessorKind.Field, Name=UserDataGenericClass<int>.FieldName)]
extern static ref string GetPrivateFieldInt(UserDataGenericClass<int> d);

[UnsafeAccessor(UnsafeAccessorKind.Field, Name=UserDataGenericClass<string>.FieldName)]
extern static ref string GetPrivateFieldString(UserDataGenericClass<string> d);
}

[Fact]
public static void Verify_AccessStaticMethodClass()
{
Expand Down

0 comments on commit 3db080c

Please sign in to comment.