diff --git a/eng/Versions.props b/eng/Versions.props index ea29c2eae231..cef1af03cc2b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -25,6 +25,7 @@ $(MicrosoftCodeAnalysisVersion) 1.0.1-beta1.* 3.3.2 + 7.0.0-preview.7.22375.6 diff --git a/external/cecil b/external/cecil index 2cd569a98964..1840b7410d37 160000 --- a/external/cecil +++ b/external/cecil @@ -1 +1 @@ -Subproject commit 2cd569a98964629b8fa88284a8b5af8077d5f9de +Subproject commit 1840b7410d37a613e684b6f9650e39e2d4950bbb diff --git a/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs index f47097cc475d..c4504332e9b9 100644 --- a/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs +++ b/src/ILLink.RoslynAnalyzer/RequiresISymbolExtensions.cs @@ -72,6 +72,15 @@ private static bool IsInRequiresScope (this ISymbol member, string requiresAttri if (checkAssociatedSymbol && member is IMethodSymbol { AssociatedSymbol: { } associated } && associated.HasAttribute (requiresAttribute)) return true; + // When using instance fields suppress the warning if the constructor has already the Requires annotation + if (member is IFieldSymbol field && !field.IsStatic) { + foreach (var constructor in field.ContainingType.InstanceConstructors) { + if (!constructor.HasAttribute (requiresAttribute)) + return false; + } + return true; + } + return false; } } diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs index 66733c12a402..81b4b5909001 100644 --- a/src/linker/Linker.Steps/MarkStep.cs +++ b/src/linker/Linker.Steps/MarkStep.cs @@ -59,7 +59,7 @@ protected LinkContext Context { } protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods; - protected List<(MethodDefinition, MarkScopeStack.Scope)> _virtual_methods; + protected HashSet<(MethodDefinition, MarkScopeStack.Scope)> _virtual_methods; protected Queue _assemblyLevelAttributes; readonly List _ivt_attributes; protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes; @@ -224,7 +224,7 @@ internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeH public MarkStep () { _methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> (); - _virtual_methods = new List<(MethodDefinition, MarkScopeStack.Scope)> (); + _virtual_methods = new HashSet<(MethodDefinition, MarkScopeStack.Scope)> (); _assemblyLevelAttributes = new Queue (); _ivt_attributes = new List (); _lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> (); @@ -3352,7 +3352,6 @@ void MarkBaseMethods (MethodDefinition method) if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) { // These are all virtual, no need to check IsVirtual before adding to list _virtual_methods.Add ((base_method, ScopeStack.CurrentScope)); - // _virtual_methods is a list and might have duplicates, but it's mostly just used for override validation, so it shouldn't matter continue; } diff --git a/test/Mono.Linker.Tests.Cases/Attributes/GenericAttributes.cs b/test/Mono.Linker.Tests.Cases/Attributes/GenericAttributes.cs new file mode 100644 index 000000000000..430fbc71417d --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Attributes/GenericAttributes.cs @@ -0,0 +1,69 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Attributes +{ + class GenericAttributes + { + static void Main () + { + new WithGenericAttribute_OfString (); + new WithGenericAttribute_OfInt (); + new WithConstrainedGenericAttribute (); + } + + [Kept] + [KeptAttributeAttribute (typeof (GenericAttribute))] + [KeptMember (".ctor()")] + [GenericAttribute("t", F = "f", P = "p")] + class WithGenericAttribute_OfString { + } + + [Kept] + [KeptAttributeAttribute (typeof (GenericAttribute))] + [KeptMember (".ctor()")] + [GenericAttribute(1, F = 2, P = 3)] + class WithGenericAttribute_OfInt { + } + + [Kept] + [KeptAttributeAttribute (typeof (ConstrainedGenericAttribute))] + [KeptMember (".ctor()")] + [ConstrainedGenericAttribute()] + class WithConstrainedGenericAttribute { + } + + [KeptBaseType (typeof (Attribute))] + class GenericAttribute : Attribute { + [Kept] + public GenericAttribute(T t) {} + + [Kept] + public T F; + + [Kept] + [KeptBackingField] + public T P { + get; + [Kept] + set; + } + } + + [Kept] + class ConstraintType { + } + + [KeptBaseType (typeof (ConstraintType))] + class DerivedFromConstraintType : ConstraintType { + } + + [KeptBaseType (typeof (Attribute))] + class ConstrainedGenericAttribute : Attribute + where T : ConstraintType { + [Kept] + public ConstrainedGenericAttribute() {} + } + } +} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs index 262e9b3f72b4..9e4df4cbcc51 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs @@ -351,6 +351,7 @@ public static void Test () TestWithMultipleArgumentsWithRequirements (); + StaticInterfaceMethods.Test (); NewConstraint.Test (); StructConstraint.Test (); UnmanagedConstraint.Test (); @@ -631,7 +632,6 @@ static void TestWithRequirementsFromGenericParam< .MakeGenericMethod (typeof (T)); } - static void TestWithRequirementsViaRuntimeMethod () { typeof (MakeGenericMethod).GetRuntimeMethod (nameof (GenericWithRequirements), Type.EmptyTypes) @@ -750,6 +750,36 @@ static void GenericWithMultipleArgumentsWithRequirements< { } + class StaticInterfaceMethods + { + public static void Test () + { + KnownType (); + UnannotatedGenericParam (); + AnnotatedGenericParam (); + } + + static MethodInfo KnownType () + => typeof (IFoo).GetMethod ("Method") + .MakeGenericMethod (new Type[] { typeof (int) }); + + [ExpectedWarning ("IL2090", "T", "PublicMethods")] + static MethodInfo UnannotatedGenericParam () + => typeof (IFoo).GetMethod ("Method") + .MakeGenericMethod (new Type[] { typeof (T) }); + + static MethodInfo AnnotatedGenericParam< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + => typeof (IFoo).GetMethod ("Method") + .MakeGenericMethod (new Type[] { typeof (T) }); + + interface IFoo + { + static abstract T Method< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (); + } + } + class NewConstraint { static void GenericWithNewConstraint () where T : new() diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index a0ecc2e51a81..44de82e7f7c9 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -25,6 +25,7 @@ public static void Main () TestRequiresOnBaseButNotOnDerived (); TestRequiresOnDerivedButNotOnBase (); TestRequiresOnBaseAndDerived (); + TestInstanceFieldSuppression (); TestSuppressionsOnClass (); TestStaticMethodOnRequiresTypeSuppressedByRequiresOnMethod (); TestStaticConstructorCalls (); @@ -246,6 +247,22 @@ static void TestInstanceFieldCallDontWarn () var _ = instance.field; } + public class ClassWithInstanceFieldWhichInitsDangerousClass + { + private ClassWithRequires _instanceField = new ClassWithRequires (); + + [RequiresUnreferencedCode ("Calling the constructor is dangerous")] + [RequiresDynamicCode ("Calling the constructor is dangerous")] + public ClassWithInstanceFieldWhichInitsDangerousClass () { } + } + + [ExpectedWarning ("IL2026", "Calling the constructor is dangerous")] + [ExpectedWarning ("IL3050", "Calling the constructor is dangerous", ProducedBy = ProducedBy.Analyzer)] + static void TestInstanceFieldSuppression () + { + _ = new ClassWithInstanceFieldWhichInitsDangerousClass (); + } + [RequiresUnreferencedCode ("Message for --StaticCtorTriggeredByMethodCall2--")] [RequiresDynamicCode ("Message for --StaticCtorTriggeredByMethodCall2--")] class StaticCtorTriggeredByMethodCall2 diff --git a/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj index 4a9ea7e7f2ce..448601a8a643 100644 --- a/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj +++ b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj @@ -1,4 +1,4 @@ - + true @@ -32,6 +32,7 @@ +