diff options
5 files changed, 208 insertions, 70 deletions
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 28e0e0a98..7f3b36408 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1558,10 +1558,12 @@ namespace Mono.Linker.Dataflow // Overload that has the parameters as the second or fourth argument int argsParam = parameters.Count == 2 || parameters.Count == 3 ? 1 : 3; - if (methodParams.Count > argsParam && - methodParams[argsParam] is ArrayValue arrayValue && - arrayValue.Size.AsConstInt () != null) { - ctorParameterCount = arrayValue.Size.AsConstInt (); + if (methodParams.Count > argsParam) { + if (methodParams[argsParam] is ArrayValue arrayValue && + arrayValue.Size.AsConstInt () != null) + ctorParameterCount = arrayValue.Size.AsConstInt (); + else if (methodParams[argsParam] is NullValue) + ctorParameterCount = 0; } if (parameters.Count > 3) { @@ -1588,9 +1590,14 @@ namespace Mono.Linker.Dataflow reflectionContext.RecordHandledPattern (); } else { // Otherwise fall back to the bitfield requirements - var requiredMemberTypes = ctorParameterCount == 0 - ? DynamicallyAccessedMemberTypes.PublicParameterlessConstructor - : GetDynamicallyAccessedMemberTypesFromBindingFlagsForConstructors (bindingFlags); + var requiredMemberTypes = GetDynamicallyAccessedMemberTypesFromBindingFlagsForConstructors (bindingFlags); + + // Special case the public parameterless constructor if we know that there are 0 args passed in + if (ctorParameterCount == 0 && + requiredMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors) && + !requiredMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicConstructors)) + requiredMemberTypes = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor; + RequireDynamicallyAccessedMembers (ref reflectionContext, requiredMemberTypes, value, calledMethod.Parameters[0]); } } @@ -1997,17 +2004,24 @@ namespace Mono.Linker.Dataflow // We allow a new() constraint on a generic parameter to satisfy DynamicallyAccessedMemberTypes.PublicParameterlessConstructor reflectionContext.RecordHandledPattern (); } else if (uniqueValue is LeafValueWithDynamicallyAccessedMemberNode valueWithDynamicallyAccessedMember) { - if (!valueWithDynamicallyAccessedMember.DynamicallyAccessedMemberTypes.HasFlag (requiredMemberTypes)) { + var availableMemberTypes = valueWithDynamicallyAccessedMember.DynamicallyAccessedMemberTypes; + if (!availableMemberTypes.HasFlag (requiredMemberTypes)) { string missingMemberTypes = $"'{nameof (DynamicallyAccessedMemberTypes)}.{nameof (DynamicallyAccessedMemberTypes.All)}'"; if (requiredMemberTypes != DynamicallyAccessedMemberTypes.All) { var missingMemberTypesList = AllDynamicallyAccessedMemberTypes - .Where (damt => (requiredMemberTypes & ~valueWithDynamicallyAccessedMember.DynamicallyAccessedMemberTypes & damt) == damt && damt != DynamicallyAccessedMemberTypes.None) + .Where (damt => (requiredMemberTypes & ~availableMemberTypes & damt) == damt && damt != DynamicallyAccessedMemberTypes.None) .ToList (); + // PublicConstructors is a special case since its value is 3 - so PublicParameterlessConstructor (1) | _PublicConstructor_WithMoreThanOneParameter_ (2) + // The above bit logic only works for value with single bit set. + if (requiredMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors) && + availableMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor) && + !availableMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors)) + missingMemberTypesList.Add (DynamicallyAccessedMemberTypes.PublicConstructors); + if (missingMemberTypesList.Contains (DynamicallyAccessedMemberTypes.PublicConstructors) && - missingMemberTypesList.SingleOrDefault (x => x == DynamicallyAccessedMemberTypes.PublicParameterlessConstructor) is var ppc && - ppc != DynamicallyAccessedMemberTypes.None) - missingMemberTypesList.Remove (ppc); + missingMemberTypesList.Contains (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)) + missingMemberTypesList.Remove (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor); missingMemberTypes = string.Join (", ", missingMemberTypesList.Select (mmt => { string mmtName = mmt == DynamicallyAccessedMemberTypesOverlay.Interfaces diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs index 3889225a2..09de0a015 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs @@ -264,6 +264,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow [UnrecognizedReflectionAccessPattern (typeof (GenericBaseTypeWithRequirements<>), "T", messageCode: "IL2091")] class DerivedTypeWithOpenGenericOnBase<T> : GenericBaseTypeWithRequirements<T> { + [UnrecognizedReflectionAccessPattern (typeof (GenericBaseTypeWithRequirements<>), "T", messageCode: "IL2091")] + public DerivedTypeWithOpenGenericOnBase () { } } [RecognizedReflectionAccessPattern] @@ -363,11 +365,12 @@ namespace Mono.Linker.Tests.Cases.DataFlow [RecognizedReflectionAccessPattern] set; } + public TypeRequiresPublicMethods<TOuter> PublicMethodsProperty { [UnrecognizedReflectionAccessPattern (typeof (TypeRequiresPublicMethods<>), "T", messageCode: "IL2091")] - get; + get => null; [UnrecognizedReflectionAccessPattern (typeof (TypeRequiresPublicMethods<>), "T", messageCode: "IL2091")] - set; + set { } } [RecognizedReflectionAccessPattern] @@ -424,6 +427,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow class PartialyInstantiatedMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> : BaseForPartialInstantiation<TestType, TOuter> { + [UnrecognizedReflectionAccessPattern (typeof (BaseForPartialInstantiation<,>), "TMethods", messageCode: "IL2091")] + public PartialyInstantiatedMethods () { } } [RecognizedReflectionAccessPattern] diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs b/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs index a16ffd9ef..5d3805aef 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs @@ -34,12 +34,13 @@ namespace Mono.Linker.Tests.Cases.DataFlow TestNonPublicEvents (typeof (TestType)); TestInterfaces (typeof (TestType)); TestAll (typeof (TestType)); + TestMultiple (typeof (TestType)); } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicParameterlessConstructor ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) { @@ -51,9 +52,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicConstructors ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { @@ -65,10 +67,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicParameterlessConstructor))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicParameterlessConstructor), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicConstructors ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type) { @@ -80,9 +82,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicMethods))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), "y '" + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors) + "' i")] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicMethods ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { @@ -93,9 +95,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicMethods ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type) { @@ -106,9 +108,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicFields ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) { @@ -119,9 +121,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicFields ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) { @@ -132,9 +134,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicNestedTypes ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] Type type) { @@ -145,9 +147,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicNestedTypes))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicNestedTypes ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] Type type) { @@ -158,9 +160,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicProperties))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicProperties), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicProperties))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicProperties ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { @@ -171,9 +173,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicProperties))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicProperties), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicProperties))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicProperties ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type) { @@ -184,9 +186,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicEvents))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicEvents), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicEvents))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestPublicEvents ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] Type type) { @@ -197,9 +199,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicEvents))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicEvents), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicEvents))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestNonPublicEvents ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicEvents)] Type type) { @@ -210,9 +212,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresAll (); // Warns } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicNestedTypes))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] static void TestInterfaces ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type type) { @@ -244,6 +246,31 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.RequiresInterfaces (); } + static void RequiresMultiplePrivates ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) + { + } + + static void RequiresSomePublic ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicNestedTypes | DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + + [ExpectedWarning ("IL2067", + nameof (RequiresMultiplePrivates), + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicMethods), + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] + [ExpectedWarning ("IL2067", + nameof (RequiresSomePublic), + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces), + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] + static void TestMultiple ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) + { + RequiresMultiplePrivates (type); + RequiresSomePublic (type); + } + class TestType { } } } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs b/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs index 8f1cfae07..bd21af5bc 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs @@ -16,7 +16,7 @@ namespace Mono.Linker.Tests.Cases.Reflection Activator.CreateInstance (typeof (Test1)); Activator.CreateInstance (typeof (Test2), true); Activator.CreateInstance (typeof (Test3), BindingFlags.NonPublic | BindingFlags.Instance, null, null, null); - Activator.CreateInstance (typeof (Test4), GetBindingFlags (), null, null, null); + Activator.CreateInstance (typeof (Test4), GetBindingFlags (), null, GetArgs (), null); Activator.CreateInstance (typeof (Test5), new object[] { 1, "ss" }); var p = new ActivatorCreateInstance (); @@ -51,6 +51,12 @@ namespace Mono.Linker.Tests.Cases.Reflection TestCreateInstanceOfTWithNoConstraint<TestCreateInstanceOfTWithNoConstraintType> (); TestCreateInstanceOfTWithDataflow<TestCreateInstanceOfTWithDataflowType> (); + + TestNullArgsOnKnownType (); + TestNullArgsOnAnnotatedType (typeof (TestType)); + TestNullArgsNonPublicOnly (typeof (TestType)); + + CreateInstanceWithGetTypeFromHierarchy.Test (); } [Kept] @@ -292,6 +298,12 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + private static object[] GetArgs () + { + return null; + } + + [Kept] private static void WithAssemblyName () { Activator.CreateInstance ("test", "Mono.Linker.Tests.Cases.Reflection.ActivatorCreateInstance+WithAssemblyNameParameterless1"); @@ -485,5 +497,77 @@ namespace Mono.Linker.Tests.Cases.Reflection { Activator.CreateInstance<T> (); } + + [Kept] + class TestNullArgsType + { + [Kept] + public TestNullArgsType () { } + + public TestNullArgsType (int i) { } + } + + [Kept] + [RecognizedReflectionAccessPattern] + private static void TestNullArgsOnKnownType () + { + Activator.CreateInstance (typeof (TestNullArgsType), null); + } + + [Kept] + [RecognizedReflectionAccessPattern] + private static void TestNullArgsOnAnnotatedType ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor), + KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] Type type) + { + Activator.CreateInstance (type, BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture); + } + + [Kept] + [ExpectedWarning ("IL2067", nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] + private static void TestNullArgsNonPublicOnly ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor), + KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] Type type) + { + Activator.CreateInstance (type, BindingFlags.NonPublic | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture); + } + + [Kept] + class CreateInstanceWithGetTypeFromHierarchy + { + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptMember (".ctor()")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + class AnnotatedBase + { + [Kept] + [ExpectedNoWarnings] + public void TestCreateInstance () + { + Activator.CreateInstance (GetType (), BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture, null); + } + } + + [Kept] + [KeptBaseType (typeof (AnnotatedBase))] + [KeptMember (".ctor()")] + class Derived : AnnotatedBase + { + [Kept] + public static void KeepIt () { } + } + + [Kept] + public static void Test () + { + Derived.KeepIt (); + (new AnnotatedBase ()).TestCreateInstance (); + } + } + + [Kept] + [KeptMember (".ctor()")] + class TestType { } } } diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index 7319df57b..7c71f3270 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -765,16 +765,7 @@ namespace Mono.Linker.Tests.TestCasesRunner return false; } else { - if (mc.Origin?.MemberDefinition?.FullName == attrProvider.FullName) - return true; - - // Compensate for cases where for some reason the OM doesn't preserve the declaring types - // on certain things after trimming. - if (mc.Origin?.MemberDefinition != null && mc.Origin?.MemberDefinition.DeclaringType == null && - mc.Origin?.MemberDefinition.Name == attrProvider.Name) - return true; - - return false; + return LogMessageHasSameOriginMember (mc, attrProvider); } return true; @@ -805,7 +796,10 @@ namespace Mono.Linker.Tests.TestCasesRunner if (expectedWarningCode != null) { int expectedWarningCodeNumber = int.Parse (expectedWarningCode.Substring (2)); - var matchedMessages = loggedMessages.Where (mc => mc.Category == MessageCategory.Warning && mc.Code == expectedWarningCodeNumber).ToList (); + var matchedMessages = loggedMessages.Where (mc => + mc.Category == MessageCategory.Warning && + mc.Code == expectedWarningCodeNumber && + LogMessageHasSameOriginMember (mc, attrProvider)).ToList (); foreach (var matchedMessage in matchedMessages) loggedMessages.Remove (matchedMessage); } @@ -854,6 +848,20 @@ namespace Mono.Linker.Tests.TestCasesRunner var remainingErrors = loggedMessages.Where (m => Regex.IsMatch (m.ToString (), @".*(error | warning): \d{4}.*")); Assert.IsEmpty (remainingErrors, $"Found unexpected errors:{Environment.NewLine}{string.Join (Environment.NewLine, remainingErrors)}"); } + + bool LogMessageHasSameOriginMember (MessageContainer mc, IMemberDefinition expectedOriginMember) + { + if (mc.Origin?.MemberDefinition?.FullName == expectedOriginMember.FullName) + return true; + + // Compensate for cases where for some reason the OM doesn't preserve the declaring types + // on certain things after trimming. + if (mc.Origin?.MemberDefinition != null && mc.Origin?.MemberDefinition.DeclaringType == null && + mc.Origin?.MemberDefinition.Name == expectedOriginMember.Name) + return true; + + return false; + } } void VerifyRecordedDependencies (AssemblyDefinition original, TestDependencyRecorder dependencyRecorder) |