From 036e683fe6af618eab5ca2c6079b94c8af79f934 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 2 Oct 2024 20:48:31 +0000 Subject: [PATCH 1/3] Fix ILLink behavior for modreq types --- .../linker/Linker/TypeReferenceExtensions.cs | 17 ++++++++------- .../DataFlow/FieldDataFlow.cs | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs index ae2984377a7062..8e9632f7cdf181 100644 --- a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs +++ b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs @@ -415,19 +415,22 @@ public static TypeReference WithoutModifiers (this TypeReference type) // not an array, pointer, byref, or generic parameter. Conceptually this is supposed to represent the same idea as Roslyn's // INamedTypeSymbol, or ILC's DefType/MetadataType. public static bool IsNamedType (this TypeReference typeReference) { + // Shouldn't get called for these cases + Debug.Assert (!typeReference.IsFunctionPointer); + Debug.Assert (!typeReference.IsPinned); + Debug.Assert (!typeReference.IsSentinel); + + if (typeReference.IsRequiredModifier) + typeReference = ((RequiredModifierType) typeReference).ElementType; + if (typeReference.IsOptionalModifier) + typeReference = ((OptionalModifierType) typeReference).ElementType; + if (typeReference.IsDefinition || typeReference.IsGenericInstance) return true; if (typeReference.IsArray || typeReference.IsByReference || typeReference.IsPointer || typeReference.IsGenericParameter) return false; - // Shouldn't get called for these cases - Debug.Assert (!typeReference.IsFunctionPointer); - Debug.Assert (!typeReference.IsRequiredModifier); - Debug.Assert (!typeReference.IsOptionalModifier); - Debug.Assert (!typeReference.IsPinned); - Debug.Assert (!typeReference.IsSentinel); - Debug.Assert (typeReference.GetType () == typeof (TypeReference)); return true; } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs index ac81111bf43ccd..e8222327eafa96 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs @@ -31,6 +31,7 @@ public static void Main () instance.WriteToStaticFieldOnADifferentClass (); instance.WriteUnknownValue (); + instance.WriteModReqType (); WriteCapturedField.Test (); WriteFieldOfCapturedInstance.Test (); @@ -156,6 +157,16 @@ static void MakeArrayValuesUnknown (object[] array) } } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] + volatile Type volatileType; + + [ExpectedWarning ("IL2074", nameof (GetTypeWithPublicConstructors), nameof (volatileType))] + private void WriteModReqType () + { + var type = GetTypeWithPublicConstructors (); + volatileType = type; + } + private static void TestStringEmpty () { RequirePublicMethods (string.Empty); @@ -394,11 +405,21 @@ static void TestTypeGenericParameter () GenericField.field = GetUnknownType (); } + [ExpectedWarning ("IL2097")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + static volatile Type[] volatileTypeArray; + + static void TestModReqTypeArray () + { + volatileTypeArray = new Type[1]; + } + public static void Test () { TestUnsupportedType (); StringRef.Test (); TestTypeGenericParameter (); + TestModReqTypeArray (); } } From af9087ff6a9fddecbc42be31c4d9b7e24d47b70a Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 2 Oct 2024 21:05:09 +0000 Subject: [PATCH 2/3] Fix behavior for function pointers too --- .../linker/Linker/TypeReferenceExtensions.cs | 17 +++++++++++------ .../DataFlow/FieldDataFlow.cs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs index 8e9632f7cdf181..7e5dec5eb0c24f 100644 --- a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs +++ b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs @@ -415,11 +415,6 @@ public static TypeReference WithoutModifiers (this TypeReference type) // not an array, pointer, byref, or generic parameter. Conceptually this is supposed to represent the same idea as Roslyn's // INamedTypeSymbol, or ILC's DefType/MetadataType. public static bool IsNamedType (this TypeReference typeReference) { - // Shouldn't get called for these cases - Debug.Assert (!typeReference.IsFunctionPointer); - Debug.Assert (!typeReference.IsPinned); - Debug.Assert (!typeReference.IsSentinel); - if (typeReference.IsRequiredModifier) typeReference = ((RequiredModifierType) typeReference).ElementType; if (typeReference.IsOptionalModifier) @@ -428,7 +423,17 @@ public static bool IsNamedType (this TypeReference typeReference) { if (typeReference.IsDefinition || typeReference.IsGenericInstance) return true; - if (typeReference.IsArray || typeReference.IsByReference || typeReference.IsPointer || typeReference.IsGenericParameter) + if (typeReference.IsArray || + typeReference.IsByReference || + typeReference.IsPointer || + typeReference.IsFunctionPointer || + typeReference.IsGenericParameter) + return false; + + // Shouldn't get called for these cases + Debug.Assert (!typeReference.IsPinned); + Debug.Assert (!typeReference.IsSentinel); + if (typeReference.IsPinned || typeReference.IsSentinel) return false; Debug.Assert (typeReference.GetType () == typeof (TypeReference)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs index e8222327eafa96..4b0af683b7f623 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; using Mono.Linker.Tests.Cases.Expectations.Helpers; namespace Mono.Linker.Tests.Cases.DataFlow @@ -11,6 +12,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow // Note: this test's goal is to validate that the product correctly reports unrecognized patterns // - so the main validation is done by the ExpectedWarning attributes. [SkipKeptItemsValidation] + [SetupCompileArgument ("/unsafe")] [ExpectedNoWarnings] public class FieldDataFlow { @@ -414,12 +416,22 @@ static void TestModReqTypeArray () volatileTypeArray = new Type[1]; } + [ExpectedWarning ("IL2097")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + unsafe static delegate* functionPointer; + + unsafe static void TestFunctionPointer () + { + functionPointer = null; + } + public static void Test () { TestUnsupportedType (); StringRef.Test (); TestTypeGenericParameter (); TestModReqTypeArray (); + TestFunctionPointer (); } } From fe75257ec14e3702dedf4be8bef9b8a4fe237f96 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 3 Oct 2024 22:44:40 +0000 Subject: [PATCH 3/3] Add IL test, fix behavior f or multiple modreq/modopt --- .../linker/Linker/TypeReferenceExtensions.cs | 4 +- .../DataFlow/Dependencies/ModifierDataFlow.il | 176 ++++++++++++++++++ .../DataFlow/FieldDataFlow.cs | 21 --- .../DataFlow/ModifierDataFlow.cs | 66 +++++++ .../TestCasesRunner/ResultChecker.cs | 5 + 5 files changed, 249 insertions(+), 23 deletions(-) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/ModifierDataFlow.il create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ModifierDataFlow.cs diff --git a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs index 7e5dec5eb0c24f..7ddb8fe77e5751 100644 --- a/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs +++ b/src/tools/illink/src/linker/Linker/TypeReferenceExtensions.cs @@ -416,9 +416,9 @@ public static TypeReference WithoutModifiers (this TypeReference type) // INamedTypeSymbol, or ILC's DefType/MetadataType. public static bool IsNamedType (this TypeReference typeReference) { if (typeReference.IsRequiredModifier) - typeReference = ((RequiredModifierType) typeReference).ElementType; + return ((RequiredModifierType) typeReference).ElementType.IsNamedType (); if (typeReference.IsOptionalModifier) - typeReference = ((OptionalModifierType) typeReference).ElementType; + return ((OptionalModifierType) typeReference).ElementType.IsNamedType (); if (typeReference.IsDefinition || typeReference.IsGenericInstance) return true; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/ModifierDataFlow.il b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/ModifierDataFlow.il new file mode 100644 index 00000000000000..0d30d8710b7678 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/ModifierDataFlow.il @@ -0,0 +1,176 @@ +// Metadata version: v4.0.30319 +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) +} +.assembly 'library' +{ + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} +.module library.dll + +.class public auto ansi sealed beforefieldinit Library.ModifierDataFlow + extends [System.Runtime]System.Object +{ + .field public static class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) modReqType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) modreq(Library.ModifierDataFlow/ModifierType) multipleModReqType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modopt(Library.ModifierDataFlow/ModifierType) modOptType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modopt(Library.ModifierDataFlow/ModifierType) modreq(Library.ModifierDataFlow/ModifierType) modReqModOptType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) modopt(Library.ModifierDataFlow/ModifierType) modOptModReqType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type[] modreq(Library.ModifierDataFlow/ModifierType) modReqArrayType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType)[] arrayModReqType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .field public static class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType)[] modreq(Library.ModifierDataFlow/ModifierType) modReqArrayModReqType + .custom instance void [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) = ( + 01 00 20 00 00 00 00 00 + ) + + .class nested public auto ansi beforefieldinit ModifierType + extends [System.Runtime]System.Object + { + } // end of class ModifierType + + .method private hidebysig static + class [System.Runtime]System.Type GetUnknownType () cil managed + { + .maxstack 8 + + IL_0000: ldnull + IL_0001: ret + } // end of method Library.ModifierDataFlow::GetUnknownType + + .method public hidebysig static + void WriteModReqType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + IL_0006: stsfld class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modReqType + IL_000b: ret + } // end of method C::WriteModReqType + + .method public hidebysig static + void WriteMultipleModReqType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + IL_0006: stsfld class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) modreq(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::multipleModReqType + IL_000b: ret + } // end of method Library.ModifierDataFlow::WriteMultipleModReqType + + .method public hidebysig static + void WriteModOptType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + IL_0006: stsfld class [System.Runtime]System.Type modopt(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modOptType + IL_000b: ret + } // end of method Library.ModifierDataFlow::WriteModOptType + + .method public hidebysig static + void WriteModReqModOptType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + IL_0006: stsfld class [System.Runtime]System.Type modopt(Library.ModifierDataFlow/ModifierType) modreq(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modReqModOptType + IL_000b: ret + } // end of method Library.ModifierDataFlow::WriteModReqModOptType + + .method public hidebysig static + void WriteModOptModReqType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + IL_0006: stsfld class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType) modopt(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modOptModReqType + IL_000b: ret + } // end of method Library.ModifierDataFlow::WriteModOptModReqType + + .method public hidebysig static + void WriteModReqArrayType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: newarr [System.Runtime]System.Type + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + + IL_000e: stelem.ref + IL_000f: stsfld class [System.Runtime]System.Type[] modreq(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modReqArrayType + IL_0014: ret + } // end of method Library.ModifierDataFlow::WriteModReqArrayType + + .method public hidebysig static + void WriteArrayModReqType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: newarr [System.Runtime]System.Type + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + + IL_000e: stelem.ref + IL_000f: stsfld class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType)[] Library.ModifierDataFlow::arrayModReqType + IL_0014: ret + } // end of method Library.ModifierDataFlow::WriteArrayModReqType + + .method public hidebysig static + void WriteModReqArrayModReqType () cil managed + { + .maxstack 8 + + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: newarr [System.Runtime]System.Type + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: call class [System.Runtime]System.Type Library.ModifierDataFlow::GetUnknownType() + + IL_000e: stelem.ref + IL_000f: stsfld class [System.Runtime]System.Type modreq(Library.ModifierDataFlow/ModifierType)[] modreq(Library.ModifierDataFlow/ModifierType) Library.ModifierDataFlow::modReqArrayModReqType + IL_0014: ret + } // end of method Library.ModifierDataFlow::WriteModReqArrayModReqType + +} // end of class Library.ModifierDataFlow diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs index 4b0af683b7f623..425ccb5cd95162 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs @@ -33,7 +33,6 @@ public static void Main () instance.WriteToStaticFieldOnADifferentClass (); instance.WriteUnknownValue (); - instance.WriteModReqType (); WriteCapturedField.Test (); WriteFieldOfCapturedInstance.Test (); @@ -159,16 +158,6 @@ static void MakeArrayValuesUnknown (object[] array) } } - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] - volatile Type volatileType; - - [ExpectedWarning ("IL2074", nameof (GetTypeWithPublicConstructors), nameof (volatileType))] - private void WriteModReqType () - { - var type = GetTypeWithPublicConstructors (); - volatileType = type; - } - private static void TestStringEmpty () { RequirePublicMethods (string.Empty); @@ -407,15 +396,6 @@ static void TestTypeGenericParameter () GenericField.field = GetUnknownType (); } - [ExpectedWarning ("IL2097")] - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - static volatile Type[] volatileTypeArray; - - static void TestModReqTypeArray () - { - volatileTypeArray = new Type[1]; - } - [ExpectedWarning ("IL2097")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] unsafe static delegate* functionPointer; @@ -430,7 +410,6 @@ public static void Test () TestUnsupportedType (); StringRef.Test (); TestTypeGenericParameter (); - TestModReqTypeArray (); TestFunctionPointer (); } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ModifierDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ModifierDataFlow.cs new file mode 100644 index 00000000000000..5416dfd9d051a2 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ModifierDataFlow.cs @@ -0,0 +1,66 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + // Note: this test's goal is to validate that the product correctly reports unrecognized patterns + // - so the main validation is done by the ExpectedWarning attributes. + [SkipKeptItemsValidation] + [SetupCompileArgument ("/unsafe")] + [Define ("IL_ASSEMBLY_AVAILABLE")] + [SetupCompileBefore ("library.dll", new[] { "Dependencies/ModifierDataFlow.il" })] + [ExpectedNoWarnings] + [LogContains ("IL2074: Library.ModifierDataFlow.WriteModReqType().*'Library.ModifierDataFlow.modReqType'.*GetUnknownType()", regexMatch: true)] + [LogContains ("IL2074: Library.ModifierDataFlow.WriteMultipleModReqType().*'Library.ModifierDataFlow.multipleModReqType'.*GetUnknownType()", regexMatch: true)] + [LogContains ("IL2074: Library.ModifierDataFlow.WriteModOptType().*'Library.ModifierDataFlow.modOptType'.*GetUnknownType()", regexMatch: true)] + [LogContains ("IL2074: Library.ModifierDataFlow.WriteModReqModOptType().*'Library.ModifierDataFlow.modReqModOptType'.*GetUnknownType()", regexMatch: true)] + [LogContains ("IL2074: Library.ModifierDataFlow.WriteModOptModReqType().*'Library.ModifierDataFlow.modOptModReqType'.*GetUnknownType()", regexMatch: true)] + [LogDoesNotContain ("IL2074")] + [LogContains ("IL2097:.*Library.ModifierDataFlow.arrayModReqType", regexMatch: true)] + [LogContains ("IL2097:.*Library.ModifierDataFlow.modReqArrayType", regexMatch: true)] + [LogContains ("IL2097:.*Library.ModifierDataFlow.modReqArrayModReqType", regexMatch: true)] + [LogDoesNotContain ("IL2097")] + public class ModifierDataFlow + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] + static volatile Type volatileType; + + [ExpectedWarning ("IL2074", nameof (GetUnknownType), nameof (volatileType))] + static void WriteVolatileType () + { + volatileType = GetUnknownType (); + } + + static Type GetUnknownType () => null; + + [ExpectedWarning ("IL2097")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + static volatile Type[] volatileTypeArray; + + static void WriteVolatileTypeArray () + { + volatileTypeArray = new Type[] { GetUnknownType () }; + } + + public static void Main () + { + WriteVolatileType (); + WriteVolatileTypeArray (); +#if IL_ASSEMBLY_AVAILABLE + Library.ModifierDataFlow.WriteModReqType (); + Library.ModifierDataFlow.WriteMultipleModReqType (); + Library.ModifierDataFlow.WriteModOptType (); + Library.ModifierDataFlow.WriteModReqModOptType (); + Library.ModifierDataFlow.WriteModOptModReqType (); + Library.ModifierDataFlow.WriteModReqArrayType (); + Library.ModifierDataFlow.WriteArrayModReqType (); +#endif + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index acf9bf7a2b14d9..56d78af63d3496 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -78,6 +78,11 @@ protected static void ValidateTypeRefsHaveValidAssemblyRefs (AssemblyDefinition Assert.IsNotNull (assemblyRef, $"Type reference '{typeRef.FullName}' has a reference to assembly '{typeRef.Scope.Name}' which is not a reference of '{linked.FullName}'"); continue; } + case ModuleDefinition: { + // There should be a Module row for this assembly + Assert.AreEqual (linked.MainModule.Name, typeRef.Scope.Name, $"Type reference '{typeRef.FullName}' has a reference to module '{typeRef.Scope.Name}' which is not the module of '{linked.FullName}'"); + continue; + } default: throw new NotImplementedException ($"Unexpected scope type '{typeRef.Scope.GetType ()}' for type reference '{typeRef.FullName}'"); }