From 9ecf5bd2809f93d98c1dbea640790ca5a88d35ec Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 15 Jul 2021 11:23:09 -0700 Subject: [PATCH] Fix warning suppressions on types for type hierarchy (#2148) * Fix warning suppressions on types for type hierarchy * Add non-library mode tests --- src/linker/Linker.Steps/MarkStep.cs | 6 +- .../TypeHierarchyLibraryModeSuppressions.cs | 51 ++++++ .../Reflection/TypeHierarchySuppressions.cs | 167 ++++++++++++++++++ 3 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyLibraryModeSuppressions.cs create mode 100644 test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchySuppressions.cs diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs index 7bb060381d23..c9d46760ffd3 100644 --- a/src/linker/Linker.Steps/MarkStep.cs +++ b/src/linker/Linker.Steps/MarkStep.cs @@ -1756,14 +1756,16 @@ protected internal virtual TypeDefinition MarkType (TypeReference reference, Dep MarkType (type.BaseType, new DependencyInfo (DependencyKind.BaseType, type)); + MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); + // The DynamicallyAccessedMembers hiearchy processing must be done after the base type was marked - // (to avoid inconsistencies in the cache), but before anything else as work done below + // (to avoid inconsistencies in the cache), and after marking custom attributes (in case the attributes have + // warning suppressions for the type hierarchy marking) but before anything else as work done below // might need the results of the processing here. _dynamicallyAccessedMembersTypeHierarchy.ProcessMarkedTypeForDynamicallyAccessedMembersHierarchy (type); if (type.DeclaringType != null) MarkType (type.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, type)); - MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); MarkSecurityDeclarations (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); if (type.IsMulticastDelegate ()) { diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyLibraryModeSuppressions.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyLibraryModeSuppressions.cs new file mode 100644 index 000000000000..6d81d5b07bcd --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyLibraryModeSuppressions.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Reflection +{ + [SetupLinkerArgument ("-a", "test.exe", "library")] + [ExpectedNoWarnings] + [KeptMember (".ctor()")] + public class TypeHierarchyLibraryModeSuppressions + { + public static void Main () + { + var t1 = typeof (Unsuppressed); + var t2 = typeof (Suppressed); + } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + [ExpectedWarning ("IL2026", nameof (Unsuppressed))] + class Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on Unsuppressed--")] + public void RUCMethod () { } + } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptAttributeAttribute (typeof (UnconditionalSuppressMessageAttribute))] + [UnconditionalSuppressMessage ("TrimAnalysis", "IL2026")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + class Suppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on Suppressed--")] + public void RUCMethod () { } + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchySuppressions.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchySuppressions.cs new file mode 100644 index 000000000000..67c9e4efcb4e --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchySuppressions.cs @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Reflection +{ + [ExpectedNoWarnings] + public class TypeHierarchySuppressions + { + // https://github.com/mono/linker/issues/2136 + // Warnings should originate from the types (or rather their members, with the + // proposed behavior), and the type suppressions should silence the relevant + // warnings. + + // Should originate from types instead + [ExpectedWarning ("IL2026", "--RUC on Unsuppressed--")] + [ExpectedWarning ("IL2026", "--RUC on DerivedFromUnsuppressed1--")] + + // Should be suppressed by type-level suppression + [ExpectedWarning ("IL2026", "--RUC on Suppressed--")] + [ExpectedWarning ("IL2026", "--RUC on SuppressedOnDerived1--")] + [ExpectedWarning ("IL2026", "--RUC on DerivedFromSuppressed1--")] + public static void Main () + { + RequireMethods (unsuppressed.GetType ()); + RequireMethods (suppressed.GetType ()); + + var t = typeof (DerivedFromSuppressed1); + var t2 = typeof (DerivedFromUnsuppressed1); + var t3 = typeof (SuppressedOnDerived1); + + UseDerivedTypes (); + } + + // Referencing these types in a separate method ensures that they get + // marked after applying annotations on the base type. + [Kept] + static void UseDerivedTypes () + { + var t = typeof (DerivedFromUnsuppressed2); + var t2 = typeof (DerivedFromSuppressed2); + var t3 = typeof (SuppressedOnDerived2); + } + + [Kept] + static Unsuppressed unsuppressed; + + [Kept] + static Suppressed suppressed; + + [Kept] + static void RequireMethods ( + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + Type type) + { } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + // https://github.com/mono/linker/issues/2136 + // [ExpectedWarning ("IL2026", "--RUC on Unsuppressed--")] + class Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on Unsuppressed--")] + public void RUCMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Unsuppressed))] + // https://github.com/mono/linker/issues/2136 + // [ExpectedWarning ("IL2026", "--RUC on DerivedFromUnsuppressed1--")] + class DerivedFromUnsuppressed1 : Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on DerivedFromUnsuppressed1--")] + public void DerivedRUCMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Unsuppressed))] + [ExpectedWarning ("IL2026", "--RUC on DerivedFromUnsuppressed2")] + // https://github.com/mono/linker/issues/2136 + // Should originate from the base type instead + [ExpectedWarning ("IL2026", "--RUC on Unsuppressed--")] + class DerivedFromUnsuppressed2 : Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on DerivedFromUnsuppressed2--")] + public void DerivedRUCMethod () { } + } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptAttributeAttribute (typeof (UnconditionalSuppressMessageAttribute))] + [UnconditionalSuppressMessage ("TrimAnalysis", "IL2026")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + class Suppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on Suppressed--")] + public void RUCMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Suppressed))] + // https://github.com/mono/linker/issues/2136 + // [ExpectedWarning ("IL2026", "--RUC on DerivedFromSuppressed1--")] + class DerivedFromSuppressed1 : Suppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on DerivedFromSuppressed1--")] + public void RUCDerivedMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Suppressed))] + [ExpectedWarning ("IL2026", "--RUC on DerivedFromSuppressed2--")] + // https://github.com/mono/linker/issues/2136 + [ExpectedWarning ("IL2026", "--RUC on Suppressed--")] + class DerivedFromSuppressed2 : Suppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on DerivedFromSuppressed2--")] + public void RUCDerivedMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Unsuppressed))] + [KeptAttributeAttribute (typeof (UnconditionalSuppressMessageAttribute))] + [UnconditionalSuppressMessage ("TrimAnalysis", "IL2026")] + class SuppressedOnDerived1 : Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on SuppressedOnDerived1--")] + public void DerivedRUCMethod () { } + } + + [Kept] + [KeptBaseType (typeof (Unsuppressed))] + [KeptAttributeAttribute (typeof (UnconditionalSuppressMessageAttribute))] + [UnconditionalSuppressMessage ("TrimAnalysis", "IL2026")] + class SuppressedOnDerived2 : Unsuppressed + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("--RUC on SuppressedOnDerived2--")] + public void DerivedRUCMethod () { } + } + } +}