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:
Diffstat (limited to 'src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs')
-rw-r--r--src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs71
1 files changed, 47 insertions, 24 deletions
diff --git a/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs b/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs
index 7ad261191..819653eeb 100644
--- a/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs
+++ b/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs
@@ -136,12 +136,9 @@ namespace ILLink.RoslynAnalyzer.DataFlow
// Avoid visiting the property reference because for captured properties, we can't
// correctly detect whether it is used for reading or writing inside of VisitPropertyReference.
// https://github.com/dotnet/roslyn/issues/25057
- IPropertySymbol? property = propertyRef.Property;
- IMethodSymbol? setMethod;
- while ((setMethod = property.SetMethod) == null) {
- if ((property = property.OverriddenProperty) == null)
- break;
- }
+ TValue instanceValue = Visit (propertyRef.Instance, state);
+ TValue value = Visit (operation.Value, state);
+ IMethodSymbol? setMethod = propertyRef.Property.GetSetMethod ();
if (setMethod == null) {
// This can happen in a constructor - there it is possible to assign to a property
// without a setter. This turns into an assignment to the compiler-generated backing field.
@@ -149,17 +146,34 @@ namespace ILLink.RoslynAnalyzer.DataFlow
// For now, just don't warn. https://github.com/dotnet/linker/issues/2731
break;
}
- TValue instanceValue = Visit (propertyRef.Instance, state);
- TValue value = Visit (operation.Value, state);
- HandleMethodCall (
- setMethod,
- instanceValue,
- ImmutableArray.Create (value),
- operation);
+ HandleMethodCall (setMethod, instanceValue, ImmutableArray.Create (value), operation);
// The return value of a property set expression is the value,
// even though a property setter has no return value.
return value;
}
+ case IImplicitIndexerReferenceOperation indexerRef: {
+ // An implicit reference to an indexer where the argument is a System.Index
+ TValue instanceValue = Visit (indexerRef.Instance, state);
+ TValue indexArgumentValue = Visit (indexerRef.Argument, state);
+ TValue value = Visit (operation.Value, state);
+
+ var property = (IPropertySymbol) indexerRef.IndexerSymbol;
+
+ var argumentsBuilder = ImmutableArray.CreateBuilder<TValue> ();
+ argumentsBuilder.Add (indexArgumentValue);
+ argumentsBuilder.Add (value);
+
+ IMethodSymbol? setMethod = property.GetSetMethod ();
+ if (setMethod == null) {
+ // It might actually be a call to a ref-returning get method,
+ // like Span<T>.this[int].get. We don't handle ref returns yet.
+ break;
+ }
+
+ HandleMethodCall (setMethod, instanceValue, argumentsBuilder.ToImmutableArray (), operation);
+ return value;
+ }
+
// TODO: when setting a property in an attribute, target is an IPropertyReference.
case ILocalReferenceOperation localRef: {
TValue value = Visit (operation.Value, state);
@@ -208,7 +222,7 @@ namespace ILLink.RoslynAnalyzer.DataFlow
// (don't have specific I*Operation types), such as pointer dereferences.
if (targetOperation.Kind is OperationKind.None)
break;
- throw new NotImplementedException (targetOperation.GetType ().ToString ());
+ throw new NotImplementedException ($"{targetOperation.GetType ().ToString ()}: {targetOperation.Syntax.GetLocation ().GetLineSpan ()}");
}
return Visit (operation.Value, state);
}
@@ -272,17 +286,26 @@ namespace ILLink.RoslynAnalyzer.DataFlow
// Accessing property for reading is really a call to the getter
// The setter case is handled in assignment operation since here we don't have access to the value to pass to the setter
TValue instanceValue = Visit (operation.Instance, state);
- IPropertySymbol? property = operation.Property;
- IMethodSymbol? getMethod;
- while ((getMethod = property.GetMethod) == null) {
- if ((property = property.OverriddenProperty) == null)
- break;
+ IMethodSymbol? getMethod = operation.Property.GetGetMethod ();
+ return HandleMethodCall (getMethod!, instanceValue, ImmutableArray<TValue>.Empty, operation);
+ }
+
+ public override TValue VisitImplicitIndexerReference (IImplicitIndexerReferenceOperation operation, LocalDataFlowState<TValue, TValueLattice> state)
+ {
+ if (!operation.GetValueUsageInfo (Context.OwningSymbol).HasFlag (ValueUsageInfo.Read))
+ return TopValue;
+
+ TValue instanceValue = Visit (operation.Instance, state);
+ TValue indexArgumentValue = Visit (operation.Argument, state);
+
+ if (operation.IndexerSymbol is not IPropertySymbol indexerProperty) {
+ // For example, System.Span<T>.Slice(int, int).
+ // Don't try to handle it for now.
+ return TopValue;
}
- return HandleMethodCall (
- getMethod!,
- instanceValue,
- ImmutableArray<TValue>.Empty,
- operation);
+
+ IMethodSymbol getMethod = indexerProperty.GetGetMethod ()!;
+ return HandleMethodCall (getMethod, instanceValue, ImmutableArray.Create (indexArgumentValue), operation);
}
public override TValue VisitArrayElementReference (IArrayElementReferenceOperation operation, LocalDataFlowState<TValue, TValueLattice> state)