Files
PURErat-crack-scode/decompiled/Libraries/microsoft.codeanalysis.csharp/Microsoft.CodeAnalysis.CSharp/ControlFlowPass.cs
T
2026-08-27 10:56:38 -06:00

404 lines
13 KiB
C#

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp;
internal class ControlFlowPass : AbstractFlowPass<ControlFlowPass.LocalState, ControlFlowPass.LocalFunctionState>
{
internal struct LocalState : ILocalState
{
internal bool Alive;
internal bool Reported;
public bool Reachable => Alive;
internal LocalState(bool live, bool reported)
{
Alive = live;
Reported = reported;
}
public LocalState Clone()
{
return this;
}
}
internal sealed class LocalFunctionState : AbstractLocalFunctionState
{
public LocalFunctionState(LocalState unreachableState)
: base(unreachableState.Clone(), unreachableState.Clone())
{
}
}
private readonly PooledDictionary<LabelSymbol, BoundNode> _labelsDefined = PooledDictionary<LabelSymbol, BoundNode>.GetInstance();
private readonly PooledHashSet<LabelSymbol> _labelsUsed = PooledHashSet<LabelSymbol>.GetInstance();
protected bool _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException;
private readonly ArrayBuilder<(LocalSymbol symbol, BoundBlock block)> _usingDeclarations = ArrayBuilder<(LocalSymbol, BoundBlock)>.GetInstance();
private BoundBlock _currentBlock;
public sealed override bool AwaitUsingAndForeachAddsPendingBranch => false;
protected override void Free()
{
_labelsDefined.Free();
_labelsUsed.Free();
_usingDeclarations.Free();
base.Free();
}
internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node)
: base(compilation, member, node, (BoundNode)null, (BoundNode)null, false, false)
{
}
internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
: base(compilation, member, node, firstInRegion, lastInRegion, false, false)
{
}
protected override LocalFunctionState CreateLocalFunctionState(LocalFunctionSymbol symbol)
{
return new LocalFunctionState(UnreachableState());
}
protected override bool Meet(ref LocalState self, ref LocalState other)
{
LocalState localState = self;
self.Alive &= other.Alive;
self.Reported &= other.Reported;
return self.Alive != localState.Alive;
}
protected override bool Join(ref LocalState self, ref LocalState other)
{
LocalState localState = self;
self.Alive |= other.Alive;
self.Reported &= other.Reported;
return self.Alive != localState.Alive;
}
protected override string Dump(LocalState state)
{
return "[alive: " + state.Alive + "; reported: " + state.Reported + "]";
}
protected override LocalState TopState()
{
return new LocalState(live: true, reported: false);
}
protected override LocalState UnreachableState()
{
return new LocalState(live: false, State.Reported);
}
protected override LocalState LabelState(LabelSymbol label)
{
LocalState result = base.LabelState(label);
result.Reported = false;
return result;
}
public override BoundNode Visit(BoundNode node)
{
if (!(node is BoundExpression))
{
return base.Visit(node);
}
return null;
}
protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion)
{
base.Diagnostics.Clear();
ImmutableArray<PendingBranch> result = base.Scan(ref badRegion);
LabelSymbol labelSymbol = default(LabelSymbol);
BoundNode boundNode = default(BoundNode);
foreach (KeyValuePair<LabelSymbol, BoundNode> item in (Dictionary<LabelSymbol, BoundNode>)(object)_labelsDefined)
{
KeyValuePairUtil.Deconstruct<LabelSymbol, BoundNode>(item, ref labelSymbol, ref boundNode);
LabelSymbol labelSymbol2 = labelSymbol;
if (!(boundNode is BoundSwitchStatement) && !((HashSet<LabelSymbol>)(object)_labelsUsed).Contains(labelSymbol2))
{
base.Diagnostics.Add(ErrorCode.WRN_UnreferencedLabel, labelSymbol2.GetFirstLocation());
}
}
return result;
}
public static bool Analyze(CSharpCompilation compilation, Symbol member, BoundBlock block, DiagnosticBag diagnostics)
{
ControlFlowPass controlFlowPass = new ControlFlowPass(compilation, member, block);
if (diagnostics != null)
{
controlFlowPass._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true;
}
try
{
bool badRegion = false;
return controlFlowPass.Analyze(ref badRegion, diagnostics);
}
catch (CancelledByStackGuardException ex) when (diagnostics != null)
{
ex.AddAnError(diagnostics);
return true;
}
finally
{
controlFlowPass.Free();
}
}
protected override bool ConvertInsufficientExecutionStackExceptionToCancelledByStackGuardException()
{
return _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException;
}
protected bool Analyze(ref bool badRegion, DiagnosticBag diagnostics)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
Analyze(ref badRegion);
if (diagnostics != null)
{
diagnostics.AddRange(base.Diagnostics);
}
return State.Alive;
}
protected override ImmutableArray<PendingBranch> RemoveReturns()
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
ImmutableArray<PendingBranch> result = base.RemoveReturns();
ImmutableArray<PendingBranch>.Enumerator enumerator = result.GetEnumerator();
while (enumerator.MoveNext())
{
PendingBranch current = enumerator.Current;
if (current.Branch != null)
{
switch (current.Branch.Kind)
{
case BoundKind.GotoStatement:
{
SyntaxToken firstToken = current.Branch.Syntax.GetFirstToken(false, false, false, false);
SourceLocation location2 = new SourceLocation(ref firstToken);
base.Diagnostics.Add(ErrorCode.ERR_LabelNotFound, (Location)(object)location2, ((BoundGotoStatement)current.Branch).Label.Name);
break;
}
case BoundKind.BreakStatement:
case BoundKind.ContinueStatement:
{
SyntaxToken firstToken = current.Branch.Syntax.GetFirstToken(false, false, false, false);
SourceLocation location = new SourceLocation(ref firstToken);
base.Diagnostics.Add(ErrorCode.ERR_BadDelegateLeave, (Location)(object)location);
break;
}
}
}
}
return result;
}
protected override void VisitStatement(BoundStatement statement)
{
switch (statement.Kind)
{
case BoundKind.Block:
case BoundKind.LocalFunctionStatement:
case BoundKind.NoOpStatement:
case BoundKind.ThrowStatement:
case BoundKind.LabeledStatement:
base.VisitStatement(statement);
break;
case BoundKind.StatementList:
VisitStatementList((BoundStatementList)statement);
break;
default:
CheckReachable(statement);
base.VisitStatement(statement);
break;
}
}
private void CheckReachable(BoundStatement statement)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
if (!State.Alive && !State.Reported && !statement.WasCompilerGenerated)
{
TextSpan span = statement.Syntax.Span;
if (((TextSpan)(ref span)).Length != 0)
{
SyntaxToken firstToken = statement.Syntax.GetFirstToken(false, false, false, false);
base.Diagnostics.Add(ErrorCode.WRN_UnreachableCode, (Location)new SourceLocation(ref firstToken));
State.Reported = true;
}
}
}
protected override void VisitTryBlock(BoundStatement tryBlock, BoundTryStatement node, ref LocalState tryState)
{
if (node.CatchBlocks.IsEmpty)
{
base.VisitTryBlock(tryBlock, node, ref tryState);
return;
}
SavedPending oldPending = SavePending();
base.VisitTryBlock(tryBlock, node, ref tryState);
RestorePending(oldPending);
}
protected override void VisitCatchBlock(BoundCatchBlock catchBlock, ref LocalState finallyState)
{
SavedPending oldPending = SavePending();
base.VisitCatchBlock(catchBlock, ref finallyState);
RestorePending(oldPending);
}
protected override void VisitFinallyBlock(BoundStatement finallyBlock, ref LocalState endState)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
SavedPending oldPending = SavePending();
SavedPending oldPending2 = SavePending();
base.VisitFinallyBlock(finallyBlock, ref endState);
RestorePending(oldPending2);
foreach (PendingBranch item in base.PendingBranches.AsEnumerable())
{
if (item.Branch != null)
{
SyntaxToken firstToken = item.Branch.Syntax.GetFirstToken(false, false, false, false);
SourceLocation location = new SourceLocation(ref firstToken);
BoundKind kind = item.Branch.Kind;
if (kind - 89 > BoundKind.PropertyEqualsValue)
{
base.Diagnostics.Add(ErrorCode.ERR_BadFinallyLeave, (Location)(object)location);
}
}
}
RestorePending(oldPending);
}
protected override void VisitLabel(BoundLabeledStatement node)
{
((Dictionary<LabelSymbol, BoundNode>)(object)_labelsDefined)[node.Label] = _currentBlock;
base.VisitLabel(node);
}
public override BoundNode VisitLabeledStatement(BoundLabeledStatement node)
{
VisitLabel(node);
CheckReachable(node);
VisitStatement(node.Body);
return null;
}
public override BoundNode VisitGotoStatement(BoundGotoStatement node)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
((HashSet<LabelSymbol>)(object)_labelsUsed).Add(node.Label);
Location location = node.Syntax.Location;
TextSpan sourceSpan = location.SourceSpan;
int start = ((TextSpan)(ref sourceSpan)).Start;
sourceSpan = node.Label.GetFirstLocation().SourceSpan;
int start2 = ((TextSpan)(ref sourceSpan)).Start;
Enumerator<(LocalSymbol, BoundBlock)> enumerator = _usingDeclarations.GetEnumerator();
while (enumerator.MoveNext())
{
(LocalSymbol, BoundBlock) current = enumerator.Current;
sourceSpan = current.Item1.GetFirstLocation().SourceSpan;
int start3 = ((TextSpan)(ref sourceSpan)).Start;
if (start < start3 && start2 > start3)
{
base.Diagnostics.Add(ErrorCode.ERR_GoToForwardJumpOverUsingVar, location);
break;
}
if (start > start3 && start2 < start3 && ((Dictionary<LabelSymbol, BoundNode>)(object)_labelsDefined)[node.Label] == current.Item2)
{
base.Diagnostics.Add(ErrorCode.ERR_GoToBackwardJumpOverUsingVar, location);
break;
}
}
return base.VisitGotoStatement(node);
}
protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
base.VisitSwitchSection(node, isLastSection);
if (State.Alive)
{
SyntaxNode syntax = node.SwitchLabels.Last().Syntax;
base.Diagnostics.Add(isLastSection ? ErrorCode.ERR_SwitchFallOut : ErrorCode.ERR_SwitchFallThrough, (Location)new SourceLocation(syntax), ((object)syntax).ToString());
}
}
public override BoundNode VisitSwitchStatement(BoundSwitchStatement node)
{
ImmutableArray<BoundSwitchSection>.Enumerator enumerator = node.SwitchSections.GetEnumerator();
while (enumerator.MoveNext())
{
ImmutableArray<BoundSwitchLabel>.Enumerator enumerator2 = enumerator.Current.SwitchLabels.GetEnumerator();
while (enumerator2.MoveNext())
{
BoundSwitchLabel current = enumerator2.Current;
((Dictionary<LabelSymbol, BoundNode>)(object)_labelsDefined)[current.Label] = node;
}
}
return base.VisitSwitchStatement(node);
}
public override BoundNode VisitBlock(BoundBlock node)
{
BoundBlock currentBlock = _currentBlock;
_currentBlock = node;
int count = _usingDeclarations.Count;
ImmutableArray<LocalSymbol>.Enumerator enumerator = node.Locals.GetEnumerator();
while (enumerator.MoveNext())
{
LocalSymbol current = enumerator.Current;
if (current.IsUsing)
{
_usingDeclarations.Add((current, node));
}
}
BoundNode result = base.VisitBlock(node);
_usingDeclarations.Clip(count);
_currentBlock = currentBlock;
return result;
}
}