diff options
author | Aaron Robinson <arobins@microsoft.com> | 2022-01-23 17:39:24 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-23 17:39:24 +0300 |
commit | 4a6d169f5391532340074b0be4cab737c6ccdfc8 (patch) | |
tree | 072452b265367c60a88a17118772c0d2f37569c7 /src/tests/Loader | |
parent | 5605bdff4b104496941cc9e6acfc19783a52e7b8 (diff) |
Add runtime support for `ref` fields (#63985)
* Add mono and coreclr runtime support for ref fields
* Update Reflection.Emit tests to validate ref fields.
Add test for TypedReference as a ref field.
Diffstat (limited to 'src/tests/Loader')
4 files changed, 202 insertions, 0 deletions
diff --git a/src/tests/Loader/classloader/RefFields/InvalidCSharp.il b/src/tests/Loader/classloader/RefFields/InvalidCSharp.il new file mode 100644 index 00000000000..b976227547d --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/InvalidCSharp.il @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) } + +.assembly InvalidCSharp { } + +.class public auto ansi sealed beforefieldinit InvalidCSharp.InvalidStructWithRefField + extends [System.Runtime]System.ValueType +{ + // Type requires IsByRefLikeAttribute to be valid. + .field public string& invalid +} + +// This is invalid metadata and is unable to be loaded. +// - [field sig] (0x80131815 (VER_E_FIELD_SIG)) +// +// .class public auto ansi sealed beforefieldinit InvalidCSharp.InvalidStructWithStaticRefField +// extends [System.Runtime]System.ValueType +// { +// .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( +// 01 00 00 00 +// ) +// .field public static string& invalid +// } + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithRefField + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public string& Str + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + string& + ) cil managed + { + ldarg.0 + ldarg.1 + stfld string& InvalidCSharp.WithRefField::Str + ret + } + + .method public hidebysig + instance bool ConfirmFieldInstance ( + string + ) cil managed + { + ldarg.0 + ldfld string& InvalidCSharp.WithRefField::Str + ldind.ref + ldarg.1 + ceq + ret + } +} + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithRefStructField + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public valuetype InvalidCSharp.WithRefField& Field + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + valuetype InvalidCSharp.WithRefField& + ) cil managed + { + ldarg.0 + ldarg.1 + stfld valuetype InvalidCSharp.WithRefField& InvalidCSharp.WithRefStructField::Field + ret + } + + .method public hidebysig + instance bool ConfirmFieldInstance ( + valuetype InvalidCSharp.WithRefField& + ) cil managed + { + ldarg.0 + ldfld valuetype InvalidCSharp.WithRefField& InvalidCSharp.WithRefStructField::Field + ldind.ref + ldarg.1 + ldind.ref + ceq + ret + } +} + +.class public auto ansi sealed beforefieldinit InvalidCSharp.WithTypedReferenceField`1<T> + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public typedref Field + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + !T + ) cil managed + { + ldarg.0 + ldarga.s 1 + mkrefany !T + stfld typedref InvalidCSharp.WithTypedReferenceField`1::Field + ret + } + + .method public hidebysig + instance class [System.Runtime]System.Type GetFieldType () cil managed + { + ldarg.0 + ldfld typedref InvalidCSharp.WithTypedReferenceField`1::Field + refanytype + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle ) + ret + } +}
\ No newline at end of file diff --git a/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj b/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj new file mode 100644 index 00000000000..d577c8f9c7a --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/InvalidCSharp.ilproj @@ -0,0 +1,8 @@ +<Project Sdk="Microsoft.NET.Sdk.IL"> + <PropertyGroup> + <OutputType>Library</OutputType> + </PropertyGroup> + <ItemGroup> + <Compile Include="InvalidCSharp.il" /> + </ItemGroup> +</Project> diff --git a/src/tests/Loader/classloader/RefFields/Validate.cs b/src/tests/Loader/classloader/RefFields/Validate.cs new file mode 100644 index 00000000000..bffcd53de2f --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/Validate.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using InvalidCSharp; + +using Xunit; + +class Validate +{ + [Fact] + public static void Validate_Invalid_RefField_Fails() + { + Console.WriteLine($"{nameof(Validate_Invalid_RefField_Fails)}..."); + Assert.Throws<TypeLoadException>(() => { var t = typeof(InvalidStructWithRefField); }); + } + + [Fact] + public static void Validate_RefStructWithRefField_Load() + { + Console.WriteLine($"{nameof(Validate_RefStructWithRefField_Load)}..."); + var t = typeof(WithRefField); + } + + [Fact] + public static void Validate_Create_RefField() + { + var str = nameof(Validate_Create_RefField); + Console.WriteLine($"{str}..."); + + WithRefField s = new(ref str); + Assert.True(s.ConfirmFieldInstance(str)); + + string newStr = new(str); + Assert.False(s.ConfirmFieldInstance(newStr)); + } + + [Fact] + public static void Validate_Create_RefStructField() + { + var str = nameof(Validate_Create_RefStructField); + Console.WriteLine($"{str}..."); + + WithRefField s = new(ref str); + WithRefStructField t = new(ref s); + Assert.True(t.ConfirmFieldInstance(ref s)); + } + + [Fact] + public static void Validate_Create_TypedReferenceRefField() + { + Console.WriteLine($"{nameof(Validate_Create_TypedReferenceRefField)}..."); + + Validate v = new(); + WithTypedReferenceField<Validate> s = new(v); + Assert.Equal(typeof(Validate), s.GetFieldType()); + } +}
\ No newline at end of file diff --git a/src/tests/Loader/classloader/RefFields/Validate.csproj b/src/tests/Loader/classloader/RefFields/Validate.csproj new file mode 100644 index 00000000000..96fedddd4bd --- /dev/null +++ b/src/tests/Loader/classloader/RefFields/Validate.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> + <Compile Include="Validate.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="InvalidCSharp.ilproj" /> + </ItemGroup> +</Project> |