using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp; internal class DefiniteAssignmentPass : LocalDataFlowPass { private sealed class SameDiagnosticComparer : EqualityComparer { public static readonly SameDiagnosticComparer Instance = new SameDiagnosticComparer(); public override bool Equals(Diagnostic x, Diagnostic y) { return x.Equals(y); } public override int GetHashCode(Diagnostic obj) { return Hash.Combine(Hash.CombineValues((IEnumerable)obj.Arguments, int.MaxValue), Hash.Combine(((object)obj.Location).GetHashCode(), obj.Code)); } } internal struct LocalState : ILocalDataFlowState, ILocalState { internal BitVector Assigned; public bool NormalizeToBottom { get; } public bool Reachable { get { if (((BitVector)(ref Assigned)).Capacity > 0) { return !IsAssigned(0); } return true; } } internal LocalState(BitVector assigned, bool normalizeToBottom = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Assigned = assigned; NormalizeToBottom = normalizeToBottom; } public LocalState Clone() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return new LocalState(((BitVector)(ref Assigned)).Clone()); } public bool IsAssigned(int slot) { return ((BitVector)(ref Assigned))[slot]; } public void Assign(int slot) { if (slot != -1) { ((BitVector)(ref Assigned))[slot] = true; } } public void Unassign(int slot) { if (slot != -1) { ((BitVector)(ref Assigned))[slot] = false; } } } internal sealed class LocalFunctionState(LocalState stateFromBottom, LocalState stateFromTop) : AbstractLocalFunctionState(stateFromBottom, stateFromTop) { public BitVector ReadVars = BitVector.Empty; public BitVector CapturedMask = BitVector.Null; public BitVector InvertedCapturedMask = BitVector.Null; } private readonly PooledDictionary _variableSlot = PooledDictionary.VariableIdentifier, int>.GetInstance(); protected readonly ArrayBuilder variableBySlot = ArrayBuilder.VariableIdentifier>.GetInstance(1, default(LocalDataFlowPass.VariableIdentifier)); private readonly HashSet? initiallyAssignedVariables; private readonly PooledHashSet _usedVariables = PooledHashSet.GetInstance(); private PooledHashSet? _readParameters; private readonly PooledHashSet _usedLocalFunctions = PooledHashSet.GetInstance(); private readonly PooledHashSet _writtenVariables = PooledHashSet.GetInstance(); private PooledHashSet? _implicitlyInitializedFieldsOpt; private readonly PooledDictionary _unsafeAddressTakenVariables = PooledDictionary.GetInstance(); private readonly PooledHashSet _capturedVariables = PooledHashSet.GetInstance(); private readonly PooledHashSet _capturedInside = PooledHashSet.GetInstance(); private readonly PooledHashSet _capturedOutside = PooledHashSet.GetInstance(); private readonly SourceAssemblySymbol? _sourceAssembly; private readonly HashSet? _unassignedVariableAddressOfSyntaxes; private BitVector _alreadyReported; private readonly bool _requireOutParamsAssigned; private readonly bool _trackClassFields; private readonly bool _trackStaticMembers; protected MethodSymbol? topLevelMethod; protected bool _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException; private readonly bool _shouldCheckConverted; private bool TrackImplicitlyInitializedFields { get { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 if (_requireOutParamsAssigned && !_emptyStructTypeCache._dev12CompilerCompatibility) { Symbol currentSymbol = CurrentSymbol; if (currentSymbol is MethodSymbol methodSymbol && (int)methodSymbol.MethodKind == 1) { NamedTypeSymbol containingType = currentSymbol.ContainingType; if ((object)containingType != null) { return (int)containingType.TypeKind == 10; } } return false; } return false; } } public sealed override bool AwaitUsingAndForeachAddsPendingBranch => true; private void AddImplicitlyInitializedField(FieldSymbol field) { if (TrackImplicitlyInitializedFields) { ((HashSet)(object)(_implicitlyInitializedFieldsOpt ?? (_implicitlyInitializedFieldsOpt = PooledHashSet.GetInstance()))).Add(field); } } internal DefiniteAssignmentPass(CSharpCompilation compilation, Symbol member, BoundNode node, bool strictAnalysis, bool trackUnassignments = false, HashSet? unassignedVariableAddressOfSyntaxes = null, bool requireOutParamsAssigned = true, bool trackClassFields = false, bool trackStaticMembers = false) : base(compilation, member, node, strictAnalysis ? EmptyStructTypeCache.CreatePrecise() : EmptyStructTypeCache.CreateForDev12Compatibility(compilation), trackUnassignments) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) initiallyAssignedVariables = null; _sourceAssembly = GetSourceAssembly(compilation, member, node); _unassignedVariableAddressOfSyntaxes = unassignedVariableAddressOfSyntaxes; _requireOutParamsAssigned = requireOutParamsAssigned; _trackClassFields = trackClassFields; _trackStaticMembers = trackStaticMembers; topLevelMethod = member as MethodSymbol; _shouldCheckConverted = GetType() == typeof(DefiniteAssignmentPass); State = new LocalState(BitVector.Empty); } internal DefiniteAssignmentPass(CSharpCompilation compilation, Symbol member, BoundNode node, EmptyStructTypeCache emptyStructs, bool trackUnassignments = false, HashSet? initiallyAssignedVariables = null) : base(compilation, member, node, emptyStructs, trackUnassignments) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) this.initiallyAssignedVariables = initiallyAssignedVariables; _sourceAssembly = GetSourceAssembly(compilation, member, node); CurrentSymbol = member; _unassignedVariableAddressOfSyntaxes = null; _requireOutParamsAssigned = true; topLevelMethod = member as MethodSymbol; _shouldCheckConverted = GetType() == typeof(DefiniteAssignmentPass); State = new LocalState(BitVector.Empty); } internal DefiniteAssignmentPass(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, HashSet initiallyAssignedVariables, HashSet unassignedVariableAddressOfSyntaxes, bool trackUnassignments) : base(compilation, member, node, EmptyStructTypeCache.CreateNeverEmpty(), firstInRegion, lastInRegion, true, trackUnassignments) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) this.initiallyAssignedVariables = initiallyAssignedVariables; _sourceAssembly = null; CurrentSymbol = member; _unassignedVariableAddressOfSyntaxes = unassignedVariableAddressOfSyntaxes; _shouldCheckConverted = GetType() == typeof(DefiniteAssignmentPass); State = new LocalState(BitVector.Empty); } private static SourceAssemblySymbol? GetSourceAssembly(CSharpCompilation compilation, Symbol member, BoundNode node) { if ((object)member == null) { return null; } if (node.Kind == BoundKind.Attribute) { return null; } return member.ContainingAssembly as SourceAssemblySymbol; } protected override void Free() { variableBySlot.Free(); _variableSlot.Free(); _usedVariables.Free(); _readParameters?.Free(); _implicitlyInitializedFieldsOpt?.Free(); _usedLocalFunctions.Free(); _writtenVariables.Free(); _capturedVariables.Free(); _capturedInside.Free(); _capturedOutside.Free(); _unsafeAddressTakenVariables.Free(); base.Free(); } protected override bool TryGetVariable(VariableIdentifier identifier, out int slot) { return ((Dictionary.VariableIdentifier, int>)(object)_variableSlot).TryGetValue(identifier, out slot); } protected override int AddVariable(VariableIdentifier identifier) { int count = variableBySlot.Count; ((Dictionary.VariableIdentifier, int>)(object)_variableSlot).Add(identifier, count); variableBySlot.Add(identifier); return count; } protected Symbol GetNonMemberSymbol(int slot) { LocalDataFlowPass.VariableIdentifier variableIdentifier = variableBySlot[slot]; while (variableIdentifier.ContainingSlot > 0) { variableIdentifier = variableBySlot[variableIdentifier.ContainingSlot]; } return variableIdentifier.Symbol; } private int RootSlot(int slot) { while (true) { int containingSlot = variableBySlot[slot].ContainingSlot; if (containingSlot == 0) { break; } slot = containingSlot; } return slot; } protected override bool ConvertInsufficientExecutionStackExceptionToCancelledByStackGuardException() { return _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException; } protected override ImmutableArray Scan(ref bool badRegion) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) base.Diagnostics.Clear(); ImmutableArray methodParameters = base.MethodParameters; ParameterSymbol methodThisParameter = base.MethodThisParameter; _alreadyReported = BitVector.Empty; regionPlace = RegionPlace.Before; EnterParameters(methodParameters); Symbol symbol = _symbol; if (symbol is MethodSymbol methodSymbol) { if (!symbol.IsStatic && symbol.ContainingSymbol is SourceMemberContainerTypeSymbol sourceMemberContainerTypeSymbol) { SynthesizedPrimaryConstructor primaryConstructor = sourceMemberContainerTypeSymbol.PrimaryConstructor; if ((object)primaryConstructor != null && !(methodSymbol is SynthesizedPrimaryConstructor)) { Symbol currentSymbol = CurrentSymbol; CurrentSymbol = primaryConstructor; ImmutableArray.Enumerator enumerator = primaryConstructor.Parameters.GetEnumerator(); while (enumerator.MoveNext()) { ParameterSymbol current = enumerator.Current; NoteWrite(current, null, read: true); } CurrentSymbol = currentSymbol; } } } else if ((symbol is FieldSymbol || symbol is PropertySymbol) && !symbol.IsStatic && symbol.ContainingSymbol is SourceMemberContainerTypeSymbol sourceMemberContainerTypeSymbol2) { SynthesizedPrimaryConstructor primaryConstructor = sourceMemberContainerTypeSymbol2.PrimaryConstructor; if ((object)primaryConstructor != null) { SynthesizedPrimaryConstructor synthesizedPrimaryConstructor = primaryConstructor; EnterParameters(synthesizedPrimaryConstructor.Parameters); } } if ((object)methodThisParameter != null) { EnterParameter(methodThisParameter); if ((int)methodThisParameter.Type.SpecialType != 0) { int orCreateSlot = GetOrCreateSlot(methodThisParameter); SetSlotState(orCreateSlot, assigned: true); } } ImmutableArray.PendingBranch> result = base.Scan(ref badRegion); if (ShouldAnalyzeOutParameters(out var location)) { LeaveParameters(methodParameters, null, location); if ((object)methodThisParameter != null) { LeaveParameter(methodThisParameter, null, location); } LocalState self = State; ImmutableArray.PendingBranch>.Enumerator enumerator2 = result.GetEnumerator(); while (enumerator2.MoveNext()) { AbstractFlowPass.PendingBranch current2 = enumerator2.Current; State = current2.State; LeaveParameters(methodParameters, current2.Branch.Syntax, null); if ((object)methodThisParameter != null) { LeaveParameter(methodThisParameter, current2.Branch.Syntax, null); } Join(ref self, ref State); } State = self; } return result; } protected override ImmutableArray RemoveReturns() { ImmutableArray.PendingBranch> immutableArray = base.RemoveReturns(); if (CurrentSymbol is MethodSymbol { IsAsync: not false, IsImplicitlyDeclared: false } && !immutableArray.Any((AbstractFlowPass.PendingBranch pending) => HasAwait(pending))) { Location location = ((CurrentSymbol is LambdaSymbol lambdaSymbol) ? lambdaSymbol.DiagnosticLocation : CurrentSymbol.GetFirstLocationOrNone()); base.Diagnostics.Add(ErrorCode.WRN_AsyncLacksAwaits, location); } return immutableArray; } private static bool HasAwait(PendingBranch pending) { BoundNode branch = pending.Branch; if (branch == null) { return false; } return branch.Kind switch { BoundKind.AwaitExpression => true, BoundKind.UsingStatement => ((BoundUsingStatement)branch).AwaitOpt != null, BoundKind.ForEachStatement => ((BoundForEachStatement)branch).AwaitOpt != null, BoundKind.UsingLocalDeclarations => ((BoundUsingLocalDeclarations)branch).AwaitOpt != null, _ => false, }; } protected virtual void ReportUnassignedOutParameter(ParameterSymbol parameter, SyntaxNode node, Location location) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Invalid comparison between Unknown and I4 if ((!_requireOutParamsAssigned && (object)topLevelMethod == CurrentSymbol) || base.Diagnostics == null || !State.Reachable) { return; } if (location == (Location)null) { location = (Location)new SourceLocation(node); } bool flag = false; if (parameter.IsThis) { int num = VariableSlot(parameter); if (!State.IsAssigned(num)) { TypeSymbol type = parameter.Type; foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type)) { if (_emptyStructTypeCache.IsEmptyStructType(structInstanceField.Type) || LocalDataFlowPass.HasInitializer(structInstanceField)) { continue; } int num2 = VariableSlot(structInstanceField, num); if (num2 == -1 || !State.IsAssigned(num2)) { Symbol associatedSymbol = structInstanceField.AssociatedSymbol; bool flag2 = (object)associatedSymbol != null && (int)associatedSymbol.Kind == 15; if (compilation.IsFeatureEnabled(MessageID.IDS_FeatureAutoDefaultStructs)) { base.Diagnostics.Add(flag2 ? ErrorCode.WRN_UnassignedThisAutoPropertySupportedVersion : ErrorCode.WRN_UnassignedThisSupportedVersion, location, flag2 ? associatedSymbol : structInstanceField); } else { base.Diagnostics.Add(flag2 ? ErrorCode.ERR_UnassignedThisAutoPropertyUnsupportedVersion : ErrorCode.ERR_UnassignedThisUnsupportedVersion, location, flag2 ? associatedSymbol : structInstanceField, new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureAutoDefaultStructs.RequiredVersion())); } AddImplicitlyInitializedField(structInstanceField); flag = true; } } if (!flag) { if (type.HasInlineArrayAttribute(out var length) && length > 1) { FieldSymbol fieldSymbol = type.TryGetPossiblyUnsupportedByLanguageInlineArrayElementField(); if ((object)fieldSymbol != null) { if (!compilation.IsFeatureEnabled(MessageID.IDS_FeatureAutoDefaultStructs)) { base.Diagnostics.Add(ErrorCode.ERR_ParamUnassigned, location, parameter.Name); } AddImplicitlyInitializedField(fieldSymbol); } } flag = true; } } } if (!flag) { base.Diagnostics.Add(ErrorCode.ERR_ParamUnassigned, location, parameter.Name); } } public static void Analyze(CSharpCompilation compilation, MethodSymbol member, BoundNode node, DiagnosticBag diagnostics, out ImmutableArray implicitlyInitializedFieldsOpt, bool requireOutParamsAssigned) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Invalid comparison between Unknown and I4 DiagnosticBag val; (val, implicitlyInitializedFieldsOpt) = analyze(strictAnalysis: true); if (!val.HasAnyErrors()) { diagnostics.AddRangeAndFree(val); return; } DiagnosticBag item = analyze(strictAnalysis: false).Item1; if (item.AsEnumerable().Any((Diagnostic d) => d.Code == 8078)) { diagnostics.AddRangeAndFree(item); val.Free(); return; } if (val.Count == item.Count) { diagnostics.AddRangeAndFree(val); item.Free(); return; } HashSet hashSet = new HashSet(item.AsEnumerable(), SameDiagnosticComparer.Instance); item.Free(); foreach (Diagnostic item3 in val.AsEnumerable()) { if ((int)item3.Severity != 3 || hashSet.Contains(item3)) { diagnostics.Add(item3); continue; } ErrorCode code = (ErrorCode)item3.Code; ErrorCode code2 = code switch { ErrorCode.ERR_UnassignedThisAutoPropertyUnsupportedVersion => ErrorCode.WRN_UnassignedThisAutoPropertyUnsupportedVersion, ErrorCode.ERR_UnassignedThisUnsupportedVersion => ErrorCode.WRN_UnassignedThisUnsupportedVersion, ErrorCode.ERR_ParamUnassigned => ErrorCode.WRN_ParamUnassigned, ErrorCode.ERR_UseDefViolationProperty => ErrorCode.WRN_UseDefViolationProperty, ErrorCode.ERR_UseDefViolationField => ErrorCode.WRN_UseDefViolationField, ErrorCode.ERR_UseDefViolationThisUnsupportedVersion => ErrorCode.WRN_UseDefViolationThisUnsupportedVersion, ErrorCode.ERR_UseDefViolationPropertyUnsupportedVersion => ErrorCode.WRN_UseDefViolationPropertyUnsupportedVersion, ErrorCode.ERR_UseDefViolationFieldUnsupportedVersion => ErrorCode.WRN_UseDefViolationFieldUnsupportedVersion, ErrorCode.ERR_UseDefViolationOut => ErrorCode.WRN_UseDefViolationOut, ErrorCode.ERR_UseDefViolation => ErrorCode.WRN_UseDefViolation, _ => code, }; DiagnosticWithInfo val2 = (DiagnosticWithInfo)(object)((item3 is DiagnosticWithInfo) ? item3 : null); object[] array; if (val2 != null) { DiagnosticInfo info = val2.Info; if (info != null) { object[] arguments = info.Arguments; array = arguments; goto IL_024f; } } array = item3.Arguments.ToArray(); goto IL_024f; IL_024f: object[] args = array; diagnostics.Add(code2, item3.Location, args); } val.Free(); (DiagnosticBag, ImmutableArray implicitlyInitializedFieldsOpt) analyze(bool strictAnalysis) { DiagnosticBag instance = DiagnosticBag.GetInstance(); ImmutableArray item2 = default(ImmutableArray); DefiniteAssignmentPass definiteAssignmentPass = new DefiniteAssignmentPass(compilation, member, node, strictAnalysis, trackUnassignments: false, null, requireOutParamsAssigned) { _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true }; try { bool badRegion = false; definiteAssignmentPass.Analyze(ref badRegion, instance); PooledHashSet implicitlyInitializedFieldsOpt2 = definiteAssignmentPass._implicitlyInitializedFieldsOpt; if (implicitlyInitializedFieldsOpt2 != null) { ArrayBuilder instance2 = ArrayBuilder.GetInstance(((HashSet)(object)implicitlyInitializedFieldsOpt2).Count); foreach (FieldSymbol item4 in (HashSet)(object)implicitlyInitializedFieldsOpt2) { instance2.Add(item4); } instance2.Sort((IComparer)LexicalOrderSymbolComparer.Instance); item2 = instance2.ToImmutableAndFree(); } } catch (CancelledByStackGuardException ex) when (diagnostics != null) { ex.AddAnError(instance); } finally { definiteAssignmentPass.Free(); } return (instance, implicitlyInitializedFieldsOpt: item2); } } protected void 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) { return; } foreach (Symbol item in (HashSet)(object)_capturedVariables) { if (((Dictionary)(object)_unsafeAddressTakenVariables).TryGetValue(item, out Location value) && (!(item is ParameterSymbol key) || !(item.ContainingSymbol is SynthesizedPrimaryConstructor synthesizedPrimaryConstructor) || !synthesizedPrimaryConstructor.GetCapturedParameters().ContainsKey(key))) { diagnostics.Add(ErrorCode.ERR_LocalCantBeFixedAndHoisted, value, item.Name); } } diagnostics.AddRange(base.Diagnostics); } private void CheckCaptured(Symbol variable, ParameterSymbol? rangeVariableUnderlyingParameter = null) { if (CurrentSymbol is SourceMethodSymbol containingSymbol && Symbol.IsCaptured(rangeVariableUnderlyingParameter ?? variable, containingSymbol)) { NoteCaptured(variable); } } private void NoteCaptured(Symbol variable) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 if (regionPlace == RegionPlace.Inside) { ((HashSet)(object)_capturedInside).Add(variable); ((HashSet)(object)_capturedVariables).Add(variable); } else if ((int)variable.Kind != 16) { ((HashSet)(object)_capturedOutside).Add(variable); ((HashSet)(object)_capturedVariables).Add(variable); } } protected IEnumerable GetCapturedInside() { return ((IEnumerable)_capturedInside).ToArray(); } protected IEnumerable GetCapturedOutside() { return ((IEnumerable)_capturedOutside).ToArray(); } protected IEnumerable GetCaptured() { return ((IEnumerable)_capturedVariables).ToArray(); } protected IEnumerable GetUnsafeAddressTaken() { return ((Dictionary)(object)_unsafeAddressTakenVariables).Keys.ToArray(); } protected IEnumerable GetUsedLocalFunctions() { return ((IEnumerable)_usedLocalFunctions).ToArray(); } private void NotePrimaryConstructorParameterReadIfNeeded(Symbol symbol) { if (symbol is ParameterSymbol item && symbol.ContainingSymbol is SynthesizedPrimaryConstructor) { if (_readParameters == null) { _readParameters = PooledHashSet.GetInstance(); } ((HashSet)(object)_readParameters).Add(item); } } protected virtual void NoteRead(Symbol variable, ParameterSymbol rangeVariableUnderlyingParameter = null) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 if (variable is LocalSymbol item) { ((HashSet)(object)_usedVariables).Add(item); } NotePrimaryConstructorParameterReadIfNeeded(variable); if (variable is LocalFunctionSymbol item2) { ((HashSet)(object)_usedLocalFunctions).Add(item2); } if ((object)variable != null) { if ((object)_sourceAssembly != null && (int)variable.Kind == 6) { _sourceAssembly.NoteFieldAccess((FieldSymbol)variable.OriginalDefinition, read: true, write: false); } CheckCaptured(variable, rangeVariableUnderlyingParameter); } } private void NoteRead(BoundNode fieldOrEventAccess) { BoundNode boundNode = fieldOrEventAccess; while (boundNode != null) { switch (boundNode.Kind) { default: return; case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)boundNode; NoteRead(boundFieldAccess.FieldSymbol); if (MayRequireTracking(boundFieldAccess.ReceiverOpt, boundFieldAccess.FieldSymbol)) { boundNode = boundFieldAccess.ReceiverOpt; break; } return; } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)boundNode; FieldSymbol associatedField = boundEventAccess.EventSymbol.AssociatedField; if ((object)associatedField != null) { NoteRead(associatedField); if (MayRequireTracking(boundEventAccess.ReceiverOpt, associatedField)) { boundNode = boundEventAccess.ReceiverOpt; break; } return; } return; } case BoundKind.ThisReference: NoteRead(base.MethodThisParameter); return; case BoundKind.Local: NoteRead(((BoundLocal)boundNode).LocalSymbol); return; case BoundKind.Parameter: NoteRead(((BoundParameter)boundNode).ParameterSymbol); return; case BoundKind.InlineArrayAccess: boundNode = ((BoundInlineArrayAccess)boundNode).Expression; break; } } } protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool read) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if ((object)variable != null) { ((HashSet)(object)_writtenVariables).Add(variable); if ((object)_sourceAssembly != null && (int)variable.Kind == 6) { FieldSymbol fieldSymbol = (FieldSymbol)variable.OriginalDefinition; _sourceAssembly.NoteFieldAccess(fieldSymbol, read && WriteConsideredUse(fieldSymbol.Type, value), write: true); } LocalSymbol localSymbol = variable as LocalSymbol; if ((object)localSymbol != null && read && WriteConsideredUse(localSymbol.Type, value)) { ((HashSet)(object)_usedVariables).Add(localSymbol); } CheckCaptured(variable); } } internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if (value == null || value.HasAnyErrors) { return true; } if ((object)type != null && type.IsReferenceType && (int)type.SpecialType != 20) { if (type is ArrayTypeSymbol { IsSZArray: not false } arrayTypeSymbol) { TypeSymbol elementType = arrayTypeSymbol.ElementType; if ((object)elementType != null && (int)elementType.SpecialType == 10) { goto IL_0059; } } return value.ConstantValueOpt != ConstantValue.Null; } goto IL_0059; IL_0059: if ((object)type != null && type.IsPointerOrFunctionPointer()) { return true; } if (value != null && value.ConstantValueOpt != null && value.Kind != BoundKind.InterpolatedString) { return false; } switch (value.Kind) { case BoundKind.Conversion: { BoundConversion boundConversion = (BoundConversion)value; if (boundConversion.ConversionKind.IsUserDefinedConversion() || boundConversion.ConversionKind == ConversionKind.IntPtr) { return true; } return WriteConsideredUse(null, boundConversion.Operand); } case BoundKind.DefaultLiteral: case BoundKind.DefaultExpression: return false; case BoundKind.ObjectCreationExpression: { BoundObjectCreationExpression boundObjectCreationExpression = (BoundObjectCreationExpression)value; if (boundObjectCreationExpression.Constructor.IsImplicitlyDeclared) { return boundObjectCreationExpression.InitializerExpressionOpt != null; } return true; } case BoundKind.Utf8String: case BoundKind.TupleLiteral: case BoundKind.ConvertedTupleLiteral: return false; default: return true; } } private void NoteWrite(BoundExpression n, BoundExpression value, bool read) { while (n != null) { switch (n.Kind) { case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)n; if ((object)_sourceAssembly != null) { FieldSymbol originalDefinition2 = boundFieldAccess.FieldSymbol.OriginalDefinition; _sourceAssembly.NoteFieldAccess(originalDefinition2, value == null || WriteConsideredUse(boundFieldAccess.FieldSymbol.Type, value), write: true); } if (MayRequireTracking(boundFieldAccess.ReceiverOpt, boundFieldAccess.FieldSymbol)) { n = boundFieldAccess.ReceiverOpt; if (n.Kind == BoundKind.Local) { ((HashSet)(object)_usedVariables).Add(((BoundLocal)n).LocalSymbol); } break; } return; } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)n; FieldSymbol associatedField = boundEventAccess.EventSymbol.AssociatedField; if ((object)associatedField != null) { if ((object)_sourceAssembly != null) { FieldSymbol originalDefinition = associatedField.OriginalDefinition; _sourceAssembly.NoteFieldAccess(originalDefinition, value == null || WriteConsideredUse(associatedField.Type, value), write: true); } if (MayRequireTracking(boundEventAccess.ReceiverOpt, associatedField)) { n = boundEventAccess.ReceiverOpt; break; } return; } return; } case BoundKind.ThisReference: NoteWrite(base.MethodThisParameter, value, read); return; case BoundKind.Local: NoteWrite(((BoundLocal)n).LocalSymbol, value, read); return; case BoundKind.Parameter: NoteWrite(((BoundParameter)n).ParameterSymbol, value, read); return; case BoundKind.RangeVariable: NoteWrite(((BoundRangeVariable)n).Value, value, read); return; case BoundKind.InlineArrayAccess: n = ((BoundInlineArrayAccess)n).Expression; value = null; break; default: return; } } } protected override void Normalize(ref LocalState state) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 int capacity = ((BitVector)(ref state.Assigned)).Capacity; int count = variableBySlot.Count; ((BitVector)(ref state.Assigned)).EnsureCapacity(count); for (int i = capacity; i < count; i++) { int containingSlot = variableBySlot[i].ContainingSlot; bool flag = containingSlot > 0 && ((BitVector)(ref state.Assigned))[containingSlot] && (int)variableBySlot[containingSlot].Symbol.GetTypeOrReturnType().TypeKind == 10; if (state.NormalizeToBottom && containingSlot == 0) { flag = true; } ((BitVector)(ref state.Assigned))[i] = flag; } } protected override bool TryGetReceiverAndMember(BoundExpression expr, out BoundExpression receiver, out Symbol member) { receiver = null; member = null; switch (expr.Kind) { case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)expr; FieldSymbol fieldSymbol = (FieldSymbol)(member = boundFieldAccess.FieldSymbol); if (fieldSymbol.IsFixedSizeBuffer) { return false; } if (fieldSymbol.IsStatic) { return _trackStaticMembers; } receiver = boundFieldAccess.ReceiverOpt; break; } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)expr; EventSymbol eventSymbol = boundEventAccess.EventSymbol; member = eventSymbol.AssociatedField; if (eventSymbol.IsStatic) { return _trackStaticMembers; } receiver = boundEventAccess.ReceiverOpt; break; } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)expr; if (Binder.AccessingAutoPropertyFromConstructor(boundPropertyAccess, CurrentSymbol)) { PropertySymbol propertySymbol = boundPropertyAccess.PropertySymbol; member = (propertySymbol as SourcePropertySymbolBase)?.BackingField; if ((object)member == null) { return false; } if (propertySymbol.IsStatic) { return _trackStaticMembers; } receiver = boundPropertyAccess.ReceiverOpt; } break; } } if ((object)member != null && receiver != null && receiver.Kind != BoundKind.TypeExpression) { return MayRequireTrackingReceiverType(receiver.Type); } return false; } private bool MayRequireTrackingReceiverType(TypeSymbol type) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if ((object)type != null) { if (!_trackClassFields) { return (int)type.TypeKind == 10; } return true; } return false; } protected bool MayRequireTracking(BoundExpression receiverOpt, FieldSymbol fieldSymbol) { if ((object)fieldSymbol != null && receiverOpt != null && !fieldSymbol.IsStatic && !fieldSymbol.IsFixedSizeBuffer && receiverOpt.Kind != BoundKind.TypeExpression && MayRequireTrackingReceiverType(receiverOpt.Type)) { return !receiverOpt.Type.IsPrimitiveRecursiveStruct(); } return false; } protected void CheckAssigned(Symbol symbol, SyntaxNode node) { if ((object)symbol == null) { return; } NoteRead(symbol); if (State.Reachable) { int num = VariableSlot(symbol); if (num >= ((BitVector)(ref State.Assigned)).Capacity) { Normalize(ref State); } if (num > 0 && !State.IsAssigned(num)) { ReportUnassignedIfNotCapturedInLocalFunction(symbol, node, num); } } } private void ReportUnassignedIfNotCapturedInLocalFunction(Symbol symbol, SyntaxNode node, int slot, bool skipIfUseBeforeDeclaration = true) { if (IsCapturedInLocalFunction(slot)) { RecordReadInLocalFunction(slot); } else { ReportUnassigned(symbol, node, slot, skipIfUseBeforeDeclaration); } } protected virtual void ReportUnassigned(Symbol symbol, SyntaxNode node, int slot, bool skipIfUseBeforeDeclaration) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Invalid comparison between Unknown and I4 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Invalid comparison between Unknown and I4 //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Invalid comparison between Unknown and I4 DefiniteAssignmentPass definiteAssignmentPass = this; SyntaxNode node2 = node; if (slot <= 0 || symbol is LocalSymbol { IsConst: not false }) { return; } if (slot >= ((BitVector)(ref _alreadyReported)).Capacity) { ((BitVector)(ref _alreadyReported)).EnsureCapacity(variableBySlot.Count); } if (!skipIfUseBeforeDeclaration || (int)symbol.Kind != 8) { goto IL_008c; } Location val = symbol.TryGetFirstLocation(); if (val != null) { TextSpan val2 = node2.Span; int end = ((TextSpan)(ref val2)).End; val2 = val.SourceSpan; if (end >= ((TextSpan)(ref val2)).Start) { goto IL_008c; } } goto IL_015c; IL_008c: if (!((BitVector)(ref _alreadyReported))[slot] && !symbol.GetTypeOrReturnType().Type.IsErrorType()) { string name = symbol.Name; if ((int)symbol.Kind == 6) { addDiagnosticForStructField(slot, (FieldSymbol)symbol); } else if ((int)symbol.Kind == 13 && (int)((ParameterSymbol)symbol).RefKind == 2) { if (((ParameterSymbol)symbol).IsThis) { addDiagnosticForStructThis(symbol, slot); } else { base.Diagnostics.Add(ErrorCode.ERR_UseDefViolationOut, node2.Location, name); } } else { base.Diagnostics.Add(ErrorCode.ERR_UseDefViolation, node2.Location, name); } } goto IL_015c; IL_015c: ((BitVector)(ref _alreadyReported))[slot] = true; void addDiagnosticForStructField(int fieldSlot, FieldSymbol fieldSymbol) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 //IL_010d: Unknown result type (might be due to invalid IL or missing references) Symbol associatedSymbol = fieldSymbol.AssociatedSymbol; bool flag = (object)associatedSymbol != null && (int)associatedSymbol.Kind == 15; string text = (flag ? associatedSymbol.Name : fieldSymbol.Name); Symbol currentSymbol = CurrentSymbol; if (currentSymbol is MethodSymbol methodSymbol && (int)methodSymbol.MethodKind == 1) { NamedTypeSymbol containingType = currentSymbol.ContainingType; if ((object)containingType != null && (int)containingType.TypeKind == 10) { int orCreateSlot = GetOrCreateSlot(CurrentSymbol.EnclosingThisSymbol()); LocalDataFlowPass.VariableIdentifier variableIdentifier; while (true) { if (fieldSlot == 0) { base.Diagnostics.Add(flag ? ErrorCode.ERR_UseDefViolationProperty : ErrorCode.ERR_UseDefViolationField, node2.Location, text); return; } variableIdentifier = variableBySlot[fieldSlot]; int containingSlot = variableIdentifier.ContainingSlot; if (containingSlot == orCreateSlot) { break; } fieldSlot = containingSlot; } AddImplicitlyInitializedField((FieldSymbol)variableIdentifier.Symbol); if ((int)fieldSymbol.RefKind != 0) { if (!flag) { base.Diagnostics.Add(ErrorCode.WRN_UseDefViolationRefField, node2.Location, text); } } else if (compilation.IsFeatureEnabled(MessageID.IDS_FeatureAutoDefaultStructs)) { base.Diagnostics.Add(flag ? ErrorCode.WRN_UseDefViolationPropertySupportedVersion : ErrorCode.WRN_UseDefViolationFieldSupportedVersion, node2.Location, text); } else { base.Diagnostics.Add(flag ? ErrorCode.ERR_UseDefViolationPropertyUnsupportedVersion : ErrorCode.ERR_UseDefViolationFieldUnsupportedVersion, node2.Location, text, new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureAutoDefaultStructs.RequiredVersion())); } return; } } base.Diagnostics.Add(flag ? ErrorCode.ERR_UseDefViolationProperty : ErrorCode.ERR_UseDefViolationField, node2.Location, text); } void addDiagnosticForStructThis(Symbol thisParameter, int thisSlot) { if (TrackImplicitlyInitializedFields) { bool flag = false; NamedTypeSymbol containingType = thisParameter.ContainingType; foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(containingType)) { if (!_emptyStructTypeCache.IsEmptyStructType(structInstanceField.Type) && !(structInstanceField is TupleErrorFieldSymbol)) { int num = VariableSlot(structInstanceField, thisSlot); if (num == -1 || !State.IsAssigned(num)) { AddImplicitlyInitializedField(structInstanceField); flag = true; } } } if (!flag && containingType.HasInlineArrayAttribute(out var length) && length > 1) { FieldSymbol fieldSymbol = containingType.TryGetPossiblyUnsupportedByLanguageInlineArrayElementField(); if ((object)fieldSymbol != null) { AddImplicitlyInitializedField(fieldSymbol); flag = true; } } } if (compilation.IsFeatureEnabled(MessageID.IDS_FeatureAutoDefaultStructs)) { base.Diagnostics.Add(ErrorCode.WRN_UseDefViolationThisSupportedVersion, node2.Location); } else { base.Diagnostics.Add(ErrorCode.ERR_UseDefViolationThisUnsupportedVersion, node2.Location, new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureAutoDefaultStructs.RequiredVersion())); } } } protected virtual void CheckAssigned(BoundExpression expr, FieldSymbol fieldSymbol, SyntaxNode node) { if (State.Reachable && !IsAssigned(expr, out var unassignedSlot)) { ReportUnassignedIfNotCapturedInLocalFunction(fieldSymbol, node, unassignedSlot); } NoteRead(expr); } private bool IsAssigned(BoundExpression node, out int unassignedSlot) { unassignedSlot = -1; if (_emptyStructTypeCache.IsEmptyStructType(node.Type)) { return true; } switch (node.Kind) { case BoundKind.ThisReference: if ((object)base.MethodThisParameter == null) { unassignedSlot = -1; return true; } unassignedSlot = GetOrCreateSlot(base.MethodThisParameter); break; case BoundKind.Local: unassignedSlot = GetOrCreateSlot(((BoundLocal)node).LocalSymbol); break; case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)node; if (!MayRequireTracking(boundFieldAccess.ReceiverOpt, boundFieldAccess.FieldSymbol) || IsAssigned(boundFieldAccess.ReceiverOpt, out unassignedSlot)) { return true; } unassignedSlot = GetOrCreateSlot(boundFieldAccess.FieldSymbol, unassignedSlot); break; } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)node; if (!MayRequireTracking(boundEventAccess.ReceiverOpt, boundEventAccess.EventSymbol.AssociatedField) || IsAssigned(boundEventAccess.ReceiverOpt, out unassignedSlot)) { return true; } unassignedSlot = GetOrCreateSlot(boundEventAccess.EventSymbol.AssociatedField, unassignedSlot); break; } case BoundKind.InlineArrayAccess: { BoundInlineArrayAccess boundInlineArrayAccess = (BoundInlineArrayAccess)node; return IsAssigned(boundInlineArrayAccess.Expression, out unassignedSlot); } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)node; if (Binder.AccessingAutoPropertyFromConstructor(boundPropertyAccess, CurrentSymbol)) { SynthesizedBackingFieldSymbol synthesizedBackingFieldSymbol = (boundPropertyAccess.PropertySymbol as SourcePropertySymbolBase)?.BackingField; if (synthesizedBackingFieldSymbol != null) { if (!MayRequireTracking(boundPropertyAccess.ReceiverOpt, synthesizedBackingFieldSymbol) || IsAssigned(boundPropertyAccess.ReceiverOpt, out unassignedSlot)) { return true; } unassignedSlot = GetOrCreateSlot(synthesizedBackingFieldSymbol, unassignedSlot); break; } } goto default; } case BoundKind.Parameter: { BoundParameter boundParameter = (BoundParameter)node; unassignedSlot = GetOrCreateSlot(boundParameter.ParameterSymbol); break; } default: unassignedSlot = -1; return true; } if (unassignedSlot > 0) { return State.IsAssigned(unassignedSlot); } return true; } private Symbol UseNonFieldSymbolUnsafely(BoundExpression expression) { while (expression != null) { BoundFieldAccess boundFieldAccess; switch (expression.Kind) { case BoundKind.FieldAccess: { boundFieldAccess = (BoundFieldAccess)expression; FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol; if ((object)_sourceAssembly != null) { _sourceAssembly.NoteFieldAccess(fieldSymbol, read: true, write: true); } if (fieldSymbol.ContainingType.IsReferenceType || fieldSymbol.IsStatic) { return null; } break; } case BoundKind.Local: { LocalSymbol localSymbol = ((BoundLocal)expression).LocalSymbol; ((HashSet)(object)_usedVariables).Add(localSymbol); return localSymbol; } case BoundKind.RangeVariable: return ((BoundRangeVariable)expression).RangeVariableSymbol; case BoundKind.Parameter: return ((BoundParameter)expression).ParameterSymbol; case BoundKind.ThisReference: return base.MethodThisParameter; case BoundKind.BaseReference: return base.MethodThisParameter; default: return null; } expression = boundFieldAccess.ReceiverOpt; } return null; } protected void Assign(BoundNode node, BoundExpression value, bool isRef = false, bool read = true) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if (!isRef && node is BoundFieldAccess boundFieldAccess) { FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol; if ((object)fieldSymbol != null && (int)fieldSymbol.RefKind != 0) { CheckAssigned(boundFieldAccess, node.Syntax); } } AssignImpl(node, value, isRef, written: true, read); } protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool isRef, bool written, bool read) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Invalid comparison between Unknown and I4 //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Invalid comparison between Unknown and I4 BoundInlineArrayAccess boundInlineArrayAccess; switch (node.Kind) { case BoundKind.DeclarationPattern: case BoundKind.RecursivePattern: case BoundKind.ListPattern: { BoundObjectPattern boundObjectPattern = (BoundObjectPattern)node; if (boundObjectPattern.Variable is LocalSymbol symbol) { int orCreateSlot = GetOrCreateSlot(symbol); SetSlotState(orCreateSlot, written || !State.Reachable); } if (written) { NoteWrite(boundObjectPattern.VariableAccess, value, read); } break; } case BoundKind.LocalDeclaration: { LocalSymbol localSymbol = ((BoundLocalDeclaration)node).LocalSymbol; int orCreateSlot2 = GetOrCreateSlot(localSymbol); SetSlotState(orCreateSlot2, written || !State.Reachable); if (written) { NoteWrite(localSymbol, value, read); } break; } case BoundKind.Local: { BoundLocal boundLocal = (BoundLocal)node; if ((int)boundLocal.LocalSymbol.RefKind != 0 && !isRef) { if (written) { VisitRvalue(boundLocal, isKnownToBeAnLvalue: true); } break; } int slot = MakeSlot(boundLocal); SetSlotState(slot, written); if (written) { NoteWrite(boundLocal, value, read); } break; } case BoundKind.InlineArrayAccess: { boundInlineArrayAccess = (BoundInlineArrayAccess)node; if (written) { NoteWrite(boundInlineArrayAccess.Expression, null, read); } if (boundInlineArrayAccess.Expression.Type.HasInlineArrayAttribute(out var length)) { ConstantValue constantValueOpt = boundInlineArrayAccess.Argument.ConstantValueOpt; if (constantValueOpt == null || (int)constantValueOpt.SpecialType != 13 || constantValueOpt.Int32Value != 0) { SyntaxNode location; int? num = Binder.InferConstantIndexFromSystemIndex(compilation, boundInlineArrayAccess.Argument, length, out location); if ((num ?? 1) != 0) { goto IL_022c; } } int num2 = MakeMemberSlot(boundInlineArrayAccess.Expression, boundInlineArrayAccess.Expression.Type.TryGetInlineArrayElementField()); if (num2 > 0) { SetSlotState(num2, written); break; } } goto IL_022c; } case BoundKind.Parameter: { BoundParameter boundParameter = (BoundParameter)node; ParameterSymbol parameterSymbol = boundParameter.ParameterSymbol; if (isRef && (int)parameterSymbol.RefKind == 2) { LeaveParameter(parameterSymbol, node.Syntax, boundParameter.Syntax.Location); } int slot4 = MakeSlot(boundParameter); SetSlotState(slot4, written); if (written) { NoteWrite(boundParameter, value, read); } break; } case BoundKind.ThisReference: case BoundKind.FieldAccess: case BoundKind.PropertyAccess: case BoundKind.EventAccess: { BoundExpression boundExpression = (BoundExpression)node; int slot3 = MakeSlot(boundExpression); SetSlotState(slot3, written); if (written) { NoteWrite(boundExpression, value, read); } break; } case BoundKind.RangeVariable: AssignImpl(((BoundRangeVariable)node).Value, value, isRef, written, read); break; case BoundKind.BadExpression: { BoundBadExpression boundBadExpression = (BoundBadExpression)node; if (!boundBadExpression.ChildBoundNodes.IsDefault && boundBadExpression.ChildBoundNodes.Length == 1) { AssignImpl(boundBadExpression.ChildBoundNodes[0], value, isRef, written, read); } break; } case BoundKind.TupleLiteral: case BoundKind.ConvertedTupleLiteral: { ((BoundTupleExpression)node).VisitAllElements(delegate(BoundExpression x, (DefiniteAssignmentPass self, bool isRef) arg) { arg.self.Assign(x, null, arg.isRef); }, (this, isRef)); break; } IL_022c: if (!written) { AssignImpl(boundInlineArrayAccess.Expression, null, isRef, written, read); int slot2 = MakeSlot(boundInlineArrayAccess.Expression); SetSlotState(slot2, written); } break; } } private bool FieldsAllSet(int containingSlot, LocalState state) { TypeSymbol type = variableBySlot[containingSlot].Symbol.GetTypeOrReturnType().Type; if (type.HasInlineArrayAttribute(out var length) && length > 1 && (object)type.TryGetPossiblyUnsupportedByLanguageInlineArrayElementField() != null) { return false; } foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type)) { if (!_emptyStructTypeCache.IsEmptyStructType(structInstanceField.Type) && !(structInstanceField is TupleErrorFieldSymbol)) { int num = VariableSlot(structInstanceField, containingSlot); if (num == -1 || !state.IsAssigned(num)) { return false; } } } return true; } protected void SetSlotState(int slot, bool assigned) { if (slot > 0) { if (assigned) { SetSlotAssigned(slot); } else { SetSlotUnassigned(slot); } } } protected void SetSlotAssigned(int slot, ref LocalState state) { if (slot < 0) { return; } LocalDataFlowPass.VariableIdentifier variableIdentifier = variableBySlot[slot]; TypeSymbol type = variableIdentifier.Symbol.GetTypeOrReturnType().Type; if (slot >= ((BitVector)(ref state.Assigned)).Capacity) { Normalize(ref state); } if (state.IsAssigned(slot)) { return; } state.Assign(slot); if (EmptyStructTypeCache.IsTrackableStructType(type)) { foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type)) { int num = VariableSlot(structInstanceField, slot); if (num > 0) { SetSlotAssigned(num, ref state); } } } while (variableIdentifier.ContainingSlot > 0) { slot = variableIdentifier.ContainingSlot; if (!state.IsAssigned(slot) && FieldsAllSet(slot, state)) { state.Assign(slot); variableIdentifier = variableBySlot[slot]; continue; } break; } } private void SetSlotAssigned(int slot) { SetSlotAssigned(slot, ref State); } private void SetSlotUnassigned(int slot, ref LocalState state) { if (slot < 0) { return; } LocalDataFlowPass.VariableIdentifier variableIdentifier = variableBySlot[slot]; TypeSymbol type = variableIdentifier.Symbol.GetTypeOrReturnType().Type; if (!state.IsAssigned(slot)) { return; } state.Unassign(slot); if (EmptyStructTypeCache.IsTrackableStructType(type)) { foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type)) { int num = VariableSlot(structInstanceField, slot); if (num > 0) { SetSlotUnassigned(num, ref state); } } } while (variableIdentifier.ContainingSlot > 0) { slot = variableIdentifier.ContainingSlot; state.Unassign(slot); variableIdentifier = variableBySlot[slot]; } } private void SetSlotUnassigned(int slot) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (NonMonotonicState.HasValue) { LocalState state = NonMonotonicState.Value; SetSlotUnassigned(slot, ref state); NonMonotonicState = Optional.op_Implicit(state); } SetSlotUnassigned(slot, ref State); } protected override LocalState TopState() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Invalid comparison between Unknown and I4 //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Invalid comparison between Unknown and I4 //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Invalid comparison between Unknown and I4 //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Invalid comparison between Unknown and I4 LocalState state = new LocalState(BitVector.Empty); Symbol symbol = CurrentSymbol; while (true) { SymbolKind? val = symbol?.Kind; bool flag; if (val.HasValue) { SymbolKind valueOrDefault = val.GetValueOrDefault(); if ((int)valueOrDefault == 6 || (int)valueOrDefault == 9 || (int)valueOrDefault == 15) { flag = true; goto IL_0172; } } flag = false; goto IL_0172; IL_0172: if (!flag) { break; } if ((object)symbol != CurrentSymbol && symbol is MethodSymbol { Parameters: var parameters } methodSymbol) { ImmutableArray.Enumerator enumerator = parameters.GetEnumerator(); while (enumerator.MoveNext()) { ParameterSymbol current = enumerator.Current; int orCreateSlot = GetOrCreateSlot(current); if (orCreateSlot > 0) { SetSlotAssigned(orCreateSlot, ref state); } } if (methodSymbol.TryGetThisParameter(out var thisParameter) && (object)thisParameter != null) { int orCreateSlot2 = GetOrCreateSlot(thisParameter); if (orCreateSlot2 > 0) { SetSlotAssigned(orCreateSlot2, ref state); } } } Symbol containingSymbol = symbol.ContainingSymbol; if (!symbol.IsStatic && containingSymbol is SourceMemberContainerTypeSymbol sourceMemberContainerTypeSymbol) { SynthesizedPrimaryConstructor primaryConstructor = sourceMemberContainerTypeSymbol.PrimaryConstructor; if ((object)primaryConstructor != null && (object)symbol != primaryConstructor) { ImmutableArray.Enumerator enumerator = primaryConstructor.Parameters.GetEnumerator(); while (enumerator.MoveNext()) { ParameterSymbol current2 = enumerator.Current; int orCreateSlot3 = GetOrCreateSlot(current2); if (orCreateSlot3 > 0) { if (!(symbol is MethodSymbol) && (int)current2.RefKind == 2) { SetSlotUnassigned(orCreateSlot3, ref state); } else { SetSlotAssigned(orCreateSlot3, ref state); } } } break; } } symbol = containingSymbol; } return state; } protected override LocalState ReachableBottomState() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) LocalState result = new LocalState(BitVector.AllSet(variableBySlot.Count)); ((BitVector)(ref result.Assigned))[0] = false; return result; } protected override void EnterParameter(ParameterSymbol parameter) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 int orCreateSlot = GetOrCreateSlot(parameter); if ((int)parameter.RefKind == 2 && !(CurrentSymbol is MethodSymbol { IsAsync: not false })) { if (orCreateSlot > 0) { SetSlotState(orCreateSlot, initiallyAssignedVariables?.Contains(parameter) ?? false); } } else { if (orCreateSlot > 0) { SetSlotState(orCreateSlot, assigned: true); } NoteWrite(parameter, null, read: true); } SourceComplexParameterSymbolBase sourceComplexParameterSymbolBase = parameter as SourceComplexParameterSymbolBase; bool flag; if ((object)sourceComplexParameterSymbolBase != null) { Symbol containingSymbol = sourceComplexParameterSymbolBase.ContainingSymbol; if (containingSymbol is LocalFunctionSymbol || containingSymbol is LambdaSymbol) { flag = true; goto IL_0089; } } flag = false; goto IL_0089; IL_0089: if (flag) { VisitAttributes(sourceComplexParameterSymbolBase.BindParameterAttributes()); BoundParameterEqualsValue boundParameterEqualsValue = sourceComplexParameterSymbolBase.BindParameterEqualsValue(); if (boundParameterEqualsValue != null) { VisitRvalue(boundParameterEqualsValue.Value); } } } private void VisitAttributes(ImmutableArray<(CSharpAttributeData, BoundAttribute)> boundAttributes) { if (boundAttributes.IsDefaultOrEmpty) { return; } ImmutableArray<(CSharpAttributeData, BoundAttribute)>.Enumerator enumerator = boundAttributes.GetEnumerator(); while (enumerator.MoveNext()) { var (cSharpAttributeData, boundAttribute) = enumerator.Current; if (!((AttributeData)cSharpAttributeData).HasErrors) { ImmutableArray.Enumerator enumerator2 = boundAttribute.ConstructorArguments.GetEnumerator(); while (enumerator2.MoveNext()) { BoundExpression current = enumerator2.Current; VisitRvalue(current); } ImmutableArray.Enumerator enumerator3 = boundAttribute.NamedArguments.GetEnumerator(); while (enumerator3.MoveNext()) { BoundAssignmentOperator current2 = enumerator3.Current; VisitRvalue(current2.Right); } } } } protected override void LeaveParameters(ImmutableArray parameters, SyntaxNode syntax, Location location) { if (State.Reachable) { base.LeaveParameters(parameters, syntax, location); } } protected override void LeaveParameter(ParameterSymbol parameter, SyntaxNode syntax, Location location) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if (!parameter.IsThis && (int)parameter.RefKind != 2 && parameter.ContainingSymbol is SynthesizedPrimaryConstructor synthesizedPrimaryConstructor) { PooledHashSet? readParameters = _readParameters; if ((readParameters == null || !((HashSet)(object)readParameters).Contains(parameter)) && !synthesizedPrimaryConstructor.GetCapturedParameters().ContainsKey(parameter)) { DiagnosticBag diagnostics = base.Diagnostics; SourceMemberContainerTypeSymbol containingType = synthesizedPrimaryConstructor.ContainingType; bool flag = (((object)containingType != null && (containingType.IsRecord || containingType.IsRecordStruct)) ? true : false); diagnostics.Add(flag ? ErrorCode.WRN_UnreadRecordParameter : ErrorCode.WRN_UnreadPrimaryConstructorParameter, parameter.GetFirstLocationOrNone(), parameter.Name); } } if ((int)parameter.RefKind != 0) { int num = VariableSlot(parameter); if (num > 0 && !State.IsAssigned(num)) { ReportUnassignedOutParameter(parameter, syntax, location); } NoteRead(parameter); } } protected override LocalState UnreachableState() { LocalState result = State.Clone(); ((BitVector)(ref result.Assigned)).EnsureCapacity(1); result.Assign(0); return result; } public override void VisitPattern(BoundPattern pattern) { base.VisitPattern(pattern); LocalState stateWhenFalse = StateWhenFalse; SetState(StateWhenTrue); assignPatternVariablesAndMarkReadFields(pattern); SetConditionalState(State, stateWhenFalse); void assignPatternVariablesAndMarkReadFields(BoundPattern boundPattern, bool definitely = true) { switch (boundPattern.Kind) { case BoundKind.DeclarationPattern: { BoundDeclarationPattern node = (BoundDeclarationPattern)boundPattern; if (definitely) { Assign(node, null, isRef: false, read: false); } break; } case BoundKind.SlicePattern: { BoundSlicePattern boundSlicePattern = (BoundSlicePattern)boundPattern; if (boundSlicePattern.Pattern != null) { assignPatternVariablesAndMarkReadFields(boundSlicePattern.Pattern, definitely); } break; } case BoundKind.ConstantPattern: { BoundConstantPattern boundConstantPattern = (BoundConstantPattern)boundPattern; VisitRvalue(boundConstantPattern.Value); break; } case BoundKind.RecursivePattern: { BoundRecursivePattern boundRecursivePattern = (BoundRecursivePattern)boundPattern; if (!boundRecursivePattern.Deconstruction.IsDefaultOrEmpty) { ImmutableArray.Enumerator enumerator = boundRecursivePattern.Deconstruction.GetEnumerator(); while (enumerator.MoveNext()) { BoundPositionalSubpattern current3 = enumerator.Current; assignPatternVariablesAndMarkReadFields(current3.Pattern, definitely); } } if (!boundRecursivePattern.Properties.IsDefaultOrEmpty) { ImmutableArray.Enumerator enumerator3 = boundRecursivePattern.Properties.GetEnumerator(); while (enumerator3.MoveNext()) { BoundPropertySubpattern current4 = enumerator3.Current; if ((object)_sourceAssembly != null) { for (BoundPropertySubpatternMember boundPropertySubpatternMember = current4.Member; boundPropertySubpatternMember != null; boundPropertySubpatternMember = boundPropertySubpatternMember.Receiver) { if (boundPropertySubpatternMember.Symbol is FieldSymbol field) { _sourceAssembly.NoteFieldAccess(field, read: true, write: false); } } } assignPatternVariablesAndMarkReadFields(current4.Pattern, definitely); } } if (definitely) { Assign(boundRecursivePattern, null, isRef: false, read: false); } break; } case BoundKind.ITuplePattern: { ImmutableArray.Enumerator enumerator = ((BoundITuplePattern)boundPattern).Subpatterns.GetEnumerator(); while (enumerator.MoveNext()) { BoundPositionalSubpattern current = enumerator.Current; assignPatternVariablesAndMarkReadFields(current.Pattern, definitely); } break; } case BoundKind.ListPattern: { BoundListPattern boundListPattern = (BoundListPattern)boundPattern; ImmutableArray.Enumerator enumerator2 = boundListPattern.Subpatterns.GetEnumerator(); while (enumerator2.MoveNext()) { BoundPattern current2 = enumerator2.Current; assignPatternVariablesAndMarkReadFields(current2, definitely); } if (definitely) { Assign(boundListPattern, null, isRef: false, read: false); } break; } case BoundKind.RelationalPattern: { BoundRelationalPattern boundRelationalPattern = (BoundRelationalPattern)boundPattern; VisitRvalue(boundRelationalPattern.Value); break; } case BoundKind.NegatedPattern: { BoundNegatedPattern boundNegatedPattern = (BoundNegatedPattern)boundPattern; assignPatternVariablesAndMarkReadFields(boundNegatedPattern.Negated, definitely: false); break; } case BoundKind.BinaryPattern: { BoundBinaryPattern boundBinaryPattern = (BoundBinaryPattern)boundPattern; bool definitely2 = definitely && !boundBinaryPattern.Disjunction; assignPatternVariablesAndMarkReadFields(boundBinaryPattern.Left, definitely2); assignPatternVariablesAndMarkReadFields(boundBinaryPattern.Right, definitely2); break; } default: throw ExceptionUtilities.UnexpectedValue((object)boundPattern.Kind); case BoundKind.DiscardPattern: case BoundKind.TypePattern: break; } } } public override BoundNode VisitBlock(BoundBlock node) { if (node.Instrumentation != null) { DeclareVariable(node.Instrumentation.Local); Visit(node.Instrumentation.Prologue); } DeclareVariables(node.Locals); VisitStatementsWithLocalFunctions(node); ImmutableArray.Enumerator enumerator = node.Locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; if (current.IsUsing) { NoteRead(current); } } ReportUnusedVariables(node.Locals); ReportUnusedVariables(node.LocalFunctions); if (node.Instrumentation != null) { Visit(node.Instrumentation.Epilogue); } return null; } private void VisitStatementsWithLocalFunctions(BoundBlock block) { if (!TrackingRegions && !block.LocalFunctions.IsDefaultOrEmpty) { ImmutableArray.Enumerator enumerator = block.Statements.GetEnumerator(); while (enumerator.MoveNext()) { BoundStatement current = enumerator.Current; if (current is BoundLocalFunctionStatement boundLocalFunctionStatement) { VisitAttributes(boundLocalFunctionStatement.Symbol.BindMethodAttributes()); VisitAlways(current); } } enumerator = block.Statements.GetEnumerator(); while (enumerator.MoveNext()) { BoundStatement current2 = enumerator.Current; if (current2.Kind != BoundKind.LocalFunctionStatement) { VisitStatement(current2); } } } else { ImmutableArray.Enumerator enumerator = block.Statements.GetEnumerator(); while (enumerator.MoveNext()) { BoundStatement current3 = enumerator.Current; VisitStatement(current3); } } } public override BoundNode VisitSwitchStatement(BoundSwitchStatement node) { DeclareVariables(node.InnerLocals); BoundNode result = base.VisitSwitchStatement(node); ReportUnusedVariables(node.InnerLocals); ReportUnusedVariables(node.InnerLocalFunctions); return result; } protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection) { DeclareVariables(node.Locals); base.VisitSwitchSection(node, isLastSection); } public override BoundNode VisitForStatement(BoundForStatement node) { DeclareVariables(node.OuterLocals); DeclareVariables(node.InnerLocals); BoundNode result = base.VisitForStatement(node); ReportUnusedVariables(node.InnerLocals); ReportUnusedVariables(node.OuterLocals); return result; } public override BoundNode VisitDoStatement(BoundDoStatement node) { DeclareVariables(node.Locals); BoundNode result = base.VisitDoStatement(node); ReportUnusedVariables(node.Locals); return result; } public override BoundNode VisitWhileStatement(BoundWhileStatement node) { DeclareVariables(node.Locals); BoundNode result = base.VisitWhileStatement(node); ReportUnusedVariables(node.Locals); return result; } public override BoundNode VisitUsingStatement(BoundUsingStatement node) { ImmutableArray locals = node.Locals; DeclareVariables(locals); BoundNode result = base.VisitUsingStatement(node); if (!locals.IsDefaultOrEmpty) { ImmutableArray.Enumerator enumerator = locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; if (current.DeclarationKind == LocalDeclarationKind.UsingVariable) { NoteRead(current); } } } return result; } public override BoundNode VisitFixedStatement(BoundFixedStatement node) { DeclareVariables(node.Locals); return base.VisitFixedStatement(node); } public override BoundNode VisitSequence(BoundSequence node) { DeclareVariables(node.Locals); BoundNode result = base.VisitSequence(node); ReportUnusedVariables(node.Locals); return result; } private void DeclareVariables(ImmutableArray locals) { ImmutableArray.Enumerator enumerator = locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; DeclareVariable(current); } } private void DeclareVariable(LocalSymbol symbol) { bool assigned = symbol.IsConst || (initiallyAssignedVariables?.Contains(symbol) ?? false); SetSlotState(GetOrCreateSlot(symbol), assigned); } private void ReportUnusedVariables(ImmutableArray locals) { ImmutableArray.Enumerator enumerator = locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; ReportIfUnused(current, assigned: true); } } private void ReportIfUnused(LocalSymbol symbol, bool assigned) { if (!((HashSet)(object)_usedVariables).Contains(symbol) && symbol.DeclarationKind != LocalDeclarationKind.PatternVariable && !string.IsNullOrEmpty(symbol.Name)) { base.Diagnostics.Add((assigned && ((HashSet)(object)_writtenVariables).Contains((Symbol)symbol)) ? ErrorCode.WRN_UnreferencedVarAssg : ErrorCode.WRN_UnreferencedVar, symbol.GetFirstLocationOrNone(), symbol.Name); } } private void ReportUnusedVariables(ImmutableArray locals) { ImmutableArray.Enumerator enumerator = locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalFunctionSymbol current = enumerator.Current; ReportIfUnused(current); } } private void ReportIfUnused(LocalFunctionSymbol symbol) { if (!((HashSet)(object)_usedLocalFunctions).Contains(symbol) && !string.IsNullOrEmpty(symbol.Name)) { base.Diagnostics.Add(ErrorCode.WRN_UnreferencedLocalFunction, symbol.GetFirstLocationOrNone(), symbol.Name); } } public override BoundNode VisitLocal(BoundLocal node) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown LocalSymbol localSymbol = node.LocalSymbol; SourceLocalSymbol obj = localSymbol as SourceLocalSymbol; if ((object)obj != null && obj.IsVar) { SyntaxNode forbiddenZone = localSymbol.ForbiddenZone; if (forbiddenZone != null && forbiddenZone.Contains(node.Syntax)) { int orCreateSlot = GetOrCreateSlot(node.LocalSymbol); if (orCreateSlot > 0) { ((BitVector)(ref _alreadyReported))[orCreateSlot] = true; } } } CheckAssigned(localSymbol, node.Syntax); if (localSymbol.IsFixed && CurrentSymbol is MethodSymbol methodSymbol && ((int)methodSymbol.MethodKind == 0 || (int)methodSymbol.MethodKind == 17) && ((HashSet)(object)_capturedVariables).Contains((Symbol)localSymbol)) { base.Diagnostics.Add(ErrorCode.ERR_FixedLocalInLambda, (Location)new SourceLocation(node.Syntax), localSymbol); } SplitIfBooleanConstant(node); return null; } public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node) { GetOrCreateSlot(node.LocalSymbol); HashSet? hashSet = initiallyAssignedVariables; if (hashSet != null && hashSet.Contains(node.LocalSymbol)) { Assign(node, null); } BoundNode result = base.VisitLocalDeclaration(node); if (node.InitializerOpt != null) { Assign(node, node.InitializerOpt); } return result; } public override BoundNode VisitLocalId(BoundLocalId node) { return null; } public override BoundNode VisitParameterId(BoundParameterId node) { return null; } public override BoundNode VisitStateMachineInstanceId(BoundStateMachineInstanceId node) { return null; } public override BoundNode VisitMethodGroup(BoundMethodGroup node) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 ImmutableArray.Enumerator enumerator = node.Methods.GetEnumerator(); while (enumerator.MoveNext()) { MethodSymbol current = enumerator.Current; if ((int)current.MethodKind == 17) { ((HashSet)(object)_usedLocalFunctions).Add((LocalFunctionSymbol)current); } } return base.VisitMethodGroup(node); } public override BoundNode VisitLambda(BoundLambda node) { Symbol currentSymbol = CurrentSymbol; CurrentSymbol = node.Symbol; VisitAttributes(node.Symbol.BindMethodAttributes()); AbstractFlowPass.SavedPending oldPending = SavePending(); LocalState self = State; State = (State.Reachable ? State.Clone() : ReachableBottomState()); if (!node.WasCompilerGenerated) { EnterParameters(node.Symbol.Parameters); } AbstractFlowPass.SavedPending oldPending2 = SavePending(); VisitAlways(node.Body); RestorePending(oldPending2); ImmutableArray.PendingBranch> immutableArray = RemoveReturns(); RestorePending(oldPending); LeaveParameters(node.Symbol.Parameters, node.Syntax, null); Join(ref self, ref State); ImmutableArray.PendingBranch>.Enumerator enumerator = immutableArray.GetEnumerator(); while (enumerator.MoveNext()) { AbstractFlowPass.PendingBranch current = enumerator.Current; State = current.State; if (current.Branch.Kind == BoundKind.ReturnStatement) { LeaveParameters(node.Symbol.Parameters, current.Branch.Syntax, null); } Join(ref self, ref State); } State = self; CurrentSymbol = currentSymbol; return null; } public override BoundNode VisitThisReference(BoundThisReference node) { CheckAssigned(base.MethodThisParameter, node.Syntax); return null; } public override BoundNode VisitParameter(BoundParameter node) { if (!node.WasCompilerGenerated) { CheckAssigned(node.ParameterSymbol, node.Syntax); } else { NotePrimaryConstructorParameterReadIfNeeded(node.ParameterSymbol); } return null; } public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) { base.VisitAssignmentOperator(node); Assign(node.Left, node.Right, node.IsRef); return null; } public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node) { base.VisitDeconstructionAssignmentOperator(node); Assign(node.Left, node.Right); return null; } public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) { base.VisitIncrementOperator(node); Assign(node.Operand, node); return null; } public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmentOperator node) { VisitCompoundAssignmentTarget(node); VisitRvalue(node.Right); AfterRightHasBeenVisited(node); Assign(node.Left, node); return null; } public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCollectionInitializer node) { BoundExpression boundExpression = node.Expression; if (boundExpression.Kind == BoundKind.AddressOfOperator) { boundExpression = ((BoundAddressOfOperator)boundExpression).Operand; } VisitAddressOfOperand(boundExpression, shouldReadOperand: false); return null; } public override BoundNode VisitAddressOfOperator(BoundAddressOfOperator node) { BoundExpression operand = node.Operand; bool shouldReadOperand = false; Symbol symbol = UseNonFieldSymbolUnsafely(operand); if ((object)symbol != null) { HashSet? unassignedVariableAddressOfSyntaxes = _unassignedVariableAddressOfSyntaxes; if (unassignedVariableAddressOfSyntaxes != null && !unassignedVariableAddressOfSyntaxes.Contains(node.Syntax as PrefixUnaryExpressionSyntax)) { shouldReadOperand = true; } if (!((Dictionary)(object)_unsafeAddressTakenVariables).ContainsKey(symbol)) { ((Dictionary)(object)_unsafeAddressTakenVariables).Add(symbol, node.Syntax.Location); } } VisitAddressOfOperand(node.Operand, shouldReadOperand); return null; } 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 //IL_001b: Unknown result type (might be due to invalid IL or missing references) if ((int)refKind == 1) { CheckAssigned(arg, arg.Syntax); } Assign(arg, null); if ((int)refKind != 0 && ((object)method == null || method.IsExtern)) { TypeSymbol type = arg.Type; if ((object)type != null) { MarkFieldsUsed(type); } } } protected void CheckAssigned(BoundExpression expr, SyntaxNode node) { if (!State.Reachable) { return; } MakeSlot(expr); switch (expr.Kind) { case BoundKind.Local: CheckAssigned(((BoundLocal)expr).LocalSymbol, node); break; case BoundKind.Parameter: CheckAssigned(((BoundParameter)expr).ParameterSymbol, node); break; case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)expr; FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol; if (!fieldSymbol.IsFixedSizeBuffer && MayRequireTracking(boundFieldAccess.ReceiverOpt, fieldSymbol)) { CheckAssigned(expr, fieldSymbol, node); } break; } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)expr; FieldSymbol associatedField = boundEventAccess.EventSymbol.AssociatedField; if ((object)associatedField != null && MayRequireTracking(boundEventAccess.ReceiverOpt, associatedField)) { CheckAssigned(boundEventAccess, associatedField, node); } break; } case BoundKind.ThisReference: case BoundKind.BaseReference: CheckAssigned(base.MethodThisParameter, node); break; case BoundKind.InlineArrayAccess: CheckAssigned(((BoundInlineArrayAccess)expr).Expression, node); break; } } private void MarkFieldsUsed(TypeSymbol type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 TypeKind typeKind = type.TypeKind; if ((int)typeKind != 1) { if (((int)typeKind != 2 && (int)typeKind != 10) || !type.IsFromCompilation(compilation) || !(type.ContainingAssembly is SourceAssemblySymbol sourceAssemblySymbol) || !sourceAssemblySymbol.TypesReferencedInExternalMethods.Add(type)) { return; } ImmutableArray.Enumerator enumerator = ((NamedTypeSymbol)type).GetMembersUnordered().GetEnumerator(); while (enumerator.MoveNext()) { Symbol current = enumerator.Current; if ((int)current.Kind == 6) { FieldSymbol fieldSymbol = (FieldSymbol)current; sourceAssemblySymbol.NoteFieldAccess(fieldSymbol, read: true, write: true); MarkFieldsUsed(fieldSymbol.Type); } } } else { MarkFieldsUsed(((ArrayTypeSymbol)type).ElementType); } } public override BoundNode VisitBaseReference(BoundBaseReference node) { CheckAssigned(base.MethodThisParameter, node.Syntax); return null; } protected override void VisitCatchBlock(BoundCatchBlock catchBlock, ref LocalState finallyState) { DeclareVariables(catchBlock.Locals); BoundExpression exceptionSourceOpt = catchBlock.ExceptionSourceOpt; if (exceptionSourceOpt != null) { Assign(exceptionSourceOpt, null, isRef: false, read: false); } base.VisitCatchBlock(catchBlock, ref finallyState); ImmutableArray.Enumerator enumerator = catchBlock.Locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; ReportIfUnused(current, current.DeclarationKind != LocalDeclarationKind.CatchVariable); } } public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundNode result = base.VisitFieldAccess(node); NoteRead(node.FieldSymbol); if (node.FieldSymbol.IsFixedSizeBuffer && node.Syntax != null && !SyntaxFacts.IsFixedStatementExpression(node.Syntax)) { Symbol symbol = UseNonFieldSymbolUnsafely(node.ReceiverOpt); if ((object)symbol != null) { CheckCaptured(symbol); if (!((Dictionary)(object)_unsafeAddressTakenVariables).ContainsKey(symbol)) { ((Dictionary)(object)_unsafeAddressTakenVariables).Add(symbol, node.Syntax.Location); return result; } } } else if (MayRequireTracking(node.ReceiverOpt, node.FieldSymbol)) { CheckAssigned(node, node.FieldSymbol, node.Syntax); } return result; } public override BoundNode VisitPropertyAccess(BoundPropertyAccess node) { BoundNode result = base.VisitPropertyAccess(node); if (Binder.AccessingAutoPropertyFromConstructor(node, CurrentSymbol)) { SynthesizedBackingFieldSymbol synthesizedBackingFieldSymbol = (node.PropertySymbol as SourcePropertySymbolBase)?.BackingField; if (synthesizedBackingFieldSymbol != null && MayRequireTracking(node.ReceiverOpt, synthesizedBackingFieldSymbol) && State.Reachable && !IsAssigned(node, out var unassignedSlot)) { ReportUnassignedIfNotCapturedInLocalFunction(synthesizedBackingFieldSymbol, node.Syntax, unassignedSlot); } } return result; } public override BoundNode VisitEventAccess(BoundEventAccess node) { BoundNode result = base.VisitEventAccess(node); FieldSymbol associatedField = node.EventSymbol.AssociatedField; if ((object)associatedField != null) { NoteRead(associatedField); if (MayRequireTracking(node.ReceiverOpt, associatedField)) { CheckAssigned(node, associatedField, node.Syntax); } } return result; } public override void VisitForEachIterationVariables(BoundForEachStatement node) { ImmutableArray.Enumerator enumerator = node.IterationVariables.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; int orCreateSlot = GetOrCreateSlot(current); if (orCreateSlot > 0) { SetSlotAssigned(orCreateSlot); } NoteWrite(current, null, read: true); } } public override BoundNode VisitObjectInitializerMember(BoundObjectInitializerMember node) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 BoundNode result = base.VisitObjectInitializerMember(node); if ((object)_sourceAssembly != null && node.MemberSymbol != null && (int)node.MemberSymbol.Kind == 6) { _sourceAssembly.NoteFieldAccess((FieldSymbol)node.MemberSymbol.OriginalDefinition, read: false, write: true); } return result; } public override BoundNode VisitDynamicObjectInitializerMember(BoundDynamicObjectInitializerMember node) { return null; } protected override void VisitAssignmentOfNullCoalescingAssignment(BoundNullCoalescingAssignmentOperator node, BoundPropertyAccess propertyAccessOpt) { base.VisitAssignmentOfNullCoalescingAssignment(node, propertyAccessOpt); Assign(node.LeftOperand, node.RightOperand); } protected override void AdjustStateForNullCoalescingAssignmentNonNullCase(BoundNullCoalescingAssignmentOperator node) { Assign(node.LeftOperand, node.LeftOperand); } protected override void AfterVisitInlineArrayAccess(BoundInlineArrayAccess node) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)node.GetItemOrSliceHelper == 402) { NoteWrite(node.Expression, null, read: false); } } protected override void AfterVisitConversion(BoundConversion node) { if (node.Conversion.IsInlineArray && node.Type.OriginalDefinition.Equals(compilation.GetWellKnownType((WellKnownType)275), (TypeCompareKind)63)) { NoteWrite(node.Operand, null, read: false); } } protected override string Dump(LocalState state) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[assigned "); AppendBitNames(state.Assigned, stringBuilder); stringBuilder.Append("]"); return stringBuilder.ToString(); } protected void AppendBitNames(BitVector a, StringBuilder builder) { bool flag = false; foreach (int item in ((BitVector)(ref a)).TrueBits()) { if (flag) { builder.Append(", "); } flag = true; AppendBitName(item, builder); } } protected void AppendBitName(int bit, StringBuilder builder) { LocalDataFlowPass.VariableIdentifier variableIdentifier = variableBySlot[bit]; if (variableIdentifier.ContainingSlot > 0) { AppendBitName(variableIdentifier.ContainingSlot, builder); builder.Append("."); } builder.Append((bit == 0) ? "" : (string.IsNullOrEmpty(variableIdentifier.Symbol.Name) ? ("" + variableIdentifier.Symbol.GetHashCode()) : variableIdentifier.Symbol.Name)); } protected override bool Meet(ref LocalState self, ref LocalState other) { if (((BitVector)(ref self.Assigned)).Capacity != ((BitVector)(ref other.Assigned)).Capacity) { Normalize(ref self); Normalize(ref other); } if (!other.Reachable) { ((BitVector)(ref self.Assigned))[0] = true; return true; } bool result = false; for (int i = 1; i < ((BitVector)(ref self.Assigned)).Capacity; i++) { if (((BitVector)(ref other.Assigned))[i] && !((BitVector)(ref self.Assigned))[i]) { SetSlotAssigned(i, ref self); result = true; } } return result; } protected override bool Join(ref LocalState self, ref LocalState other) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (self.Reachable == other.Reachable) { if (((BitVector)(ref self.Assigned)).Capacity != ((BitVector)(ref other.Assigned)).Capacity) { Normalize(ref self); Normalize(ref other); } return ((BitVector)(ref self.Assigned)).IntersectWith(ref other.Assigned); } if (!self.Reachable) { self.Assigned = ((BitVector)(ref other.Assigned)).Clone(); return true; } return false; } protected override LocalFunctionState CreateLocalFunctionState(LocalFunctionSymbol symbol) { return CreateLocalFunctionState(); } private LocalFunctionState CreateLocalFunctionState() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return new LocalFunctionState(new LocalState(BitVector.AllSet(variableBySlot.Count), normalizeToBottom: true), UnreachableState()); } protected override void VisitLocalFunctionUse(LocalFunctionSymbol localFunc, LocalFunctionState localFunctionState, SyntaxNode syntax, bool isCall) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ((HashSet)(object)_usedLocalFunctions).Add(localFunc); BitVector readVars = localFunctionState.ReadVars; for (int i = 1; i < ((BitVector)(ref readVars)).Capacity; i++) { if (((BitVector)(ref readVars))[i]) { Symbol symbol = variableBySlot[i].Symbol; CheckIfAssignedDuringLocalFunctionReplay(symbol, syntax, i); } } base.VisitLocalFunctionUse(localFunc, localFunctionState, syntax, isCall); } private void CheckIfAssignedDuringLocalFunctionReplay(Symbol symbol, SyntaxNode node, int slot) { if ((object)symbol == null) { return; } NoteRead(symbol); if (State.Reachable) { if (slot >= ((BitVector)(ref State.Assigned)).Capacity) { Normalize(ref State); } if (slot > 0 && !State.IsAssigned(slot)) { ReportUnassignedIfNotCapturedInLocalFunction(symbol, node, slot, skipIfUseBeforeDeclaration: false); } } } private void RecordReadInLocalFunction(int slot) { LocalFunctionSymbol nearestLocalFunctionOpt = GetNearestLocalFunctionOpt(CurrentSymbol); LocalFunctionState orCreateLocalFuncUsages = GetOrCreateLocalFuncUsages(nearestLocalFunctionOpt); TypeSymbol type = variableBySlot[slot].Symbol.GetTypeOrReturnType().Type; if (EmptyStructTypeCache.IsTrackableStructType(type)) { foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type)) { int orCreateSlot = GetOrCreateSlot(structInstanceField, slot); if (orCreateSlot > 0 && !State.IsAssigned(orCreateSlot)) { RecordReadInLocalFunction(orCreateSlot); } } return; } ((BitVector)(ref orCreateLocalFuncUsages.ReadVars))[slot] = true; } private BitVector GetCapturedBitmask() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) int count = variableBySlot.Count; BitVector result = BitVector.AllSet(count); for (int i = 1; i < count; i++) { ((BitVector)(ref result))[i] = IsCapturedInLocalFunction(i); } return result; } private bool IsCapturedInLocalFunction(int slot) { if (slot <= 0) { return false; } Symbol symbol = variableBySlot[RootSlot(slot)].Symbol; LocalFunctionSymbol nearestLocalFunctionOpt = GetNearestLocalFunctionOpt(CurrentSymbol); if ((object)nearestLocalFunctionOpt != null) { return Symbol.IsCaptured(symbol, nearestLocalFunctionOpt); } return false; } private static LocalFunctionSymbol GetNearestLocalFunctionOpt(Symbol symbol) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 while (symbol != null) { if ((int)symbol.Kind == 9 && (int)((MethodSymbol)symbol).MethodKind == 17) { return (LocalFunctionSymbol)symbol; } symbol = symbol.ContainingSymbol; } return null; } protected override LocalFunctionState LocalFunctionStart(LocalFunctionState startState) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) LocalFunctionState localFunctionState = CreateLocalFunctionState(); localFunctionState.ReadVars = ((BitVector)(ref startState.ReadVars)).Clone(); ((BitVector)(ref startState.ReadVars)).Clear(); return localFunctionState; } protected override bool LocalFunctionEnd(LocalFunctionState savedState, LocalFunctionState currentState, ref LocalState stateAtReturn) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (((BitVector)(ref currentState.CapturedMask)).IsNull) { currentState.CapturedMask = GetCapturedBitmask(); currentState.InvertedCapturedMask = ((BitVector)(ref currentState.CapturedMask)).Clone(); ((BitVector)(ref currentState.InvertedCapturedMask)).Invert(); } ((BitVector)(ref stateAtReturn.Assigned)).IntersectWith(ref currentState.CapturedMask); if (NonMonotonicState.HasValue) { LocalState value = NonMonotonicState.Value; ((BitVector)(ref value.Assigned)).UnionWith(ref currentState.InvertedCapturedMask); NonMonotonicState = Optional.op_Implicit(value); } BitVector readVars = currentState.ReadVars; ((BitVector)(ref readVars)).IntersectWith(ref currentState.CapturedMask); return ((BitVector)(ref savedState.ReadVars)).UnionWith(ref readVars); } }