forked from dotnet/roslyn-analyzers
/
PointsToAnalysis.cs
107 lines (93 loc) · 5.91 KB
/
PointsToAnalysis.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Diagnostics;
using Analyzer.Utilities;
using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis.Diagnostics;
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis
{
using CopyAnalysisResult = DataFlowAnalysisResult<CopyAnalysis.CopyBlockAnalysisResult, CopyAnalysis.CopyAbstractValue>;
/// <summary>
/// Dataflow analysis to track locations pointed to by <see cref="AnalysisEntity"/> and <see cref="IOperation"/> instances.
/// </summary>
public partial class PointsToAnalysis : ForwardDataFlowAnalysis<PointsToAnalysisData, PointsToAnalysisContext, PointsToAnalysisResult, PointsToBlockAnalysisResult, PointsToAbstractValue>
{
internal static readonly AbstractValueDomain<PointsToAbstractValue> PointsToAbstractValueDomainInstance = PointsToAbstractValueDomain.Default;
private PointsToAnalysis(PointsToAnalysisDomain analysisDomain, PointsToDataFlowOperationVisitor operationVisitor)
: base(analysisDomain, operationVisitor)
{
}
public static PointsToAnalysisResult TryGetOrComputeResult(
ControlFlowGraph cfg,
ISymbol owningSymbol,
AnalyzerOptions analyzerOptions,
WellKnownTypeProvider wellKnownTypeProvider,
InterproceduralAnalysisConfiguration interproceduralAnalysisConfig,
InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt,
bool pessimisticAnalysis = true,
bool performCopyAnalysis = false,
bool exceptionPathsAnalysis = false)
{
return TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider,
out var _, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt,
pessimisticAnalysis, performCopyAnalysis, exceptionPathsAnalysis);
}
public static PointsToAnalysisResult TryGetOrComputeResult(
ControlFlowGraph cfg,
ISymbol owningSymbol,
AnalyzerOptions analyzerOptions,
WellKnownTypeProvider wellKnownTypeProvider,
out CopyAnalysisResult copyAnalysisResultOpt,
InterproceduralAnalysisConfiguration interproceduralAnalysisConfig,
InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt,
bool pessimisticAnalysis = true,
bool performCopyAnalysis = false,
bool exceptionPathsAnalysis = false)
{
copyAnalysisResultOpt = performCopyAnalysis ?
CopyAnalysis.CopyAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig,
interproceduralAnalysisPredicateOpt, pessimisticAnalysis, performPointsToAnalysis: true, exceptionPathsAnalysis) :
null;
if (cfg == null)
{
Debug.Fail("Expected non-null CFG");
return null;
}
var analysisContext = PointsToAnalysisContext.Create(PointsToAbstractValueDomain.Default, wellKnownTypeProvider, cfg,
owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, copyAnalysisResultOpt,
TryGetOrComputeResultForAnalysisContext, interproceduralAnalysisPredicateOpt);
return TryGetOrComputeResultForAnalysisContext(analysisContext);
}
private static PointsToAnalysisResult TryGetOrComputeResultForAnalysisContext(PointsToAnalysisContext analysisContext)
{
using var trackedEntitiesBuilder = new TrackedEntitiesBuilder();
var defaultPointsToValueGenerator = new DefaultPointsToValueGenerator(trackedEntitiesBuilder);
var analysisDomain = new PointsToAnalysisDomain(defaultPointsToValueGenerator);
var operationVisitor = new PointsToDataFlowOperationVisitor(trackedEntitiesBuilder, defaultPointsToValueGenerator, analysisDomain, analysisContext);
var pointsToAnalysis = new PointsToAnalysis(analysisDomain, operationVisitor);
return pointsToAnalysis.TryGetOrComputeResultCore(analysisContext, cacheResult: true);
}
internal static bool ShouldBeTracked(ITypeSymbol typeSymbol) => typeSymbol.IsReferenceTypeOrNullableValueType() ||
typeSymbol is ITypeParameterSymbol typeParameter && !typeParameter.IsValueType;
internal static bool ShouldBeTracked(AnalysisEntity analysisEntity)
=> ShouldBeTracked(analysisEntity.Type) || analysisEntity.IsLValueFlowCaptureEntity || analysisEntity.IsThisOrMeInstance;
[Conditional("DEBUG")]
internal static void AssertValidPointsToAnalysisData(PointsToAnalysisData data)
{
data.AssertValidPointsToAnalysisData();
}
protected override PointsToAnalysisResult ToResult(PointsToAnalysisContext analysisContext, DataFlowAnalysisResult<PointsToBlockAnalysisResult, PointsToAbstractValue> dataFlowAnalysisResult)
{
var operationVisitor = ((PointsToDataFlowOperationVisitor)OperationVisitor);
return new PointsToAnalysisResult(
dataFlowAnalysisResult,
operationVisitor.GetEscapedLocationsThroughOperationsMap(),
operationVisitor.GetEscapedLocationsThroughReturnValuesMap(),
operationVisitor.GetEscapedLocationsThroughEntitiesMap(),
operationVisitor.TrackedEntitiesBuilder);
}
protected override PointsToBlockAnalysisResult ToBlockResult(BasicBlock basicBlock, PointsToAnalysisData blockAnalysisData)
=> new PointsToBlockAnalysisResult(basicBlock, blockAnalysisData);
}
}