private bool IsTrackedLocation(AbstractLocation location)
            {
                return(CurrentAnalysisData.ContainsKey(location) ||
                       location.SymbolOpt is IParameterSymbol parameter &&
                       parameter.Type.IsReferenceType &&
                       Equals(parameter.ContainingSymbol, GetBottomOfStackOwningSymbol()));

                ISymbol GetBottomOfStackOwningSymbol()
                {
                    if (DataFlowAnalysisContext.InterproceduralAnalysisDataOpt == null)
                    {
                        return(OwningSymbol);
                    }

                    return(DataFlowAnalysisContext.InterproceduralAnalysisDataOpt.MethodsBeingAnalyzed
                           .Single(m => m.InterproceduralAnalysisDataOpt == null)
                           .OwningSymbol);
                }
            }
            public override DisposeAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument)
            {
                var value = base.VisitFieldReference(operation, argument);

                if (_trackedInstanceFieldLocationsOpt != null &&
                    !operation.Field.IsStatic &&
                    operation.Instance?.Kind == OperationKind.InstanceReference)
                {
                    var pointsToAbstractValue = GetPointsToAbstractValue(operation);
                    if (pointsToAbstractValue.Kind == PointsToAbstractValueKind.KnownLocations &&
                        pointsToAbstractValue.Locations.Count == 1)
                    {
                        var location = pointsToAbstractValue.Locations.Single();
                        if (location.IsAnalysisEntityDefaultLocation)
                        {
                            if (!_trackedInstanceFieldLocationsOpt.TryGetValue(operation.Field, out _))
                            {
                                // First field reference on any control flow path.
                                // Create a default instance to represent the object referenced by the field at start of the method and
                                // check if the instance has NotDisposed state, indicating it is a disposable field that must be tracked.
                                if (HandleInstanceCreation(operation, pointsToAbstractValue, defaultValue: DisposeAbstractValue.NotDisposable) == DisposeAbstractValue.NotDisposed)
                                {
                                    _trackedInstanceFieldLocationsOpt.Add(operation.Field, pointsToAbstractValue);
                                }
                            }
                            else if (!CurrentAnalysisData.ContainsKey(location))
                            {
                                // This field has already started being tracked on a different control flow path.
                                // Process the default instance creation on this control flow path as well.
                                var disposedState = HandleInstanceCreation(operation, pointsToAbstractValue, DisposeAbstractValue.NotDisposable);
                                Debug.Assert(disposedState == DisposeAbstractValue.NotDisposed);
                            }
                        }
                    }
                }

                return(value);
            }
Пример #3
0
 protected override bool HasAbstractValue(AnalysisEntity analysisEntity) => CurrentAnalysisData.ContainsKey(analysisEntity);