Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>2022-03-01 21:03:18 +0300
committerGitHub <noreply@github.com>2022-03-01 21:03:18 +0300
commit8c0df916d86bfd223bc0cd4830611fa8611bb72f (patch)
tree878e66432914af97e8e8896943e821eb03ce9590
parenta8f953291e17745ee920d37c5143ab7556031301 (diff)
Share intrinsics for Expression.Property and Field (#2671)
Shares two more intrinsics, with supporting infra. Fixed a bug in the intrinsics - passing null to the name of a property/field will throw at runtime, so no need to validate anything. Modifies the existing tests to add warnings, since that is the only verifyable behavior for the analyzer.
-rw-r--r--src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs1
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs13
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/ReflectionAccessAnalyzer.cs6
-rw-r--r--src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs63
-rw-r--r--src/linker/Linker.Dataflow/HandleCallAction.cs10
-rw-r--r--src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs67
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs14
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/ExpressionFieldString.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs56
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyString.cs31
11 files changed, 194 insertions, 100 deletions
diff --git a/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs b/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
index e525c52c3..fa7a8ca8a 100644
--- a/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs
@@ -37,6 +37,7 @@ namespace ILLink.RoslynAnalyzer
diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersFieldAccessedViaReflection));
diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection));
diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.UnrecognizedTypeInRuntimeHelpersRunClassConstructor));
+ diagDescriptorsArrayBuilder.Add (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined));
return diagDescriptorsArrayBuilder.ToImmutable ();
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
index ebb14a434..6e743f9b7 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using ILLink.RoslynAnalyzer;
@@ -79,6 +80,18 @@ namespace ILLink.Shared.TrimAnalysis
// TODO: Does the analyzer need to do something here?
private partial void MarkType (TypeProxy type) { }
+ private partial bool MarkAssociatedProperty (MethodProxy method)
+ {
+ if (method.Method.MethodKind == MethodKind.PropertyGet || method.Method.MethodKind == MethodKind.PropertySet) {
+ var property = (IPropertySymbol) method.Method.AssociatedSymbol!;
+ Debug.Assert (property != null);
+ ReflectionAccessAnalyzer.GetReflectionAccessDiagnosticsForProperty (_diagnosticContext, property!);
+ return true;
+ }
+
+ return false;
+ }
+
private partial string GetContainingSymbolDisplayName () => _operation.FindContainingSymbol (_owningSymbol).GetDisplayName ();
}
}
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/ReflectionAccessAnalyzer.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/ReflectionAccessAnalyzer.cs
index b5663698a..d190370a3 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/ReflectionAccessAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/ReflectionAccessAnalyzer.cs
@@ -24,7 +24,7 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
GetDiagnosticsForField (diagnosticContext, field);
break;
case IPropertySymbol property:
- GetDiagnosticsForProperty (diagnosticContext, property);
+ GetReflectionAccessDiagnosticsForProperty (diagnosticContext, property);
break;
/* Skip Type and InterfaceImplementation marking since doesnt seem relevant for diagnostic generation
case ITypeSymbol nestedType:
@@ -56,7 +56,7 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
internal void GetReflectionAccessDiagnosticsForPropertiesOnTypeHierarchy (in DiagnosticContext diagnosticContext, ITypeSymbol typeSymbol, string name, BindingFlags? bindingFlags)
{
foreach (var prop in typeSymbol.GetPropertiesOnTypeHierarchy (p => p.Name == name, bindingFlags))
- GetDiagnosticsForProperty (diagnosticContext, prop);
+ GetReflectionAccessDiagnosticsForProperty (diagnosticContext, prop);
}
static void ReportRequiresUnreferencedCodeDiagnostic (in DiagnosticContext diagnosticContext, AttributeData requiresAttributeData, ISymbol member)
@@ -85,7 +85,7 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
}
}
- static void GetDiagnosticsForProperty (in DiagnosticContext diagnosticContext, IPropertySymbol propertySymbol)
+ internal static void GetReflectionAccessDiagnosticsForProperty (in DiagnosticContext diagnosticContext, IPropertySymbol propertySymbol)
{
if (propertySymbol.SetMethod is not null)
GetReflectionAccessDiagnosticsForMethod (diagnosticContext, propertySymbol.SetMethod);
diff --git a/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs b/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
index 216d5a105..002c213b9 100644
--- a/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
+++ b/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using ILLink.Shared.DataFlow;
@@ -479,6 +480,66 @@ namespace ILLink.Shared.TrimAnalysis
}
break;
+ //
+ // System.Linq.Expressions.Expression
+ //
+ // static Property (Expression, MethodInfo)
+ //
+ case IntrinsicId.Expression_Property when calledMethod.HasParameterOfType (1, "System.Reflection.MethodInfo"): {
+ foreach (var value in argumentValues[1]) {
+ if (value is SystemReflectionMethodBaseValue methodBaseValue) {
+ // We have one of the accessors for the property. The Expression.Property will in this case search
+ // for the matching PropertyInfo and store that. So to be perfectly correct we need to mark the
+ // respective PropertyInfo as "accessed via reflection".
+ if (MarkAssociatedProperty (methodBaseValue.MethodRepresented))
+ continue;
+ } else if (value == NullValue.Instance) {
+ continue;
+ }
+
+ // In all other cases we may not even know which type this is about, so there's nothing we can do
+ // report it as a warning.
+ _diagnosticContext.AddDiagnostic (DiagnosticId.PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined,
+ GetMethodParameterValue (calledMethod, 1, DynamicallyAccessedMemberTypes.None).GetDiagnosticArgumentsForAnnotationMismatch ().ToArray ());
+ }
+ }
+ break;
+
+ //
+ // System.Linq.Expressions.Expression
+ //
+ // static Field (Expression, Type, String)
+ // static Property (Expression, Type, String)
+ //
+ case var fieldOrPropertyInstrinsic when fieldOrPropertyInstrinsic == IntrinsicId.Expression_Field || fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property: {
+ DynamicallyAccessedMemberTypes memberTypes = fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property
+ ? DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties
+ : DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields;
+
+ var targetValue = GetMethodParameterValue (calledMethod, 1, memberTypes);
+ foreach (var value in argumentValues[1]) {
+ if (value is SystemTypeValue systemTypeValue) {
+ foreach (var stringParam in argumentValues[2]) {
+ if (stringParam is KnownStringValue stringValue) {
+ BindingFlags bindingFlags = argumentValues[0].AsSingleValue () is NullValue ? BindingFlags.Static : BindingFlags.Default;
+ if (fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property) {
+ MarkPropertiesOnTypeHierarchy (systemTypeValue.RepresentedType, stringValue.Contents, bindingFlags);
+ } else {
+ MarkFieldsOnTypeHierarchy (systemTypeValue.RepresentedType, stringValue.Contents, bindingFlags);
+ }
+ } else if (stringParam is NullValue) {
+ // Null name will always throw, so there's nothing to do
+ } else {
+ _requireDynamicallyAccessedMembersAction.Invoke (value, targetValue);
+ }
+ }
+ } else {
+ _requireDynamicallyAccessedMembersAction.Invoke (value, targetValue);
+ }
+ }
+ }
+ break;
+
case IntrinsicId.None:
methodReturnValue = MultiValueLattice.Top;
return false;
@@ -637,6 +698,8 @@ namespace ILLink.Shared.TrimAnalysis
private partial void MarkType (TypeProxy type);
+ private partial bool MarkAssociatedProperty (MethodProxy method);
+
// Only used for internal diagnostic purposes (not even for warning messages)
private partial string GetContainingSymbolDisplayName ();
}
diff --git a/src/linker/Linker.Dataflow/HandleCallAction.cs b/src/linker/Linker.Dataflow/HandleCallAction.cs
index b88e6d8e9..de8dcf8f2 100644
--- a/src/linker/Linker.Dataflow/HandleCallAction.cs
+++ b/src/linker/Linker.Dataflow/HandleCallAction.cs
@@ -86,6 +86,16 @@ namespace ILLink.Shared.TrimAnalysis
private partial void MarkType (TypeProxy type)
=> _reflectionMethodBodyScanner.MarkType (_analysisContext, type.Type);
+ private partial bool MarkAssociatedProperty (MethodProxy method)
+ {
+ if (method.Method.TryGetProperty (out PropertyDefinition? propertyDefinition)) {
+ _reflectionMethodBodyScanner.MarkProperty (_analysisContext, propertyDefinition);
+ return true;
+ }
+
+ return false;
+ }
+
private partial string GetContainingSymbolDisplayName () => _callingMethodDefinition.GetDisplayName ();
}
}
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
index be5306e55..61325ae6b 100644
--- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
+++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
@@ -287,7 +287,9 @@ namespace Mono.Linker.Dataflow
|| getRuntimeMember == IntrinsicId.RuntimeReflectionExtensions_GetRuntimeProperty:
case IntrinsicId.Type_GetMember:
case IntrinsicId.Type_GetMethod:
- case IntrinsicId.Type_GetNestedType: {
+ case IntrinsicId.Type_GetNestedType:
+ case IntrinsicId.Expression_Property when calledMethod.HasParameterOfType (1, "System.Reflection.MethodInfo"):
+ case var fieldOrPropertyInstrinsic when fieldOrPropertyInstrinsic == IntrinsicId.Expression_Field || fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property: {
var instanceValue = MultiValueLattice.Top;
IReadOnlyList<MultiValue> parameterValues = methodParams;
if (calledMethodDefinition.HasImplicitThis ()) {
@@ -415,67 +417,6 @@ namespace Mono.Linker.Dataflow
//
// System.Linq.Expressions.Expression
//
- // static Property (Expression, MethodInfo)
- //
- case IntrinsicId.Expression_Property when calledMethod.HasParameterOfType (1, "System.Reflection.MethodInfo"): {
- foreach (var value in methodParams[1]) {
- if (value is SystemReflectionMethodBaseValue methodBaseValue) {
- // We have one of the accessors for the property. The Expression.Property will in this case search
- // for the matching PropertyInfo and store that. So to be perfectly correct we need to mark the
- // respective PropertyInfo as "accessed via reflection".
- if (methodBaseValue.MethodRepresented.Method.TryGetProperty (out PropertyDefinition? propertyDefinition)) {
- MarkProperty (analysisContext, propertyDefinition);
- continue;
- }
- } else if (value == NullValue.Instance) {
- continue;
- }
-
- // In all other cases we may not even know which type this is about, so there's nothing we can do
- // report it as a warning.
- analysisContext.ReportWarning (DiagnosticId.PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined,
- DiagnosticUtilities.GetParameterNameForErrorMessage (calledMethodDefinition.Parameters[1]),
- DiagnosticUtilities.GetMethodSignatureDisplayName (calledMethodDefinition));
- }
- }
- break;
-
- //
- // System.Linq.Expressions.Expression
- //
- // static Field (Expression, Type, String)
- // static Property (Expression, Type, String)
- //
- case var fieldOrPropertyInstrinsic when fieldOrPropertyInstrinsic == IntrinsicId.Expression_Field || fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property: {
- DynamicallyAccessedMemberTypes memberTypes = fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property
- ? DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties
- : DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields;
-
- var targetValue = GetMethodParameterValue (calledMethodDefinition, 1, memberTypes);
- foreach (var value in methodParams[1]) {
- if (value is SystemTypeValue systemTypeValue) {
- foreach (var stringParam in methodParams[2]) {
- if (stringParam is KnownStringValue stringValue) {
- BindingFlags bindingFlags = methodParams[0].AsSingleValue () is NullValue ? BindingFlags.Static : BindingFlags.Default;
- if (fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property) {
- MarkPropertiesOnTypeHierarchy (analysisContext, systemTypeValue.RepresentedType.Type, filter: p => p.Name == stringValue.Contents, bindingFlags);
- } else {
- MarkFieldsOnTypeHierarchy (analysisContext, systemTypeValue.RepresentedType.Type, filter: f => f.Name == stringValue.Contents, bindingFlags);
- }
- } else {
- RequireDynamicallyAccessedMembers (analysisContext, value, targetValue);
- }
- }
- } else {
- RequireDynamicallyAccessedMembers (analysisContext, value, targetValue);
- }
- }
- }
- break;
-
- //
- // System.Linq.Expressions.Expression
- //
// static New (Type)
//
case IntrinsicId.Expression_New: {
@@ -1151,7 +1092,7 @@ namespace Mono.Linker.Dataflow
_markStep.MarkFieldVisibleToReflection (field, new DependencyInfo (dependencyKind, analysisContext.Origin.Provider));
}
- void MarkProperty (in AnalysisContext analysisContext, PropertyDefinition property, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
+ internal void MarkProperty (in AnalysisContext analysisContext, PropertyDefinition property, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
_markStep.MarkPropertyVisibleToReflection (property, new DependencyInfo (dependencyKind, analysisContext.Origin.Provider));
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
index 7dc1e1639..0e12517ab 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
@@ -55,6 +55,12 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
+ public Task ExpressionFieldString ()
+ {
+ return RunTest ();
+ }
+
+ [Fact]
public Task ExpressionNewType ()
{
return RunTest (allowMissingWarnings: true);
@@ -63,7 +69,13 @@ namespace ILLink.RoslynAnalyzer.Tests
[Fact]
public Task ExpressionPropertyMethodInfo ()
{
- return RunTest (allowMissingWarnings: true);
+ return RunTest ();
+ }
+
+ [Fact]
+ public Task ExpressionPropertyString ()
+ {
+ return RunTest ();
}
[Fact]
diff --git a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
index 2ef192d11..6e1bf553d 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
@@ -44,18 +44,6 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
- public Task ExpressionFieldString ()
- {
- return RunTest (allowMissingWarnings: true);
- }
-
- [Fact]
- public Task ExpressionPropertyString ()
- {
- return RunTest (allowMissingWarnings: true);
- }
-
- [Fact]
public Task ObjectGetTypeLibraryMode ()
{
return RunTest (allowMissingWarnings: true);
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionFieldString.cs b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionFieldString.cs
index 3f1396000..1a7e121dc 100644
--- a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionFieldString.cs
+++ b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionFieldString.cs
@@ -10,13 +10,16 @@ namespace Mono.Linker.Tests.Cases.Reflection
[ExpectedNoWarnings]
public class ExpressionFieldString
{
+ [ExpectedWarning ("IL2110", nameof (StaticWithDAM))]
+ [ExpectedWarning ("IL2110", "_publicFieldOnBase")]
[ExpectedWarning ("IL2072", nameof (Expression) + "." + nameof (Expression.Field))]
public static void Main ()
{
- Expression.Field (Expression.Parameter (typeof (int), ""), typeof (ExpressionFieldString), "Field");
+ Expression.Field (Expression.Parameter (typeof (int), ""), typeof (ExpressionFieldString), "InstanceField");
Expression.Field (null, typeof (ExpressionFieldString), "StaticField");
+ Expression.Field (null, typeof (ExpressionFieldString), "StaticWithDAM"); // IL2110
Expression.Field (null, typeof (Derived), "_protectedFieldOnBase");
- Expression.Field (null, typeof (Derived), "_publicFieldOnBase");
+ Expression.Field (null, typeof (Derived), "_publicFieldOnBase"); // IL2110
UnknownType.Test ();
UnknownTypeNoAnnotation.Test ();
UnknownString.Test ();
@@ -29,13 +32,20 @@ namespace Mono.Linker.Tests.Cases.Reflection
}
[Kept]
- private int Field;
+ private int InstanceField;
[Kept]
static private int StaticField;
+ [Kept]
+ [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ static private Type StaticWithDAM;
+
private int UnusedField;
+ public static int StaticField1 { get => StaticField; set => StaticField = value; }
+
[Kept]
static Type GetType ()
{
@@ -142,7 +152,6 @@ namespace Mono.Linker.Tests.Cases.Reflection
Expression.Field (null, typeof (Base), noValue);
}
-
[Kept]
class Base
{
@@ -150,7 +159,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
protected static bool _protectedFieldOnBase;
[Kept]
- public static bool _publicFieldOnBase;
+ [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type _publicFieldOnBase;
}
[Kept]
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs
index b4d9613ae..b0de477dc 100644
--- a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs
+++ b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -32,10 +33,12 @@ namespace Mono.Linker.Tests.Cases.Reflection
{
[Kept]
[KeptBackingField]
- public static int StaticProperty {
+ public static int StaticPropertyExpressionAccess {
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (StaticPropertyExpressionAccess))]
set;
}
@@ -45,6 +48,8 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (StaticPropertyViaReflection))]
set;
}
@@ -54,15 +59,19 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (StaticPropertyViaRuntimeMethod))]
set;
}
[Kept]
[KeptBackingField]
- public int InstanceProperty {
+ public int InstancePropertyExpressionAccess {
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (InstancePropertyExpressionAccess))]
set;
}
@@ -72,18 +81,27 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (InstancePropertyViaReflection))]
set;
}
[Kept]
+ // https://github.com/dotnet/linker/issues/2669
+ [ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", nameof (StaticPropertyViaReflection))]
+ [ExpectedWarning ("IL2026", nameof (StaticPropertyViaRuntimeMethod))]
+ // https://github.com/dotnet/linker/issues/2669
+ [ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", nameof (InstancePropertyViaReflection))]
public static void Test ()
{
- Expression<Func<int>> staticGetter = () => StaticProperty;
+ Expression<Func<int>> staticGetter = () => StaticPropertyExpressionAccess;
Expression.Property (null, typeof (PropertyGetter).GetMethod ("get_StaticPropertyViaReflection"));
PropertyGetter instance = new PropertyGetter ();
- Expression<Func<PropertyGetter, int>> instanceGetter = i => i.InstanceProperty;
+ Expression<Func<PropertyGetter, int>> instanceGetter = i => i.InstancePropertyExpressionAccess;
Expression.Property (Expression.New (typeof (PropertyGetter)), typeof (PropertyGetter).GetMethod ("get_InstancePropertyViaReflection"));
@@ -97,8 +115,10 @@ namespace Mono.Linker.Tests.Cases.Reflection
{
[Kept]
[KeptBackingField]
- public static int StaticProperty {
+ public static int StaticPropertyReflectionAccess {
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (StaticPropertyReflectionAccess))]
get;
[Kept]
set;
@@ -108,6 +128,8 @@ namespace Mono.Linker.Tests.Cases.Reflection
[KeptBackingField]
public static int StaticPropertyViaRuntimeMethod {
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (StaticPropertyViaRuntimeMethod))]
get;
[Kept]
set;
@@ -115,21 +137,26 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
[KeptBackingField]
- public int InstanceProperty {
+ public int InstancePropertyReflectionAccess {
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (InstancePropertyReflectionAccess))]
get;
[Kept]
set;
}
[Kept]
+ [ExpectedWarning ("IL2026", nameof (StaticPropertyReflectionAccess))]
+ [ExpectedWarning ("IL2026", nameof (StaticPropertyViaRuntimeMethod))]
+ [ExpectedWarning ("IL2026", nameof (InstancePropertyReflectionAccess))]
public static void Test ()
{
- Expression.Property (null, typeof (PropertySetter).GetMethod ("set_StaticProperty"));
+ Expression.Property (null, typeof (PropertySetter).GetMethod ("set_StaticPropertyReflectionAccess"));
Expression.Property (null, typeof (PropertySetter).GetRuntimeMethod ("set_StaticPropertyViaRuntimeMethod", Type.EmptyTypes));
- Expression.Property (Expression.New (typeof (PropertySetter)), typeof (PropertySetter).GetMethod ("set_InstanceProperty"));
+ Expression.Property (Expression.New (typeof (PropertySetter)), typeof (PropertySetter).GetMethod ("set_InstancePropertyReflectionAccess"));
}
}
@@ -158,10 +185,12 @@ namespace Mono.Linker.Tests.Cases.Reflection
{
[Kept]
[KeptBackingField]
- public static int StaticProperty {
+ public static int FirstStaticProperty {
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (FirstStaticProperty))]
set;
}
@@ -171,16 +200,20 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
get;
[Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (SecondStaticProperty))]
set;
}
[Kept]
+ [ExpectedWarning ("IL2026", nameof (FirstStaticProperty))]
+ [ExpectedWarning ("IL2026", nameof (SecondStaticProperty))]
public static void Test (int p)
{
MethodInfo mi;
switch (p) {
case 0:
- mi = typeof (MultipleMethods).GetMethod ("get_StaticProperty");
+ mi = typeof (MultipleMethods).GetMethod ("get_FirstStaticProperty");
break;
case 1:
mi = typeof (MultipleMethods).GetMethod ("get_SecondStaticProperty");
@@ -195,7 +228,8 @@ namespace Mono.Linker.Tests.Cases.Reflection
}
[Kept]
- [ExpectedWarning ("IL2103", nameof (Expression) + "." + nameof (Expression.Property))]
+ // https://github.com/dotnet/linker/issues/2670
+ [ExpectedWarning ("IL2103", nameof (Expression) + "." + nameof (Expression.Property), ProducedBy = ProducedBy.Trimmer)]
static void TestUnknownMethod (MethodInfo mi)
{
Expression.Property (null, mi);
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyString.cs b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyString.cs
index 9f9f8591d..ff8530d5c 100644
--- a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyString.cs
+++ b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyString.cs
@@ -12,11 +12,14 @@ namespace Mono.Linker.Tests.Cases.Reflection
[ExpectedNoWarnings]
public class ExpressionPropertyString
{
+ [ExpectedWarning ("IL2026", nameof (BasicProperty))]
+ [ExpectedWarning ("IL2111", "ProtectedPropertyOnBase")]
+ [ExpectedWarning ("IL2026", "PublicPropertyOnBase")]
[ExpectedWarning ("IL2072", nameof (Expression) + "." + nameof (Expression.Property))]
public static void Main ()
{
- Expression.Property (Expression.Parameter (typeof (int), ""), typeof (ExpressionPropertyString), "Property");
- Expression.Property (null, typeof (ExpressionPropertyString), "StaticProperty");
+ Expression.Property (Expression.Parameter (typeof (int), ""), typeof (ExpressionPropertyString), nameof (BasicProperty));
+ Expression.Property (null, typeof (ExpressionPropertyString), nameof (StaticProperty));
Expression.Property (null, typeof (Derived), "ProtectedPropertyOnBase");
Expression.Property (null, typeof (Derived), "PublicPropertyOnBase");
UnknownType.Test ();
@@ -30,13 +33,15 @@ namespace Mono.Linker.Tests.Cases.Reflection
}
[Kept]
- private int Property {
+ private int BasicProperty {
[Kept]
[ExpectBodyModified]
get;
[Kept]
[ExpectBodyModified]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (BasicProperty))]
set;
}
@@ -159,11 +164,27 @@ namespace Mono.Linker.Tests.Cases.Reflection
{
[Kept]
[KeptBackingField]
- protected static bool ProtectedPropertyOnBase { [Kept] get; }
+ [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ protected static Type ProtectedPropertyOnBase {
+ [Kept]
+ get;
+
+ [Kept]
+ set;
+ }
[Kept]
[KeptBackingField]
- public static bool PublicPropertyOnBase { [Kept] get; }
+ public static bool PublicPropertyOnBase {
+ [Kept]
+ get;
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
+ [RequiresUnreferencedCode (nameof (PublicPropertyOnBase))]
+ set;
+ }
}
[Kept]