diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs
index d6d4526e5c771a..deb9474117f478 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs
@@ -476,7 +476,7 @@ protected virtual void Scan(MethodIL methodBody, ref InterproceduralState interp
{
if (methodBody.GetObject(reader.ReadILToken()) is MethodDesc methodOperand)
{
- HandleMethodReflectionAccess(methodBody, offset, methodOperand);
+ HandleMethodTokenAccess(methodBody, offset, methodOperand);
TrackNestedFunctionReference(methodOperand, ref interproceduralState);
}
@@ -537,7 +537,7 @@ protected virtual void Scan(MethodIL methodBody, ref InterproceduralState interp
{
if (methodBody.GetObject(reader.ReadILToken()) is MethodDesc methodOperand)
{
- HandleMethodReflectionAccess(methodBody, offset, methodOperand);
+ HandleMethodTokenAccess(methodBody, offset, methodOperand);
}
PopUnknown(currentStack, 1, methodBody, offset);
@@ -963,14 +963,14 @@ private void ScanLdtoken(MethodIL methodBody, int offset, object operand, Stack<
}
}
- HandleTypeReflectionAccess(methodBody, offset, type);
+ HandleTypeTokenAccess(methodBody, offset, type);
}
else if (operand is MethodDesc method)
{
StackSlot slot = new StackSlot(new RuntimeMethodHandleValue(method));
currentStack.Push(slot);
- HandleMethodReflectionAccess(methodBody, offset, method);
+ HandleMethodTokenAccess(methodBody, offset, method);
}
else
{
@@ -978,7 +978,7 @@ private void ScanLdtoken(MethodIL methodBody, int offset, object operand, Stack<
PushUnknown(currentStack);
- HandleFieldReflectionAccess(methodBody, offset, (FieldDesc)operand);
+ HandleFieldTokenAccess(methodBody, offset, (FieldDesc)operand);
}
}
@@ -1248,19 +1248,19 @@ protected void AssignRefAndOutParameters(
}
///
- /// Called when type is accessed directly (basically only ldtoken)
+ /// Called when type is accessed directly by its token (so creating a RuntimeHandle)
///
- protected abstract void HandleTypeReflectionAccess(MethodIL methodBody, int offset, TypeDesc accessedType);
+ protected abstract void HandleTypeTokenAccess(MethodIL methodBody, int offset, TypeDesc accessedType);
///
- /// Called to handle reflection access to a method without any other specifics (ldtoken or ldftn for example)
+ /// Called to handle access to a method by its token (so creating a RuntimeHandle)
///
- protected abstract void HandleMethodReflectionAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod);
+ protected abstract void HandleMethodTokenAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod);
///
- /// Called to handle reflection access to a field without any other specifics (ldtoken for example)
+ /// Called to handle access to a field by its token (so creating a RuntimeHandle)
///
- protected abstract void HandleFieldReflectionAccess(MethodIL methodBody, int offset, FieldDesc accessedField);
+ protected abstract void HandleFieldTokenAccess(MethodIL methodBody, int offset, FieldDesc accessedField);
private void HandleCall(
MethodIL callingMethodBody,
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
index 4ecabf6aad6d64..d32757d162d80b 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
@@ -31,6 +31,13 @@ public class ReflectionMarker
public FlowAnnotations Annotations { get; }
public DependencyList Dependencies { get => _dependencies; }
+ internal enum AccessKind
+ {
+ Unspecified,
+ DynamicallyAccessedMembersMark,
+ TokenAccess
+ }
+
public ReflectionMarker(Logger logger, NodeFactory factory, FlowAnnotations annotations, MetadataType? typeHierarchyDataFlowOrigin, bool enabled)
{
_logger = logger;
@@ -47,28 +54,28 @@ internal void MarkTypeForDynamicallyAccessedMembers(in MessageOrigin origin, Typ
foreach (var member in typeDefinition.GetDynamicallyAccessedMembers(requiredMemberTypes, declaredOnly))
{
- MarkTypeSystemEntity(origin, member, reason);
+ MarkTypeSystemEntity(origin, member, reason, AccessKind.DynamicallyAccessedMembersMark);
}
}
- internal void MarkTypeSystemEntity(in MessageOrigin origin, TypeSystemEntity entity, string reason)
+ internal void MarkTypeSystemEntity(in MessageOrigin origin, TypeSystemEntity entity, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
switch (entity)
{
case MethodDesc method:
- MarkMethod(origin, method, reason);
+ MarkMethod(origin, method, reason, accessKind);
break;
case FieldDesc field:
- MarkField(origin, field, reason);
+ MarkField(origin, field, reason, accessKind);
break;
case MetadataType nestedType:
- MarkType(origin, nestedType, reason);
+ MarkType(origin, nestedType, reason, accessKind);
break;
case PropertyPseudoDesc property:
- MarkProperty(origin, property, reason);
+ MarkProperty(origin, property, reason, accessKind);
break;
case EventPseudoDesc @event:
- MarkEvent(origin, @event, reason);
+ MarkEvent(origin, @event, reason, accessKind);
break;
// case InterfaceImplementation
// Nothing to do currently as Native AOT will preserve all interfaces on a preserved type
@@ -107,7 +114,7 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di
return true;
}
- internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason)
+ internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
@@ -115,27 +122,27 @@ internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason)
RootingHelpers.TryGetDependenciesForReflectedType(ref _dependencies, Factory, type, reason);
}
- internal void MarkMethod(in MessageOrigin origin, MethodDesc method, string reason)
+ internal void MarkMethod(in MessageOrigin origin, MethodDesc method, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
- CheckAndWarnOnReflectionAccess(origin, method);
+ CheckAndWarnOnReflectionAccess(origin, method, accessKind);
RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, Factory, method, reason);
}
- internal void MarkField(in MessageOrigin origin, FieldDesc field, string reason)
+ internal void MarkField(in MessageOrigin origin, FieldDesc field, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
- CheckAndWarnOnReflectionAccess(origin, field);
+ CheckAndWarnOnReflectionAccess(origin, field, accessKind);
RootingHelpers.TryGetDependenciesForReflectedField(ref _dependencies, Factory, field, reason);
}
- internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property, string reason)
+ internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
@@ -146,7 +153,7 @@ internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property,
MarkMethod(origin, property.SetMethod, reason);
}
- private void MarkEvent(in MessageOrigin origin, EventPseudoDesc @event, string reason)
+ private void MarkEvent(in MessageOrigin origin, EventPseudoDesc @event, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
@@ -209,86 +216,137 @@ internal void MarkStaticConstructor(in MessageOrigin origin, TypeDesc type, stri
}
}
- internal void CheckAndWarnOnReflectionAccess(in MessageOrigin origin, TypeSystemEntity entity)
+ internal void CheckAndWarnOnReflectionAccess(in MessageOrigin origin, TypeSystemEntity entity, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;
+ if (_typeHierarchyDataFlowOrigin is not null)
+ {
+ ReportWarningsForTypeHierarchyReflectionAccess(origin, entity);
+ }
+ else
+ {
+ ReportWarningsForReflectionAccess(origin, entity, accessKind);
+ }
+ }
+
+ private void ReportWarningsForReflectionAccess(in MessageOrigin origin, TypeSystemEntity entity, AccessKind accessKind)
+ {
+ Debug.Assert(entity is MethodDesc or FieldDesc);
+
// Note that we're using `ShouldSuppressAnalysisWarningsForRequires` instead of `DoesMemberRequire`.
// This is because reflection access is actually problematic on all members which are in a "requires" scope
// so for example even instance methods. See for example https://github.com/dotnet/linker/issues/3140 - it's possible
// to call a method on a "null" instance via reflection.
if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresAttribute))
{
- if (_typeHierarchyDataFlowOrigin is not null)
- {
- _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode,
- _typeHierarchyDataFlowOrigin.GetDisplayName(),
- entity.GetDisplayName(),
- MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(requiresAttribute.Value)),
- MessageFormat.FormatRequiresAttributeUrlArg(DiagnosticUtilities.GetRequiresAttributeUrl(requiresAttribute.Value)));
- }
- else
- {
+ if (!ShouldSkipWarningsForOverride(entity, accessKind))
ReportRequires(origin, entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, requiresAttribute.Value);
- }
}
if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, out requiresAttribute))
{
- if (_typeHierarchyDataFlowOrigin is not null)
- {
- // For now we decided to not report single-file warnings due to type hierarchy marking.
- // It is considered too complex to figure out for the user and the likelihood of this
- // causing problems is pretty low.
- }
- else
- {
+ if (!ShouldSkipWarningsForOverride(entity, accessKind))
ReportRequires(origin, entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, requiresAttribute.Value);
- }
}
if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, out requiresAttribute))
{
- if (_typeHierarchyDataFlowOrigin is not null)
- {
- // For now we decided to not report dynamic code warnings due to type hierarchy marking.
- // It is considered too complex to figure out for the user and the likelihood of this
- // causing problems is pretty low.
- }
- else
- {
+ if (!ShouldSkipWarningsForOverride(entity, accessKind))
ReportRequires(origin, entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, requiresAttribute.Value);
- }
}
- if (!Annotations.ShouldWarnWhenAccessedForReflection(entity))
+ // Below is about accessing DAM annotated members, so only RUC is applicable as a suppression scope
+ if (_logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute))
return;
- if (_typeHierarchyDataFlowOrigin is not null)
+ bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity);
+ if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity, accessKind))
{
- // Don't check whether the current scope is a RUC type or RUC method because these warnings
- // are not suppressed in RUC scopes. Here the scope represents the DynamicallyAccessedMembers
- // annotation on a type, not a callsite which uses the annotation. We always want to warn about
- // possible reflection access indicated by these annotations.
- _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers,
- _typeHierarchyDataFlowOrigin.GetDisplayName(), entity.GetDisplayName());
+ if (entity is MethodDesc)
+ _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName());
+ else
+ _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersFieldAccessedViaReflection, entity.GetDisplayName());
}
- else
+
+ // We decided to not warn on reflection access to compiler-generated methods:
+ // https://github.com/dotnet/runtime/issues/85042
+
+ // All override methods should have the same annotations as their base methods
+ // (else we will produce warning IL2046 or IL2092 or some other warning).
+ // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method.
+ // PERF: Avoid precomputing this as this method is relatively expensive. Only call it once we're about to produce a warning.
+ static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity, AccessKind accessKind)
+ {
+ if (accessKind != AccessKind.DynamicallyAccessedMembersMark || entity is not MethodDesc method || !method.IsVirtual)
+ return false;
+
+ return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method;
+ }
+ }
+
+ private void ReportWarningsForTypeHierarchyReflectionAccess(MessageOrigin origin, TypeSystemEntity entity)
+ {
+ Debug.Assert(entity is MethodDesc or FieldDesc);
+
+ // Don't check whether the current scope is a RUC type or RUC method because these warnings
+ // are not suppressed in RUC scopes. Here the scope represents the DynamicallyAccessedMembers
+ // annotation on a type, not a callsite which uses the annotation. We always want to warn about
+ // possible reflection access indicated by these annotations.
+
+ Debug.Assert(_typeHierarchyDataFlowOrigin != null);
+
+ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type)
{
- if (!_logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute))
+ TypeDesc owningType = member.GetOwningType();
+ while (owningType != null)
{
- if (entity is FieldDesc)
- {
- _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersFieldAccessedViaReflection, entity.GetDisplayName());
- }
- else
- {
- Debug.Assert(entity is MethodDesc);
-
- _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName());
- }
+ if (owningType == type)
+ return true;
+
+ owningType = owningType.GetOwningType();
}
+ return false;
+ }
+
+ var reportOnMember = IsDeclaredWithinType(entity, _typeHierarchyDataFlowOrigin);
+ if (reportOnMember)
+ origin = new MessageOrigin(entity);
+
+ // For now we decided to not report single-file or dynamic-code warnings due to type hierarchy marking.
+ // It is considered too complex to figure out for the user and the likelihood of this
+ // causing problems is pretty low.
+
+ bool isReflectionAccessCoveredByRUC = _logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresUnreferencedCodeAttribute);
+ if (isReflectionAccessCoveredByRUC && !ShouldSkipWarningsForOverride(entity))
+ {
+ var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode;
+ _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(),
+ entity.GetDisplayName(),
+ MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(requiresUnreferencedCodeAttribute!.Value)),
+ MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeUrl(requiresUnreferencedCodeAttribute!.Value)));
+ }
+
+ bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity);
+ if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity))
+ {
+ var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers;
+ _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(), entity.GetDisplayName());
+ }
+
+ // We decided to not warn on reflection access to compiler-generated methods:
+ // https://github.com/dotnet/runtime/issues/85042
+
+ // All override methods should have the same annotations as their base methods
+ // (else we will produce warning IL2046 or IL2092 or some other warning).
+ // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method.
+ static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity)
+ {
+ if (entity is not MethodDesc method || !method.IsVirtual)
+ return false;
+
+ return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method;
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs
index b0979861ef166a..79c0cf011bf9ba 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs
@@ -135,7 +135,42 @@ public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, Flo
DynamicallyAccessedMemberTypes annotation = flowAnnotations.GetTypeAnnotation(type);
Debug.Assert(annotation != DynamicallyAccessedMemberTypes.None);
var reflectionMarker = new ReflectionMarker(logger, factory, flowAnnotations, typeHierarchyDataFlowOrigin: type, enabled: true);
- reflectionMarker.MarkTypeForDynamicallyAccessedMembers(new MessageOrigin(type), type, annotation, type.GetDisplayName());
+
+ // We need to apply annotations to this type, and its base/interface types (recursively)
+ // But the annotations on base/interfaces may already be applied so we don't need to apply those
+ // again (and should avoid doing so as it would produce extra warnings).
+ MessageOrigin origin = new MessageOrigin(type);
+ if (type.HasBaseType)
+ {
+ var baseAnnotation = flowAnnotations.GetTypeAnnotation(type.BaseType);
+ var annotationToApplyToBase = Annotations.GetMissingMemberTypes(annotation, baseAnnotation);
+
+ // Apply any annotations that didn't exist on the base type to the base type.
+ // This may produce redundant warnings when the annotation is DAMT.All or DAMT.PublicConstructors and the base already has a
+ // subset of those annotations.
+ reflectionMarker.MarkTypeForDynamicallyAccessedMembers(origin, type.BaseType, annotationToApplyToBase, type.GetDisplayName(), declaredOnly: false);
+ }
+
+ // Most of the DynamicallyAccessedMemberTypes don't select members on interfaces. We only need to apply
+ // annotations to interfaces separately if dealing with DAMT.All or DAMT.Interfaces.
+ if (annotation.HasFlag(DynamicallyAccessedMemberTypes.Interfaces))
+ {
+ var annotationToApplyToInterfaces = annotation == DynamicallyAccessedMemberTypes.All ? annotation : DynamicallyAccessedMemberTypes.Interfaces;
+ foreach (var iface in type.RuntimeInterfaces)
+ {
+ if (flowAnnotations.GetTypeAnnotation(iface).HasFlag(annotationToApplyToInterfaces))
+ continue;
+
+ // Apply All or Interfaces to the interface type.
+ // DAMT.All may produce redundant warnings from implementing types, when the interface type already had some annotations.
+ reflectionMarker.MarkTypeForDynamicallyAccessedMembers(origin, iface, annotationToApplyToInterfaces, type.GetDisplayName(), declaredOnly: false);
+ }
+ }
+
+ // The annotations this type inherited from its base types or interfaces should not produce
+ // warnings on the respective base/interface members, since those are already covered by applying
+ // the annotations to those types. So we only need to handle the members directly declared on this type.
+ reflectionMarker.MarkTypeForDynamicallyAccessedMembers(new MessageOrigin(type), type, annotation, type.GetDisplayName(), declaredOnly: true);
return reflectionMarker.Dependencies;
}
@@ -193,7 +228,7 @@ protected override void HandleStoreParameter(MethodIL methodBody, int offset, Me
protected override void HandleStoreMethodReturnValue(MethodIL methodBody, int offset, MethodReturnValue returnValue, MultiValue valueToStore)
=> HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, returnValue, valueToStore, returnValue.Method.GetDisplayName());
- protected override void HandleTypeReflectionAccess(MethodIL methodBody, int offset, TypeDesc accessedType)
+ protected override void HandleTypeTokenAccess(MethodIL methodBody, int offset, TypeDesc accessedType)
{
// Note that ldtoken alone is technically a reflection access to the type
// it doesn't lead to full reflection marking of the type
@@ -204,20 +239,20 @@ protected override void HandleTypeReflectionAccess(MethodIL methodBody, int offs
ProcessGenericArgumentDataFlow(accessedType);
}
- protected override void HandleMethodReflectionAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod)
+ protected override void HandleMethodTokenAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod)
{
_origin = _origin.WithInstructionOffset(methodBody, offset);
- TrimAnalysisPatterns.Add(new TrimAnalysisReflectionAccessPattern(accessedMethod, _origin));
+ TrimAnalysisPatterns.Add(new TrimAnalysisTokenAccessPattern(accessedMethod, _origin));
ProcessGenericArgumentDataFlow(accessedMethod);
}
- protected override void HandleFieldReflectionAccess(MethodIL methodBody, int offset, FieldDesc accessedField)
+ protected override void HandleFieldTokenAccess(MethodIL methodBody, int offset, FieldDesc accessedField)
{
_origin = _origin.WithInstructionOffset(methodBody, offset);
- TrimAnalysisPatterns.Add(new TrimAnalysisReflectionAccessPattern(accessedField, _origin));
+ TrimAnalysisPatterns.Add(new TrimAnalysisTokenAccessPattern(accessedField, _origin));
ProcessGenericArgumentDataFlow(accessedField);
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs
index 64c539b0346d30..258f2bcfef26cc 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs
@@ -15,7 +15,7 @@ public readonly struct TrimAnalysisPatternStore
{
private readonly Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern> AssignmentPatterns;
private readonly Dictionary MethodCallPatterns;
- private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern> ReflectionAccessPatterns;
+ private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisTokenAccessPattern> TokenAccessPatterns;
private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern> GenericInstantiations;
private readonly Dictionary<(MessageOrigin, FieldDesc), TrimAnalysisFieldAccessPattern> FieldAccessPatterns;
private readonly ValueSetLattice Lattice;
@@ -25,7 +25,7 @@ public TrimAnalysisPatternStore(ValueSetLattice lattice, Logger log
{
AssignmentPatterns = new Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern>();
MethodCallPatterns = new Dictionary();
- ReflectionAccessPatterns = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern>();
+ TokenAccessPatterns = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisTokenAccessPattern>();
GenericInstantiations = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern>();
FieldAccessPatterns = new Dictionary<(MessageOrigin, FieldDesc), TrimAnalysisFieldAccessPattern>();
Lattice = lattice;
@@ -60,9 +60,9 @@ public void Add(TrimAnalysisMethodCallPattern pattern)
MethodCallPatterns[pattern.Origin] = pattern.Merge(Lattice, existingPattern);
}
- public void Add(TrimAnalysisReflectionAccessPattern pattern)
+ public void Add(TrimAnalysisTokenAccessPattern pattern)
{
- ReflectionAccessPatterns.TryAdd((pattern.Origin, pattern.Entity), pattern);
+ TokenAccessPatterns.TryAdd((pattern.Origin, pattern.Entity), pattern);
// No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity
// and there's only one way to "access" a generic instantiation.
@@ -92,7 +92,7 @@ public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker)
foreach (var pattern in MethodCallPatterns.Values)
pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger);
- foreach (var pattern in ReflectionAccessPatterns.Values)
+ foreach (var pattern in TokenAccessPatterns.Values)
pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger);
foreach (var pattern in GenericInstantiations.Values)
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisTokenAccessPattern.cs
similarity index 76%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs
rename to src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisTokenAccessPattern.cs
index 8f40b94c02d811..6d7308235cfbf1 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisTokenAccessPattern.cs
@@ -9,30 +9,30 @@
namespace ILCompiler.Dataflow
{
- public readonly record struct TrimAnalysisReflectionAccessPattern
+ public readonly record struct TrimAnalysisTokenAccessPattern
{
public TypeSystemEntity Entity { init; get; }
public MessageOrigin Origin { init; get; }
- internal TrimAnalysisReflectionAccessPattern(TypeSystemEntity entity, MessageOrigin origin)
+ internal TrimAnalysisTokenAccessPattern(TypeSystemEntity entity, MessageOrigin origin)
{
Entity = entity;
Origin = origin;
}
// No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity
- // and there's only one way to "reflection access" an entity.
+ // and there's only one way to access entity by its handle.
public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker, Logger logger)
{
switch (Entity)
{
case MethodDesc method:
- reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, method);
+ reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, method, ReflectionMarker.AccessKind.TokenAccess);
break;
case FieldDesc field:
- reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, field);
+ reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, field, ReflectionMarker.AccessKind.TokenAccess);
break;
default:
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
index 13942b8d45c40f..aa7a3ccad51f1b 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
@@ -149,11 +149,6 @@ public void LogError(TypeSystemEntity origin, DiagnosticId id, params string[] a
internal bool IsWarningSuppressed(int code, MessageOrigin origin)
{
- // This is causing too much noise
- // https://github.com/dotnet/runtime/issues/81156
- if (code == 2110 || code == 2111 || code == 2113 || code == 2115)
- return true;
-
if (_suppressedWarnings.Contains(code))
return true;
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
index 3e71f63059fcbf..f62b3b66557f3f 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
@@ -383,7 +383,7 @@
-
+
Compiler\Dataflow\TypeNameParser.cs
diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs
index fc9b8f26650bc5..2eb46309c7d379 100644
--- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs
+++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs
@@ -34,6 +34,11 @@ public static IEnumerable