diff options
author | James S. Wang <jjameswwang@gmail.com> | 2022-09-29 17:18:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-29 17:18:09 +0300 |
commit | 48468d194d666a66280fc8abc7e8a47603bcb68f (patch) | |
tree | 1646d0e42878d631f8e2a67f6be3f72a725f5951 /src | |
parent | e5d2c3e7fe8576c6904c9cc4e47acd9c97817f87 (diff) |
Fix value type with static method fails to load (#76262)
* Allow static methods if checking type equivalence
* Add test for loading value type with static method
* Add test in which loading a value type with an instance method should throw a TypeLoadException
Diffstat (limited to 'src')
5 files changed, 53 insertions, 8 deletions
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 19d1164dc94..ebefaf50e56 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -2659,14 +2659,6 @@ MethodTableBuilder::EnumerateClassMethods() METHOD_IMPL_TYPE implType; LPSTR strMethodName; -#ifdef FEATURE_TYPEEQUIVALENCE - // TypeEquivalent structs must not have methods - if (bmtProp->fIsTypeEquivalent && fIsClassValueType) - { - BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS); - } -#endif - // // Go to the next method and retrieve its attributes. // @@ -2686,6 +2678,14 @@ MethodTableBuilder::EnumerateClassMethods() BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT); } +#ifdef FEATURE_TYPEEQUIVALENCE + // TypeEquivalent structs must not have non-static methods + if (!IsMdStatic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent && fIsClassValueType) + { + BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS); + } +#endif + bool isVtblGap = false; if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate()) { diff --git a/src/tests/baseservices/typeequivalence/pia/PIAContract.csproj b/src/tests/baseservices/typeequivalence/pia/PIAContract.csproj new file mode 100644 index 00000000000..4895e31531d --- /dev/null +++ b/src/tests/baseservices/typeequivalence/pia/PIAContract.csproj @@ -0,0 +1,9 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Library</OutputType> + <CLRTestKind>SharedLibrary</CLRTestKind> + </PropertyGroup> + <ItemGroup> + <Compile Include="Types.cs" /> + </ItemGroup> +</Project> diff --git a/src/tests/baseservices/typeequivalence/pia/Types.cs b/src/tests/baseservices/typeequivalence/pia/Types.cs new file mode 100644 index 00000000000..915dc0adca7 --- /dev/null +++ b/src/tests/baseservices/typeequivalence/pia/Types.cs @@ -0,0 +1,19 @@ +// 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.Runtime.InteropServices; + +[assembly: PrimaryInteropAssembly(1, 0)] + +public struct ValueTypeWithStaticMethod +{ + public int F; + public static void M() { } +} + +public struct ValueTypeWithInstanceMethod +{ + public int F; + public void M() { } +}
\ No newline at end of file diff --git a/src/tests/baseservices/typeequivalence/simple/Simple.cs b/src/tests/baseservices/typeequivalence/simple/Simple.cs index c79f46ce27b..1d1528f3bf1 100644 --- a/src/tests/baseservices/typeequivalence/simple/Simple.cs +++ b/src/tests/baseservices/typeequivalence/simple/Simple.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Text; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Xunit; @@ -253,6 +254,20 @@ public class Simple } } + [MethodImpl (MethodImplOptions.NoInlining)] + private static void TestLoadingValueTypesWithMethod() + { + Console.WriteLine($"{nameof(TestLoadingValueTypesWithMethod)}"); + Console.WriteLine($"-- {typeof(ValueTypeWithStaticMethod).Name}"); + Assert.Throws<TypeLoadException>(() => LoadInvalidType()); + } + + [MethodImpl (MethodImplOptions.NoInlining)] + private static void LoadInvalidType() + { + Console.WriteLine($"-- {typeof(ValueTypeWithInstanceMethod).Name}"); + } + public static int Main(string[] noArgs) { if (!OperatingSystem.IsWindows()) @@ -270,6 +285,7 @@ public class Simple TestGenericClassNonEquivalence(); TestGenericInterfaceEquivalence(); TestTypeEquivalenceWithTypePunning(); + TestLoadingValueTypesWithMethod(); } catch (Exception e) { diff --git a/src/tests/baseservices/typeequivalence/simple/Simple.csproj b/src/tests/baseservices/typeequivalence/simple/Simple.csproj index 37e57397b2c..39d83e32fcc 100644 --- a/src/tests/baseservices/typeequivalence/simple/Simple.csproj +++ b/src/tests/baseservices/typeequivalence/simple/Simple.csproj @@ -15,6 +15,7 @@ <ProjectReference Include="../impl/TypeImpl.csproj" /> <ProjectReference Include="../impl/PunningLib.ilproj" /> <ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" /> + <ProjectReference Include="../pia/PIAContract.csproj" /> </ItemGroup> <Import Project="$([MSBuild]::GetPathOfFileAbove(TypeEquivalence.targets))" /> </Project> |