Implement checking for Requires* on attributes for NativeAOT (#83550)
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>
Mon, 27 Mar 2023 11:28:03 +0000 (04:28 -0700)
committerGitHub <noreply@github.com>
Mon, 27 Mar 2023 11:28:03 +0000 (04:28 -0700)
Any of the RUC/RDC/RAF attributes can be added to an attribute (either the type or the .ctor or properties). The compiler needs to check for these and produce warnings if such attribute is instantiated somewhere.

This was added to "Dataflow" existing class, while it's not exactly data flow, adding a new abstraction didn't seem worth it.

Also does a simple dedupe of RUC/RDC/RAF checks in some places.

Adapt the tests to the new behavior. The most notable change is that NativeAOT will only look at attributes for reflection enabled members, so had to modify the tests to reflection access basically everything.

Use GetDisplayName for anything which is supported by that extension method - this fixes wrong origin printed out for property/event (we would print out 'PropertyPseudoDescriptor').

Mapping IL offset to source file/line number - if the PDB specifies that line as "hidden", then don't use it, instead look for the begining of the method - so first non-hidden sequence point in the method's body.
This is a copy of the logic implemented in illink already.

src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/AttributeDataFlow.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisFieldAccessPattern.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageOrigin.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttributeCtor.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs

index 31ae384..3dac7c1 100644 (file)
@@ -1,7 +1,6 @@
 // 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.Diagnostics;
 using System.Text;
 
@@ -23,7 +22,7 @@ namespace ILCompiler
                 PropertyPseudoDesc property => property.GetDisplayName(),
                 EventPseudoDesc @event => @event.GetDisplayName(),
 #endif
-                _ => throw new InvalidOperationException(),
+                _ => null,
             };
         }
 
index c37e954..40fe1df 100644 (file)
@@ -28,6 +28,7 @@ namespace ILCompiler.Dataflow
         private readonly NodeFactory _factory;
         private readonly FlowAnnotations _annotations;
         private readonly MessageOrigin _origin;
+        private readonly DiagnosticContext _diagnosticContext;
 
         public AttributeDataFlow(Logger logger, NodeFactory factory, FlowAnnotations annotations, in MessageOrigin origin)
         {
@@ -35,12 +36,21 @@ namespace ILCompiler.Dataflow
             _factory = factory;
             _logger = logger;
             _origin = origin;
+
+            _diagnosticContext = new DiagnosticContext(
+                _origin,
+                _logger.ShouldSuppressAnalysisWarningsForRequires(_origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute),
+                _logger.ShouldSuppressAnalysisWarningsForRequires(_origin.MemberDefinition, DiagnosticUtilities.RequiresDynamicCodeAttribute),
+                _logger.ShouldSuppressAnalysisWarningsForRequires(_origin.MemberDefinition, DiagnosticUtilities.RequiresAssemblyFilesAttribute),
+                _logger);
         }
 
         public DependencyList? ProcessAttributeDataflow(MethodDesc method, CustomAttributeValue arguments)
         {
             DependencyList? result = null;
 
+            ReflectionMethodBodyScanner.CheckAndReportAllRequires(_diagnosticContext, method);
+
             // First do the dataflow for the constructor parameters if necessary.
             if (_annotations.RequiresDataflowAnalysisDueToSignature(method))
             {
@@ -62,6 +72,8 @@ namespace ILCompiler.Dataflow
                     FieldDesc field = attributeType.GetField(namedArgument.Name);
                     if (field != null)
                     {
+                        ReflectionMethodBodyScanner.CheckAndReportAllRequires(_diagnosticContext, field);
+
                         ProcessAttributeDataflow(field, namedArgument.Value, ref result);
                     }
                 }
@@ -72,6 +84,8 @@ namespace ILCompiler.Dataflow
                     MethodDesc setter = property.SetMethod;
                     if (setter != null && setter.Signature.Length > 0 && !setter.Signature.IsStatic)
                     {
+                        ReflectionMethodBodyScanner.CheckAndReportAllRequires(_diagnosticContext, setter);
+
                         ProcessAttributeDataflow(setter, ImmutableArray.Create(namedArgument.Value), ref result);
                     }
                 }
@@ -88,21 +102,19 @@ namespace ILCompiler.Dataflow
                 if (parameterValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None)
                 {
                     MultiValue value = GetValueForCustomAttributeArgument(arguments[parameter.MetadataIndex]);
-                    var diagnosticContext = new DiagnosticContext(_origin, diagnosticsEnabled: true, _logger);
-                    RequireDynamicallyAccessedMembers(diagnosticContext, value, parameterValue, method.GetDisplayName(), ref result);
+                    RequireDynamicallyAccessedMembers(_diagnosticContext, value, parameterValue, method.GetDisplayName(), ref result);
                 }
             }
         }
 
-        public void ProcessAttributeDataflow(FieldDesc field, object? value, ref DependencyList? result)
+        private void ProcessAttributeDataflow(FieldDesc field, object? value, ref DependencyList? result)
         {
             var fieldValueCandidate = _annotations.GetFieldValue(field);
             if (fieldValueCandidate is ValueWithDynamicallyAccessedMembers fieldValue
                 && fieldValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None)
             {
                 MultiValue valueNode = GetValueForCustomAttributeArgument(value);
-                var diagnosticContext = new DiagnosticContext(_origin, diagnosticsEnabled: true, _logger);
-                RequireDynamicallyAccessedMembers(diagnosticContext, valueNode, fieldValue, field.GetDisplayName(), ref result);
+                RequireDynamicallyAccessedMembers(_diagnosticContext, valueNode, fieldValue, field.GetDisplayName(), ref result);
             }
         }
 
index 265d84f..b097986 100644 (file)
@@ -57,6 +57,13 @@ namespace ILCompiler.Dataflow
                 field.DoesFieldRequire(DiagnosticUtilities.RequiresDynamicCodeAttribute, out _);
         }
 
+        internal static void CheckAndReportAllRequires(in DiagnosticContext diagnosticContext, TypeSystemEntity calledMember)
+        {
+            CheckAndReportRequires(diagnosticContext, calledMember, DiagnosticUtilities.RequiresUnreferencedCodeAttribute);
+            CheckAndReportRequires(diagnosticContext, calledMember, DiagnosticUtilities.RequiresDynamicCodeAttribute);
+            CheckAndReportRequires(diagnosticContext, calledMember, DiagnosticUtilities.RequiresAssemblyFilesAttribute);
+        }
+
         internal static void CheckAndReportRequires(in DiagnosticContext diagnosticContext, TypeSystemEntity calledMember, string requiresAttributeName)
         {
             if (!calledMember.DoesMemberRequire(requiresAttributeName, out var requiresAttribute))
@@ -358,9 +365,7 @@ namespace ILCompiler.Dataflow
                             }
                         }
 
-                        CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresUnreferencedCodeAttribute);
-                        CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute);
-                        CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresAssemblyFilesAttribute);
+                        CheckAndReportAllRequires(diagnosticContext, calledMethod);
 
                         return handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue);
                     }
index 3b0f976..b0ecb0e 100644 (file)
@@ -30,9 +30,7 @@ namespace ILCompiler.Dataflow
                 logger.ShouldSuppressAnalysisWarningsForRequires(Origin.MemberDefinition, DiagnosticUtilities.RequiresAssemblyFilesAttribute),
                 logger);
 
-            ReflectionMethodBodyScanner.CheckAndReportRequires(diagnosticContext, Field, DiagnosticUtilities.RequiresUnreferencedCodeAttribute);
-            ReflectionMethodBodyScanner.CheckAndReportRequires(diagnosticContext, Field, DiagnosticUtilities.RequiresDynamicCodeAttribute);
-            ReflectionMethodBodyScanner.CheckAndReportRequires(diagnosticContext, Field, DiagnosticUtilities.RequiresAssemblyFilesAttribute);
+            ReflectionMethodBodyScanner.CheckAndReportAllRequires(diagnosticContext, Field);
         }
     }
 }
index c4cf5c8..0d7f824 100644 (file)
@@ -300,11 +300,7 @@ namespace ILCompiler.Logging
 
             if (Origin?.MemberDefinition != null)
             {
-                if (Origin?.MemberDefinition is MethodDesc method)
-                    sb.Append(method.GetDisplayName());
-                else
-                    sb.Append(Origin?.MemberDefinition.ToString());
-
+                sb.Append(Origin?.MemberDefinition?.GetDisplayName() ?? Origin?.MemberDefinition?.ToString());
                 sb.Append(": ");
             }
 
index 5e4b824..561efc1 100644 (file)
@@ -25,6 +25,8 @@ namespace ILCompiler.Logging
         public int? SourceColumn { get; }
         public int? ILOffset { get; }
 
+        private const int HiddenLineNumber = 0xfeefee;
+
         public MessageOrigin(string fileName, int? sourceLine = null, int? sourceColumn = null)
         {
             FileName = fileName;
@@ -56,9 +58,7 @@ namespace ILCompiler.Logging
 
         public MessageOrigin(MethodIL methodBody, int ilOffset)
         {
-            string? document = null;
-            int? lineNumber = null;
-
+            ILSequencePoint? correspondingSequencePoint = null;
             IEnumerable<ILSequencePoint>? sequencePoints = methodBody.GetDebugInfo()?.GetSequencePoints();
             if (sequencePoints != null)
             {
@@ -66,14 +66,30 @@ namespace ILCompiler.Logging
                 {
                     if (sequencePoint.Offset <= ilOffset)
                     {
-                        document = sequencePoint.Document;
-                        lineNumber = sequencePoint.LineNumber;
+                        correspondingSequencePoint = sequencePoint;
+                    }
+                }
+
+                // If the warning comes from hidden line (compiler generated code typically)
+                // search for any sequence point with non-hidden line number and report that as a best effort.
+                if (correspondingSequencePoint?.LineNumber == HiddenLineNumber)
+                {
+                    // Reset the information as we don't want to use any of the info in the hidden sequence point
+                    correspondingSequencePoint = null;
+                    foreach (var sequencePoint in sequencePoints)
+                    {
+                        if (sequencePoint.LineNumber != HiddenLineNumber)
+                        {
+                            correspondingSequencePoint = sequencePoint;
+                            break;
+                        }
                     }
                 }
+
             }
-            FileName = document;
+            FileName = correspondingSequencePoint?.Document;
             MemberDefinition = methodBody.OwningMethod;
-            SourceLine = lineNumber;
+            SourceLine = correspondingSequencePoint?.LineNumber;
             SourceColumn = null;
             ILOffset = ilOffset;
         }
index 18fc51f..86edad4 100644 (file)
@@ -8,14 +8,19 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
 
 namespace Mono.Linker.Tests.Cases.RequiresCapability
 {
-       [IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/82447", IgnoredBy = Tool.NativeAot)]
        [SkipKeptItemsValidation]
        [ExpectedNoWarnings]
        class RequiresOnAttribute
        {
+               // Using these as a simple way to suppress all warning in Main
+               // it causes lot of warning due to DAM marking everything in the class.
+               [RequiresUnreferencedCode ("main")]
+               [RequiresDynamicCode ("main")]
+               [RequiresAssemblyFiles ("main")]
                public static void Main ()
                {
                        TestRequiresOnAttributeOnGenericParameter ();
@@ -24,7 +29,15 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                        _fieldWithAttributeWhichRequires = 0;
                        PropertyWithAttributeWhichRequires = false;
                        TestMethodWhichRequiresWithAttributeWhichRequires ();
+                       RequiresTriggeredByAttributeUsage.Test ();
+
+                       // Accessing the members to test via direct calls/access is not enough
+                       // in NativeAOT custom attributes are only looked at if the member is
+                       // reflection enabled - so there has to be a reflection access to it somewhere.
+                       // On the other hand the analyzer reports RDC/RAF only on direct access. So we need to have "both"
+                       typeof (RequiresOnAttribute).RequiresAll ();
                }
+
                class AttributeWhichRequiresAttribute : Attribute
                {
                        [RequiresUnreferencedCode ("Message for --AttributeWhichRequiresAttribute.ctor--")]
@@ -52,16 +65,16 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                }
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                class GenericTypeWithAttributedParameter<[AttributeWhichRequires] T>
                {
                        public static void TestMethod () { }
                }
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                static void GenericMethodWithAttributedParameter<[AttributeWhichRequires] T> () { }
 
                static void TestRequiresOnAttributeOnGenericParameter ()
@@ -71,11 +84,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                }
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [AttributeWhichRequires]
                [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)]
                class TypeWithAttributeWhichRequires
@@ -83,31 +96,36 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                }
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [AttributeWhichRequires]
                [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)]
                static void MethodWithAttributeWhichRequires () { }
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [AttributeWhichRequires]
                [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)]
                static int _fieldWithAttributeWhichRequires;
 
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer)]
+               // https://github.com/dotnet/runtime/issues/83581
+               [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Trimmer)] // Trimmer can produce duplicate warnings for property access
+               [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Trimmer)] // Trimmer can produce duplicate warnings for property access
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")]
-               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Trimmer)] // Trimmer can produce duplicate warnings for property access
+               [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Trimmer)] // Trimmer can produce duplicate warnings for property access
+               [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                [AttributeWhichRequires]
                [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)]
                static bool PropertyWithAttributeWhichRequires { get; set; }
@@ -120,11 +138,52 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                static void MethodWhichRequiresWithAttributeWhichRequires () { }
 
                [ExpectedWarning ("IL2026", "--MethodWhichRequiresWithAttributeWhichRequires--")]
-               [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer)]
+               [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                static void TestMethodWhichRequiresWithAttributeWhichRequires ()
                {
                        MethodWhichRequiresWithAttributeWhichRequires ();
                }
+
+               class RequiresTriggeredByAttributeUsage
+               {
+                       class AttributeWhichMarksPublicMethods : Attribute
+                       {
+                               public AttributeWhichMarksPublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { }
+                       }
+
+                       class TypeWithMethodWhichRequires
+                       {
+                               [RequiresUnreferencedCode ("--TypeWithMethodWhichRequires--")]
+                               [RequiresDynamicCode ("--TypeWithMethodWhichRequires--")]
+                               [RequiresAssemblyFiles ("--TypeWithMethodWhichRequires--")]
+                               public void MethodWhichRequires () { }
+                       }
+
+                       [ExpectedWarning ("IL2026", "--TypeWithMethodWhichRequires--")]
+                       [ExpectedWarning ("IL3002", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)]
+                       [ExpectedWarning ("IL3050", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)]
+                       [AttributeWhichMarksPublicMethods (typeof(TypeWithMethodWhichRequires))]
+                       static void ShouldWarn()
+                       {
+                       }
+
+                       [RequiresUnreferencedCode ("test")]
+                       [RequiresDynamicCode ("test")]
+                       [RequiresAssemblyFiles ("test")]
+                       [AttributeWhichMarksPublicMethods (typeof (TypeWithMethodWhichRequires))]
+                       static void SuppressedDueToRequires()
+                       {
+                       }
+
+                       [UnconditionalSuppressMessage("test", "IL2026")]
+                       [UnconditionalSuppressMessage ("test", "IL3002")]
+                       [UnconditionalSuppressMessage ("test", "IL3050")]
+                       public static void Test()
+                       {
+                               ShouldWarn ();
+                               SuppressedDueToRequires ();
+                       }
+               }
        }
 }
index b794c97..2e0c92c 100644 (file)
@@ -4,20 +4,20 @@
 using System;
 using System.Diagnostics.CodeAnalysis;
 using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
 using Mono.Linker.Tests.Cases.Expectations.Metadata;
 using Mono.Linker.Tests.Cases.RequiresCapability.Dependencies;
 
 namespace Mono.Linker.Tests.Cases.RequiresCapability
 {
-       [IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/82447", IgnoredBy = Tool.NativeAot)]
        [SetupLinkerAction ("link", "test.exe")]
        [SetupCompileBefore ("RequiresOnAttributeCtor.dll", new[] { "Dependencies/RequiresOnAttributeCtorAttribute.cs" })]
        [SkipKeptItemsValidation]
        [ExpectedNoWarnings]
        public class RequiresOnAttributeCtor
        {
-               [ExpectedWarning ("IL2026", "RUC on MethodAnnotatedWithRequires")]
-               [ExpectedWarning ("IL2026", "RUC on TestTypeWithRequires")]
+               // Simple way to suppress all warnings in Main
+               [RequiresUnreferencedCode ("main")]
                public static void Main ()
                {
                        var type = new Type ();
@@ -31,6 +31,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                        Type.Interface annotatedInterface = new Type.NestedType ();
 
                        TestTypeWithRequires ();
+
+                       typeof (RequiresOnAttributeCtor).RequiresAll ();
                }
 
                [RequiresUnreferencedCode ("RUC on TestTypeWithRequires")]
index 822c1a9..edad844 100644 (file)
@@ -1061,11 +1061,18 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                        }
                }
 
-               // https://github.com/dotnet/runtime/issues/82447
                [AttributeWithRequires (PropertyOnAttribute = 42)]
-               [ExpectedWarning ("IL2026", "AttributeWithRequires.AttributeWithRequires()", ProducedBy = Tool.Trimmer | Tool.Analyzer)]
-               [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", ProducedBy = Tool.Analyzer)]
-               static void KeepFieldOnAttribute () { }
+               [ExpectedWarning ("IL2026", "AttributeWithRequires.AttributeWithRequires()")]
+               [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", ProducedBy = Tool.Analyzer | Tool.NativeAot)]
+               static void KeepFieldOnAttributeInner () { }
+
+               static void KeepFieldOnAttribute ()
+               {
+                       KeepFieldOnAttributeInner ();
+
+                       // NativeAOT only considers attribute on reflection visible members
+                       typeof (RequiresOnClass).GetMethod (nameof (KeepFieldOnAttributeInner), BindingFlags.NonPublic | BindingFlags.Static).Invoke (null, new object[] { });
+               }
 
                public class AttributeParametersAndProperties
                {
@@ -1166,9 +1173,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                                        }
                                }
 
-                               // https://github.com/dotnet/runtime/issues/82447
                                // NOTE: The enclosing RUC does not apply to nested types.
-                               [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--", ProducedBy = Tool.Trimmer | Tool.Analyzer)]
+                               [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--")]
                                [RequiresOnCtor]
                                public class ClassWithAttribute
                                {