diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index fbe2ee3439aabf..515a3018fc486e 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -1775,9 +1775,19 @@ void ProcessAnalysisAnnotationsForField (FieldDefinition field, DependencyKind d (origin.Provider is MethodDefinition originMethod && CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (originMethod))); } - if (dependencyKind == DependencyKind.DynamicallyAccessedMemberOnType) { + switch (dependencyKind) { + // Marked through things like descriptor - don't want to warn as it's intentional choice + case DependencyKind.AlreadyMarked: + case DependencyKind.TypePreserve: + case DependencyKind.PreservedMethod: + return; + + case DependencyKind.DynamicallyAccessedMemberOnType: ReportWarningsForTypeHierarchyReflectionAccess (field, origin); return; + + default: + break; } if (Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (origin.Provider, out _)) @@ -3189,9 +3199,10 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo if (!Annotations.ProcessSatelliteAssemblies && KnownMembers.IsSatelliteAssemblyMarker (method)) Annotations.ProcessSatelliteAssemblies = true; } else if (method.TryGetProperty (out PropertyDefinition? property)) - MarkProperty (property, new DependencyInfo (DependencyKind.PropertyOfPropertyMethod, method)); - else if (method.TryGetEvent (out EventDefinition? @event)) - MarkEvent (@event, new DependencyInfo (DependencyKind.EventOfEventMethod, method)); + MarkProperty (property, new DependencyInfo (PropagateDependencyKindToAccessors (reason.Kind, DependencyKind.PropertyOfPropertyMethod), method)); + else if (method.TryGetEvent (out EventDefinition? @event)) { + MarkEvent (@event, new DependencyInfo (PropagateDependencyKindToAccessors(reason.Kind, DependencyKind.EventOfEventMethod), method)); + } if (method.HasMetadataParameters ()) { #pragma warning disable RS0030 // MethodReference.Parameters is banned. It's easiest to leave the code as is for now @@ -3270,6 +3281,20 @@ protected virtual void DoAdditionalMethodProcessing (MethodDefinition method) { } + static DependencyKind PropagateDependencyKindToAccessors(DependencyKind parentDependencyKind, DependencyKind kind) + { + switch (parentDependencyKind) { + // If the member is marked due to descriptor or similar, propagate the original reason to suppress some warnings correctly + case DependencyKind.AlreadyMarked: + case DependencyKind.TypePreserve: + case DependencyKind.PreservedMethod: + return parentDependencyKind; + + default: + return kind; + } + } + void MarkImplicitlyUsedFields (TypeDefinition type) { if (type?.HasFields != true) @@ -3506,9 +3531,12 @@ protected internal virtual void MarkEvent (EventDefinition evt, in DependencyInf using var eventScope = ScopeStack.PushScope (new MessageOrigin (evt)); MarkCustomAttributes (evt, new DependencyInfo (DependencyKind.CustomAttribute, evt)); - MarkMethodIfNotNull (evt.AddMethod, new DependencyInfo (DependencyKind.EventMethod, evt), ScopeStack.CurrentScope.Origin); - MarkMethodIfNotNull (evt.InvokeMethod, new DependencyInfo (DependencyKind.EventMethod, evt), ScopeStack.CurrentScope.Origin); - MarkMethodIfNotNull (evt.RemoveMethod, new DependencyInfo (DependencyKind.EventMethod, evt), ScopeStack.CurrentScope.Origin); + + DependencyKind dependencyKind = PropagateDependencyKindToAccessors(reason.Kind, DependencyKind.EventMethod); + MarkMethodIfNotNull (evt.AddMethod, new DependencyInfo (dependencyKind, evt), ScopeStack.CurrentScope.Origin); + MarkMethodIfNotNull (evt.InvokeMethod, new DependencyInfo (dependencyKind, evt), ScopeStack.CurrentScope.Origin); + MarkMethodIfNotNull (evt.RemoveMethod, new DependencyInfo (dependencyKind, evt), ScopeStack.CurrentScope.Origin); + DoAdditionalEventProcessing (evt); } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs index 12e0844b559389..b711d35078c660 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs @@ -58,6 +58,12 @@ public Task RequiresInCompilerGeneratedCodeRelease () return RunTest (); } + [Fact] + public Task RequiresInLibraryAssembly () + { + return RunTest (); + } + [Fact] public Task RequiresOnAttribute () { @@ -112,4 +118,4 @@ public Task SuppressRequires () return RunTest (nameof (SuppressRequires)); } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInLibraryAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInLibraryAssembly.cs new file mode 100644 index 00000000000000..d5b55e0b4970d0 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInLibraryAssembly.cs @@ -0,0 +1,62 @@ +// 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 Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [SetupLinkerArgument ("-a", "test.exe", "library")] + + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + public class RequiresInLibraryAssembly + { + public static void Main () + { + } + + [RequiresDynamicCode ("--MethodWhichRequires--")] + public static void MethodWhichRequires () { } + + [RequiresDynamicCode ("--InstanceMethodWhichRequires--")] + public void InstanceMethodWhichRequires () { } + } + + [ExpectedNoWarnings] + public sealed class ClassWithDAMAnnotatedMembers + { + public static void Method ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + public static Type Field; + } + + [ExpectedNoWarnings] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + public sealed class ClassWithDAMAnnotation + { + public void Method () { } + } + + [ExpectedNoWarnings] + [RequiresUnreferencedCode ("--ClassWithRequires--")] + public sealed class ClassWithRequires + { + public static int Field; + + internal static int InternalField; + + private static int PrivateField; + + public static void Method () { } + + public void InstanceMethod () { } + + public static int Property { get; set; } + + public static event EventHandler PropertyChanged; + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs index 46e199fc84bd75..5ad0c16f5503fc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs @@ -17,8 +17,6 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [SetupLinkerDescriptorFile ("RequiresViaXml.descriptor.xml")] [SkipKeptItemsValidation] [ExpectedNoWarnings] - // [LogContains ("--RequiresOnlyViaDescriptor--")] // https://github.com/dotnet/linker/issues/2103 - [ExpectedWarning ("IL2026", "RequiresOnFieldOnlyViaDescriptor.Field", FileName = "RequiresViaXml.descriptor.xml", ProducedBy = Tool.Trimmer)] class RequiresViaXml {