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 @@ -592,39 +592,21 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
}
}

if (IsAutoProperty(property))
FieldDesc? backingField = backingFieldFromSetter ?? backingFieldFromGetter;
if (backingField is not null)
{
FieldDesc? backingField = null;
if ((property.SetMethod is not null
&& property.SetMethod.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute")
&& backingFieldFromSetter is null)
|| (property.GetMethod is not null
&& property.GetMethod.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute")
&& backingFieldFromGetter is null))
bool validBackingFieldFound = backingFieldFromGetter is null
|| backingFieldFromSetter is null
|| backingFieldFromGetter == backingFieldFromSetter;
if (validBackingFieldFound)
{
// We failed to find the backing field of an auto-property accessor
_logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
}
else if (backingFieldFromGetter is not null && backingFieldFromSetter is not null
&& backingFieldFromSetter != backingFieldFromGetter)
{
// We found two different backing fields for the getter and the setter
_logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
}
else
{
// We either have a single auto-property accessor or both accessors point to the same backing field
backingField = backingFieldFromSetter ?? backingFieldFromGetter;
}

if (backingField != null)
{
if (annotatedFields.Any(a => a.Field == backingField))
if (annotatedFields.Any(a => a.Field == backingField && a.Annotation != annotation))
{
_logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
}
else
{
// Unique backing field with no conflicts with property or existing field
annotatedFields.Add(new FieldAnnotation(backingField, annotation));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ internal static DynamicallyAccessedMemberTypes GetFieldAnnotation(IFieldSymbol f
if (!field.OriginalDefinition.Type.IsTypeInterestingForDataflow(isByRef: field.RefKind is not RefKind.None))
return DynamicallyAccessedMemberTypes.None;

if (field.AssociatedSymbol is IPropertySymbol property)
if (field.AssociatedSymbol is IPropertySymbol property
&& property.IsAutoProperty())
{
// If this is an auto property, we get the property annotation
if (property.IsAutoProperty())
return property.GetDynamicallyAccessedMemberTypes();
return property.GetDynamicallyAccessedMemberTypes();
}

return field.GetDynamicallyAccessedMemberTypes();
Expand Down
2 changes: 1 addition & 1 deletion src/tools/illink/src/ILLink.Shared/DiagnosticId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public enum DiagnosticId
XmlInvalidValueForAttributeActionForResource = 2039,
XmlCouldNotFindResourceToRemoveInAssembly = 2040,
DynamicallyAccessedMembersIsNotAllowedOnMethods = 2041,
DynamicallyAccessedMembersCouldNotFindBackingField = 2042,
unused_DynamicallyAccessedMembersCouldNotFindBackingField = 2042,
DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor = 2043,
XmlCouldNotFindAnyTypeInNamespace = 2044,
AttributeIsReferencedButTrimmerRemoveAllInstances = 2045,
Expand Down
35 changes: 9 additions & 26 deletions src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,39 +417,22 @@ TypeAnnotations BuildTypeAnnotations(TypeDefinition type)
}
}

if (IsAutoProperty(property))

FieldDefinition? backingField = backingFieldFromSetter ?? backingFieldFromGetter;
if (backingField is not null)
{
FieldDefinition? backingField = null;
// If it's an annotated auto-prop, we should be able to find the compiler generated field
if ((property.SetMethod is not null
&& property.SetMethod.IsCompilerGenerated()
&& backingFieldFromSetter is null)
|| (property.GetMethod is not null
&& property.GetMethod.IsCompilerGenerated()
&& backingFieldFromGetter is null))
{
// We failed to find the backing field of an auto-property accessor
_context.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
}
else if (backingFieldFromGetter is not null && backingFieldFromSetter is not null
&& backingFieldFromSetter != backingFieldFromGetter)
{
// We found two different backing fields for the getter and the setter
_context.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
}
else
{
// We either have a single auto-property accessor or both accessors point to the same backing field
backingField = backingFieldFromSetter ?? backingFieldFromGetter;
}
if (backingField != null)
bool validBackingFieldFound = backingFieldFromGetter is null
|| backingFieldFromSetter is null
|| backingFieldFromGetter == backingFieldFromSetter;
if (validBackingFieldFound)
{
if (annotatedFields.Any(a => a.Field == backingField))
if (annotatedFields.Any(a => a.Field == backingField && a.Annotation != annotation))
{
_context.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
}
else
{
// Unique backing field with no conflicts with property or existing field
annotatedFields.Add(new FieldAnnotation(backingField, annotation));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,6 @@ public void TestPropertyWithDifferentBackingFields()
private Type PropertyWithDifferentBackingFields_SetterField;

// Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273
[ExpectedWarning("IL2042",
"Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithDifferentBackingFields", Tool.Trimmer | Tool.NativeAot, "Requires IL")]
[ExpectedWarning("IL2078",
nameof(TestAutomaticPropagationType) + "." + nameof(PropertyWithDifferentBackingFields) + ".get",
"Type", Tool.Analyzer, "")]
Expand All @@ -313,32 +311,57 @@ Type PropertyWithDifferentBackingFields

public void TestPropertyWithExistingAttributes()
{
_ = PropertyWithExistingAttributes;
PropertyWithExistingAttributes = null;
_ = PropertyWithExistingMatchingAttributes;
PropertyWithExistingMatchingAttributes = null;
_ = PropertyWithExistingMismatchedAttributes;
PropertyWithExistingMismatchedAttributes = null;
}

// Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273
[ExpectedWarning("IL2056", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[CompilerGenerated]
Type PropertyWithExistingAttributes_Field;
Type PropertyWithExistingMatchingAttributes_Field;

[ExpectedWarning("IL2043", ["PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get"], Tool.Analyzer, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set"], Tool.Analyzer, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingMatchingAttributes", "PropertyWithExistingMatchingAttributes.get"], Tool.Analyzer, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingMatchingAttributes", "PropertyWithExistingMatchingAttributes.set"], Tool.Analyzer, "")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
Type PropertyWithExistingAttributes
Type PropertyWithExistingMatchingAttributes
{
// On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654
[ExpectedWarning("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingMatchingAttributes", "PropertyWithExistingMatchingAttributes.get"], Tool.Trimmer | Tool.NativeAot, "")]
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[CompilerGenerated]
get { return PropertyWithExistingAttributes_Field; }
get { return PropertyWithExistingMatchingAttributes_Field; }

// On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654
[ExpectedWarning("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingMatchingAttributes", "PropertyWithExistingMatchingAttributes.set"], Tool.Trimmer | Tool.NativeAot, "")]
[param: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[CompilerGenerated]
set { PropertyWithExistingAttributes_Field = value; }
set { PropertyWithExistingMatchingAttributes_Field = value; }
}

// Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273
[ExpectedWarning("IL2056", "PropertyWithExistingMismatchedAttributes", "PropertyWithExistingMismatchedAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
[CompilerGenerated]
Type PropertyWithExistingMismatchedAttributes_Field;

[ExpectedWarning("IL2043", ["PropertyWithExistingMismatchedAttributes", "PropertyWithExistingMismatchedAttributes.get"], Tool.Analyzer, "")]
[ExpectedWarning("IL2043", ["PropertyWithExistingMismatchedAttributes", "PropertyWithExistingMismatchedAttributes.set"], Tool.Analyzer, "")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
Type PropertyWithExistingMismatchedAttributes
{
// On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654
[ExpectedWarning("IL2043", "PropertyWithExistingMismatchedAttributes", "PropertyWithExistingMismatchedAttributes.get", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning("IL2078", "return value", "PropertyWithExistingMismatchedAttributes_Field")]
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
[CompilerGenerated]
get { return PropertyWithExistingMismatchedAttributes_Field; }

// On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654
[ExpectedWarning("IL2043", "PropertyWithExistingMismatchedAttributes", "PropertyWithExistingMismatchedAttributes.set", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning("IL2069", "PropertyWithExistingMismatchedAttributes_Field", "parameter 'value'")]
[param: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
[CompilerGenerated]
set { PropertyWithExistingMismatchedAttributes_Field = value; }
}

// When the property annotation conflicts with the getter/setter annotation,
Expand Down Expand Up @@ -959,7 +982,6 @@ class AutoPropertyUnrecognizedField
private Type Property_BackingField;

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type Property
{
[CompilerGenerated]
Expand All @@ -980,7 +1002,6 @@ public Type Property
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyAutoSet
{
[CompilerGenerated]
Expand All @@ -995,10 +1016,8 @@ public Type PropertyAutoSet
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyAutoGet
{
[ExpectedWarning("IL2078", ["return value", nameof(PropertyAutoGet), "BackingField"], producedBy: Tool.NativeAot | Tool.Trimmer, "Requires IL")]
get;
[CompilerGenerated]
set
Expand All @@ -1010,7 +1029,6 @@ public Type PropertyAutoGet
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyManualSet
{
[CompilerGenerated]
Expand All @@ -1025,7 +1043,6 @@ public Type PropertyManualSet
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyManualGet
{
[ExpectedWarning("IL2078", "return value", nameof(Property_BackingField))]
Expand All @@ -1040,7 +1057,6 @@ public Type PropertyManualGet
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyOnlyGet
{
[CompilerGenerated]
Expand All @@ -1054,7 +1070,6 @@ public Type PropertyOnlyGet
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[ExpectedWarning("IL2042", nameof(PropertyOnlySet), Tool.NativeAot | Tool.Trimmer, "Requires IL")] // Can't find backing field
public Type PropertyOnlySet
{
[CompilerGenerated]
Expand Down
Loading