139 lines
3.9 KiB
C#
139 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal class AlwaysAssignedWalker : AbstractRegionDataFlowPass
|
|
{
|
|
private LocalState _endOfRegionState;
|
|
|
|
private readonly HashSet<LabelSymbol> _labelsInside = new HashSet<LabelSymbol>();
|
|
|
|
private AlwaysAssignedWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
|
|
: base(compilation, member, node, firstInRegion, lastInRegion)
|
|
{
|
|
}
|
|
|
|
internal static IEnumerable<Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
|
|
{
|
|
AlwaysAssignedWalker alwaysAssignedWalker = new AlwaysAssignedWalker(compilation, member, node, firstInRegion, lastInRegion);
|
|
bool badRegion = false;
|
|
try
|
|
{
|
|
List<Symbol> list = alwaysAssignedWalker.Analyze(ref badRegion);
|
|
IEnumerable<Symbol> result;
|
|
if (!badRegion)
|
|
{
|
|
IEnumerable<Symbol> enumerable = list;
|
|
result = enumerable;
|
|
}
|
|
else
|
|
{
|
|
result = SpecializedCollections.EmptyEnumerable<Symbol>();
|
|
}
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
alwaysAssignedWalker.Free();
|
|
}
|
|
}
|
|
|
|
private List<Symbol> Analyze(ref bool badRegion)
|
|
{
|
|
Analyze(ref badRegion, null);
|
|
List<Symbol> list = new List<Symbol>();
|
|
if (_endOfRegionState.Reachable)
|
|
{
|
|
foreach (int item in ((BitVector)(ref _endOfRegionState.Assigned)).TrueBits())
|
|
{
|
|
if (item < variableBySlot.Count)
|
|
{
|
|
LocalDataFlowPass<LocalState, LocalFunctionState>.VariableIdentifier variableIdentifier = variableBySlot[item];
|
|
if (variableIdentifier.Exists && !(variableIdentifier.Symbol is FieldSymbol))
|
|
{
|
|
list.Add(variableIdentifier.Symbol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
protected override void WriteArgument(BoundExpression arg, RefKind refKind, MethodSymbol method)
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0002: Invalid comparison between Unknown and I4
|
|
if ((int)refKind == 2)
|
|
{
|
|
Assign(arg, null);
|
|
}
|
|
}
|
|
|
|
protected override void ResolveBranch(PendingBranch pending, LabelSymbol label, BoundStatement target, ref bool labelStateChanged)
|
|
{
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
if (base.IsInside && pending.Branch != null && !RegionContains(pending.Branch.Syntax.Span))
|
|
{
|
|
pending.State = (pending.State.Reachable ? TopState() : UnreachableState());
|
|
}
|
|
base.ResolveBranch(pending, label, target, ref labelStateChanged);
|
|
}
|
|
|
|
public override BoundNode VisitLabel(BoundLabel node)
|
|
{
|
|
ResolveLabel(node, node.Label);
|
|
return base.VisitLabel(node);
|
|
}
|
|
|
|
public override BoundNode VisitLabeledStatement(BoundLabeledStatement node)
|
|
{
|
|
ResolveLabel(node, node.Label);
|
|
return base.VisitLabeledStatement(node);
|
|
}
|
|
|
|
private void ResolveLabel(BoundNode node, LabelSymbol label)
|
|
{
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
if (node.Syntax != null && RegionContains(node.Syntax.Span))
|
|
{
|
|
_labelsInside.Add(label);
|
|
}
|
|
}
|
|
|
|
protected override LocalState TopState()
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
return new LocalState(BitVector.Empty);
|
|
}
|
|
|
|
protected override void EnterRegion()
|
|
{
|
|
State = TopState();
|
|
base.EnterRegion();
|
|
}
|
|
|
|
protected override void LeaveRegion()
|
|
{
|
|
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
|
if (IsConditionalState)
|
|
{
|
|
_endOfRegionState = StateWhenTrue.Clone();
|
|
Join(ref _endOfRegionState, ref StateWhenFalse);
|
|
}
|
|
else
|
|
{
|
|
_endOfRegionState = State.Clone();
|
|
}
|
|
foreach (AbstractFlowPass<LocalState, LocalFunctionState>.PendingBranch item in base.PendingBranches.AsEnumerable())
|
|
{
|
|
if (item.Branch != null && RegionContains(item.Branch.Syntax.Span) && !_labelsInside.Contains(item.Label))
|
|
{
|
|
Join(ref _endOfRegionState, ref item.State);
|
|
}
|
|
}
|
|
base.LeaveRegion();
|
|
}
|
|
}
|