| File: src\ffd9070534249528\PointsToAnalysis.PointsToAbstractValueDomain.cs | Web Access |
| Project: src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.NetAnalyzers\Microsoft.CodeAnalysis.NetAnalyzers.csproj (Microsoft.CodeAnalysis.NetAnalyzers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis { public partial class PointsToAnalysis : ForwardDataFlowAnalysis<PointsToAnalysisData, PointsToAnalysisContext, PointsToAnalysisResult, PointsToBlockAnalysisResult, PointsToAbstractValue> { /// <summary> /// Abstract value domain for <see cref="PointsToAnalysis"/> to merge and compare <see cref="PointsToAbstractValue"/> values. /// </summary> private sealed class PointsToAbstractValueDomain : AbstractValueDomain<PointsToAbstractValue> { public static PointsToAbstractValueDomain Default = new(); private readonly SetAbstractDomain<AbstractLocation> _locationsDomain = SetAbstractDomain<AbstractLocation>.Default; private readonly SetAbstractDomain<IOperation> _lValueCapturesDomain = SetAbstractDomain<IOperation>.Default; private PointsToAbstractValueDomain() { } public override PointsToAbstractValue Bottom => PointsToAbstractValue.Undefined; public override PointsToAbstractValue UnknownOrMayBeValue => PointsToAbstractValue.Unknown; public override int Compare(PointsToAbstractValue oldValue, PointsToAbstractValue newValue, bool assertMonotonicity) { if (ReferenceEquals(oldValue, newValue)) { return 0; } if (oldValue.Kind == newValue.Kind) { int locationsCompareResult = _locationsDomain.Compare(oldValue.Locations, newValue.Locations); int lValueCapturesCompareResult = _lValueCapturesDomain.Compare(oldValue.LValueCapturedOperations, newValue.LValueCapturedOperations); var nullCompareResult = NullAbstractValueDomain.Default.Compare(oldValue.NullState, newValue.NullState); if (locationsCompareResult > 0 || lValueCapturesCompareResult > 0 || nullCompareResult > 0) { FireNonMonotonicAssertIfNeeded(assertMonotonicity); return 1; } else if (locationsCompareResult < 0 || lValueCapturesCompareResult < 0 || nullCompareResult < 0) { return -1; } else { return 0; } } else if (oldValue.Kind < newValue.Kind) { #if DEBUG if (NullAbstractValueDomain.Default.Compare(oldValue.NullState, newValue.NullState) > 0) { FireNonMonotonicAssertIfNeeded(assertMonotonicity); } #endif return -1; } else { FireNonMonotonicAssertIfNeeded(assertMonotonicity); return 1; } } public override PointsToAbstractValue Merge(PointsToAbstractValue value1, PointsToAbstractValue value2) { PointsToAbstractValue result; if (value1 == value2) { result = value1; } else if (value1.Kind == PointsToAbstractValueKind.Invalid) { result = value2.Kind == PointsToAbstractValueKind.Undefined ? PointsToAbstractValue.Unknown : value2; } else if (value2.Kind == PointsToAbstractValueKind.Invalid) { result = value1.Kind == PointsToAbstractValueKind.Undefined ? PointsToAbstractValue.Unknown : value1; } else if (value1.Kind == PointsToAbstractValueKind.Undefined) { result = value2; } else if (value2.Kind == PointsToAbstractValueKind.Undefined) { result = value1; } else if (value1.Kind == PointsToAbstractValueKind.Unknown || value2.Kind == PointsToAbstractValueKind.Unknown) { result = PointsToAbstractValue.Unknown; } else if (value1.Kind == PointsToAbstractValueKind.UnknownNull) { return value2.NullState == NullAbstractValue.Null ? PointsToAbstractValue.UnknownNull : PointsToAbstractValue.Unknown; } else if (value2.Kind == PointsToAbstractValueKind.UnknownNull) { return value1.NullState == NullAbstractValue.Null ? PointsToAbstractValue.UnknownNull : PointsToAbstractValue.Unknown; } else if (value1.Kind == PointsToAbstractValueKind.UnknownNotNull) { return value2.NullState == NullAbstractValue.NotNull ? PointsToAbstractValue.UnknownNotNull : PointsToAbstractValue.Unknown; } else if (value2.Kind == PointsToAbstractValueKind.UnknownNotNull) { return value1.NullState == NullAbstractValue.NotNull ? PointsToAbstractValue.UnknownNotNull : PointsToAbstractValue.Unknown; } else if (value1.Kind == PointsToAbstractValueKind.KnownLValueCaptures) { Debug.Assert(value2.Kind == PointsToAbstractValueKind.KnownLValueCaptures); var mergedLValueCaptures = _lValueCapturesDomain.Merge(value1.LValueCapturedOperations, value2.LValueCapturedOperations); result = PointsToAbstractValue.Create(mergedLValueCaptures); } else { Debug.Assert(value1.Kind == PointsToAbstractValueKind.KnownLocations); Debug.Assert(value2.Kind == PointsToAbstractValueKind.KnownLocations); var mergedLocations = _locationsDomain.Merge(value1.Locations, value2.Locations); var mergedNullState = NullAbstractValueDomain.Default.Merge(value1.NullState, value2.NullState); result = PointsToAbstractValue.Create(mergedLocations, mergedNullState); } Debug.Assert(Compare(value1, result) <= 0); Debug.Assert(Compare(value2, result) <= 0); return result; } } } }