protected override void ProcessOutOfScopeLocalsAndFlowCaptures(IEnumerable <ILocalSymbol> locals, IEnumerable <CaptureId> flowCaptures) { Debug.Assert(locals.Any() || flowCaptures.Any()); base.ProcessOutOfScopeLocalsAndFlowCaptures(locals, flowCaptures); using var allEntities = PooledHashSet <AnalysisEntity> .GetInstance(); AddTrackedEntities(allEntities); // Stop tracking entities for locals and capture Ids that are now out of scope. foreach (var local in locals) { if (AnalysisEntityFactory.TryCreateForSymbolDeclaration(local, out var analysisEntity)) { StopTrackingDataForEntity(analysisEntity, allEntities); } else { Debug.Fail("TryCreateForSymbolDeclaration failed"); } } foreach (var captureId in flowCaptures) { if (AnalysisEntityFactory.TryGetForFlowCapture(captureId, out var analysisEntity)) { StopTrackingDataForEntity(analysisEntity, allEntities); } } }
protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray <AbstractIndex> indices, ITypeSymbol elementType, IOperation initializer, TAbstractAnalysisValue value) { if (AnalysisEntityFactory.TryCreateForArrayElementInitializer(arrayCreation, indices, elementType, out var analysisEntity)) { SetAbstractValueForAssignment(analysisEntity, initializer, value); } }
protected virtual void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, IOperation?assignedValueOperation, TAbstractAnalysisValue assignedValue) { AnalysisEntity?assignedValueEntity = null; if (assignedValueOperation != null) { var success = AnalysisEntityFactory.TryCreate(assignedValueOperation, out assignedValueEntity); Debug.Assert(success || assignedValueEntity == null); } SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueEntity, assignedValueOperation, assignedValue); }
protected override void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false) { if (AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetAnalysisEntity)) { if (mayBeAssignment) { assignedValue = ValueDomain.Merge(GetAbstractValue(targetAnalysisEntity), assignedValue); } SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueOperation, assignedValue); } }
protected sealed override TAbstractAnalysisValue ComputeAnalysisValueForEscapedRefOrOutArgument(IArgumentOperation operation, TAbstractAnalysisValue defaultValue) { Debug.Assert(operation.Parameter.RefKind is RefKind.Ref or RefKind.Out); if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { var value = ComputeAnalysisValueForEscapedRefOrOutArgument(analysisEntity, operation, defaultValue); SetAbstractValueForAssignment(analysisEntity, operation, value); return(GetAbstractValue(analysisEntity)); } else { return(defaultValue); } }
protected override TAbstractAnalysisValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TAbstractAnalysisValue defaultValue) { if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { if (!HasAbstractValue(analysisEntity)) { SetAbstractValue(analysisEntity, defaultValue); } return(GetAbstractValue(analysisEntity)); } else { return(defaultValue); } }
protected override void SetAbstractValueForAssignment(IOperation target, IOperation?assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false) { if (AnalysisEntityFactory.TryCreate(target, out var targetAnalysisEntity)) { if (!HasCompletePointsToAnalysisResult && targetAnalysisEntity.IsChildOrInstanceMemberNeedingCompletePointsToAnalysis()) { // We are not tracking points to values for fields and properties. // So, it is not possible to accurately track value changes to target entity which is a member. // Conservatively assume that the entity is assigned an unknown value. assignedValue = ValueDomain.UnknownOrMayBeValue; } else if (mayBeAssignment) { assignedValue = ValueDomain.Merge(GetAbstractValue(targetAnalysisEntity), assignedValue); } SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueOperation, assignedValue); } }
/// <summary> /// Transfers the analysis data rooted from <paramref name="valueAnalysisEntity"/> or <paramref name="assignedValueOperation"/> to <paramref name="targetAnalysisEntity"/>, for a value type assignment operation. /// This involves transfer of data for of all <see cref="AnalysisEntity"/> instances that share the same <see cref="AnalysisEntity.InstanceLocation"/> as <paramref name="valueAnalysisEntity"/> or allocation for the <paramref name="assignedValueOperation"/> /// to all <see cref="AnalysisEntity"/> instances that share the same <see cref="AnalysisEntity.InstanceLocation"/> as <paramref name="targetAnalysisEntity"/>. /// </summary> private void TransferValueTypeInstanceAnalysisDataForAssignment(AnalysisEntity targetAnalysisEntity, AnalysisEntity?valueAnalysisEntity, IOperation?assignedValueOperation) { Debug.Assert(HasPointsToAnalysisResult); Debug.Assert(targetAnalysisEntity.Type.HasValueCopySemantics()); IEnumerable <AnalysisEntity> dependentAnalysisEntities; if (valueAnalysisEntity != null) { if (!valueAnalysisEntity.Type.HasValueCopySemantics()) { // Unboxing conversion from assigned value (reference type) to target (value copy semantics). // We do not need to transfer any data for such a case as there is no entity for unboxed value. return; } dependentAnalysisEntities = GetChildAnalysisEntities(valueAnalysisEntity); } else if (assignedValueOperation != null) { // For allocations. PointsToAbstractValue newValueLocation = GetPointsToAbstractValue(assignedValueOperation); dependentAnalysisEntities = GetChildAnalysisEntities(newValueLocation); } else { return; } foreach (AnalysisEntity dependentInstance in dependentAnalysisEntities) { // Clone the dependent instance but with with target as the root. AnalysisEntity newAnalysisEntity = AnalysisEntityFactory.CreateWithNewInstanceRoot(dependentInstance, targetAnalysisEntity); var dependentValue = GetAbstractValue(dependentInstance); SetAbstractValue(newAnalysisEntity, dependentValue); } }