Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ private void ProcessAttributeDataflow(MethodDesc method, ImmutableArray<object?>
if (parameterValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None)
{
MultiValue value = GetValueForCustomAttributeArgument(arguments[parameter.MetadataIndex]);
RequireDynamicallyAccessedMembers(_diagnosticContext, value, parameterValue, method.GetDisplayName(), ref result);
RequireDynamicallyAccessedMembers(_diagnosticContext, value, parameterValue, method, ref result);
}
}
}
Expand All @@ -114,7 +114,7 @@ private void ProcessAttributeDataflow(FieldDesc field, object? value, ref Depend
&& fieldValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None)
{
MultiValue valueNode = GetValueForCustomAttributeArgument(value);
RequireDynamicallyAccessedMembers(_diagnosticContext, valueNode, fieldValue, field.GetDisplayName(), ref result);
RequireDynamicallyAccessedMembers(_diagnosticContext, valueNode, fieldValue, field, ref result);
}
}

Expand All @@ -132,7 +132,7 @@ private void RequireDynamicallyAccessedMembers(
in DiagnosticContext diagnosticContext,
in MultiValue value,
ValueWithDynamicallyAccessedMembers targetValue,
string reason,
TypeSystemEntity reason,
ref DependencyList? result)
{
var reflectionMarker = new ReflectionMarker(_logger, _factory, _annotations, typeHierarchyDataFlowOrigin: null, enabled: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private static void ProcessGenericInstantiation(in DiagnosticContext diagnosticC
var genericParameterValue = reflectionMarker.Annotations.GetGenericParameterValue(genericParameter);
Debug.Assert(genericParameterValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None);
MultiValue genericArgumentValue = reflectionMarker.Annotations.GetTypeValueFromGenericArgument(genericArgument);
var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction(reflectionMarker, diagnosticContext, genericParameter.GetDisplayName());
var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction(reflectionMarker, diagnosticContext, genericParameter);
requireDynamicallyAccessedMembersAction.Invoke(genericArgumentValue, genericParameterValue);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ internal partial struct HandleCallAction
private readonly ReflectionMarker _reflectionMarker;
private ILOpcode _operation;
private readonly MethodDesc _callingMethod;
private readonly string _reason;
private readonly MethodDesc _reason;

public HandleCallAction(
FlowAnnotations annotations,
ILOpcode operation,
ReflectionMarker reflectionMarker,
in DiagnosticContext diagnosticContext,
MethodDesc callingMethod,
string reason)
MethodDesc reason)
{
_reflectionMarker = reflectionMarker;
_operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ public ReflectionMarker(Logger logger, NodeFactory factory, FlowAnnotations anno
_enabled = enabled;
}

internal void MarkTypeForDynamicallyAccessedMembers(in MessageOrigin origin, TypeDesc typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes, string reason, bool declaredOnly = false)
internal void MarkTypeForDynamicallyAccessedMembers(in MessageOrigin origin, TypeDesc typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes, TypeSystemEntity reason, bool declaredOnly = false)
{
if (!_enabled)
return;

string displayName = reason.GetDisplayName();
foreach (var member in typeDefinition.GetDynamicallyAccessedMembers(requiredMemberTypes, declaredOnly))
{
MarkTypeSystemEntity(origin, member, reason, AccessKind.DynamicallyAccessedMembersMark);
MarkTypeSystemEntity(origin, member, displayName, AccessKind.DynamicallyAccessedMembersMark);
}
}

Expand Down Expand Up @@ -83,7 +84,7 @@ internal void MarkTypeSystemEntity(in MessageOrigin origin, TypeSystemEntity ent
}
}

internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext diagnosticContext, bool needsAssemblyName, string reason, [NotNullWhen(true)] out TypeDesc? type)
internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext diagnosticContext, bool needsAssemblyName, TypeSystemEntity reason, [NotNullWhen(true)] out TypeDesc? type)
{
ModuleDesc? callingModule = (diagnosticContext.Origin.MemberDefinition.GetOwningType() as MetadataType)?.Module;

Expand All @@ -102,14 +103,15 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di

if (_enabled)
{
string displayName = reason.GetDisplayName();
foreach (ModuleDesc referencedModule in referencedModules)
{
// Also add module metadata in case this reference was through a type forward
if (Factory.MetadataManager.CanGenerateMetadata(referencedModule.GetGlobalModuleType()))
_dependencies.Add(Factory.ModuleMetadata(referencedModule), reason);
_dependencies.Add(Factory.ModuleMetadata(referencedModule), displayName);
}

MarkType(diagnosticContext.Origin, foundType, reason);
MarkType(diagnosticContext.Origin, foundType, displayName);
}

type = foundType;
Expand Down Expand Up @@ -143,6 +145,14 @@ internal bool TryResolveTypeNameAndMark(ModuleDesc assembly, string typeName, in
return true;
}

internal void MarkType(in MessageOrigin origin, TypeDesc type, TypeSystemEntity reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;

MarkType(origin, type, reason.GetDisplayName(), accessKind);
}

internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
Expand All @@ -151,6 +161,14 @@ internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason, Ac
RootingHelpers.TryGetDependenciesForReflectedType(ref _dependencies, Factory, type, reason);
}

internal void MarkMethod(in MessageOrigin origin, MethodDesc method, TypeSystemEntity reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;

MarkMethod(origin, method, reason.GetDisplayName(), accessKind);
}

internal void MarkMethod(in MessageOrigin origin, MethodDesc method, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
Expand All @@ -171,6 +189,14 @@ internal void MarkField(in MessageOrigin origin, FieldDesc field, string reason,
RootingHelpers.TryGetDependenciesForReflectedField(ref _dependencies, Factory, field, reason);
}

internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property, TypeSystemEntity reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
return;

MarkProperty(origin, property, reason.GetDisplayName(), accessKind);
}

internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property, string reason, AccessKind accessKind = AccessKind.Unspecified)
{
if (!_enabled)
Expand All @@ -193,50 +219,54 @@ private void MarkEvent(in MessageOrigin origin, EventPseudoDesc @event, string r
MarkMethod(origin, @event.RemoveMethod, reason);
}

internal void MarkConstructorsOnType(in MessageOrigin origin, TypeDesc type, Func<MethodDesc, bool>? filter, string reason, BindingFlags? bindingFlags = null)
internal void MarkConstructorsOnType(in MessageOrigin origin, TypeDesc type, Func<MethodDesc, bool>? filter, TypeSystemEntity reason, BindingFlags? bindingFlags = null)
{
if (!_enabled)
return;

string displayName = reason.GetDisplayName();
foreach (var ctor in type.GetConstructorsOnType(filter, bindingFlags))
MarkMethod(origin, ctor, reason);
MarkMethod(origin, ctor, displayName);
}

internal void MarkFieldsOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<FieldDesc, bool> filter, string reason, BindingFlags? bindingFlags = BindingFlags.Default)
internal void MarkFieldsOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<FieldDesc, bool> filter, TypeSystemEntity reason, BindingFlags? bindingFlags = BindingFlags.Default)
{
if (!_enabled)
return;

string displayName = reason.GetDisplayName();
foreach (var field in type.GetFieldsOnTypeHierarchy(filter, bindingFlags))
MarkField(origin, field, reason);
MarkField(origin, field, displayName);
}

internal void MarkPropertiesOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<PropertyPseudoDesc, bool> filter, string reason, BindingFlags? bindingFlags = BindingFlags.Default)
internal void MarkPropertiesOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<PropertyPseudoDesc, bool> filter, TypeSystemEntity reason, BindingFlags? bindingFlags = BindingFlags.Default)
{
if (!_enabled)
return;

string displayName = reason.GetDisplayName();
foreach (var property in type.GetPropertiesOnTypeHierarchy(filter, bindingFlags))
MarkProperty(origin, property, reason);
MarkProperty(origin, property, displayName);
}

internal void MarkEventsOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<EventPseudoDesc, bool> filter, string reason, BindingFlags? bindingFlags = BindingFlags.Default)
internal void MarkEventsOnTypeHierarchy(in MessageOrigin origin, TypeDesc type, Func<EventPseudoDesc, bool> filter, TypeSystemEntity reason, BindingFlags? bindingFlags = BindingFlags.Default)
{
if (!_enabled)
return;

string displayName = reason.GetDisplayName();
foreach (var @event in type.GetEventsOnTypeHierarchy(filter, bindingFlags))
MarkEvent(origin, @event, reason);
MarkEvent(origin, @event, displayName);
}

internal void MarkStaticConstructor(in MessageOrigin origin, TypeDesc type, string reason)
internal void MarkStaticConstructor(in MessageOrigin origin, TypeDesc type, TypeSystemEntity reason)
{
if (!_enabled)
return;

MethodDesc cctor = type.GetStaticConstructor();
if (cctor != null)
MarkMethod(origin, cctor, reason);
MarkMethod(origin, cctor, reason.GetDisplayName());
}

internal void CheckAndWarnOnReflectionAccess(in MessageOrigin origin, TypeSystemEntity entity, AccessKind accessKind = AccessKind.Unspecified)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, Flo
// 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);
reflectionMarker.MarkTypeForDynamicallyAccessedMembers(origin, type.BaseType, annotationToApplyToBase, type, declaredOnly: false);
}

// Most of the DynamicallyAccessedMemberTypes don't select members on interfaces. We only need to apply
Expand All @@ -186,14 +186,14 @@ public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, Flo

// 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);
reflectionMarker.MarkTypeForDynamicallyAccessedMembers(origin, iface, annotationToApplyToInterfaces, type, 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);
reflectionMarker.MarkTypeForDynamicallyAccessedMembers(new MessageOrigin(type), type, annotation, type, declaredOnly: true);
return reflectionMarker.Dependencies;
}

Expand Down Expand Up @@ -235,7 +235,7 @@ protected override MultiValue HandleGetField(MethodIL methodIL, int offset, Fiel
return _annotations.GetFieldValue(field);
}

private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodIL, int offset, ValueWithDynamicallyAccessedMembers targetValue, MultiValue sourceValue, int? parameterIndex, string reason)
private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodIL, int offset, ValueWithDynamicallyAccessedMembers targetValue, MultiValue sourceValue, int? parameterIndex, TypeSystemEntity reason)
{
if (targetValue.DynamicallyAccessedMemberTypes != 0)
{
Expand All @@ -245,13 +245,13 @@ private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodIL, i
}

protected override void HandleStoreField(MethodIL methodIL, int offset, FieldValue field, MultiValue valueToStore, int? parameterIndex)
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, field, valueToStore, parameterIndex, field.Field.GetDisplayName());
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, field, valueToStore, parameterIndex, field.Field);

protected override void HandleStoreParameter(MethodIL methodIL, int offset, MethodParameterValue parameter, MultiValue valueToStore, int? parameterIndex)
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, parameter, valueToStore, parameterIndex, parameter.Parameter.Method.GetDisplayName());
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, parameter, valueToStore, parameterIndex, parameter.Parameter.Method.Method);

protected override void HandleReturnValue(MethodIL methodIL, int offset, MethodReturnValue returnValue, MultiValue valueToStore)
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, returnValue, valueToStore, null, returnValue.Method.GetDisplayName());
=> HandleStoreValueWithDynamicallyAccessedMembers(methodIL, offset, returnValue, valueToStore, null, returnValue.Method.Method);

protected override void HandleTypeTokenAccess(MethodIL methodIL, int offset, TypeDesc accessedType)
{
Expand Down Expand Up @@ -342,7 +342,7 @@ public static MultiValue HandleCall(
RequiresReflectionMethodBodyScannerForCallSite(reflectionMarker.Annotations, calledMethod) ||
annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None);

var handleCallAction = new HandleCallAction(reflectionMarker.Annotations, operation, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod.GetDisplayName());
var handleCallAction = new HandleCallAction(reflectionMarker.Annotations, operation, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod);
var intrinsicId = Intrinsics.GetIntrinsicIdForMethod(calledMethod);
if (!handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out MultiValue methodReturnValue))
throw new NotImplementedException($"Unhandled intrinsic {intrinsicId}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ namespace ILLink.Shared.TrimAnalysis
internal partial struct RequireDynamicallyAccessedMembersAction
{
private readonly ReflectionMarker _reflectionMarker;
private readonly string _reason;
private readonly TypeSystemEntity _reason;

public RequireDynamicallyAccessedMembersAction(
ReflectionMarker reflectionMarker,
in DiagnosticContext diagnosticContext,
string reason)
TypeSystemEntity reason)
{
_reflectionMarker = reflectionMarker;
_diagnosticContext = diagnosticContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using ILLink.Shared.DataFlow;
using ILLink.Shared.TrimAnalysis;

using Internal.TypeSystem;

using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>;

#nullable enable
Expand All @@ -22,9 +24,9 @@ public readonly record struct TrimAnalysisAssignmentPattern
// For assignment of a method parameter, we store the parameter index to disambiguate
// assignments from different out parameters of a single method call.
public int? ParameterIndex { get; init; }
internal string Reason { get; init; }
internal TypeSystemEntity Reason { get; init; }

internal TrimAnalysisAssignmentPattern(MultiValue source, MultiValue target, MessageOrigin origin, int? parameterIndex, string reason)
internal TrimAnalysisAssignmentPattern(MultiValue source, MultiValue target, MessageOrigin origin, int? parameterIndex, TypeSystemEntity reason)
{
Source = source.DeepCopy();
Target = target.DeepCopy();
Expand Down
Loading