From 0b4ffc86ae00c6577433602cb90eab6ffb82f92f Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 21 Jul 2025 14:23:50 -0700 Subject: [PATCH 1/4] Add ExcludeStatics tests --- .../Compiler/Dataflow/DiagnosticUtilities.cs | 24 +- .../TestCaseCompilationMetadataProvider.cs | 6 + .../RequiresISymbolExtensions.cs | 36 +- .../RequiresDynamicCodeAttribute.cs | 48 + .../RequiresUnreferencedCodeAttribute.cs | 49 + .../illink/src/linker/Linker/Annotations.cs | 18 +- .../Linker/LinkerAttributesInformation.cs | 16 +- .../illink/src/linker/Mono.Linker.csproj | 2 + .../RequiresCapabilityTests.cs | 12 + .../TestCaseCompilation.cs | 19 +- .../TestCaseUtils.cs | 2 +- ...ono.Linker.Tests.Cases.Expectations.csproj | 2 + .../Mono.Linker.Tests.Cases.csproj | 2 + .../RequiresCapability/RequiresIsolated.cs | 42 + .../RequiresCapability/RequiresOnClass.cs | 3 +- .../RequiresOnClassExcludeStatics.cs | 1317 +++++++++++++++++ .../TestCaseCompilationMetadataProvider.cs | 6 + 17 files changed, 1584 insertions(+), 20 deletions(-) create mode 100644 src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs create mode 100644 src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs index 9f5bb5b0bd4a5f..3692f1448f9683 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs @@ -101,7 +101,13 @@ internal static bool IsInRequiresScope(this MethodDesc method, string requiresAt return true; if (method.OwningType is TypeDesc type && TryGetRequiresAttribute(type, requiresAttribute, out attribute)) - return true; + { + if (!ExcludeStatics(attribute.Value)) + return true; + + if (!method.Signature.IsStatic) + return true; + } if (method.GetPropertyForAccessor() is PropertyPseudoDesc property && TryGetRequiresAttribute(property, requiresAttribute, out attribute)) return true; @@ -123,7 +129,13 @@ internal static bool DoesMethodRequire(this MethodDesc method, string requiresAt if ((method.Signature.IsStatic || method.IsConstructor) && method.OwningType is TypeDesc owningType && !owningType.IsArray && TryGetRequiresAttribute(owningType, requiresAttribute, out attribute)) - return true; + { + if (!ExcludeStatics(attribute.Value)) + return true; + + if (method.IsConstructor) + return true; + } if (method.GetPropertyForAccessor() is PropertyPseudoDesc @property && TryGetRequiresAttribute(@property, requiresAttribute, out attribute)) @@ -144,7 +156,7 @@ internal static bool DoesFieldRequire(this FieldDesc field, string requiresAttri return false; } - return TryGetRequiresAttribute(field.OwningType, requiresAttribute, out attribute); + return TryGetRequiresAttribute(field.OwningType, requiresAttribute, out attribute) && !ExcludeStatics(attribute.Value); } internal static bool DoesPropertyRequire(this PropertyPseudoDesc property, string requiresAttribute, [NotNullWhen(returnValue: true)] out CustomAttributeValue? attribute) => @@ -174,6 +186,12 @@ internal static bool DoesMemberRequire(this TypeSystemEntity member, string requ }; } + private static bool ExcludeStatics(CustomAttributeValue attribute) => + attribute.NamedArguments.Length == 1 && + attribute.NamedArguments[0].Name == "ExcludeStatics" && + attribute.NamedArguments[0].Value is bool excludeStatics && + excludeStatics; + internal const string RequiresUnreferencedCodeAttribute = nameof(RequiresUnreferencedCodeAttribute); internal const string RequiresDynamicCodeAttribute = nameof(RequiresDynamicCodeAttribute); internal const string RequiresAssemblyFilesAttribute = nameof(RequiresAssemblyFilesAttribute); diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index f44456c12efd7c..f8fe337cb5cd34 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -138,6 +138,12 @@ public IEnumerable GetCommonSourceFiles() .Combine("Support") .Combine("DynamicallyAccessedMembersAttribute.cs"); yield return dam; + + var sharedDir = _testCase.RootCasesDirectory.Parent.Parent + .Combine("src") + .Combine("ILLink.Shared"); + yield return sharedDir.Combine("RequiresDynamicCodeAttribute.cs"); + yield return sharedDir.Combine("RequiresUnreferencedCodeAttribute.cs"); } public virtual IEnumerable GetCommonReferencedAssemblies(NPath workingDirectory) diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs index 7189f424441b1f..e5672cf070398c 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs @@ -22,8 +22,14 @@ public static bool DoesMemberRequire(this ISymbol member, string requiresAttribu return true; // Also check the containing type - if (member.IsStatic || member.IsConstructor()) - return member.ContainingType.TryGetAttribute(requiresAttribute, out requiresAttributeData); + if ((member.IsStatic || member.IsConstructor()) && member.ContainingType.TryGetAttribute(requiresAttribute, out requiresAttributeData)) + { + if (!ExcludeStatics(requiresAttributeData)) + return true; + + if (member.IsConstructor()) + return true; + } return false; } @@ -33,6 +39,18 @@ public static bool IsInRequiresScope(this ISymbol member, string attributeName) return member.IsInRequiresScope(attributeName, out _); } + private static bool ExcludeStatics(AttributeData attributeData) + { + foreach (var namedArg in attributeData.NamedArguments) + { + if (namedArg.Key == "ExcludeStatics" && namedArg.Value.Value is bool b) + { + return b; + } + } + return false; + } + // TODO: Consider sharing with ILLink IsInRequiresScope method /// /// True if the source of a call is considered to be annotated with the Requires... attribute @@ -58,7 +76,19 @@ public static bool IsInRequiresScope(this ISymbol member, string attributeName, } if (member.ContainingType is ITypeSymbol containingType && containingType.TryGetAttribute(attributeName, out requiresAttribute)) - return true; + { + if (containingType.Name == "ClassWithRequires" && + containingType.ContainingType is ITypeSymbol containingTypeContainingType && + containingTypeContainingType.Name == "RequiresOnClassExcludeStatics") + { + containingType.TryGetAttribute(attributeName, out _); + } + if (!ExcludeStatics(requiresAttribute)) + return true; + + if (!member.IsStatic) + return true; + } if (member is IMethodSymbol { AssociatedSymbol: { } associated } && associated.TryGetAttribute(attributeName, out requiresAttribute)) return true; diff --git a/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs new file mode 100644 index 00000000000000..d7220b680549d7 --- /dev/null +++ b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that the specified method requires the ability to generate new code at runtime, + /// for example through . + /// + /// + /// This allows tools to understand which methods are unsafe to call when compiling ahead of time. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class RequiresDynamicCodeAttribute : Attribute + { + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of dynamic code. + /// + public RequiresDynamicCodeAttribute(string message) + { + Message = message; + } + + public bool ExcludeStatics { get; set; } + + /// + /// Gets a message that contains information about the usage of dynamic code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires dynamic code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } + } +} diff --git a/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs new file mode 100644 index 00000000000000..b41ffc9de5ccac --- /dev/null +++ b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that the specified method requires dynamic access to code that is not referenced + /// statically, for example through . + /// + /// + /// This allows tools to understand which methods are unsafe to call when removing unreferenced + /// code from an application. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class RequiresUnreferencedCodeAttribute : Attribute + { + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of unreferenced code. + /// + public RequiresUnreferencedCodeAttribute(string message) + { + Message = message; + } + + public bool ExcludeStatics { get; set; } + + /// + /// Gets a message that contains information about the usage of unreferenced code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires unreferenced code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } + } +} diff --git a/src/tools/illink/src/linker/Linker/Annotations.cs b/src/tools/illink/src/linker/Linker/Annotations.cs index df777fc7901b5c..1518bd5407c088 100644 --- a/src/tools/illink/src/linker/Linker/Annotations.cs +++ b/src/tools/illink/src/linker/Linker/Annotations.cs @@ -626,7 +626,13 @@ internal bool IsInRequiresUnreferencedCodeScope(MethodDefinition method, [NotNul return true; if (method.DeclaringType is not null && TryGetLinkerAttribute(method.DeclaringType, out attribute)) - return true; + { + if (!attribute.ExcludeStatics) + return true; + + if (!method.IsStatic) + return true; + } attribute = null; return false; @@ -676,7 +682,13 @@ internal bool DoesMethodRequireUnreferencedCode(MethodDefinition originalMethod, if ((method.IsStatic || method.IsConstructor) && method.DeclaringType is not null && TryGetLinkerAttribute(method.DeclaringType, out attribute)) - return true; + { + if (!attribute.ExcludeStatics) + return true; + + if (method.IsConstructor) + return true; + } } while (context.CompilerGeneratedState.TryGetOwningMethodForCompilerGeneratedMember(method, out method)); attribute = null; @@ -691,7 +703,7 @@ internal bool DoesFieldRequireUnreferencedCode(FieldDefinition field, [NotNullWh return false; } - return TryGetLinkerAttribute(field.DeclaringType, out attribute); + return TryGetLinkerAttribute(field.DeclaringType, out attribute) && !attribute.ExcludeStatics; } /// diff --git a/src/tools/illink/src/linker/Linker/LinkerAttributesInformation.cs b/src/tools/illink/src/linker/Linker/LinkerAttributesInformation.cs index 1aa5abe6a0c217..c343ff3a1ede44 100644 --- a/src/tools/illink/src/linker/Linker/LinkerAttributesInformation.cs +++ b/src/tools/illink/src/linker/Linker/LinkerAttributesInformation.cs @@ -120,20 +120,28 @@ public IEnumerable GetAttributes() where T : Attribute if (customAttribute.HasConstructorArguments && customAttribute.ConstructorArguments[0].Value is string message) { - var ruca = new RequiresUnreferencedCodeAttribute(message); + string? url = null; + bool excludeStatics = false; if (customAttribute.HasProperties) { foreach (var prop in customAttribute.Properties) { if (prop.Name == "Url") { - ruca.Url = prop.Argument.Value as string; - break; + url = prop.Argument.Value as string; + } + else if (prop.Name == "ExcludeStatics" && prop.Argument.Value is true) + { + excludeStatics = true; } } } - return ruca; + return new RequiresUnreferencedCodeAttribute(message) + { + Url = url, + ExcludeStatics = excludeStatics + }; } context.LogWarning((IMemberDefinition)provider, DiagnosticId.AttributeDoesntHaveTheRequiredNumberOfParameters, typeof(RequiresUnreferencedCodeAttribute).FullName ?? ""); diff --git a/src/tools/illink/src/linker/Mono.Linker.csproj b/src/tools/illink/src/linker/Mono.Linker.csproj index af73b43ef4cdcf..35293cd7078a82 100644 --- a/src/tools/illink/src/linker/Mono.Linker.csproj +++ b/src/tools/illink/src/linker/Mono.Linker.csproj @@ -21,6 +21,8 @@ Major false $(NoWarn);NU5131 + + $(NoWarn);CS0436 $(TargetsForTfmSpecificContentInPackage);_AddReferenceAssemblyToPackage $(DefineConstants);ILLINK true diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs index ec1b99aef0f068..88c84d35aa67e3 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs @@ -88,6 +88,18 @@ public Task RequiresOnClass() return RunTest(nameof(RequiresOnClass)); } + [Fact] + public Task RequiresOnClassExcludeStatics() + { + return RunTest(); + } + + [Fact] + public Task RequiresIsolated() + { + return RunTest(); + } + [Fact] public Task RequiresOnEvents() { diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs index 5181d88744efb6..a7a0453742adb9 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs @@ -45,11 +45,20 @@ public static (CompilationWithAnalyzers Compilation, SemanticModel SemanticModel var sources = new List() { src }; sources.AddRange(additionalSources ?? Array.Empty()); TestCaseUtils.GetDirectoryPaths(out string rootSourceDirectory); - var commonSourcePath = Path.Combine(Path.GetDirectoryName(rootSourceDirectory)!, - "Mono.Linker.Tests.Cases.Expectations", - "Support", - "DynamicallyAccessedMembersAttribute.cs"); - sources.Add(CSharpSyntaxTree.ParseText(File.ReadAllText(commonSourcePath), path: commonSourcePath)); + var testDir = Path.GetDirectoryName(rootSourceDirectory)!; + var srcDir = Path.Combine(Path.GetDirectoryName(testDir)!, "src"); + var sharedDir = Path.Combine(srcDir, "ILLink.Shared"); + var commonSourcePaths = new List() + { + Path.Combine(testDir, + "Mono.Linker.Tests.Cases.Expectations", + "Support", + "DynamicallyAccessedMembersAttribute.cs"), + Path.Combine(sharedDir, "RequiresUnreferencedCodeAttribute.cs"), + Path.Combine(sharedDir, "RequiresDynamicCodeAttribute.cs"), + }; + + sources.AddRange(commonSourcePaths.Select(p => CSharpSyntaxTree.ParseText(File.ReadAllText(p), path: p))); var comp = CSharpCompilation.Create( assemblyName: Guid.NewGuid().ToString("N"), syntaxTrees: sources, diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index 7de145d1423032..baa3a5b96831b0 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -58,7 +58,7 @@ public static async Task RunTestFile(string suiteName, string testName, bool all testCaseDir = testSuiteDir; testPath = Path.Combine(testSuiteDir, $"{testName}.cs"); } - Assert.True(File.Exists(testPath)); + Assert.True(File.Exists(testPath), $"{testPath} should exist"); var tree = SyntaxFactory.ParseSyntaxTree( SourceText.From(File.OpenRead(testPath), Encoding.UTF8), path: testPath); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj index 09d87f8f83f020..6211174e391459 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj @@ -5,5 +5,7 @@ + + diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj index ccc1d915f1515c..c2f17e501e555c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj @@ -68,6 +68,8 @@ + + diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs new file mode 100644 index 00000000000000..4c2745d80f8f14 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs @@ -0,0 +1,42 @@ +// 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.Helpers; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + class RequiresIsolated + { + public static void Main() + { + MembersOnClassWithRequires.Test(); + } + + class MembersOnClassWithRequires + { + public class RequiresAll<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] U> + { + } + + [RequiresDynamicCode("--ClassWithRequires--", ExcludeStatics = true)] + public class ClassWithRequires + { + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + public static RequiresAll field; + } + + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + public static void Test(ClassWithRequires inst = null) + { + var f = ClassWithRequires.field; + } + + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index ec8d7a1b92a313..967f9b2c6eed39 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -82,6 +82,8 @@ public static void TestSuppressions(Type[] types) void LocalFunction(int a) { } LocalFunction(2); + + AttributedMethod(); } // The attribute would generate warning, but it is suppressed due to the Requires on the type @@ -1322,7 +1324,6 @@ public class ClassWithRequires { public static RequiresAll field; - // Instance fields get generic warnings but static fields don't. [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/108523")] public RequiresAll instanceField; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs new file mode 100644 index 00000000000000..54035b121b9977 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs @@ -0,0 +1,1317 @@ +// 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.Helpers; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + class RequiresOnClassExcludeStatics + { + public static void Main() + { + TestRequiresInClassAccessedByStaticMethod(); + TestRequiresInParentClassAccesedByStaticMethod(); + TestRequiresInClassAccessedByCctor(); + TestRequiresOnBaseButNotOnDerived(); + TestRequiresOnDerivedButNotOnBase(); + TestRequiresOnBaseAndDerived(); + TestInstanceFieldSuppression(); + TestSuppressionsOnClass(); + TestStaticMethodOnRequiresTypeSuppressedByRequiresOnMethod(); + TestStaticConstructorCalls(); + TestOtherMemberTypesWithRequires(); + TestNameOfDoesntWarn(); + ReflectionAccessOnMethod.Test(); + ReflectionAccessOnCtor.Test(); + ReflectionAccessOnField.Test(); + ReflectionAccessOnEvents.Test(); + ReflectionAccessOnProperties.Test(); + KeepFieldOnAttribute(); + AttributeParametersAndProperties.Test(); + MembersOnClassWithRequires.Test(); + ConstFieldsOnClassWithRequires.Test(); + } + + [RequiresUnreferencedCode("Message for --ClassWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --ClassWithRequires--", ExcludeStatics = true)] + class ClassWithRequires + { + public static object Instance; + + public ClassWithRequires() { } + + public static void StaticMethod() { } + + public void NonStaticMethod() { } + + [ExpectedWarning("IL2026", "RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] + [ExpectedWarning("IL3050", "RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + public static void CallMethodWithRequires() => RequiresOnMethod.MethodWithRequires(); + + public class NestedClass + { + public static void NestedStaticMethod() { } + + // This warning doesn't get suppressed since the declaring type NestedClass is not annotated with Requires + [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] + [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + public static void CallMethodWithRequires() => RequiresOnMethod.MethodWithRequires(); + } + + // RequiresUnfereferencedCode on the type will suppress IL2072 + static ClassWithRequires() + { + Instance = Activator.CreateInstance(Type.GetType("SomeText")); + } + + [ExpectedWarning("IL2065", "GetMethods")] + public static void TestSuppressions(Type[] types) + { + // StaticMethod is a static method on a Requires annotated type, so it should warn. But Requires in the + // class suppresses other Requires messages + StaticMethod(); + + var nested = new NestedClass(); + + // Requires in the class suppresses DynamicallyAccessedMembers messages + types[1].GetMethods(); + + void LocalFunction(int a) { } + LocalFunction(2); + + AttributedMethod(); + typeof(ClassWithRequires).GetMethod("AttributedMethod"); + } + + [ExpectedWarning("IL2026", "AttributeWithRequires.AttributeWithRequires()")] + [ExpectedWarning("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [AttributeWithRequires()] + public static void AttributedMethod() { } + } + + class RequiresOnMethod + { + [RequiresUnreferencedCode("MethodWithRequires", ExcludeStatics = true)] + [RequiresDynamicCode("MethodWithRequires", ExcludeStatics = true)] + public static void MethodWithRequires() { } + } + + [ExpectedWarning("IL2109", "RequiresOnClassExcludeStatics.DerivedWithoutRequires", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--")] + private class DerivedWithoutRequires : ClassWithRequires + { + // This method contains implicit call to ClassWithRequires.ctor() + [ExpectedWarning("IL2026")] + [ExpectedWarning("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + public DerivedWithoutRequires() { } + + public static void StaticMethodInInheritedClass() { } + + public class DerivedNestedClass + { + public static void NestedStaticMethod() { } + } + + public static void ShouldntWarn(object objectToCast) + { + _ = typeof(ClassWithRequires); + var type = (ClassWithRequires)objectToCast; + } + } + + // In order to generate IL2109 the nested class would also need to be annotated with Requires + // otherwise we threat the nested class as safe + private class DerivedWithoutRequires2 : ClassWithRequires.NestedClass + { + public static void StaticMethod() { } + } + + [UnconditionalSuppressMessage("trim", "IL2109")] + class TestUnconditionalSuppressMessage : ClassWithRequires + { + public static void StaticMethodInTestSuppressionClass() { } + } + + class ClassWithoutRequires + { + public ClassWithoutRequires() { } + + public static void StaticMethod() { } + + public void NonStaticMethod() { } + + public class NestedClass + { + public static void NestedStaticMethod() { } + } + } + + [RequiresUnreferencedCode("Message for --StaticCtor--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --StaticCtor--", ExcludeStatics = true)] + class StaticCtor + { + static StaticCtor() + { + } + } + + [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.StaticCtor.StaticCtor()", "Message for --StaticCtor--")] + [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.StaticCtor.StaticCtor()", "Message for --StaticCtor--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + static void TestStaticCctorRequires() + { + _ = new StaticCtor(); + } + + [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByFieldAccess--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --StaticCtorTriggeredByFieldAccess--", ExcludeStatics = true)] + class StaticCtorTriggeredByFieldAccess + { + static StaticCtorTriggeredByFieldAccess() + { + field = 0; + } + + public static int field; + } + + static void TestStaticCtorMarkingIsTriggeredByFieldAccessWrite() + { + StaticCtorTriggeredByFieldAccess.field = 1; + } + + static void TestStaticCtorMarkingTriggeredOnSecondAccessWrite() + { + StaticCtorTriggeredByFieldAccess.field = 2; + } + + [RequiresUnreferencedCode("--TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner--", ExcludeStatics = true)] + [RequiresDynamicCode("--TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner--", ExcludeStatics = true)] + static void TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner() + { + StaticCtorTriggeredByFieldAccess.field = 3; + } + + [UnconditionalSuppressMessage("test", "IL2026")] + [UnconditionalSuppressMessage("test", "IL3050")] + static void TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod() + { + TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner(); + } + + [RequiresUnreferencedCode("Message for --StaticCCtorTriggeredByFieldAccessRead--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --StaticCCtorTriggeredByFieldAccessRead--", ExcludeStatics = true)] + class StaticCCtorTriggeredByFieldAccessRead + { + public static int field = 42; + } + + static void TestStaticCtorMarkingIsTriggeredByFieldAccessRead() + { + var _ = StaticCCtorTriggeredByFieldAccessRead.field; + } + + [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByCtorCalls--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --StaticCtorTriggeredByCtorCalls--", ExcludeStatics = true)] + class StaticCtorTriggeredByCtorCalls + { + static StaticCtorTriggeredByCtorCalls() + { + } + + public void TriggerStaticCtorMarking() + { + } + } + + [ExpectedWarning("IL2026", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()")] + [ExpectedWarning("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + static void TestStaticCtorTriggeredByCtorCall() + { + new StaticCtorTriggeredByCtorCalls(); + } + + [RequiresUnreferencedCode("Message for --ClassWithInstanceField--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --ClassWithInstanceField--", ExcludeStatics = true)] + class ClassWithInstanceField + { + public int field = 42; + } + + [ExpectedWarning("IL2026", "ClassWithInstanceField.ClassWithInstanceField()")] + [ExpectedWarning("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + static void TestInstanceFieldCallDontWarn() + { + ClassWithInstanceField instance = new ClassWithInstanceField(); + var _ = instance.field; + } + + public class ClassWithInstanceFieldWhichInitsDangerousClass + { + private ClassWithRequires _instanceField = new ClassWithRequires(); + + [RequiresUnreferencedCode("Calling the constructor is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("Calling the constructor is dangerous", ExcludeStatics = true)] + public ClassWithInstanceFieldWhichInitsDangerousClass() { } + } + + [ExpectedWarning("IL2026", "Calling the constructor is dangerous")] + [ExpectedWarning("IL3050", "Calling the constructor is dangerous", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + static void TestInstanceFieldSuppression() + { + _ = new ClassWithInstanceFieldWhichInitsDangerousClass(); + } + + [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByMethodCall2--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --StaticCtorTriggeredByMethodCall2--", ExcludeStatics = true)] + class StaticCtorTriggeredByMethodCall2 + { + static StaticCtorTriggeredByMethodCall2() + { + } + + public void TriggerStaticCtorMarking() + { + } + } + + static void TestNullInstanceTryingToCallMethod() + { + StaticCtorTriggeredByMethodCall2 instance = null; + instance.TriggerStaticCtorMarking(); + } + + [RequiresUnreferencedCode("Message for --DerivedWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --DerivedWithRequires--", ExcludeStatics = true)] + private class DerivedWithRequires : ClassWithoutRequires + { + public static void StaticMethodInInheritedClass() { } + + public class DerivedNestedClass + { + public static void NestedStaticMethod() { } + } + } + + [RequiresUnreferencedCode("Message for --DerivedWithRequires2--", ExcludeStatics = true)] + [RequiresDynamicCode("Message for --DerivedWithRequires2--", ExcludeStatics = true)] + private class DerivedWithRequires2 : ClassWithRequires + { + public static void StaticMethodInInheritedClass() { } + + // A nested class is not considered a static method nor constructor therefore RequiresUnreferencedCode doesn't apply + // and this warning is not suppressed + [ExpectedWarning("IL2109", "RequiresOnClassExcludeStatics.DerivedWithRequires2.DerivedNestedClass", "--ClassWithRequires--")] + public class DerivedNestedClass : ClassWithRequires + { + // This method contains implicit call to ClassWithRequires.ctor() + [ExpectedWarning("IL2026")] + [ExpectedWarning("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + public DerivedNestedClass() { } + + public static void NestedStaticMethod() { } + } + } + + class BaseWithoutRequiresOnType + { + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + public virtual void Method() { } + } + + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + class DerivedWithRequiresOnType : BaseWithoutRequiresOnType + { + public override void Method() { } + } + + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + class BaseWithRequiresOnType + { + public virtual void Method() { } + } + + [ExpectedWarning("IL2109", nameof(BaseWithRequiresOnType))] + class DerivedWithoutRequiresOnType : BaseWithRequiresOnType + { + public override void Method() { } + } + + class BaseWithNoRequires + { + public virtual void Method() { } + } + + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + class DerivedWithRequiresOnTypeOverBaseWithNoRequires : BaseWithNoRequires + { + // Should not warn since the members are not static + public override void Method() + { + } + } + + public interface InterfaceWithoutRequires + { + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + static int Method() + { + return 0; + } + + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + int Method(int a); + } + + [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] + [RequiresDynamicCode("RDC", ExcludeStatics = true)] + class ImplementationWithRequiresOnType : InterfaceWithoutRequires + { + public static int Method() + { + return 1; + } + + public int Method(int a) + { + return a; + } + } + + static void TestRequiresInClassAccessedByStaticMethod() + { + ClassWithRequires.StaticMethod(); + } + + [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--")] + [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + static void TestRequiresInClassAccessedByCctor() + { + var classObject = new ClassWithRequires(); + } + + static void TestRequiresInParentClassAccesedByStaticMethod() + { + ClassWithRequires.NestedClass.NestedStaticMethod(); + } + + static void TestRequiresOnBaseButNotOnDerived() + { + var a = new DerivedWithoutRequires(); // Must instantiate to force checks on the base type (otherwise base type is non-interesting) + DerivedWithoutRequires.StaticMethodInInheritedClass(); + DerivedWithoutRequires.StaticMethod(); + DerivedWithoutRequires.CallMethodWithRequires(); + DerivedWithoutRequires.DerivedNestedClass.NestedStaticMethod(); + DerivedWithoutRequires.NestedClass.NestedStaticMethod(); + DerivedWithoutRequires.NestedClass.CallMethodWithRequires(); + DerivedWithoutRequires.ShouldntWarn(null); + DerivedWithoutRequires.Instance.ToString(); + DerivedWithoutRequires2.StaticMethod(); + } + + static void TestRequiresOnDerivedButNotOnBase() + { + DerivedWithRequires.StaticMethodInInheritedClass(); + DerivedWithRequires.StaticMethod(); + DerivedWithRequires.DerivedNestedClass.NestedStaticMethod(); + DerivedWithRequires.NestedClass.NestedStaticMethod(); + } + + static void TestRequiresOnBaseAndDerived() + { + DerivedWithRequires2.StaticMethodInInheritedClass(); + DerivedWithRequires2.StaticMethod(); + var a = new DerivedWithRequires2.DerivedNestedClass(); + DerivedWithRequires2.DerivedNestedClass.NestedStaticMethod(); + DerivedWithRequires2.NestedClass.NestedStaticMethod(); + } + + static void TestSuppressionsOnClass() + { + ClassWithRequires.TestSuppressions(new[] { typeof(ClassWithRequires) }); + TestUnconditionalSuppressMessage.StaticMethodInTestSuppressionClass(); + } + + [RequiresUnreferencedCode("--StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod--", ExcludeStatics = true)] + [RequiresDynamicCode("--StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod--", ExcludeStatics = true)] + static void StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod() + { + DerivedWithRequires.StaticMethodInInheritedClass(); + } + + [UnconditionalSuppressMessage("test", "IL2026")] + [UnconditionalSuppressMessage("test", "IL3050")] + static void TestStaticMethodOnRequiresTypeSuppressedByRequiresOnMethod() + { + StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod(); + } + + static void TestStaticConstructorCalls() + { + TestStaticCctorRequires(); + TestStaticCtorMarkingIsTriggeredByFieldAccessWrite(); + TestStaticCtorMarkingTriggeredOnSecondAccessWrite(); + TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod(); + TestStaticCtorMarkingIsTriggeredByFieldAccessRead(); + //TestStaticCtorTriggeredByMethodCall(); + TestStaticCtorTriggeredByCtorCall(); + TestInstanceFieldCallDontWarn(); + } + + [RequiresUnreferencedCode("--MemberTypesWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--MemberTypesWithRequires--", ExcludeStatics = true)] + class MemberTypesWithRequires + { + public static int field; + public static int Property { get; set; } + + public static event EventHandler Event; + } + + static void TestOtherMemberTypesWithRequires() + { + MemberTypesWithRequires.field = 1; + MemberTypesWithRequires.Property = 1; + MemberTypesWithRequires.Event -= null; + } + + static void TestNameOfDoesntWarn() + { + _ = nameof(ClassWithRequires.StaticMethod); + _ = nameof(MemberTypesWithRequires.field); + _ = nameof(MemberTypesWithRequires.Property); + _ = nameof(MemberTypesWithRequires.Event); + } + + class ReflectionAccessOnMethod + { + [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method(Int32)")] + [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method()")] + [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] + [ExpectedWarning("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", Tool.NativeAot, "")] + static void TestDAMAccess() + { + // Warns because BaseWithoutRequiresOnType.Method has Requires on the method + typeof(BaseWithoutRequiresOnType).RequiresPublicMethods(); + + // Doesn't warn because DerivedWithRequiresOnType doesn't have any static methods + typeof(DerivedWithRequiresOnType).RequiresPublicMethods(); + + // Warns twice since both methods on InterfaceWithoutRequires have RUC on the method + typeof(InterfaceWithoutRequires).RequiresPublicMethods(); + + // Warns because ImplementationWithRequiresOnType.Method is a static public method on a RUC type + typeof(ImplementationWithRequiresOnType).RequiresPublicMethods(); + + // Warns for instance method on BaseWithRequiresOnType + typeof(BaseWithRequiresOnType).RequiresPublicMethods(); + + // Warns for instance method on base type + typeof(DerivedWithoutRequiresOnType).RequiresPublicMethods(); + + // Doesn't warn since the type has no statics + typeof(DerivedWithRequiresOnTypeOverBaseWithNoRequires).RequiresPublicMethods(); + } + + [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] + [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method(Int32)")] + [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method()")] + [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] + [ExpectedWarning("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] + static void TestDirectReflectionAccess() + { + // Requires on the method itself + typeof(BaseWithoutRequiresOnType).GetMethod(nameof(BaseWithoutRequiresOnType.Method)); + + // Requires on the method itself + typeof(InterfaceWithoutRequires).GetMethod(nameof(InterfaceWithoutRequires.Method)); + + // Warns for static and instance methods on ImplementationWithRequiresOnType + typeof(ImplementationWithRequiresOnType).GetMethod(nameof(ImplementationWithRequiresOnType.Method)); + + // Warns for instance Method on RUC type + typeof(BaseWithRequiresOnType).GetMethod(nameof(BaseWithRequiresOnType.Method)); + } + + public static void Test() + { + TestDAMAccess(); + TestDirectReflectionAccess(); + } + } + + class ReflectionAccessOnCtor + { + [RequiresUnreferencedCode("--BaseWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--BaseWithRequires--", ExcludeStatics = true)] + class BaseWithRequires + { + public BaseWithRequires() { } + } + + [ExpectedWarning("IL2109", "ReflectionAccessOnCtor.DerivedWithoutRequires", "ReflectionAccessOnCtor.BaseWithRequires")] + class DerivedWithoutRequires : BaseWithRequires + { + [ExpectedWarning("IL2026", "--BaseWithRequires--")] // The body has direct call to the base.ctor() + [ExpectedWarning("IL3050", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning")] + public DerivedWithoutRequires() { } + } + + [RequiresUnreferencedCode("--DerivedWithRequiresOnBaseWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedWithRequiresOnBaseWithRequires--", ExcludeStatics = true)] + class DerivedWithRequiresOnBaseWithRequires : BaseWithRequires + { + // No warning - suppressed by the Requires on this type + private DerivedWithRequiresOnBaseWithRequires() { } + } + + class BaseWithoutRequires { } + + [RequiresUnreferencedCode("--DerivedWithRequiresOnBaseWithout--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedWithRequiresOnBaseWithout--", ExcludeStatics = true)] + class DerivedWithRequiresOnBaseWithoutRequires : BaseWithoutRequires + { + public DerivedWithRequiresOnBaseWithoutRequires() { } + } + + [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] + [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] + [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] + static void TestDAMAccess() + { + // Warns because the type has Requires + typeof(BaseWithRequires).RequiresPublicConstructors(); + + // Doesn't warn since there's no Requires on this type + typeof(DerivedWithoutRequires).RequiresPublicParameterlessConstructor(); + + // Warns - Requires on the type + typeof(DerivedWithRequiresOnBaseWithRequires).RequiresNonPublicConstructors(); + + // Warns - Requires On the type + typeof(DerivedWithRequiresOnBaseWithoutRequires).RequiresPublicConstructors(); + } + + [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] + [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] + [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] + static void TestDirectReflectionAccess() + { + typeof(BaseWithRequires).GetConstructor(Type.EmptyTypes); + typeof(DerivedWithoutRequires).GetConstructor(Type.EmptyTypes); + typeof(DerivedWithRequiresOnBaseWithRequires).GetConstructor(BindingFlags.NonPublic, Type.EmptyTypes); + typeof(DerivedWithRequiresOnBaseWithoutRequires).GetConstructor(Type.EmptyTypes); + } + + public static void Test() + { + TestDAMAccess(); + TestDirectReflectionAccess(); + } + } + + class ReflectionAccessOnField + { + [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] + class WithRequires + { + public int InstanceField; + public static int StaticField; + private static int PrivateStaticField; + } + + [RequiresUnreferencedCode("--WithRequiresOnlyInstanceFields--", ExcludeStatics = true)] + [RequiresDynamicCode("--WithRequiresOnlyInstanceFields--", ExcludeStatics = true)] + class WithRequiresOnlyInstanceFields + { + public int InstanceField; + } + + [ExpectedWarning("IL2109", "ReflectionAccessOnField.DerivedWithoutRequires", "ReflectionAccessOnField.WithRequires")] + class DerivedWithoutRequires : WithRequires + { + public static int DerivedStaticField; + } + + [RequiresUnreferencedCode("--DerivedWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedWithRequires--", ExcludeStatics = true)] + class DerivedWithRequires : WithRequires + { + public static int DerivedStaticField; + } + + static void TestDAMAccess() + { + typeof(WithRequires).RequiresPublicFields(); + typeof(WithRequires).RequiresNonPublicFields(); + typeof(WithRequiresOnlyInstanceFields).RequiresPublicFields(); + typeof(DerivedWithoutRequires).RequiresPublicFields(); + typeof(DerivedWithRequires).RequiresPublicFields(); + } + + static void TestDirectReflectionAccess() + { + typeof(WithRequires).GetField(nameof(WithRequires.StaticField)); + typeof(WithRequires).GetField(nameof(WithRequires.InstanceField)); // Doesn't warn + typeof(WithRequires).GetField("PrivateStaticField", BindingFlags.NonPublic); + typeof(WithRequiresOnlyInstanceFields).GetField(nameof(WithRequiresOnlyInstanceFields.InstanceField)); // Doesn't warn + typeof(DerivedWithoutRequires).GetField(nameof(DerivedWithoutRequires.DerivedStaticField)); // Doesn't warn + typeof(DerivedWithRequires).GetField(nameof(DerivedWithRequires.DerivedStaticField)); + } + + [DynamicDependency(nameof(WithRequires.StaticField), typeof(WithRequires))] + [DynamicDependency(nameof(WithRequires.InstanceField), typeof(WithRequires))] // Doesn't warn + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(DerivedWithoutRequires))] // Doesn't warn + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(DerivedWithRequires))] + static void TestDynamicDependencyAccess() + { + } + + [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] + class BaseForDAMAnnotatedClass + { + public static int baseField; + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] + [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] + class DAMAnnotatedClass : BaseForDAMAnnotatedClass + { + public static int publicField; + + static int privatefield; + } + + static void TestDAMOnTypeAccess(DAMAnnotatedClass instance) + { + instance.GetType().GetField("publicField"); + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + class DAMAnnotatedClassAccessedFromRUCScope + { + [ExpectedWarning("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod")] + [RequiresUnreferencedCode("--RUCMethod--", ExcludeStatics = true)] + public static void RUCMethod() { } + } + + // RUC on the callsite to GetType should not suppress warnings about the + // attribute on the type. + [RequiresUnreferencedCode("--TestDAMOnTypeAccessInRUCScope--", ExcludeStatics = true)] + static void TestDAMOnTypeAccessInRUCScope(DAMAnnotatedClassAccessedFromRUCScope instance = null) + { + instance.GetType().GetMethod("RUCMethod"); + } + + [RequiresUnreferencedCode("--GenericTypeWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--GenericTypeWithRequires--", ExcludeStatics = true)] + class GenericTypeWithRequires + { + public static int NonGenericField; + } + + static void TestDAMAccessOnOpenGeneric() + { + typeof(GenericTypeWithRequires<>).RequiresPublicFields(); + } + + static void TestDAMAccessOnInstantiatedGeneric() + { + typeof(GenericTypeWithRequires).RequiresPublicFields(); + } + + [ExpectedWarning("IL2026", "--TestDAMOnTypeAccessInRUCScope--")] + [ExpectedWarning("IL2026", "DAMAnnotatedClass.DAMAnnotatedClass()")] + [ExpectedWarning("IL3050", "DAMAnnotatedClass.DAMAnnotatedClass()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] + public static void Test() + { + TestDAMAccess(); + TestDirectReflectionAccess(); + TestDynamicDependencyAccess(); + TestDAMOnTypeAccess(new DAMAnnotatedClass()); + TestDAMOnTypeAccessInRUCScope(new DAMAnnotatedClassAccessedFromRUCScope()); + TestDAMAccessOnOpenGeneric(); + TestDAMAccessOnInstantiatedGeneric(); + } + } + + class ReflectionAccessOnEvents + { + [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] + class WithRequires + { + public static event EventHandler StaticEvent; + public event EventHandler InstanceEvent; + private event EventHandler PrivateInstanceEvent; + } + + [RequiresUnreferencedCode("--DerivedRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedRequires--", ExcludeStatics = true)] + class DerivedRequires : WithRequires + { + public static event EventHandler DerivedStaticEvent; + public event EventHandler DerivedInstanceEvent; + private event EventHandler DerivedPrivateInstanceEvent; + } + + [ExpectedWarning("IL2109", "ReflectionAccessOnEvents.DerivedWithoutRequires", "ReflectionAccessOnEvents.WithRequires")] + class DerivedWithoutRequires : WithRequires + { + public static event EventHandler DerivedStaticEvent; + public event EventHandler DerivedInstanceEvent; + private event EventHandler DerivedPrivateInstanceEvent; + } + + static void ReflectOverSingleEvent() + { + typeof(WithRequires).GetEvent(nameof(WithRequires.StaticEvent)); + typeof(DerivedRequires).GetEvent(nameof(DerivedRequires.DerivedStaticEvent)); + typeof(DerivedWithoutRequires).GetEvent(nameof(DerivedWithoutRequires.DerivedStaticEvent)); + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + static void ReflectOverAllEvents() + { + typeof(WithRequires).GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] + static void DerivedReflectOverAllEvents() + { + typeof(DerivedRequires).GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + static void RequiresAllEvents() + { + RequiresAllEvents(typeof(WithRequires)); + + static void RequiresAllEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type t) + { } + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] + static void DerivedRequiresAllEvents() + { + RequiresAllEvents(typeof(DerivedRequires)); + + static void RequiresAllEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type t) + { } + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + static void RequiresPublicEvents() + { + typeof(WithRequires).RequiresPublicEvents(); + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] + static void DerivedRequiresPublicEvents() + { + typeof(DerivedRequires).RequiresPublicEvents(); + } + + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] + static void RequiresNonPublicEvents() + { + typeof(WithRequires).RequiresNonPublicEvents(); + } + + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] + [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] + static void DerivedRequiresNonPublicEvents() + { + typeof(DerivedRequires).RequiresNonPublicEvents(); + } + + public static void Test() + { + ReflectOverSingleEvent(); + ReflectOverAllEvents(); + RequiresAllEvents(); + RequiresPublicEvents(); + RequiresNonPublicEvents(); + DerivedReflectOverAllEvents(); + DerivedRequiresPublicEvents(); + DerivedRequiresNonPublicEvents(); + DerivedRequiresAllEvents(); + } + } + + class ReflectionAccessOnProperties + { + [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] + class WithRequires + { + public int InstanceProperty { get; set; } + public static int StaticProperty { get; set; } + private static int PrivateStaticProperty { get; set; } + } + + [RequiresUnreferencedCode("--WithRequiresOnlyInstanceProperties--", ExcludeStatics = true)] + [RequiresDynamicCode("--WithRequiresOnlyInstanceProperties--", ExcludeStatics = true)] + class WithRequiresOnlyInstanceProperties + { + public int InstanceProperty { get; set; } + } + + [ExpectedWarning("IL2109", "ReflectionAccessOnProperties.DerivedWithoutRequires", "ReflectionAccessOnProperties.WithRequires")] + class DerivedWithoutRequires : WithRequires + { + public static int DerivedStaticProperty { get; set; } + } + + [RequiresUnreferencedCode("--DerivedWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedWithRequires--", ExcludeStatics = true)] + class DerivedWithRequires : WithRequires + { + public static int DerivedStaticProperty { get; set; } + } + + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] + static void TestDAMAccess() + { + typeof(WithRequires).RequiresPublicProperties(); + typeof(WithRequires).RequiresNonPublicProperties(); + typeof(WithRequiresOnlyInstanceProperties).RequiresPublicProperties(); + typeof(DerivedWithoutRequires).RequiresPublicProperties(); + typeof(DerivedWithRequires).RequiresPublicProperties(); + } + + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] + [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] + [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] + static void TestDirectReflectionAccess() + { + typeof(WithRequires).GetProperty(nameof(WithRequires.StaticProperty)); + typeof(WithRequires).GetProperty(nameof(WithRequires.InstanceProperty)); + typeof(WithRequires).GetProperty("PrivateStaticProperty", BindingFlags.NonPublic); + typeof(WithRequiresOnlyInstanceProperties).GetProperty(nameof(WithRequiresOnlyInstanceProperties.InstanceProperty)); + typeof(DerivedWithoutRequires).GetProperty(nameof(DerivedWithRequires.DerivedStaticProperty)); // Doesn't warn + typeof(DerivedWithRequires).GetProperty(nameof(DerivedWithRequires.DerivedStaticProperty)); + } + + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [DynamicDependency(nameof(WithRequires.StaticProperty), typeof(WithRequires))] + [DynamicDependency(nameof(WithRequires.InstanceProperty), typeof(WithRequires))] // Doesn't warn + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(DerivedWithoutRequires))] // Doesn't warn + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(DerivedWithRequires))] + static void TestDynamicDependencyAccess() + { + } + + [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] + class BaseForDAMAnnotatedClass + { + public static int baseProperty { get; set; } + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] + class DAMAnnotatedClass : BaseForDAMAnnotatedClass + { + public static int publicProperty + { + get; + set; + } + + static int privateProperty + { + get; + set; + } + } + + static void TestDAMOnTypeAccess(DAMAnnotatedClass instance) + { + instance.GetType().GetProperty("publicProperty"); + } + + [ExpectedWarning("IL2026", "DAMAnnotatedClass.DAMAnnotatedClass()")] + [ExpectedWarning("IL3050", "DAMAnnotatedClass.DAMAnnotatedClass()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] + public static void Test() + { + TestDAMAccess(); + TestDirectReflectionAccess(); + TestDynamicDependencyAccess(); + TestDAMOnTypeAccess(new DAMAnnotatedClass()); + } + } + + [RequiresUnreferencedCode("The attribute is dangerous", ExcludeStatics = true)] + [RequiresDynamicCode("The attribute is dangerous", ExcludeStatics = true)] + public class AttributeWithRequires : Attribute + { + public static int field; + + // `field` cannot be used as named attribute argument because is static, and if accessed via + // a property the property will be the one generating the warning, but then the warning will + // be suppressed by the Requires on the declaring type + public int PropertyOnAttribute + { + get { return field; } + set { field = value; } + } + } + + [AttributeWithRequires(PropertyOnAttribute = 42)] + [ExpectedWarning("IL2026", "AttributeWithRequires.AttributeWithRequires()")] + [ExpectedWarning("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] + static void KeepFieldOnAttributeInner() { } + + static void KeepFieldOnAttribute() + { + KeepFieldOnAttributeInner(); + + // NativeAOT only considers attribute on reflection visible members + typeof(RequiresOnClassExcludeStatics).GetMethod(nameof(KeepFieldOnAttributeInner), BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { }); + } + + public class AttributeParametersAndProperties + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] + public static Type AnnotatedField; + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class AttributeWithRequirementsOnParameters : Attribute + { + public AttributeWithRequirementsOnParameters() + { + } + + public AttributeWithRequirementsOnParameters([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type) + { + } + + public int PropertyWithRequires + { + get => 0; + + [RequiresUnreferencedCode("--PropertyWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--PropertyWithRequires--", ExcludeStatics = true)] + set { } + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] + public Type AnnotatedField; + } + + [RequiresUnreferencedCode("--AttributeParametersAndProperties--", ExcludeStatics = true)] + [RequiresDynamicCode("--AttributeParametersAndProperties--", ExcludeStatics = true)] + class TestClass + { + [ExpectedWarning("IL2110", "AttributeParametersAndProperties.AnnotatedField", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + [ExpectedWarning("IL2110", "AttributeParametersAndProperties.AnnotatedField", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + [ExpectedWarning("IL2026", "AttributeParametersAndProperties.AttributeWithRequirementsOnParameters.PropertyWithRequires.set", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + [ExpectedWarning("IL3050", "AttributeParametersAndProperties.AttributeWithRequirementsOnParameters.PropertyWithRequires.set", Tool.Analyzer, "NativeAOT-specific warning, https://github.com/dotnet/runtime/issues/117899")] + [AttributeWithRequirementsOnParameters(typeof(AttributeParametersAndProperties))] + [AttributeWithRequirementsOnParameters(PropertyWithRequires = 1)] + [AttributeWithRequirementsOnParameters(AnnotatedField = typeof(AttributeParametersAndProperties))] + public static void Test() { } + } + + public static void Test() + { + + TestClass.Test(); + } + } + + class RequiresOnCtorAttribute : Attribute + { + [RequiresUnreferencedCode("--RequiresOnCtorAttribute--", ExcludeStatics = true)] + public RequiresOnCtorAttribute() + { + } + } + + class MembersOnClassWithRequires + { + public class RequiresAll<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] U> + { + } + + class RequiresNew where T : new() + { + } + + [RequiresUnreferencedCode("--ClassWithRequires--", ExcludeStatics = true)] + public class ClassWithRequires + { + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + public static RequiresAll field; + + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/108523")] + public RequiresAll instanceField; + + [RequiresOnCtor] + [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + public static int fieldWithAttribute; + + // Instance fields get attribute warnings but static fields don't. + [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Trimmer, "https://github.com/dotnet/linker/issues/3140")] + [RequiresOnCtor] + public int instanceFieldWithAttribute; + + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + public static void GenericMethod(RequiresAll r) { } + + public void GenericInstanceMethod(RequiresAll r) { } + + [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + [RequiresOnCtor] + public static void MethodWithAttribute() { } + + [RequiresOnCtor] + public void InstanceMethodWithAttribute() { } + + // NOTE: The enclosing RUC does not apply to nested types. + [ExpectedWarning("IL2091")] + public class ClassWithWarning : RequiresAll + { + [ExpectedWarning("IL2091")] + public ClassWithWarning() + { + } + } + + // NOTE: The enclosing RUC does not apply to nested types. + [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--")] + [RequiresOnCtor] + public class ClassWithAttribute + { + } + } + + // This warning should ideally be suppressed by the RUC on the type: + [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] + [RequiresUnreferencedCode("--GenericClassWithWarningWithRequires--", ExcludeStatics = true)] + public class GenericClassWithWarningWithRequires : RequiresAll + { + } + + // This warning should ideally be suppressed by the RUC on the type: + [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] + [RequiresUnreferencedCode("--ClassWithWarningWithRequires--", ExcludeStatics = true)] + public class ClassWithWarningWithRequires : RequiresAll + { + } + + [ExpectedWarning("IL2026", "ClassWithRequires()", "--ClassWithRequires--")] + class ClassWithWarningOnGenericArgumentConstructor : RequiresNew + { + // Analyzer misses warning for implicit call to the base constructor, because the new constraint is not checked in dataflow. + [ExpectedWarning("IL2026", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/108507")] + public ClassWithWarningOnGenericArgumentConstructor() + { + } + } + + [UnexpectedWarning("IL2026", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108507")] + [RequiresUnreferencedCode("--ClassWithWarningOnGenericArgumentConstructorWithRequires--", ExcludeStatics = true)] + class ClassWithWarningOnGenericArgumentConstructorWithRequires : RequiresNew + { + } + + [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] + [RequiresUnreferencedCode("--GenericAnnotatedWithWarningWithRequires--", ExcludeStatics = true)] + public class GenericAnnotatedWithWarningWithRequires<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TFields> : RequiresAll + { + } + + [ExpectedWarning("IL2026", "--GenericClassWithWarningWithRequires--")] + [ExpectedWarning("IL2026", "--ClassWithWarningWithRequires--")] + [ExpectedWarning("IL2026", "--ClassWithWarningOnGenericArgumentConstructorWithRequires--")] + [ExpectedWarning("IL2026", "--GenericAnnotatedWithWarningWithRequires--")] + [ExpectedWarning("IL2091", Tool.Trimmer, "")] + public static void Test(ClassWithRequires inst = null) + { + var f = ClassWithRequires.field; + f = inst.instanceField; + int i = ClassWithRequires.fieldWithAttribute; + i = inst.instanceFieldWithAttribute; + ClassWithRequires.GenericMethod(new()); + inst.GenericInstanceMethod(new()); + ClassWithRequires.MethodWithAttribute(); + inst.InstanceMethodWithAttribute(); + var c = new ClassWithRequires.ClassWithWarning(); + var d = new ClassWithRequires.ClassWithAttribute(); + var g = new GenericClassWithWarningWithRequires(); + var h = new ClassWithWarningWithRequires(); + var j = new ClassWithWarningOnGenericArgumentConstructor(); + var k = new ClassWithWarningOnGenericArgumentConstructorWithRequires(); + var l = new GenericAnnotatedWithWarningWithRequires(); + } + } + + class ConstFieldsOnClassWithRequires + { + [RequiresUnreferencedCode("--ConstClassWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--ConstClassWithRequires--", ExcludeStatics = true)] + class ConstClassWithRequires + { + public const string Message = "Message"; + public const int Number = 42; + + public static void Method() { } + } + + static void TestClassWithRequires() + { + var a = ConstClassWithRequires.Message; + var b = ConstClassWithRequires.Number; + + ConstClassWithRequires.Method(); + } + + [RequiresUnreferencedCode(ConstClassWithRequiresUsingField.Message, ExcludeStatics = true)] + [RequiresDynamicCode(ConstClassWithRequiresUsingField.Message, ExcludeStatics = true)] + class ConstClassWithRequiresUsingField + { + public const string Message = "--ConstClassWithRequiresUsingField--"; + + public static void Method() { } + } + + static void TestClassUsingFieldInAttribute() + { + ConstClassWithRequiresUsingField.Method(); + } + + public static void Test() + { + TestClassWithRequires(); + TestClassUsingFieldInAttribute(); + } + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index 99c745a2731772..4ce4b210d6675b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -157,6 +157,12 @@ public IEnumerable GetCommonSourceFiles() .Combine("Mono.Linker.Tests.Cases.Expectations") .Combine("Support") .Combine("DynamicallyAccessedMembersAttribute.cs"); + + var sharedDir = _testCase.RootCasesDirectory.Parent.Parent + .Combine("src") + .Combine("ILLink.Shared"); + yield return sharedDir.Combine("RequiresDynamicCodeAttribute.cs"); + yield return sharedDir.Combine("RequiresUnreferencedCodeAttribute.cs"); } public virtual IEnumerable GetCommonReferencedAssemblies(NPath workingDirectory) From 54d9fc8d2ee3f3c29a8ef1e5b82bc6940322c8cd Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 21 Jul 2025 16:06:42 -0700 Subject: [PATCH 2/4] Clean up tests And doc comments --- .../RequiresDynamicCodeAttribute.cs | 3 + .../RequiresUnreferencedCodeAttribute.cs | 3 + .../RequiresCapabilityTests.cs | 6 + .../RequiresExcludeStatics.cs | 233 +++ .../RequiresOnClassExcludeStatics.cs | 1317 ----------------- 5 files changed, 245 insertions(+), 1317 deletions(-) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresExcludeStatics.cs delete mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs diff --git a/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs index d7220b680549d7..9ab59680f26109 100644 --- a/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs +++ b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs @@ -32,6 +32,9 @@ public RequiresDynamicCodeAttribute(string message) Message = message; } + /// + /// Indicates whether the attribute should apply to static members. + /// public bool ExcludeStatics { get; set; } /// diff --git a/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs index b41ffc9de5ccac..76a754dd2fac42 100644 --- a/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs +++ b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs @@ -33,6 +33,9 @@ public RequiresUnreferencedCodeAttribute(string message) Message = message; } + /// + /// Indicates whether the attribute should apply to static members. + /// public bool ExcludeStatics { get; set; } /// diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs index 88c84d35aa67e3..8e6f3a8bf1e48b 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs @@ -34,6 +34,12 @@ public Task RequiresAttributeMismatch() return RunTest(nameof(RequiresAttributeMismatch)); } + [Fact] + public Task RequiresExcludeStatics() + { + return RunTest(); + } + [Fact] public Task RequiresCapabilityFromCopiedAssembly() { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresExcludeStatics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresExcludeStatics.cs new file mode 100644 index 00000000000000..a7651b044b7903 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresExcludeStatics.cs @@ -0,0 +1,233 @@ +// 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.Helpers; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + class RequiresExcludeStatics + { + public static void Main() + { + ClassWithRequires.Test(); + DerivedWithRequiresExcludeStatics.Test(); + DerivedWithoutRequires.Test(); + TestDerivedWithRequires(); + TestAttributeWithRequires(); + GenericWithRequires.Test(); + } + + [RequiresUnreferencedCode("--ClassWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--ClassWithRequires--", ExcludeStatics = true)] + class ClassWithRequires + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + static ClassWithRequires() + { + Requires(); + } + + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + static void StaticMethod() => Requires(); + + [RequiresUnreferencedCode("--AnnotatedStaticMethod--")] + [RequiresDynamicCode("--AnnotatedStaticMethod--")] + static void AnnotatedStaticMethod() => Requires(); + + [RequiresUnreferencedCode("--AnnotatedStaticMethodExcludeStatics--", ExcludeStatics = true)] + [RequiresDynamicCode("--AnnotatedStaticMethodExcludeStatics--", ExcludeStatics = true)] + static void AnnotatedStaticMethodExcludeStatics() => Requires(); + + void InstanceMethod() => Requires(); + + static int StaticField; + + int InstanceField; + + static bool StaticProperty + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + get + { + Requires(); + return true; + } + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + set + { + Requires(); + } + } + + bool InstanceProperty + { + get + { + Requires(); + return true; + } + set + { + Requires(); + } + } + + class Nested + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void StaticMethod() => Requires(); + + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public void InstanceMethod() => Requires(); + } + + [ExpectedWarning("IL2026", "ClassWithRequires.ClassWithRequires()")] + [ExpectedWarning("IL3050", "ClassWithRequires.ClassWithRequires()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + [ExpectedWarning("IL2026", "--AnnotatedStaticMethod--")] + [ExpectedWarning("IL3050", "--AnnotatedStaticMethod--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + [ExpectedWarning("IL2026", "--AnnotatedStaticMethodExcludeStatics--")] + [ExpectedWarning("IL3050", "--AnnotatedStaticMethodExcludeStatics--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void Test() + { + StaticMethod(); + StaticField = 42; + _ = StaticProperty; + StaticProperty = true; + + AnnotatedStaticMethod(); + AnnotatedStaticMethodExcludeStatics(); + + var instance = new ClassWithRequires(); + instance.InstanceMethod(); + instance.InstanceField = 42; + _ = instance.InstanceProperty; + instance.InstanceProperty = true; + + Nested.StaticMethod(); + var nestedInstance = new Nested(); + nestedInstance.InstanceMethod(); + } + } + + [RequiresUnreferencedCode("--BaseWithRequires--")] + [RequiresDynamicCode("--BaseWithRequires--")] + class BaseWithRequires + { + protected static void StaticMethod() => Requires(); + } + + [RequiresUnreferencedCode("--DerivedWithRequiresExcludeStatics--", ExcludeStatics = true)] + [RequiresDynamicCode("--DerivedWithRequiresExcludeStatics--", ExcludeStatics = true)] + class DerivedWithRequiresExcludeStatics : BaseWithRequires + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + static void DerivedStaticMethod() => Requires(); + + [ExpectedWarning("IL2026", "StaticMethod", "--BaseWithRequires--")] + [ExpectedWarning("IL3050", "StaticMethod", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void Test() + { + StaticMethod(); + DerivedStaticMethod(); + } + } + + [UnexpectedWarning("IL2109", "DerivedWithoutRequires", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/107660")] + class DerivedWithoutRequires : BaseWithRequires + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + static void DerivedStaticMethod() => Requires(); + + [ExpectedWarning("IL2026", "StaticMethod", "--BaseWithRequires--")] + [ExpectedWarning("IL3050", "StaticMethod", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void Test() + { + StaticMethod(); + DerivedStaticMethod(); + } + } + + [RequiresUnreferencedCode("--BaseWithRequiresExcludeStatics--", ExcludeStatics = true)] + [RequiresDynamicCode("--BaseWithRequiresExcludeStatics--", ExcludeStatics = true)] + class BaseWithRequiresExcludeStatics + { + [ExpectedWarning("IL2026", "--Requires--")] + [ExpectedWarning("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void StaticMethod() => Requires(); + } + + [RequiresUnreferencedCode("--DerivedWithRequiresExcludeStatics--")] + [RequiresDynamicCode("--DerivedWithRequiresExcludeStatics--")] + class DerivedWithRequires : BaseWithRequiresExcludeStatics + { + public static void DerivedStaticMethod() => Requires(); + } + + [ExpectedWarning("IL2026", "DerivedWithRequires")] + [ExpectedWarning("IL3050", "DerivedWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + static void TestDerivedWithRequires() + { + DerivedWithRequires.StaticMethod(); + DerivedWithRequires.DerivedStaticMethod(); + } + + [RequiresUnreferencedCode("--AttributeWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--AttributeWithRequires--", ExcludeStatics = true)] + class AttributeWithRequiresAttribute : Attribute + { + } + + [ExpectedWarning("IL2026", "--AttributeWithRequires--", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] + [ExpectedWarning("IL3050", "--AttributeWithRequires--", Tool.Analyzer, "NativeAOT Specific warning, https://github.com/dotnet/runtime/issues/117899")] + [AttributeWithRequires] + static void TestAttributeWithRequires() + { + } + + [RequiresUnreferencedCode("--GenericWithRequires--", ExcludeStatics = true)] + [RequiresDynamicCode("--GenericWithRequires--", ExcludeStatics = true)] + class GenericWithRequires + { + class Requires<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T> + { + } + + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + static Requires StaticField; + + [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] + Requires InstanceField; + + [ExpectedWarning("IL2091", "PublicFields", "Requires")] + [ExpectedWarning("IL2091", "PublicFields", "Requires")] + [ExpectedWarning("IL2026", "--GenericWithRequires--")] + [ExpectedWarning("IL3050", "--GenericWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific warning")] + public static void Test() + { + StaticField = new Requires(); + var instance = new GenericWithRequires(); + instance.InstanceField = new Requires(); + } + } + + [RequiresUnreferencedCode("--Requires--")] + [RequiresDynamicCode("--Requires--")] + static void Requires() + { + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs deleted file mode 100644 index 54035b121b9977..00000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClassExcludeStatics.cs +++ /dev/null @@ -1,1317 +0,0 @@ -// 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.Helpers; - -namespace Mono.Linker.Tests.Cases.RequiresCapability -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class RequiresOnClassExcludeStatics - { - public static void Main() - { - TestRequiresInClassAccessedByStaticMethod(); - TestRequiresInParentClassAccesedByStaticMethod(); - TestRequiresInClassAccessedByCctor(); - TestRequiresOnBaseButNotOnDerived(); - TestRequiresOnDerivedButNotOnBase(); - TestRequiresOnBaseAndDerived(); - TestInstanceFieldSuppression(); - TestSuppressionsOnClass(); - TestStaticMethodOnRequiresTypeSuppressedByRequiresOnMethod(); - TestStaticConstructorCalls(); - TestOtherMemberTypesWithRequires(); - TestNameOfDoesntWarn(); - ReflectionAccessOnMethod.Test(); - ReflectionAccessOnCtor.Test(); - ReflectionAccessOnField.Test(); - ReflectionAccessOnEvents.Test(); - ReflectionAccessOnProperties.Test(); - KeepFieldOnAttribute(); - AttributeParametersAndProperties.Test(); - MembersOnClassWithRequires.Test(); - ConstFieldsOnClassWithRequires.Test(); - } - - [RequiresUnreferencedCode("Message for --ClassWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --ClassWithRequires--", ExcludeStatics = true)] - class ClassWithRequires - { - public static object Instance; - - public ClassWithRequires() { } - - public static void StaticMethod() { } - - public void NonStaticMethod() { } - - [ExpectedWarning("IL2026", "RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] - [ExpectedWarning("IL3050", "RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - public static void CallMethodWithRequires() => RequiresOnMethod.MethodWithRequires(); - - public class NestedClass - { - public static void NestedStaticMethod() { } - - // This warning doesn't get suppressed since the declaring type NestedClass is not annotated with Requires - [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] - [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - public static void CallMethodWithRequires() => RequiresOnMethod.MethodWithRequires(); - } - - // RequiresUnfereferencedCode on the type will suppress IL2072 - static ClassWithRequires() - { - Instance = Activator.CreateInstance(Type.GetType("SomeText")); - } - - [ExpectedWarning("IL2065", "GetMethods")] - public static void TestSuppressions(Type[] types) - { - // StaticMethod is a static method on a Requires annotated type, so it should warn. But Requires in the - // class suppresses other Requires messages - StaticMethod(); - - var nested = new NestedClass(); - - // Requires in the class suppresses DynamicallyAccessedMembers messages - types[1].GetMethods(); - - void LocalFunction(int a) { } - LocalFunction(2); - - AttributedMethod(); - typeof(ClassWithRequires).GetMethod("AttributedMethod"); - } - - [ExpectedWarning("IL2026", "AttributeWithRequires.AttributeWithRequires()")] - [ExpectedWarning("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - [AttributeWithRequires()] - public static void AttributedMethod() { } - } - - class RequiresOnMethod - { - [RequiresUnreferencedCode("MethodWithRequires", ExcludeStatics = true)] - [RequiresDynamicCode("MethodWithRequires", ExcludeStatics = true)] - public static void MethodWithRequires() { } - } - - [ExpectedWarning("IL2109", "RequiresOnClassExcludeStatics.DerivedWithoutRequires", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--")] - private class DerivedWithoutRequires : ClassWithRequires - { - // This method contains implicit call to ClassWithRequires.ctor() - [ExpectedWarning("IL2026")] - [ExpectedWarning("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - public DerivedWithoutRequires() { } - - public static void StaticMethodInInheritedClass() { } - - public class DerivedNestedClass - { - public static void NestedStaticMethod() { } - } - - public static void ShouldntWarn(object objectToCast) - { - _ = typeof(ClassWithRequires); - var type = (ClassWithRequires)objectToCast; - } - } - - // In order to generate IL2109 the nested class would also need to be annotated with Requires - // otherwise we threat the nested class as safe - private class DerivedWithoutRequires2 : ClassWithRequires.NestedClass - { - public static void StaticMethod() { } - } - - [UnconditionalSuppressMessage("trim", "IL2109")] - class TestUnconditionalSuppressMessage : ClassWithRequires - { - public static void StaticMethodInTestSuppressionClass() { } - } - - class ClassWithoutRequires - { - public ClassWithoutRequires() { } - - public static void StaticMethod() { } - - public void NonStaticMethod() { } - - public class NestedClass - { - public static void NestedStaticMethod() { } - } - } - - [RequiresUnreferencedCode("Message for --StaticCtor--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --StaticCtor--", ExcludeStatics = true)] - class StaticCtor - { - static StaticCtor() - { - } - } - - [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.StaticCtor.StaticCtor()", "Message for --StaticCtor--")] - [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.StaticCtor.StaticCtor()", "Message for --StaticCtor--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - static void TestStaticCctorRequires() - { - _ = new StaticCtor(); - } - - [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByFieldAccess--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --StaticCtorTriggeredByFieldAccess--", ExcludeStatics = true)] - class StaticCtorTriggeredByFieldAccess - { - static StaticCtorTriggeredByFieldAccess() - { - field = 0; - } - - public static int field; - } - - static void TestStaticCtorMarkingIsTriggeredByFieldAccessWrite() - { - StaticCtorTriggeredByFieldAccess.field = 1; - } - - static void TestStaticCtorMarkingTriggeredOnSecondAccessWrite() - { - StaticCtorTriggeredByFieldAccess.field = 2; - } - - [RequiresUnreferencedCode("--TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner--", ExcludeStatics = true)] - [RequiresDynamicCode("--TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner--", ExcludeStatics = true)] - static void TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner() - { - StaticCtorTriggeredByFieldAccess.field = 3; - } - - [UnconditionalSuppressMessage("test", "IL2026")] - [UnconditionalSuppressMessage("test", "IL3050")] - static void TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod() - { - TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod_Inner(); - } - - [RequiresUnreferencedCode("Message for --StaticCCtorTriggeredByFieldAccessRead--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --StaticCCtorTriggeredByFieldAccessRead--", ExcludeStatics = true)] - class StaticCCtorTriggeredByFieldAccessRead - { - public static int field = 42; - } - - static void TestStaticCtorMarkingIsTriggeredByFieldAccessRead() - { - var _ = StaticCCtorTriggeredByFieldAccessRead.field; - } - - [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByCtorCalls--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --StaticCtorTriggeredByCtorCalls--", ExcludeStatics = true)] - class StaticCtorTriggeredByCtorCalls - { - static StaticCtorTriggeredByCtorCalls() - { - } - - public void TriggerStaticCtorMarking() - { - } - } - - [ExpectedWarning("IL2026", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()")] - [ExpectedWarning("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - static void TestStaticCtorTriggeredByCtorCall() - { - new StaticCtorTriggeredByCtorCalls(); - } - - [RequiresUnreferencedCode("Message for --ClassWithInstanceField--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --ClassWithInstanceField--", ExcludeStatics = true)] - class ClassWithInstanceField - { - public int field = 42; - } - - [ExpectedWarning("IL2026", "ClassWithInstanceField.ClassWithInstanceField()")] - [ExpectedWarning("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - static void TestInstanceFieldCallDontWarn() - { - ClassWithInstanceField instance = new ClassWithInstanceField(); - var _ = instance.field; - } - - public class ClassWithInstanceFieldWhichInitsDangerousClass - { - private ClassWithRequires _instanceField = new ClassWithRequires(); - - [RequiresUnreferencedCode("Calling the constructor is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("Calling the constructor is dangerous", ExcludeStatics = true)] - public ClassWithInstanceFieldWhichInitsDangerousClass() { } - } - - [ExpectedWarning("IL2026", "Calling the constructor is dangerous")] - [ExpectedWarning("IL3050", "Calling the constructor is dangerous", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - static void TestInstanceFieldSuppression() - { - _ = new ClassWithInstanceFieldWhichInitsDangerousClass(); - } - - [RequiresUnreferencedCode("Message for --StaticCtorTriggeredByMethodCall2--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --StaticCtorTriggeredByMethodCall2--", ExcludeStatics = true)] - class StaticCtorTriggeredByMethodCall2 - { - static StaticCtorTriggeredByMethodCall2() - { - } - - public void TriggerStaticCtorMarking() - { - } - } - - static void TestNullInstanceTryingToCallMethod() - { - StaticCtorTriggeredByMethodCall2 instance = null; - instance.TriggerStaticCtorMarking(); - } - - [RequiresUnreferencedCode("Message for --DerivedWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --DerivedWithRequires--", ExcludeStatics = true)] - private class DerivedWithRequires : ClassWithoutRequires - { - public static void StaticMethodInInheritedClass() { } - - public class DerivedNestedClass - { - public static void NestedStaticMethod() { } - } - } - - [RequiresUnreferencedCode("Message for --DerivedWithRequires2--", ExcludeStatics = true)] - [RequiresDynamicCode("Message for --DerivedWithRequires2--", ExcludeStatics = true)] - private class DerivedWithRequires2 : ClassWithRequires - { - public static void StaticMethodInInheritedClass() { } - - // A nested class is not considered a static method nor constructor therefore RequiresUnreferencedCode doesn't apply - // and this warning is not suppressed - [ExpectedWarning("IL2109", "RequiresOnClassExcludeStatics.DerivedWithRequires2.DerivedNestedClass", "--ClassWithRequires--")] - public class DerivedNestedClass : ClassWithRequires - { - // This method contains implicit call to ClassWithRequires.ctor() - [ExpectedWarning("IL2026")] - [ExpectedWarning("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - public DerivedNestedClass() { } - - public static void NestedStaticMethod() { } - } - } - - class BaseWithoutRequiresOnType - { - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - public virtual void Method() { } - } - - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - class DerivedWithRequiresOnType : BaseWithoutRequiresOnType - { - public override void Method() { } - } - - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - class BaseWithRequiresOnType - { - public virtual void Method() { } - } - - [ExpectedWarning("IL2109", nameof(BaseWithRequiresOnType))] - class DerivedWithoutRequiresOnType : BaseWithRequiresOnType - { - public override void Method() { } - } - - class BaseWithNoRequires - { - public virtual void Method() { } - } - - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - class DerivedWithRequiresOnTypeOverBaseWithNoRequires : BaseWithNoRequires - { - // Should not warn since the members are not static - public override void Method() - { - } - } - - public interface InterfaceWithoutRequires - { - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - static int Method() - { - return 0; - } - - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - int Method(int a); - } - - [RequiresUnreferencedCode("RUC", ExcludeStatics = true)] - [RequiresDynamicCode("RDC", ExcludeStatics = true)] - class ImplementationWithRequiresOnType : InterfaceWithoutRequires - { - public static int Method() - { - return 1; - } - - public int Method(int a) - { - return a; - } - } - - static void TestRequiresInClassAccessedByStaticMethod() - { - ClassWithRequires.StaticMethod(); - } - - [ExpectedWarning("IL2026", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--")] - [ExpectedWarning("IL3050", "RequiresOnClassExcludeStatics.ClassWithRequires", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] - static void TestRequiresInClassAccessedByCctor() - { - var classObject = new ClassWithRequires(); - } - - static void TestRequiresInParentClassAccesedByStaticMethod() - { - ClassWithRequires.NestedClass.NestedStaticMethod(); - } - - static void TestRequiresOnBaseButNotOnDerived() - { - var a = new DerivedWithoutRequires(); // Must instantiate to force checks on the base type (otherwise base type is non-interesting) - DerivedWithoutRequires.StaticMethodInInheritedClass(); - DerivedWithoutRequires.StaticMethod(); - DerivedWithoutRequires.CallMethodWithRequires(); - DerivedWithoutRequires.DerivedNestedClass.NestedStaticMethod(); - DerivedWithoutRequires.NestedClass.NestedStaticMethod(); - DerivedWithoutRequires.NestedClass.CallMethodWithRequires(); - DerivedWithoutRequires.ShouldntWarn(null); - DerivedWithoutRequires.Instance.ToString(); - DerivedWithoutRequires2.StaticMethod(); - } - - static void TestRequiresOnDerivedButNotOnBase() - { - DerivedWithRequires.StaticMethodInInheritedClass(); - DerivedWithRequires.StaticMethod(); - DerivedWithRequires.DerivedNestedClass.NestedStaticMethod(); - DerivedWithRequires.NestedClass.NestedStaticMethod(); - } - - static void TestRequiresOnBaseAndDerived() - { - DerivedWithRequires2.StaticMethodInInheritedClass(); - DerivedWithRequires2.StaticMethod(); - var a = new DerivedWithRequires2.DerivedNestedClass(); - DerivedWithRequires2.DerivedNestedClass.NestedStaticMethod(); - DerivedWithRequires2.NestedClass.NestedStaticMethod(); - } - - static void TestSuppressionsOnClass() - { - ClassWithRequires.TestSuppressions(new[] { typeof(ClassWithRequires) }); - TestUnconditionalSuppressMessage.StaticMethodInTestSuppressionClass(); - } - - [RequiresUnreferencedCode("--StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod--", ExcludeStatics = true)] - [RequiresDynamicCode("--StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod--", ExcludeStatics = true)] - static void StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod() - { - DerivedWithRequires.StaticMethodInInheritedClass(); - } - - [UnconditionalSuppressMessage("test", "IL2026")] - [UnconditionalSuppressMessage("test", "IL3050")] - static void TestStaticMethodOnRequiresTypeSuppressedByRequiresOnMethod() - { - StaticMethodOnRequiresTypeSuppressedByRequiresOnMethod(); - } - - static void TestStaticConstructorCalls() - { - TestStaticCctorRequires(); - TestStaticCtorMarkingIsTriggeredByFieldAccessWrite(); - TestStaticCtorMarkingTriggeredOnSecondAccessWrite(); - TestStaticRequiresFieldAccessSuppressedByRequiresOnMethod(); - TestStaticCtorMarkingIsTriggeredByFieldAccessRead(); - //TestStaticCtorTriggeredByMethodCall(); - TestStaticCtorTriggeredByCtorCall(); - TestInstanceFieldCallDontWarn(); - } - - [RequiresUnreferencedCode("--MemberTypesWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--MemberTypesWithRequires--", ExcludeStatics = true)] - class MemberTypesWithRequires - { - public static int field; - public static int Property { get; set; } - - public static event EventHandler Event; - } - - static void TestOtherMemberTypesWithRequires() - { - MemberTypesWithRequires.field = 1; - MemberTypesWithRequires.Property = 1; - MemberTypesWithRequires.Event -= null; - } - - static void TestNameOfDoesntWarn() - { - _ = nameof(ClassWithRequires.StaticMethod); - _ = nameof(MemberTypesWithRequires.field); - _ = nameof(MemberTypesWithRequires.Property); - _ = nameof(MemberTypesWithRequires.Event); - } - - class ReflectionAccessOnMethod - { - [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", Tool.NativeAot, "")] - static void TestDAMAccess() - { - // Warns because BaseWithoutRequiresOnType.Method has Requires on the method - typeof(BaseWithoutRequiresOnType).RequiresPublicMethods(); - - // Doesn't warn because DerivedWithRequiresOnType doesn't have any static methods - typeof(DerivedWithRequiresOnType).RequiresPublicMethods(); - - // Warns twice since both methods on InterfaceWithoutRequires have RUC on the method - typeof(InterfaceWithoutRequires).RequiresPublicMethods(); - - // Warns because ImplementationWithRequiresOnType.Method is a static public method on a RUC type - typeof(ImplementationWithRequiresOnType).RequiresPublicMethods(); - - // Warns for instance method on BaseWithRequiresOnType - typeof(BaseWithRequiresOnType).RequiresPublicMethods(); - - // Warns for instance method on base type - typeof(DerivedWithoutRequiresOnType).RequiresPublicMethods(); - - // Doesn't warn since the type has no statics - typeof(DerivedWithRequiresOnTypeOverBaseWithNoRequires).RequiresPublicMethods(); - } - - [ExpectedWarning("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] - static void TestDirectReflectionAccess() - { - // Requires on the method itself - typeof(BaseWithoutRequiresOnType).GetMethod(nameof(BaseWithoutRequiresOnType.Method)); - - // Requires on the method itself - typeof(InterfaceWithoutRequires).GetMethod(nameof(InterfaceWithoutRequires.Method)); - - // Warns for static and instance methods on ImplementationWithRequiresOnType - typeof(ImplementationWithRequiresOnType).GetMethod(nameof(ImplementationWithRequiresOnType.Method)); - - // Warns for instance Method on RUC type - typeof(BaseWithRequiresOnType).GetMethod(nameof(BaseWithRequiresOnType.Method)); - } - - public static void Test() - { - TestDAMAccess(); - TestDirectReflectionAccess(); - } - } - - class ReflectionAccessOnCtor - { - [RequiresUnreferencedCode("--BaseWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--BaseWithRequires--", ExcludeStatics = true)] - class BaseWithRequires - { - public BaseWithRequires() { } - } - - [ExpectedWarning("IL2109", "ReflectionAccessOnCtor.DerivedWithoutRequires", "ReflectionAccessOnCtor.BaseWithRequires")] - class DerivedWithoutRequires : BaseWithRequires - { - [ExpectedWarning("IL2026", "--BaseWithRequires--")] // The body has direct call to the base.ctor() - [ExpectedWarning("IL3050", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning")] - public DerivedWithoutRequires() { } - } - - [RequiresUnreferencedCode("--DerivedWithRequiresOnBaseWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--DerivedWithRequiresOnBaseWithRequires--", ExcludeStatics = true)] - class DerivedWithRequiresOnBaseWithRequires : BaseWithRequires - { - // No warning - suppressed by the Requires on this type - private DerivedWithRequiresOnBaseWithRequires() { } - } - - class BaseWithoutRequires { } - - [RequiresUnreferencedCode("--DerivedWithRequiresOnBaseWithout--", ExcludeStatics = true)] - [RequiresDynamicCode("--DerivedWithRequiresOnBaseWithout--", ExcludeStatics = true)] - class DerivedWithRequiresOnBaseWithoutRequires : BaseWithoutRequires - { - public DerivedWithRequiresOnBaseWithoutRequires() { } - } - - [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] - static void TestDAMAccess() - { - // Warns because the type has Requires - typeof(BaseWithRequires).RequiresPublicConstructors(); - - // Doesn't warn since there's no Requires on this type - typeof(DerivedWithoutRequires).RequiresPublicParameterlessConstructor(); - - // Warns - Requires on the type - typeof(DerivedWithRequiresOnBaseWithRequires).RequiresNonPublicConstructors(); - - // Warns - Requires On the type - typeof(DerivedWithRequiresOnBaseWithoutRequires).RequiresPublicConstructors(); - } - - [ExpectedWarning("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] - static void TestDirectReflectionAccess() - { - typeof(BaseWithRequires).GetConstructor(Type.EmptyTypes); - typeof(DerivedWithoutRequires).GetConstructor(Type.EmptyTypes); - typeof(DerivedWithRequiresOnBaseWithRequires).GetConstructor(BindingFlags.NonPublic, Type.EmptyTypes); - typeof(DerivedWithRequiresOnBaseWithoutRequires).GetConstructor(Type.EmptyTypes); - } - - public static void Test() - { - TestDAMAccess(); - TestDirectReflectionAccess(); - } - } - - class ReflectionAccessOnField - { - [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] - class WithRequires - { - public int InstanceField; - public static int StaticField; - private static int PrivateStaticField; - } - - [RequiresUnreferencedCode("--WithRequiresOnlyInstanceFields--", ExcludeStatics = true)] - [RequiresDynamicCode("--WithRequiresOnlyInstanceFields--", ExcludeStatics = true)] - class WithRequiresOnlyInstanceFields - { - public int InstanceField; - } - - [ExpectedWarning("IL2109", "ReflectionAccessOnField.DerivedWithoutRequires", "ReflectionAccessOnField.WithRequires")] - class DerivedWithoutRequires : WithRequires - { - public static int DerivedStaticField; - } - - [RequiresUnreferencedCode("--DerivedWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--DerivedWithRequires--", ExcludeStatics = true)] - class DerivedWithRequires : WithRequires - { - public static int DerivedStaticField; - } - - static void TestDAMAccess() - { - typeof(WithRequires).RequiresPublicFields(); - typeof(WithRequires).RequiresNonPublicFields(); - typeof(WithRequiresOnlyInstanceFields).RequiresPublicFields(); - typeof(DerivedWithoutRequires).RequiresPublicFields(); - typeof(DerivedWithRequires).RequiresPublicFields(); - } - - static void TestDirectReflectionAccess() - { - typeof(WithRequires).GetField(nameof(WithRequires.StaticField)); - typeof(WithRequires).GetField(nameof(WithRequires.InstanceField)); // Doesn't warn - typeof(WithRequires).GetField("PrivateStaticField", BindingFlags.NonPublic); - typeof(WithRequiresOnlyInstanceFields).GetField(nameof(WithRequiresOnlyInstanceFields.InstanceField)); // Doesn't warn - typeof(DerivedWithoutRequires).GetField(nameof(DerivedWithoutRequires.DerivedStaticField)); // Doesn't warn - typeof(DerivedWithRequires).GetField(nameof(DerivedWithRequires.DerivedStaticField)); - } - - [DynamicDependency(nameof(WithRequires.StaticField), typeof(WithRequires))] - [DynamicDependency(nameof(WithRequires.InstanceField), typeof(WithRequires))] // Doesn't warn - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(DerivedWithoutRequires))] // Doesn't warn - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(DerivedWithRequires))] - static void TestDynamicDependencyAccess() - { - } - - [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] - class BaseForDAMAnnotatedClass - { - public static int baseField; - } - - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] - class DAMAnnotatedClass : BaseForDAMAnnotatedClass - { - public static int publicField; - - static int privatefield; - } - - static void TestDAMOnTypeAccess(DAMAnnotatedClass instance) - { - instance.GetType().GetField("publicField"); - } - - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - class DAMAnnotatedClassAccessedFromRUCScope - { - [ExpectedWarning("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod")] - [RequiresUnreferencedCode("--RUCMethod--", ExcludeStatics = true)] - public static void RUCMethod() { } - } - - // RUC on the callsite to GetType should not suppress warnings about the - // attribute on the type. - [RequiresUnreferencedCode("--TestDAMOnTypeAccessInRUCScope--", ExcludeStatics = true)] - static void TestDAMOnTypeAccessInRUCScope(DAMAnnotatedClassAccessedFromRUCScope instance = null) - { - instance.GetType().GetMethod("RUCMethod"); - } - - [RequiresUnreferencedCode("--GenericTypeWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--GenericTypeWithRequires--", ExcludeStatics = true)] - class GenericTypeWithRequires - { - public static int NonGenericField; - } - - static void TestDAMAccessOnOpenGeneric() - { - typeof(GenericTypeWithRequires<>).RequiresPublicFields(); - } - - static void TestDAMAccessOnInstantiatedGeneric() - { - typeof(GenericTypeWithRequires).RequiresPublicFields(); - } - - [ExpectedWarning("IL2026", "--TestDAMOnTypeAccessInRUCScope--")] - [ExpectedWarning("IL2026", "DAMAnnotatedClass.DAMAnnotatedClass()")] - [ExpectedWarning("IL3050", "DAMAnnotatedClass.DAMAnnotatedClass()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] - public static void Test() - { - TestDAMAccess(); - TestDirectReflectionAccess(); - TestDynamicDependencyAccess(); - TestDAMOnTypeAccess(new DAMAnnotatedClass()); - TestDAMOnTypeAccessInRUCScope(new DAMAnnotatedClassAccessedFromRUCScope()); - TestDAMAccessOnOpenGeneric(); - TestDAMAccessOnInstantiatedGeneric(); - } - } - - class ReflectionAccessOnEvents - { - [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] - class WithRequires - { - public static event EventHandler StaticEvent; - public event EventHandler InstanceEvent; - private event EventHandler PrivateInstanceEvent; - } - - [RequiresUnreferencedCode("--DerivedRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--DerivedRequires--", ExcludeStatics = true)] - class DerivedRequires : WithRequires - { - public static event EventHandler DerivedStaticEvent; - public event EventHandler DerivedInstanceEvent; - private event EventHandler DerivedPrivateInstanceEvent; - } - - [ExpectedWarning("IL2109", "ReflectionAccessOnEvents.DerivedWithoutRequires", "ReflectionAccessOnEvents.WithRequires")] - class DerivedWithoutRequires : WithRequires - { - public static event EventHandler DerivedStaticEvent; - public event EventHandler DerivedInstanceEvent; - private event EventHandler DerivedPrivateInstanceEvent; - } - - static void ReflectOverSingleEvent() - { - typeof(WithRequires).GetEvent(nameof(WithRequires.StaticEvent)); - typeof(DerivedRequires).GetEvent(nameof(DerivedRequires.DerivedStaticEvent)); - typeof(DerivedWithoutRequires).GetEvent(nameof(DerivedWithoutRequires.DerivedStaticEvent)); - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - static void ReflectOverAllEvents() - { - typeof(WithRequires).GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] - static void DerivedReflectOverAllEvents() - { - typeof(DerivedRequires).GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - static void RequiresAllEvents() - { - RequiresAllEvents(typeof(WithRequires)); - - static void RequiresAllEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type t) - { } - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] - static void DerivedRequiresAllEvents() - { - RequiresAllEvents(typeof(DerivedRequires)); - - static void RequiresAllEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type t) - { } - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - static void RequiresPublicEvents() - { - typeof(WithRequires).RequiresPublicEvents(); - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "InstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "InstanceEvent.remove", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedInstanceEvent.remove", Tool.NativeAot, "")] - static void DerivedRequiresPublicEvents() - { - typeof(DerivedRequires).RequiresPublicEvents(); - } - - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(WithRequires), "PrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(WithRequires), "PrivateInstanceEvent.remove", Tool.NativeAot, "")] - static void RequiresNonPublicEvents() - { - typeof(WithRequires).RequiresNonPublicEvents(); - } - - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.add", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove")] - [ExpectedWarning("IL3050", nameof(DerivedRequires), "DerivedPrivateInstanceEvent.remove", Tool.NativeAot, "")] - static void DerivedRequiresNonPublicEvents() - { - typeof(DerivedRequires).RequiresNonPublicEvents(); - } - - public static void Test() - { - ReflectOverSingleEvent(); - ReflectOverAllEvents(); - RequiresAllEvents(); - RequiresPublicEvents(); - RequiresNonPublicEvents(); - DerivedReflectOverAllEvents(); - DerivedRequiresPublicEvents(); - DerivedRequiresNonPublicEvents(); - DerivedRequiresAllEvents(); - } - } - - class ReflectionAccessOnProperties - { - [RequiresUnreferencedCode("--WithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--WithRequires--", ExcludeStatics = true)] - class WithRequires - { - public int InstanceProperty { get; set; } - public static int StaticProperty { get; set; } - private static int PrivateStaticProperty { get; set; } - } - - [RequiresUnreferencedCode("--WithRequiresOnlyInstanceProperties--", ExcludeStatics = true)] - [RequiresDynamicCode("--WithRequiresOnlyInstanceProperties--", ExcludeStatics = true)] - class WithRequiresOnlyInstanceProperties - { - public int InstanceProperty { get; set; } - } - - [ExpectedWarning("IL2109", "ReflectionAccessOnProperties.DerivedWithoutRequires", "ReflectionAccessOnProperties.WithRequires")] - class DerivedWithoutRequires : WithRequires - { - public static int DerivedStaticProperty { get; set; } - } - - [RequiresUnreferencedCode("--DerivedWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--DerivedWithRequires--", ExcludeStatics = true)] - class DerivedWithRequires : WithRequires - { - public static int DerivedStaticProperty { get; set; } - } - - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] - static void TestDAMAccess() - { - typeof(WithRequires).RequiresPublicProperties(); - typeof(WithRequires).RequiresNonPublicProperties(); - typeof(WithRequiresOnlyInstanceProperties).RequiresPublicProperties(); - typeof(DerivedWithoutRequires).RequiresPublicProperties(); - typeof(DerivedWithRequires).RequiresPublicProperties(); - } - - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] - static void TestDirectReflectionAccess() - { - typeof(WithRequires).GetProperty(nameof(WithRequires.StaticProperty)); - typeof(WithRequires).GetProperty(nameof(WithRequires.InstanceProperty)); - typeof(WithRequires).GetProperty("PrivateStaticProperty", BindingFlags.NonPublic); - typeof(WithRequiresOnlyInstanceProperties).GetProperty(nameof(WithRequiresOnlyInstanceProperties.InstanceProperty)); - typeof(DerivedWithoutRequires).GetProperty(nameof(DerivedWithRequires.DerivedStaticProperty)); // Doesn't warn - typeof(DerivedWithRequires).GetProperty(nameof(DerivedWithRequires.DerivedStaticProperty)); - } - - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [ExpectedWarning("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] - [ExpectedWarning("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] - [DynamicDependency(nameof(WithRequires.StaticProperty), typeof(WithRequires))] - [DynamicDependency(nameof(WithRequires.InstanceProperty), typeof(WithRequires))] // Doesn't warn - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(DerivedWithoutRequires))] // Doesn't warn - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(DerivedWithRequires))] - static void TestDynamicDependencyAccess() - { - } - - [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] - class BaseForDAMAnnotatedClass - { - public static int baseProperty { get; set; } - } - - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] - [RequiresUnreferencedCode("This class is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("This class is dangerous", ExcludeStatics = true)] - class DAMAnnotatedClass : BaseForDAMAnnotatedClass - { - public static int publicProperty - { - get; - set; - } - - static int privateProperty - { - get; - set; - } - } - - static void TestDAMOnTypeAccess(DAMAnnotatedClass instance) - { - instance.GetType().GetProperty("publicProperty"); - } - - [ExpectedWarning("IL2026", "DAMAnnotatedClass.DAMAnnotatedClass()")] - [ExpectedWarning("IL3050", "DAMAnnotatedClass.DAMAnnotatedClass()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] - public static void Test() - { - TestDAMAccess(); - TestDirectReflectionAccess(); - TestDynamicDependencyAccess(); - TestDAMOnTypeAccess(new DAMAnnotatedClass()); - } - } - - [RequiresUnreferencedCode("The attribute is dangerous", ExcludeStatics = true)] - [RequiresDynamicCode("The attribute is dangerous", ExcludeStatics = true)] - public class AttributeWithRequires : Attribute - { - public static int field; - - // `field` cannot be used as named attribute argument because is static, and if accessed via - // a property the property will be the one generating the warning, but then the warning will - // be suppressed by the Requires on the declaring type - public int PropertyOnAttribute - { - get { return field; } - set { field = value; } - } - } - - [AttributeWithRequires(PropertyOnAttribute = 42)] - [ExpectedWarning("IL2026", "AttributeWithRequires.AttributeWithRequires()")] - [ExpectedWarning("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "NativeAOT-specific warning")] - static void KeepFieldOnAttributeInner() { } - - static void KeepFieldOnAttribute() - { - KeepFieldOnAttributeInner(); - - // NativeAOT only considers attribute on reflection visible members - typeof(RequiresOnClassExcludeStatics).GetMethod(nameof(KeepFieldOnAttributeInner), BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { }); - } - - public class AttributeParametersAndProperties - { - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] - public static Type AnnotatedField; - - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class AttributeWithRequirementsOnParameters : Attribute - { - public AttributeWithRequirementsOnParameters() - { - } - - public AttributeWithRequirementsOnParameters([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type) - { - } - - public int PropertyWithRequires - { - get => 0; - - [RequiresUnreferencedCode("--PropertyWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--PropertyWithRequires--", ExcludeStatics = true)] - set { } - } - - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] - public Type AnnotatedField; - } - - [RequiresUnreferencedCode("--AttributeParametersAndProperties--", ExcludeStatics = true)] - [RequiresDynamicCode("--AttributeParametersAndProperties--", ExcludeStatics = true)] - class TestClass - { - [ExpectedWarning("IL2110", "AttributeParametersAndProperties.AnnotatedField", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] - [ExpectedWarning("IL2110", "AttributeParametersAndProperties.AnnotatedField", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] - [ExpectedWarning("IL2026", "AttributeParametersAndProperties.AttributeWithRequirementsOnParameters.PropertyWithRequires.set", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] - [ExpectedWarning("IL3050", "AttributeParametersAndProperties.AttributeWithRequirementsOnParameters.PropertyWithRequires.set", Tool.Analyzer, "NativeAOT-specific warning, https://github.com/dotnet/runtime/issues/117899")] - [AttributeWithRequirementsOnParameters(typeof(AttributeParametersAndProperties))] - [AttributeWithRequirementsOnParameters(PropertyWithRequires = 1)] - [AttributeWithRequirementsOnParameters(AnnotatedField = typeof(AttributeParametersAndProperties))] - public static void Test() { } - } - - public static void Test() - { - - TestClass.Test(); - } - } - - class RequiresOnCtorAttribute : Attribute - { - [RequiresUnreferencedCode("--RequiresOnCtorAttribute--", ExcludeStatics = true)] - public RequiresOnCtorAttribute() - { - } - } - - class MembersOnClassWithRequires - { - public class RequiresAll<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] U> - { - } - - class RequiresNew where T : new() - { - } - - [RequiresUnreferencedCode("--ClassWithRequires--", ExcludeStatics = true)] - public class ClassWithRequires - { - [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] - public static RequiresAll field; - - [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/108523")] - public RequiresAll instanceField; - - [RequiresOnCtor] - [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] - public static int fieldWithAttribute; - - // Instance fields get attribute warnings but static fields don't. - [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Trimmer, "https://github.com/dotnet/linker/issues/3140")] - [RequiresOnCtor] - public int instanceFieldWithAttribute; - - [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] - public static void GenericMethod(RequiresAll r) { } - - public void GenericInstanceMethod(RequiresAll r) { } - - [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--", Tool.Analyzer | Tool.Trimmer, "https://github.com/dotnet/runtime/issues/117899")] - [RequiresOnCtor] - public static void MethodWithAttribute() { } - - [RequiresOnCtor] - public void InstanceMethodWithAttribute() { } - - // NOTE: The enclosing RUC does not apply to nested types. - [ExpectedWarning("IL2091")] - public class ClassWithWarning : RequiresAll - { - [ExpectedWarning("IL2091")] - public ClassWithWarning() - { - } - } - - // NOTE: The enclosing RUC does not apply to nested types. - [ExpectedWarning("IL2026", "--RequiresOnCtorAttribute--")] - [RequiresOnCtor] - public class ClassWithAttribute - { - } - } - - // This warning should ideally be suppressed by the RUC on the type: - [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] - [RequiresUnreferencedCode("--GenericClassWithWarningWithRequires--", ExcludeStatics = true)] - public class GenericClassWithWarningWithRequires : RequiresAll - { - } - - // This warning should ideally be suppressed by the RUC on the type: - [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] - [RequiresUnreferencedCode("--ClassWithWarningWithRequires--", ExcludeStatics = true)] - public class ClassWithWarningWithRequires : RequiresAll - { - } - - [ExpectedWarning("IL2026", "ClassWithRequires()", "--ClassWithRequires--")] - class ClassWithWarningOnGenericArgumentConstructor : RequiresNew - { - // Analyzer misses warning for implicit call to the base constructor, because the new constraint is not checked in dataflow. - [ExpectedWarning("IL2026", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/108507")] - public ClassWithWarningOnGenericArgumentConstructor() - { - } - } - - [UnexpectedWarning("IL2026", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108507")] - [RequiresUnreferencedCode("--ClassWithWarningOnGenericArgumentConstructorWithRequires--", ExcludeStatics = true)] - class ClassWithWarningOnGenericArgumentConstructorWithRequires : RequiresNew - { - } - - [UnexpectedWarning("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/108523")] - [RequiresUnreferencedCode("--GenericAnnotatedWithWarningWithRequires--", ExcludeStatics = true)] - public class GenericAnnotatedWithWarningWithRequires<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TFields> : RequiresAll - { - } - - [ExpectedWarning("IL2026", "--GenericClassWithWarningWithRequires--")] - [ExpectedWarning("IL2026", "--ClassWithWarningWithRequires--")] - [ExpectedWarning("IL2026", "--ClassWithWarningOnGenericArgumentConstructorWithRequires--")] - [ExpectedWarning("IL2026", "--GenericAnnotatedWithWarningWithRequires--")] - [ExpectedWarning("IL2091", Tool.Trimmer, "")] - public static void Test(ClassWithRequires inst = null) - { - var f = ClassWithRequires.field; - f = inst.instanceField; - int i = ClassWithRequires.fieldWithAttribute; - i = inst.instanceFieldWithAttribute; - ClassWithRequires.GenericMethod(new()); - inst.GenericInstanceMethod(new()); - ClassWithRequires.MethodWithAttribute(); - inst.InstanceMethodWithAttribute(); - var c = new ClassWithRequires.ClassWithWarning(); - var d = new ClassWithRequires.ClassWithAttribute(); - var g = new GenericClassWithWarningWithRequires(); - var h = new ClassWithWarningWithRequires(); - var j = new ClassWithWarningOnGenericArgumentConstructor(); - var k = new ClassWithWarningOnGenericArgumentConstructorWithRequires(); - var l = new GenericAnnotatedWithWarningWithRequires(); - } - } - - class ConstFieldsOnClassWithRequires - { - [RequiresUnreferencedCode("--ConstClassWithRequires--", ExcludeStatics = true)] - [RequiresDynamicCode("--ConstClassWithRequires--", ExcludeStatics = true)] - class ConstClassWithRequires - { - public const string Message = "Message"; - public const int Number = 42; - - public static void Method() { } - } - - static void TestClassWithRequires() - { - var a = ConstClassWithRequires.Message; - var b = ConstClassWithRequires.Number; - - ConstClassWithRequires.Method(); - } - - [RequiresUnreferencedCode(ConstClassWithRequiresUsingField.Message, ExcludeStatics = true)] - [RequiresDynamicCode(ConstClassWithRequiresUsingField.Message, ExcludeStatics = true)] - class ConstClassWithRequiresUsingField - { - public const string Message = "--ConstClassWithRequiresUsingField--"; - - public static void Method() { } - } - - static void TestClassUsingFieldInAttribute() - { - ConstClassWithRequiresUsingField.Method(); - } - - public static void Test() - { - TestClassWithRequires(); - TestClassUsingFieldInAttribute(); - } - } - } -} From baf60f510202bceddc0328cf90a4b7a66e3af6ee Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 21 Jul 2025 16:26:51 -0700 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Compiler/Dataflow/DiagnosticUtilities.cs | 18 +++++++++++++----- .../RequiresISymbolExtensions.cs | 6 ------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs index 3692f1448f9683..cc3cde0f26112f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs @@ -186,11 +186,19 @@ internal static bool DoesMemberRequire(this TypeSystemEntity member, string requ }; } - private static bool ExcludeStatics(CustomAttributeValue attribute) => - attribute.NamedArguments.Length == 1 && - attribute.NamedArguments[0].Name == "ExcludeStatics" && - attribute.NamedArguments[0].Value is bool excludeStatics && - excludeStatics; + private static bool ExcludeStatics(CustomAttributeValue attribute) + { + foreach (var namedArgument in attribute.NamedArguments) + { + if (namedArgument.Name == "ExcludeStatics" && + namedArgument.Value is bool excludeStatics && + excludeStatics) + { + return true; + } + } + return false; + } internal const string RequiresUnreferencedCodeAttribute = nameof(RequiresUnreferencedCodeAttribute); internal const string RequiresDynamicCodeAttribute = nameof(RequiresDynamicCodeAttribute); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs index e5672cf070398c..cf2e83f4b8f872 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs @@ -77,12 +77,6 @@ public static bool IsInRequiresScope(this ISymbol member, string attributeName, if (member.ContainingType is ITypeSymbol containingType && containingType.TryGetAttribute(attributeName, out requiresAttribute)) { - if (containingType.Name == "ClassWithRequires" && - containingType.ContainingType is ITypeSymbol containingTypeContainingType && - containingTypeContainingType.Name == "RequiresOnClassExcludeStatics") - { - containingType.TryGetAttribute(attributeName, out _); - } if (!ExcludeStatics(requiresAttribute)) return true; From fdc54bcaa0ddba0d1298d0377faa9a3d03a155ab Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 22 Jul 2025 10:32:34 -0700 Subject: [PATCH 4/4] Fix tests - Fix kept items validation for polyfilled attributes - Clean up tests - Fix to ignore NativeAOT injected members --- .../TestCasesRunner/AssemblyChecker.cs | 2 + .../RequiresDynamicCodeAttribute.cs | 7 ++++ .../RequiresUnreferencedCodeAttribute.cs | 7 ++++ .../RequiresCapabilityTests.cs | 12 ------ .../RequiresCapability/RequiresIsolated.cs | 42 ------------------- 5 files changed, 16 insertions(+), 54 deletions(-) delete mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/AssemblyChecker.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/AssemblyChecker.cs index 2bbc6f55408258..b5de71ed3bb079 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/AssemblyChecker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/AssemblyChecker.cs @@ -60,6 +60,8 @@ class LinkedMethodEntity : LinkedEntity ".MainMethodWrapper()", ".MainMethodWrapper(String[])", "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute.__GetFieldHelper(Int32,MethodTable*&)", + "System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute.__GetFieldHelper(Int32,MethodTable*&)", + "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.__GetFieldHelper(Int32,MethodTable*&)", "System.Runtime.InteropServices.TypeMapping", "System.Runtime.InteropServices.TypeMapping.GetOrCreateExternalTypeMapping()", "System.Runtime.InteropServices.TypeMapping.GetOrCreateProxyTypeMapping()", diff --git a/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs index 9ab59680f26109..34768f4d9bb61c 100644 --- a/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs +++ b/src/tools/illink/src/ILLink.Shared/RequiresDynamicCodeAttribute.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if INCLUDE_EXPECTATIONS +using Mono.Linker.Tests.Cases.Expectations.Assertions; +#endif + #nullable enable namespace System.Diagnostics.CodeAnalysis @@ -12,6 +16,9 @@ namespace System.Diagnostics.CodeAnalysis /// /// This allows tools to understand which methods are unsafe to call when compiling ahead of time. /// +#if INCLUDE_EXPECTATIONS + [SkipKeptItemsValidation] +#endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] #if SYSTEM_PRIVATE_CORELIB public diff --git a/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs index 76a754dd2fac42..5c2c9ce96d7266 100644 --- a/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs +++ b/src/tools/illink/src/ILLink.Shared/RequiresUnreferencedCodeAttribute.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if INCLUDE_EXPECTATIONS +using Mono.Linker.Tests.Cases.Expectations.Assertions; +#endif + #nullable enable namespace System.Diagnostics.CodeAnalysis @@ -13,6 +17,9 @@ namespace System.Diagnostics.CodeAnalysis /// This allows tools to understand which methods are unsafe to call when removing unreferenced /// code from an application. /// +#if INCLUDE_EXPECTATIONS + [SkipKeptItemsValidation] +#endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] #if SYSTEM_PRIVATE_CORELIB public diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs index 8e6f3a8bf1e48b..da78b488d0c643 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs @@ -94,18 +94,6 @@ public Task RequiresOnClass() return RunTest(nameof(RequiresOnClass)); } - [Fact] - public Task RequiresOnClassExcludeStatics() - { - return RunTest(); - } - - [Fact] - public Task RequiresIsolated() - { - return RunTest(); - } - [Fact] public Task RequiresOnEvents() { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs deleted file mode 100644 index 4c2745d80f8f14..00000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresIsolated.cs +++ /dev/null @@ -1,42 +0,0 @@ -// 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.Helpers; - -namespace Mono.Linker.Tests.Cases.RequiresCapability -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class RequiresIsolated - { - public static void Main() - { - MembersOnClassWithRequires.Test(); - } - - class MembersOnClassWithRequires - { - public class RequiresAll<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] U> - { - } - - [RequiresDynamicCode("--ClassWithRequires--", ExcludeStatics = true)] - public class ClassWithRequires - { - [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] - public static RequiresAll field; - } - - [UnexpectedWarning("IL2091", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/113249")] - public static void Test(ClassWithRequires inst = null) - { - var f = ClassWithRequires.field; - } - - } - } -}