using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using Microsoft.Cci; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp; internal sealed class RefSafetyAnalysis : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator { private enum EscapeLevel : uint { CallingMethod, ReturnOnly } private readonly struct MixableDestination { internal BoundExpression Argument { get; } internal ParameterSymbol? Parameter { get; } internal EscapeLevel EscapeLevel { get; } internal MixableDestination(ParameterSymbol parameter, BoundExpression argument) { Argument = argument; Parameter = parameter; EscapeLevel = GetParameterValEscapeLevel(parameter).Value; } internal MixableDestination(BoundExpression argument, EscapeLevel escapeLevel) { Argument = argument; Parameter = null; EscapeLevel = escapeLevel; } internal bool IsAssignableFrom(EscapeLevel level) { return EscapeLevel switch { EscapeLevel.CallingMethod => level == EscapeLevel.CallingMethod, EscapeLevel.ReturnOnly => true, _ => throw ExceptionUtilities.UnexpectedValue((object)EscapeLevel), }; } public override string? ToString() { return (Parameter, Argument, EscapeLevel).ToString(); } } private readonly struct EscapeArgument { internal ParameterSymbol? Parameter { get; } internal BoundExpression Argument { get; } internal RefKind RefKind { get; } internal EscapeArgument(ParameterSymbol? parameter, BoundExpression argument, RefKind refKind, bool isArgList = false) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Argument = argument; Parameter = parameter; RefKind = refKind; } public void Deconstruct(out ParameterSymbol? parameter, out BoundExpression argument, out RefKind refKind) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown parameter = Parameter; argument = Argument; refKind = (RefKind)(int)RefKind; } public override string? ToString() { ParameterSymbol parameter = Parameter; if ((object)parameter == null) { return Argument.ToString(); } return parameter.ToString(); } } private readonly struct EscapeValue { internal ParameterSymbol? Parameter { get; } internal BoundExpression Argument { get; } internal EscapeLevel EscapeLevel { get; } internal bool IsRefEscape { get; } internal EscapeValue(ParameterSymbol? parameter, BoundExpression argument, EscapeLevel escapeLevel, bool isRefEscape) { Argument = argument; Parameter = parameter; EscapeLevel = escapeLevel; IsRefEscape = isRefEscape; } public void Deconstruct(out ParameterSymbol? parameter, out BoundExpression argument, out EscapeLevel escapeLevel, out bool isRefEscape) { parameter = Parameter; argument = Argument; escapeLevel = EscapeLevel; isRefEscape = IsRefEscape; } public override string? ToString() { ParameterSymbol parameter = Parameter; if ((object)parameter == null) { return Argument.ToString(); } return parameter.ToString(); } } private ref struct LocalScope { private readonly RefSafetyAnalysis _analysis; private readonly ImmutableArray _locals; public LocalScope(RefSafetyAnalysis analysis, ImmutableArray locals) { _analysis = analysis; _locals = locals; _analysis._localScopeDepth++; ImmutableArray.Enumerator enumerator = locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; _analysis.AddLocalScopes(current, _analysis._localScopeDepth, 0u); } } public void Dispose() { ImmutableArray.Enumerator enumerator = _locals.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; _analysis.RemoveLocalScopes(current); } _analysis._localScopeDepth--; } } private ref struct UnsafeRegion { private readonly RefSafetyAnalysis _analysis; private readonly bool _previousRegion; public UnsafeRegion(RefSafetyAnalysis analysis, bool inUnsafeRegion) { _analysis = analysis; _previousRegion = analysis._inUnsafeRegion; _analysis._inUnsafeRegion = inUnsafeRegion; } public void Dispose() { _analysis._inUnsafeRegion = _previousRegion; } } private ref struct PatternInput { private readonly RefSafetyAnalysis _analysis; private readonly uint _previousInputValEscape; public PatternInput(RefSafetyAnalysis analysis, uint patternInputValEscape) { _analysis = analysis; _previousInputValEscape = analysis._patternInputValEscape; _analysis._patternInputValEscape = patternInputValEscape; } public void Dispose() { _analysis._patternInputValEscape = _previousInputValEscape; } } private ref struct PlaceholderRegion { private readonly RefSafetyAnalysis _analysis; private readonly ArrayBuilder<(BoundValuePlaceholderBase, uint)> _placeholders; public PlaceholderRegion(RefSafetyAnalysis analysis, ArrayBuilder<(BoundValuePlaceholderBase, uint)> placeholders) { //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) _analysis = analysis; _placeholders = placeholders; Enumerator<(BoundValuePlaceholderBase, uint)> enumerator = placeholders.GetEnumerator(); while (enumerator.MoveNext()) { var (placeholder, valEscapeScope) = enumerator.Current; _analysis.AddPlaceholderScope(placeholder, valEscapeScope); } } public void Dispose() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<(BoundValuePlaceholderBase, uint)> enumerator = _placeholders.GetEnumerator(); while (enumerator.MoveNext()) { BoundValuePlaceholderBase item = enumerator.Current.Item1; _analysis.RemovePlaceholderScope(item); } _placeholders.Free(); } } private readonly struct DeconstructionVariable { internal readonly BoundExpression Expression; internal readonly uint ValEscape; internal readonly ArrayBuilder? NestedVariables; internal DeconstructionVariable(BoundExpression expression, uint valEscape, ArrayBuilder? nestedVariables) { Expression = expression; ValEscape = valEscape; NestedVariables = nestedVariables; } } private const uint CallingMethodScope = 0u; private const uint ReturnOnlyScope = 1u; private const uint CurrentMethodScope = 2u; private readonly CSharpCompilation _compilation; private readonly MethodSymbol _symbol; private readonly bool _useUpdatedEscapeRules; private readonly BindingDiagnosticBag _diagnostics; private bool _inUnsafeRegion; private uint _localScopeDepth; private Dictionary? _localEscapeScopes; private Dictionary? _placeholderScopes; private uint _patternInputValEscape; private bool CheckLocalRefEscape(SyntaxNode node, BoundLocal local, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_0052: Unknown result type (might be due to invalid IL or missing references) LocalSymbol localSymbol = local.LocalSymbol; if (GetLocalScopes(localSymbol).RefEscapeScope <= escapeTo) { return true; } bool inUnsafeRegion = _inUnsafeRegion; if (escapeTo <= 1) { if ((int)localSymbol.RefKind == 0) { if (checkingReceiver) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_RefReturnLocal2 : ErrorCode.ERR_RefReturnLocal2, SyntaxNodeOrToken.op_Implicit(local.Syntax), localSymbol); } else { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_RefReturnLocal : ErrorCode.ERR_RefReturnLocal, SyntaxNodeOrToken.op_Implicit(node), localSymbol); } return inUnsafeRegion; } if (checkingReceiver) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_RefReturnNonreturnableLocal2 : ErrorCode.ERR_RefReturnNonreturnableLocal2, SyntaxNodeOrToken.op_Implicit(local.Syntax), localSymbol); } else { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_RefReturnNonreturnableLocal : ErrorCode.ERR_RefReturnNonreturnableLocal, SyntaxNodeOrToken.op_Implicit(node), localSymbol); } return inUnsafeRegion; } Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_EscapeVariable : ErrorCode.ERR_EscapeVariable, SyntaxNodeOrToken.op_Implicit(node), localSymbol); return inUnsafeRegion; } private static EscapeLevel? EscapeLevelFromScope(uint scope) { return scope switch { 1u => EscapeLevel.ReturnOnly, 0u => EscapeLevel.CallingMethod, _ => null, }; } private static uint GetParameterValEscape(ParameterSymbol parameter) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if ((object)parameter != null) { if ((int)parameter.EffectiveScope == 2) { return 2u; } if ((int)parameter.RefKind == 2 && parameter.UseUpdatedEscapeRules) { return 1u; } } return 0u; } private static EscapeLevel? GetParameterValEscapeLevel(ParameterSymbol parameter) { return EscapeLevelFromScope(GetParameterValEscape(parameter)); } private static uint GetParameterRefEscape(ParameterSymbol parameter) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) //IL_000c: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if ((object)parameter != null) { RefKind refKind = parameter.RefKind; if ((int)refKind == 0) { return 2u; } if ((int)parameter.EffectiveScope == 1) { return 2u; } if (parameter.HasUnscopedRefAttribute) { if ((int)refKind == 2) { return 1u; } if (!parameter.IsThis) { return 0u; } } } return 1u; } private static EscapeLevel? GetParameterRefEscapeLevel(ParameterSymbol parameter) { return EscapeLevelFromScope(GetParameterRefEscape(parameter)); } private bool CheckParameterValEscape(SyntaxNode node, ParameterSymbol parameter, uint escapeTo, BindingDiagnosticBag diagnostics) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (_useUpdatedEscapeRules) { if (GetParameterValEscape(parameter) > escapeTo) { Error(diagnostics, _inUnsafeRegion ? ErrorCode.WRN_EscapeVariable : ErrorCode.ERR_EscapeVariable, SyntaxNodeOrToken.op_Implicit(node), parameter); return _inUnsafeRegion; } return true; } return true; } private bool CheckParameterRefEscape(SyntaxNode node, BoundExpression parameter, ParameterSymbol parameterSymbol, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) uint parameterRefEscape = GetParameterRefEscape(parameterSymbol); if (parameterRefEscape > escapeTo) { bool flag = (int)parameterSymbol.EffectiveScope == 1; bool inUnsafeRegion = _inUnsafeRegion; if (parameter is BoundThisReference) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_RefReturnStructThis : ErrorCode.ERR_RefReturnStructThis, SyntaxNodeOrToken.op_Implicit(node)); return inUnsafeRegion; } var (code, val) = (checkingReceiver ? (flag ? (inUnsafeRegion ? (ErrorCode.WRN_RefReturnScopedParameter2, parameter.Syntax) : (ErrorCode.ERR_RefReturnScopedParameter2, parameter.Syntax)) : ((!inUnsafeRegion) ? ((parameterRefEscape != 1) ? (ErrorCode.ERR_RefReturnParameter2, parameter.Syntax) : (ErrorCode.ERR_RefReturnOnlyParameter2, parameter.Syntax)) : ((parameterRefEscape != 1) ? (ErrorCode.WRN_RefReturnParameter2, parameter.Syntax) : (ErrorCode.WRN_RefReturnOnlyParameter2, parameter.Syntax)))) : (flag ? (inUnsafeRegion ? (ErrorCode.WRN_RefReturnScopedParameter, node) : (ErrorCode.ERR_RefReturnScopedParameter, node)) : ((!inUnsafeRegion) ? ((parameterRefEscape != 1) ? (ErrorCode.ERR_RefReturnParameter, node) : (ErrorCode.ERR_RefReturnOnlyParameter, node)) : ((parameterRefEscape != 1) ? (ErrorCode.WRN_RefReturnParameter, node) : (ErrorCode.WRN_RefReturnOnlyParameter, node))))); Error(diagnostics, code, SyntaxNodeOrToken.op_Implicit(val), parameterSymbol.Name); return inUnsafeRegion; } return true; } private uint GetFieldRefEscape(BoundFieldAccess fieldAccess, uint scopeOfTheContainingExpression) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; if (fieldSymbol.IsStatic || fieldSymbol.ContainingType.IsReferenceType) { return 0u; } if (_useUpdatedEscapeRules && (int)fieldSymbol.RefKind != 0) { return GetValEscape(fieldAccess.ReceiverOpt, scopeOfTheContainingExpression); } return GetRefEscape(fieldAccess.ReceiverOpt, scopeOfTheContainingExpression); } private bool CheckFieldRefEscape(SyntaxNode node, BoundFieldAccess fieldAccess, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; if (fieldSymbol.IsStatic || fieldSymbol.ContainingType.IsReferenceType) { return true; } if (_useUpdatedEscapeRules && (int)fieldSymbol.RefKind != 0) { return CheckValEscape(node, fieldAccess.ReceiverOpt, escapeFrom, escapeTo, checkingReceiver: true, diagnostics); } return CheckRefEscape(node, fieldAccess.ReceiverOpt, escapeFrom, escapeTo, checkingReceiver: true, diagnostics); } private bool CheckFieldLikeEventRefEscape(SyntaxNode node, BoundEventAccess eventAccess, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { EventSymbol eventSymbol = eventAccess.EventSymbol; if (eventSymbol.IsStatic || eventSymbol.ContainingType.IsReferenceType) { return true; } return CheckRefEscape(node, eventAccess.ReceiverOpt, escapeFrom, escapeTo, checkingReceiver: true, diagnostics); } internal uint GetInterpolatedStringHandlerConversionEscapeScope(BoundExpression expression, uint scopeOfTheContainingExpression) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) uint num = GetValEscape(expression.GetInterpolatedStringHandlerData().Construction, scopeOfTheContainingExpression); ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInterpolatedStringHandlerArgumentsForEscape(expression, instance); Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; uint valEscape = GetValEscape(current, scopeOfTheContainingExpression); num = Math.Max(num, valEscape); } instance.Free(); return num; } private uint GetInvocationEscapeScope(Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, uint scopeOfTheContainingExpression, bool isRefEscape) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 if (UseUpdatedEscapeRulesForInvocation(symbol)) { return GetInvocationEscapeWithUpdatedRules(symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, scopeOfTheContainingExpression, isRefEscape); } if (!symbol.RequiresInstanceReceiver()) { receiver = null; } uint num = 0u; ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInvocationArgumentsForEscape(symbol, null, (ThreeState)0, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, ignoreArglistRefKinds: true, null, instance); try { Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out ParameterSymbol _, out BoundExpression argument, out RefKind refKind); BoundExpression expr = argument; uint val = (((int)refKind > 0 && isRefEscape) ? GetRefEscape(expr, scopeOfTheContainingExpression) : GetValEscape(expr, scopeOfTheContainingExpression)); num = Math.Max(num, val); if (num >= scopeOfTheContainingExpression) { return num; } } } finally { instance.Free(); } if (receiver != null && receiver.Type?.IsRefLikeType == true) { num = Math.Max(num, GetValEscape(receiver, scopeOfTheContainingExpression)); } return num; } private uint GetInvocationEscapeWithUpdatedRules(Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, uint scopeOfTheContainingExpression, bool isRefEscape) { //IL_000b: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 uint num = 0u; ArrayBuilder instance = ArrayBuilder.GetInstance(); GetFilteredInvocationArgumentsForEscapeWithUpdatedRules(symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, isRefEscape, ignoreArglistRefKinds: true, instance); bool flag = ReturnsRefToRefStruct(symbol); Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out ParameterSymbol parameter, out BoundExpression argument, out EscapeLevel _, out bool isRefEscape2); ParameterSymbol parameterSymbol = parameter; BoundExpression expr = argument; bool flag2 = isRefEscape2; isRefEscape2 = !flag; bool flag3; if (!isRefEscape2) { if ((object)parameterSymbol == null) { goto IL_0082; } if ((int)parameterSymbol.RefKind != 0) { TypeSymbol type = parameterSymbol.Type; if ((object)type != null && type.IsRefLikeType) { goto IL_0082; } } flag3 = false; goto IL_008a; } goto IL_0099; IL_008a: isRefEscape2 = flag3 && flag2 == isRefEscape; goto IL_0099; IL_0099: if (isRefEscape2) { uint val = (flag2 ? GetRefEscape(expr, scopeOfTheContainingExpression) : GetValEscape(expr, scopeOfTheContainingExpression)); num = Math.Max(num, val); if (num >= scopeOfTheContainingExpression) { break; } } continue; IL_0082: flag3 = true; goto IL_008a; } instance.Free(); return num; } private static bool ReturnsRefToRefStruct(Symbol symbol) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 MethodSymbol methodSymbol = ((symbol is MethodSymbol methodSymbol2) ? methodSymbol2 : ((!(symbol is PropertySymbol propertySymbol)) ? null : propertySymbol.GetMethod)); MethodSymbol methodSymbol3 = methodSymbol; if ((object)methodSymbol3 != null && (int)methodSymbol3.RefKind != 0) { TypeSymbol returnType = methodSymbol3.ReturnType; if ((object)returnType != null) { return returnType.IsRefLikeType; } } return false; } private bool CheckInvocationEscape(SyntaxNode syntax, Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, bool checkingReceiver, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics, bool isRefEscape) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0074: Invalid comparison between Unknown and I4 if (UseUpdatedEscapeRulesForInvocation(symbol)) { return CheckInvocationEscapeWithUpdatedRules(syntax, symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape); } if (!symbol.RequiresInstanceReceiver()) { receiver = null; } ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInvocationArgumentsForEscape(symbol, null, (ThreeState)0, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, ignoreArglistRefKinds: true, null, instance); try { Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { var (parameter, boundExpression2, val2) = (EscapeArgument)(ref enumerator.Current); if (!(((int)val2 > 0 && isRefEscape) ? CheckRefEscape(boundExpression2.Syntax, boundExpression2, escapeFrom, escapeTo, checkingReceiver: false, diagnostics) : CheckValEscape(boundExpression2.Syntax, boundExpression2, escapeFrom, escapeTo, checkingReceiver: false, diagnostics))) { if (!(symbol is SignatureOnlyMethodSymbol)) { ReportInvocationEscapeError(syntax, symbol, parameter, checkingReceiver, diagnostics); } return false; } } } finally { instance.Free(); } if (receiver != null && receiver.Type?.IsRefLikeType == true) { return CheckValEscape(receiver.Syntax, receiver, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return true; } private bool CheckInvocationEscapeWithUpdatedRules(SyntaxNode syntax, Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, bool checkingReceiver, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics, bool isRefEscape) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 bool result = true; ArrayBuilder instance = ArrayBuilder.GetInstance(); GetFilteredInvocationArgumentsForEscapeWithUpdatedRules(symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, isRefEscape, ignoreArglistRefKinds: true, instance); bool flag = ReturnsRefToRefStruct(symbol); Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out ParameterSymbol parameter, out BoundExpression argument, out EscapeLevel _, out bool isRefEscape2); ParameterSymbol parameterSymbol = parameter; BoundExpression boundExpression = argument; bool flag2 = isRefEscape2; isRefEscape2 = !flag; bool flag3; if (!isRefEscape2) { if ((object)parameterSymbol == null) { goto IL_0083; } if ((int)parameterSymbol.RefKind != 0) { TypeSymbol type = parameterSymbol.Type; if ((object)type != null && type.IsRefLikeType) { goto IL_0083; } } flag3 = false; goto IL_008b; } goto IL_009a; IL_008b: isRefEscape2 = flag3 && flag2 == isRefEscape; goto IL_009a; IL_009a: if (isRefEscape2 && !(flag2 ? CheckRefEscape(boundExpression.Syntax, boundExpression, escapeFrom, escapeTo, checkingReceiver: false, diagnostics) : CheckValEscape(boundExpression.Syntax, boundExpression, escapeFrom, escapeTo, checkingReceiver: false, diagnostics))) { if (((boundExpression as BoundCapturedReceiverPlaceholder)?.Receiver ?? boundExpression) != receiver && !(symbol is SignatureOnlyMethodSymbol)) { ReportInvocationEscapeError(syntax, symbol, parameterSymbol, checkingReceiver, diagnostics); } result = false; break; } continue; IL_0083: flag3 = true; goto IL_008b; } instance.Free(); return result; } private void GetInvocationArgumentsForEscape(Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, bool ignoreArglistRefKinds, ArrayBuilder? mixableArguments, ArrayBuilder escapeArguments) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Invalid comparison between Unknown and I4 //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Invalid comparison between Unknown and I4 if (receiver != null) { MethodSymbol methodSymbol2; if (!(symbol is MethodSymbol methodSymbol)) { if (!(symbol is PropertySymbol propertySymbol)) { throw ExceptionUtilities.UnexpectedValue((object)symbol); } methodSymbol2 = propertySymbol.GetMethod ?? propertySymbol.SetMethod; } else { methodSymbol2 = methodSymbol; } MethodSymbol method = methodSymbol2; if ((int)receiverIsSubjectToCloning == 2) { receiver = new BoundCapturedReceiverPlaceholder(receiver.Syntax, receiver, _localScopeDepth, receiver.Type).MakeCompilerGenerated(); } EscapeArgument escapeArgument = getReceiver(method, receiver); escapeArguments.Add(escapeArgument); if (mixableArguments != null && isMixableParameter(escapeArgument.Parameter)) { mixableArguments.Add(new MixableDestination(escapeArgument.Parameter, receiver)); } } if (argsOpt.IsDefault) { return; } for (int num = 0; num < argsOpt.Length; num++) { BoundExpression boundExpression = argsOpt[num]; if (boundExpression.Kind == BoundKind.ArgListOperator) { BoundArgListOperator boundArgListOperator = (BoundArgListOperator)boundExpression; getArgList(boundArgListOperator.Arguments, ignoreArglistRefKinds ? default(ImmutableArray) : boundArgListOperator.ArgumentRefKindsOpt, mixableArguments, escapeArguments); break; } ParameterSymbol parameterSymbol = ((num < parameters.Length) ? parameters[argsToParamsOpt.IsDefault ? num : argsToParamsOpt[num]] : null); if (mixableArguments != null && isMixableParameter(parameterSymbol) && isMixableArgument(boundExpression)) { mixableArguments.Add(new MixableDestination(parameterSymbol, boundExpression)); } RefKind val = (RefKind)(((object)parameterSymbol != null) ? ((int)parameterSymbol.RefKind) : 0); if (!argRefKindsOpt.IsDefault) { val = argRefKindsOpt[num]; } bool flag = (int)val == 0; bool flag2; if (flag) { RefKind? val2 = parameterSymbol?.RefKind; if (val2.HasValue) { RefKind valueOrDefault = val2.GetValueOrDefault(); if (valueOrDefault - 3 <= 1) { flag2 = true; goto IL_01b0; } } flag2 = false; goto IL_01b0; } goto IL_01b4; IL_01b0: flag = flag2; goto IL_01b4; IL_01b4: if (flag) { val = parameterSymbol.RefKind; } escapeArguments.Add(new EscapeArgument(parameterSymbol, boundExpression, val)); } static void getArgList(ImmutableArray immutableArray, ImmutableArray immutableArray2, ArrayBuilder? val5, ArrayBuilder val4) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 for (int i = 0; i < immutableArray.Length; i++) { BoundExpression argument = immutableArray[i]; RefKind val3 = (RefKind)((!immutableArray2.IsDefault) ? ((int)immutableArray2[i]) : 0); val4.Add(new EscapeArgument(null, argument, val3, isArgList: true)); if ((int)val3 == 1) { val5?.Add(new MixableDestination(argument, EscapeLevel.CallingMethod)); } } } static EscapeArgument getReceiver(MethodSymbol? methodSymbol3, BoundExpression argument) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (methodSymbol3 is FunctionPointerMethodSymbol) { return new EscapeArgument(null, argument, (RefKind)0); } RefKind refKind = (RefKind)0; ParameterSymbol thisParameter = null; if ((object)methodSymbol3 != null && methodSymbol3.TryGetThisParameter(out thisParameter) && (object)thisParameter != null) { refKind = thisParameter.RefKind; } return new EscapeArgument(thisParameter, argument, refKind); } static bool isMixableArgument(BoundExpression argument) { if (argument is BoundDeconstructValuePlaceholder boundDeconstructValuePlaceholder) { if ((object)boundDeconstructValuePlaceholder.VariableSymbol != null) { goto IL_0026; } } else if (argument is BoundLocal { DeclarationKind: not BoundLocalDeclarationKind.None }) { goto IL_0026; } bool flag3 = false; goto IL_002c; IL_0026: flag3 = true; goto IL_002c; IL_002c: if (flag3) { return false; } if (argument.IsDiscardExpression()) { return false; } return true; } static bool isMixableParameter([NotNullWhen(true)] ParameterSymbol? parameter) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((object)parameter != null && parameter.Type.IsRefLikeType) { return parameter.RefKind.IsWritableReference(); } return false; } } private void GetFilteredInvocationArgumentsForEscapeWithUpdatedRules(Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, bool isInvokedWithRef, bool ignoreArglistRefKinds, ArrayBuilder escapeValues) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (isInvokedWithRef || hasRefLikeReturn(symbol)) { GetEscapeValuesForUpdatedRules(symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, ignoreArglistRefKinds, null, escapeValues); } static bool hasRefLikeReturn(Symbol symbol2) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 if (symbol2 is MethodSymbol methodSymbol) { if ((int)methodSymbol.MethodKind == 1) { return methodSymbol.ContainingType.IsRefLikeType; } return methodSymbol.ReturnType.IsRefLikeType; } if (symbol2 is PropertySymbol propertySymbol) { return propertySymbol.Type.IsRefLikeType; } return false; } } private void GetEscapeValuesForUpdatedRules(Symbol symbol, BoundExpression? receiver, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, bool ignoreArglistRefKinds, ArrayBuilder? mixableArguments, ArrayBuilder escapeValues) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //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_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Invalid comparison between Unknown and I4 if (!symbol.RequiresInstanceReceiver()) { receiver = null; } ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInvocationArgumentsForEscape(symbol, receiver, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, ignoreArglistRefKinds, mixableArguments, instance); Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { var (parameterSymbol2, boundExpression2, val2) = (EscapeArgument)(ref enumerator.Current); if ((object)parameterSymbol2 == null) { if ((int)val2 != 0) { escapeValues.Add(new EscapeValue(null, boundExpression2, EscapeLevel.ReturnOnly, isRefEscape: true)); } TypeSymbol? type = boundExpression2.Type; if ((object)type != null && type.IsRefLikeType) { escapeValues.Add(new EscapeValue(null, boundExpression2, EscapeLevel.CallingMethod, isRefEscape: false)); } continue; } if (parameterSymbol2.Type.IsRefLikeType && (int)parameterSymbol2.RefKind != 2) { EscapeLevel? parameterValEscapeLevel = GetParameterValEscapeLevel(parameterSymbol2); if (parameterValEscapeLevel.HasValue) { EscapeLevel valueOrDefault = parameterValEscapeLevel.GetValueOrDefault(); escapeValues.Add(new EscapeValue(parameterSymbol2, boundExpression2, valueOrDefault, isRefEscape: false)); } } if ((int)parameterSymbol2.RefKind != 0) { EscapeLevel? parameterValEscapeLevel = GetParameterRefEscapeLevel(parameterSymbol2); if (parameterValEscapeLevel.HasValue) { EscapeLevel valueOrDefault2 = parameterValEscapeLevel.GetValueOrDefault(); escapeValues.Add(new EscapeValue(parameterSymbol2, boundExpression2, valueOrDefault2, isRefEscape: true)); } } } instance.Free(); } private static string GetInvocationParameterName(ParameterSymbol? parameter) { if ((object)parameter == null) { return "__arglist"; } string text = parameter.Name; if (string.IsNullOrEmpty(text)) { text = parameter.Ordinal.ToString(); } return text; } private static void ReportInvocationEscapeError(SyntaxNode syntax, Symbol symbol, ParameterSymbol? parameter, bool checkingReceiver, BindingDiagnosticBag diagnostics) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) ErrorCode standardCallEscapeError = GetStandardCallEscapeError(checkingReceiver); string invocationParameterName = GetInvocationParameterName(parameter); Error(diagnostics, standardCallEscapeError, SyntaxNodeOrToken.op_Implicit(syntax), symbol, invocationParameterName); } private bool UseUpdatedEscapeRulesForInvocation(Symbol symbol) { MethodSymbol methodSymbol2; if (!(symbol is MethodSymbol methodSymbol)) { if (!(symbol is PropertySymbol propertySymbol)) { throw ExceptionUtilities.UnexpectedValue((object)symbol); } methodSymbol2 = propertySymbol.GetMethod ?? propertySymbol.SetMethod; } else { methodSymbol2 = methodSymbol; } return methodSymbol2?.UseUpdatedEscapeRules ?? false; } private bool ShouldInferDeclarationExpressionValEscape(BoundExpression argument, [NotNullWhen(true)] out SourceLocalSymbol? localSymbol) { Symbol symbol = ((argument is BoundDeconstructValuePlaceholder boundDeconstructValuePlaceholder) ? boundDeconstructValuePlaceholder.VariableSymbol : ((!(argument is BoundLocal { DeclarationKind: not BoundLocalDeclarationKind.None } boundLocal)) ? null : boundLocal.LocalSymbol)); if (symbol is SourceLocalSymbol sourceLocalSymbol && GetLocalScopes(sourceLocalSymbol).ValEscapeScope == 0) { localSymbol = sourceLocalSymbol; return true; } localSymbol = null; return false; } private bool CheckInvocationArgMixing(SyntaxNode syntax, Symbol symbol, BoundExpression? receiverOpt, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, uint scopeOfTheContainingExpression, BindingDiagnosticBag diagnostics) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if (UseUpdatedEscapeRulesForInvocation(symbol)) { return CheckInvocationArgMixingWithUpdatedRules(syntax, symbol, receiverOpt, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, scopeOfTheContainingExpression, diagnostics); } if (!symbol.RequiresInstanceReceiver()) { receiverOpt = null; } uint num = scopeOfTheContainingExpression; TypeSymbol? obj = receiverOpt?.Type; if ((object)obj != null && obj.IsRefLikeType && !IsReceiverRefReadOnly(symbol)) { num = GetValEscape(receiverOpt, scopeOfTheContainingExpression); } ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInvocationArgumentsForEscape(symbol, receiverOpt, receiverIsSubjectToCloning, parameters, argsOpt, default(ImmutableArray), argsToParamsOpt, ignoreArglistRefKinds: false, null, instance); try { Enumerator enumerator = instance.GetEnumerator(); ParameterSymbol parameter; BoundExpression argument; RefKind refKind; while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out parameter, out argument, out refKind); BoundExpression boundExpression = argument; RefKind refKind2 = refKind; if (!ShouldInferDeclarationExpressionValEscape(boundExpression, out SourceLocalSymbol _) && refKind2.IsWritableReference() && !boundExpression.IsDiscardExpression()) { TypeSymbol? type = boundExpression.Type; if ((object)type != null && type.IsRefLikeType) { num = Math.Min(num, GetValEscape(boundExpression, scopeOfTheContainingExpression)); } } } bool flag = false; uint num2 = 0u; enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out parameter, out argument, out refKind); ParameterSymbol parameter2 = parameter; BoundExpression boundExpression2 = argument; num2 = Math.Max(num2, GetValEscape(boundExpression2, scopeOfTheContainingExpression)); if (!flag && !CheckValEscape(boundExpression2.Syntax, boundExpression2, scopeOfTheContainingExpression, num, checkingReceiver: false, diagnostics)) { string invocationParameterName = GetInvocationParameterName(parameter2); Error(diagnostics, ErrorCode.ERR_CallArgMixing, SyntaxNodeOrToken.op_Implicit(syntax), symbol, invocationParameterName); flag = true; } } enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Deconstruct(out parameter, out argument, out refKind); BoundExpression argument2 = argument; if (ShouldInferDeclarationExpressionValEscape(argument2, out SourceLocalSymbol localSymbol2)) { SetLocalScopes(localSymbol2, _localScopeDepth, num2); } } return !flag; } finally { instance.Free(); } } private bool CheckInvocationArgMixingWithUpdatedRules(SyntaxNode syntax, Symbol symbol, BoundExpression? receiverOpt, ThreeState receiverIsSubjectToCloning, ImmutableArray parameters, ImmutableArray argsOpt, ImmutableArray argRefKindsOpt, ImmutableArray argsToParamsOpt, uint scopeOfTheContainingExpression, BindingDiagnosticBag diagnostics) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) ArrayBuilder instance = ArrayBuilder.GetInstance(); ArrayBuilder escapeValues = ArrayBuilder.GetInstance(); GetEscapeValuesForUpdatedRules(symbol, receiverOpt, receiverIsSubjectToCloning, parameters, argsOpt, argRefKindsOpt, argsToParamsOpt, ignoreArglistRefKinds: false, instance, escapeValues); bool flag = true; Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { MixableDestination current = enumerator.Current; uint valEscape = GetValEscape(current.Argument, scopeOfTheContainingExpression); Enumerator enumerator2 = escapeValues.GetEnumerator(); while (enumerator2.MoveNext()) { var (parameterSymbol2, boundExpression2, level, flag3) = (EscapeValue)(ref enumerator2.Current); if (((object)current.Parameter == null || (object)current.Parameter != parameterSymbol2) && current.IsAssignableFrom(level)) { flag = (flag3 ? CheckRefEscape(boundExpression2.Syntax, boundExpression2, scopeOfTheContainingExpression, valEscape, checkingReceiver: false, diagnostics) : CheckValEscape(boundExpression2.Syntax, boundExpression2, scopeOfTheContainingExpression, valEscape, checkingReceiver: false, diagnostics)); if (!flag) { string invocationParameterName = GetInvocationParameterName(parameterSymbol2); Error(diagnostics, ErrorCode.ERR_CallArgMixing, SyntaxNodeOrToken.op_Implicit(syntax), symbol, invocationParameterName); break; } } } if (!flag) { break; } } inferDeclarationExpressionValEscape(); instance.Free(); escapeValues.Free(); return flag; void inferDeclarationExpressionValEscape() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) uint num = 0u; Enumerator enumerator3 = escapeValues.GetEnumerator(); while (enumerator3.MoveNext()) { enumerator3.Current.Deconstruct(out ParameterSymbol _, out BoundExpression argument, out EscapeLevel _, out bool isRefEscape); BoundExpression expr = argument; bool flag4 = isRefEscape; num = Math.Max(num, flag4 ? GetRefEscape(expr, scopeOfTheContainingExpression) : GetValEscape(expr, scopeOfTheContainingExpression)); } ImmutableArray.Enumerator enumerator4 = argsOpt.GetEnumerator(); while (enumerator4.MoveNext()) { BoundExpression current2 = enumerator4.Current; if (ShouldInferDeclarationExpressionValEscape(current2, out SourceLocalSymbol localSymbol)) { SetLocalScopes(localSymbol, _localScopeDepth, num); } } } } private static bool IsReceiverRefReadOnly(Symbol methodOrPropertySymbol) { if (!(methodOrPropertySymbol is MethodSymbol { IsEffectivelyReadOnly: var isEffectivelyReadOnly })) { if (methodOrPropertySymbol is PropertySymbol propertySymbol) { MethodSymbol getMethod = propertySymbol.GetMethod; return ((object)getMethod == null || getMethod.IsEffectivelyReadOnly) && (propertySymbol.SetMethod?.IsEffectivelyReadOnly ?? true); } throw ExceptionUtilities.UnexpectedValue((object)methodOrPropertySymbol); } return isEffectivelyReadOnly; } private static ErrorCode GetStandardCallEscapeError(bool checkingReceiver) { if (!checkingReceiver) { return ErrorCode.ERR_EscapeCall; } return ErrorCode.ERR_EscapeCall2; } private static ErrorCode GetStandardRValueRefEscapeError(uint escapeTo) { if (escapeTo <= 1) { return ErrorCode.ERR_RefReturnLvalueExpected; } return ErrorCode.ERR_EscapeOther; } internal void ValidateEscape(BoundExpression expr, uint escapeTo, bool isByRef, BindingDiagnosticBag diagnostics) { if (isByRef) { CheckRefEscape(expr.Syntax, expr, _localScopeDepth, escapeTo, checkingReceiver: false, diagnostics); } else { CheckValEscape(expr.Syntax, expr, _localScopeDepth, escapeTo, checkingReceiver: false, diagnostics); } } internal uint GetRefEscape(BoundExpression expr, uint scopeOfTheContainingExpression) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Invalid comparison between Unknown and I4 //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Invalid comparison between Unknown and I4 //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) if (expr.HasAnyErrors) { return 0u; } TypeSymbol? type = expr.Type; if ((object)type != null && (int)type.GetSpecialTypeSafe() == 6) { return 0u; } if (expr.ConstantValueOpt != (ConstantValue)null) { return scopeOfTheContainingExpression; } switch (expr.Kind) { case BoundKind.PointerIndirectionOperator: case BoundKind.PointerElementAccess: case BoundKind.ArrayAccess: return 0u; case BoundKind.RefValueOperator: return 2u; case BoundKind.Parameter: return GetParameterRefEscape(((BoundParameter)expr).ParameterSymbol); case BoundKind.Local: return GetLocalScopes(((BoundLocal)expr).LocalSymbol).RefEscapeScope; case BoundKind.CapturedReceiverPlaceholder: return ((BoundCapturedReceiverPlaceholder)expr).LocalScopeDepth; case BoundKind.ThisReference: return GetParameterRefEscape(_symbol.ThisParameter); case BoundKind.ConditionalOperator: { BoundConditionalOperator boundConditionalOperator = (BoundConditionalOperator)expr; if (boundConditionalOperator.IsRef) { return Math.Max(GetRefEscape(boundConditionalOperator.Consequence, scopeOfTheContainingExpression), GetRefEscape(boundConditionalOperator.Alternative, scopeOfTheContainingExpression)); } break; } case BoundKind.FieldAccess: return GetFieldRefEscape((BoundFieldAccess)expr, scopeOfTheContainingExpression); case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)expr; if (boundEventAccess.IsUsableAsField) { EventSymbol eventSymbol = boundEventAccess.EventSymbol; if (eventSymbol.IsStatic || eventSymbol.ContainingType.IsReferenceType) { return 0u; } return GetRefEscape(boundEventAccess.ReceiverOpt, scopeOfTheContainingExpression); } break; } case BoundKind.Call: { BoundCall boundCall = (BoundCall)expr; MethodSymbol method = boundCall.Method; if ((int)method.RefKind != 0) { return GetInvocationEscapeScope(boundCall.Method, boundCall.ReceiverOpt, boundCall.InitialBindingReceiverIsSubjectToCloning, method.Parameters, boundCall.Arguments, boundCall.ArgumentRefKindsOpt, boundCall.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: true); } break; } case BoundKind.FunctionPointerInvocation: { BoundFunctionPointerInvocation boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)expr; FunctionPointerMethodSymbol signature = boundFunctionPointerInvocation.FunctionPointer.Signature; if ((int)signature.RefKind != 0) { return GetInvocationEscapeScope(signature, null, (ThreeState)0, signature.Parameters, boundFunctionPointerInvocation.Arguments, boundFunctionPointerInvocation.ArgumentRefKindsOpt, default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: true); } break; } case BoundKind.IndexerAccess: { BoundIndexerAccess boundIndexerAccess = (BoundIndexerAccess)expr; PropertySymbol indexer = boundIndexerAccess.Indexer; return GetInvocationEscapeScope(indexer, boundIndexerAccess.ReceiverOpt, boundIndexerAccess.InitialBindingReceiverIsSubjectToCloning, indexer.Parameters, boundIndexerAccess.Arguments, boundIndexerAccess.ArgumentRefKindsOpt, boundIndexerAccess.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: true); } case BoundKind.ImplicitIndexerAccess: { BoundImplicitIndexerAccess boundImplicitIndexerAccess = (BoundImplicitIndexerAccess)expr; BoundExpression indexerOrSliceAccess = boundImplicitIndexerAccess.IndexerOrSliceAccess; if (!(indexerOrSliceAccess is BoundIndexerAccess boundIndexerAccess2)) { if (!(indexerOrSliceAccess is BoundArrayAccess)) { if (indexerOrSliceAccess is BoundCall boundCall2) { MethodSymbol method2 = boundCall2.Method; if ((int)method2.RefKind != 0) { return GetInvocationEscapeScope(boundCall2.Method, boundImplicitIndexerAccess.Receiver, boundCall2.InitialBindingReceiverIsSubjectToCloning, method2.Parameters, boundCall2.Arguments, boundCall2.ArgumentRefKindsOpt, boundCall2.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: true); } break; } throw ExceptionUtilities.UnexpectedValue((object)boundImplicitIndexerAccess.IndexerOrSliceAccess.Kind); } return 0u; } PropertySymbol indexer2 = boundIndexerAccess2.Indexer; return GetInvocationEscapeScope(indexer2, boundImplicitIndexerAccess.Receiver, boundIndexerAccess2.InitialBindingReceiverIsSubjectToCloning, indexer2.Parameters, boundIndexerAccess2.Arguments, boundIndexerAccess2.ArgumentRefKindsOpt, boundIndexerAccess2.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: true); } case BoundKind.InlineArrayAccess: { BoundInlineArrayAccess boundInlineArrayAccess = (BoundInlineArrayAccess)expr; WellKnownMember getItemOrSliceHelper = boundInlineArrayAccess.GetItemOrSliceHelper; bool flag = (((int)getItemOrSliceHelper == 400 || (int)getItemOrSliceHelper == 406) ? true : false); if (flag && !boundInlineArrayAccess.IsValue) { ImmutableArray arguments; ImmutableArray refKinds; SignatureOnlyMethodSymbol inlineArrayAccessEquivalentSignatureMethod = GetInlineArrayAccessEquivalentSignatureMethod(boundInlineArrayAccess, out arguments, out refKinds); return GetInvocationEscapeScope(inlineArrayAccessEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayAccessEquivalentSignatureMethod.Parameters, arguments, refKinds, default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: true); } break; } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)expr; return GetInvocationEscapeScope(boundPropertyAccess.PropertySymbol, boundPropertyAccess.ReceiverOpt, boundPropertyAccess.InitialBindingReceiverIsSubjectToCloning, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: true); } case BoundKind.AssignmentOperator: { BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)expr; if (boundAssignmentOperator.IsRef) { return GetRefEscape(boundAssignmentOperator.Left, scopeOfTheContainingExpression); } break; } } return scopeOfTheContainingExpression; } internal bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint escapeFrom, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Invalid comparison between Unknown and I4 //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Invalid comparison between Unknown and I4 //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) if (escapeTo >= escapeFrom) { return true; } if (expr.HasAnyErrors) { return true; } TypeSymbol? type = expr.Type; if ((object)type != null && (int)type.GetSpecialTypeSafe() == 6) { return true; } if (expr.ConstantValueOpt != (ConstantValue)null) { Error(diagnostics, GetStandardRValueRefEscapeError(escapeTo), SyntaxNodeOrToken.op_Implicit(node)); return false; } switch (expr.Kind) { case BoundKind.PointerIndirectionOperator: case BoundKind.PointerElementAccess: case BoundKind.ArrayAccess: return true; case BoundKind.RefValueOperator: if (escapeTo > 1) { return true; } break; case BoundKind.Parameter: { BoundParameter boundParameter = (BoundParameter)expr; return CheckParameterRefEscape(node, boundParameter, boundParameter.ParameterSymbol, escapeTo, checkingReceiver, diagnostics); } case BoundKind.Local: { BoundLocal local = (BoundLocal)expr; return CheckLocalRefEscape(node, local, escapeTo, checkingReceiver, diagnostics); } case BoundKind.CapturedReceiverPlaceholder: if (((BoundCapturedReceiverPlaceholder)expr).LocalScopeDepth <= escapeTo) { return true; } break; case BoundKind.ThisReference: { ParameterSymbol thisParameter = _symbol.ThisParameter; return CheckParameterRefEscape(node, expr, thisParameter, escapeTo, checkingReceiver, diagnostics); } case BoundKind.ConditionalOperator: { BoundConditionalOperator boundConditionalOperator = (BoundConditionalOperator)expr; if (boundConditionalOperator.IsRef) { if (CheckRefEscape(boundConditionalOperator.Consequence.Syntax, boundConditionalOperator.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return CheckRefEscape(boundConditionalOperator.Alternative.Syntax, boundConditionalOperator.Alternative, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } break; } case BoundKind.FieldAccess: { BoundFieldAccess fieldAccess = (BoundFieldAccess)expr; return CheckFieldRefEscape(node, fieldAccess, escapeFrom, escapeTo, diagnostics); } case BoundKind.EventAccess: { BoundEventAccess boundEventAccess = (BoundEventAccess)expr; if (boundEventAccess.IsUsableAsField) { return CheckFieldLikeEventRefEscape(node, boundEventAccess, escapeFrom, escapeTo, diagnostics); } break; } case BoundKind.Call: { BoundCall boundCall = (BoundCall)expr; MethodSymbol method = boundCall.Method; if ((int)method.RefKind != 0) { return CheckInvocationEscape(boundCall.Syntax, method, boundCall.ReceiverOpt, boundCall.InitialBindingReceiverIsSubjectToCloning, method.Parameters, boundCall.Arguments, boundCall.ArgumentRefKindsOpt, boundCall.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } break; } case BoundKind.IndexerAccess: { BoundIndexerAccess boundIndexerAccess = (BoundIndexerAccess)expr; PropertySymbol indexer = boundIndexerAccess.Indexer; if ((int)indexer.RefKind != 0) { return CheckInvocationEscape(boundIndexerAccess.Syntax, indexer, boundIndexerAccess.ReceiverOpt, boundIndexerAccess.InitialBindingReceiverIsSubjectToCloning, indexer.Parameters, boundIndexerAccess.Arguments, boundIndexerAccess.ArgumentRefKindsOpt, boundIndexerAccess.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } break; } case BoundKind.ImplicitIndexerAccess: { BoundImplicitIndexerAccess boundImplicitIndexerAccess = (BoundImplicitIndexerAccess)expr; BoundExpression indexerOrSliceAccess = boundImplicitIndexerAccess.IndexerOrSliceAccess; if (!(indexerOrSliceAccess is BoundIndexerAccess boundIndexerAccess2)) { if (indexerOrSliceAccess is BoundArrayAccess) { return true; } if (!(indexerOrSliceAccess is BoundCall boundCall2)) { throw ExceptionUtilities.UnexpectedValue((object)boundImplicitIndexerAccess.IndexerOrSliceAccess.Kind); } MethodSymbol method2 = boundCall2.Method; if ((int)method2.RefKind != 0) { return CheckInvocationEscape(boundCall2.Syntax, method2, boundImplicitIndexerAccess.Receiver, boundCall2.InitialBindingReceiverIsSubjectToCloning, method2.Parameters, boundCall2.Arguments, boundCall2.ArgumentRefKindsOpt, boundCall2.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } } else { PropertySymbol indexer2 = boundIndexerAccess2.Indexer; if ((int)indexer2.RefKind != 0) { return CheckInvocationEscape(boundIndexerAccess2.Syntax, indexer2, boundImplicitIndexerAccess.Receiver, boundIndexerAccess2.InitialBindingReceiverIsSubjectToCloning, indexer2.Parameters, boundIndexerAccess2.Arguments, boundIndexerAccess2.ArgumentRefKindsOpt, boundIndexerAccess2.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } } break; } case BoundKind.InlineArrayAccess: { BoundInlineArrayAccess boundInlineArrayAccess = (BoundInlineArrayAccess)expr; WellKnownMember getItemOrSliceHelper = boundInlineArrayAccess.GetItemOrSliceHelper; bool flag = (((int)getItemOrSliceHelper == 400 || (int)getItemOrSliceHelper == 406) ? true : false); if (flag && !boundInlineArrayAccess.IsValue) { ImmutableArray arguments; ImmutableArray refKinds; SignatureOnlyMethodSymbol inlineArrayAccessEquivalentSignatureMethod = GetInlineArrayAccessEquivalentSignatureMethod(boundInlineArrayAccess, out arguments, out refKinds); return CheckInvocationEscape(boundInlineArrayAccess.Syntax, inlineArrayAccessEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayAccessEquivalentSignatureMethod.Parameters, arguments, refKinds, default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } break; } case BoundKind.FunctionPointerInvocation: { BoundFunctionPointerInvocation boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)expr; FunctionPointerMethodSymbol signature = boundFunctionPointerInvocation.FunctionPointer.Signature; if ((int)signature.RefKind != 0) { return CheckInvocationEscape(boundFunctionPointerInvocation.Syntax, signature, boundFunctionPointerInvocation.InvokedExpression, (ThreeState)1, signature.Parameters, boundFunctionPointerInvocation.Arguments, boundFunctionPointerInvocation.ArgumentRefKindsOpt, default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } break; } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)expr; PropertySymbol propertySymbol = boundPropertyAccess.PropertySymbol; if ((int)propertySymbol.RefKind != 0) { return CheckInvocationEscape(boundPropertyAccess.Syntax, propertySymbol, boundPropertyAccess.ReceiverOpt, boundPropertyAccess.InitialBindingReceiverIsSubjectToCloning, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: true); } break; } case BoundKind.AssignmentOperator: { BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)expr; if (boundAssignmentOperator.IsRef) { return CheckRefEscape(node, boundAssignmentOperator.Left, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } break; } case BoundKind.Conversion: { BoundConversion boundConversion = (BoundConversion)expr; if (boundConversion.Conversion == Conversion.ImplicitThrow) { return CheckRefEscape(node, boundConversion.Operand, escapeFrom, escapeTo, checkingReceiver, diagnostics); } break; } case BoundKind.ThrowExpression: return true; } Error(diagnostics, GetStandardRValueRefEscapeError(escapeTo), SyntaxNodeOrToken.op_Implicit(node)); return false; } internal uint GetBroadestValEscape(BoundTupleExpression expr, uint scopeOfTheContainingExpression) { uint num = scopeOfTheContainingExpression; ImmutableArray.Enumerator enumerator = expr.Arguments.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; uint val = ((!(current is BoundTupleExpression expr2)) ? GetValEscape(current, scopeOfTheContainingExpression) : GetBroadestValEscape(expr2, scopeOfTheContainingExpression)); num = Math.Min(num, val); } return num; } internal uint GetValEscape(BoundExpression expr, uint scopeOfTheContainingExpression) { //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) if (expr.HasAnyErrors) { return 0u; } if (expr.ConstantValueOpt != (ConstantValue)null) { return 0u; } TypeSymbol? type = expr.Type; if ((object)type == null || !type.IsRefLikeType) { return 0u; } switch (expr.Kind) { case BoundKind.ThisReference: return GetParameterValEscape(_symbol.ThisParameter); case BoundKind.DefaultLiteral: case BoundKind.DefaultExpression: case BoundKind.Utf8String: return 0u; case BoundKind.Parameter: return GetParameterValEscape(((BoundParameter)expr).ParameterSymbol); case BoundKind.FromEndIndexExpression: return 0u; case BoundKind.TupleLiteral: case BoundKind.ConvertedTupleLiteral: { BoundTupleExpression boundTupleExpression = (BoundTupleExpression)expr; return GetTupleValEscape(boundTupleExpression.Arguments, scopeOfTheContainingExpression); } case BoundKind.MakeRefOperator: case BoundKind.RefValueOperator: return 0u; case BoundKind.DiscardExpression: return 0u; case BoundKind.DeconstructValuePlaceholder: case BoundKind.AwaitableValuePlaceholder: case BoundKind.InterpolatedStringArgumentPlaceholder: return GetPlaceholderScope((BoundValuePlaceholderBase)expr); case BoundKind.Local: return GetLocalScopes(((BoundLocal)expr).LocalSymbol).ValEscapeScope; case BoundKind.CapturedReceiverPlaceholder: { BoundCapturedReceiverPlaceholder boundCapturedReceiverPlaceholder = (BoundCapturedReceiverPlaceholder)expr; return GetValEscape(boundCapturedReceiverPlaceholder.Receiver, boundCapturedReceiverPlaceholder.LocalScopeDepth); } case BoundKind.StackAllocArrayCreation: case BoundKind.ConvertedStackAllocExpression: return 2u; case BoundKind.ConditionalOperator: { BoundConditionalOperator boundConditionalOperator = (BoundConditionalOperator)expr; uint valEscape = GetValEscape(boundConditionalOperator.Consequence, scopeOfTheContainingExpression); if (boundConditionalOperator.IsRef) { return valEscape; } return Math.Max(valEscape, GetValEscape(boundConditionalOperator.Alternative, scopeOfTheContainingExpression)); } case BoundKind.NullCoalescingOperator: { BoundNullCoalescingOperator boundNullCoalescingOperator = (BoundNullCoalescingOperator)expr; return Math.Max(GetValEscape(boundNullCoalescingOperator.LeftOperand, scopeOfTheContainingExpression), GetValEscape(boundNullCoalescingOperator.RightOperand, scopeOfTheContainingExpression)); } case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)expr; FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol; if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsRefLikeType) { return 0u; } return GetValEscape(boundFieldAccess.ReceiverOpt, scopeOfTheContainingExpression); } case BoundKind.Call: { BoundCall boundCall2 = (BoundCall)expr; return GetInvocationEscapeScope(boundCall2.Method, boundCall2.ReceiverOpt, boundCall2.InitialBindingReceiverIsSubjectToCloning, boundCall2.Method.Parameters, boundCall2.Arguments, boundCall2.ArgumentRefKindsOpt, boundCall2.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.FunctionPointerInvocation: { BoundFunctionPointerInvocation boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)expr; FunctionPointerMethodSymbol signature = boundFunctionPointerInvocation.FunctionPointer.Signature; return GetInvocationEscapeScope(signature, null, (ThreeState)0, signature.Parameters, boundFunctionPointerInvocation.Arguments, boundFunctionPointerInvocation.ArgumentRefKindsOpt, default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.IndexerAccess: { BoundIndexerAccess boundIndexerAccess2 = (BoundIndexerAccess)expr; PropertySymbol indexer2 = boundIndexerAccess2.Indexer; return GetInvocationEscapeScope(indexer2, boundIndexerAccess2.ReceiverOpt, boundIndexerAccess2.InitialBindingReceiverIsSubjectToCloning, indexer2.Parameters, boundIndexerAccess2.Arguments, boundIndexerAccess2.ArgumentRefKindsOpt, boundIndexerAccess2.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.ImplicitIndexerAccess: { BoundImplicitIndexerAccess boundImplicitIndexerAccess = (BoundImplicitIndexerAccess)expr; BoundExpression indexerOrSliceAccess = boundImplicitIndexerAccess.IndexerOrSliceAccess; if (!(indexerOrSliceAccess is BoundIndexerAccess boundIndexerAccess)) { if (!(indexerOrSliceAccess is BoundArrayAccess)) { if (indexerOrSliceAccess is BoundCall boundCall) { return GetInvocationEscapeScope(boundCall.Method, boundImplicitIndexerAccess.Receiver, boundCall.InitialBindingReceiverIsSubjectToCloning, boundCall.Method.Parameters, boundCall.Arguments, boundCall.ArgumentRefKindsOpt, boundCall.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: false); } throw ExceptionUtilities.UnexpectedValue((object)boundImplicitIndexerAccess.IndexerOrSliceAccess.Kind); } return scopeOfTheContainingExpression; } PropertySymbol indexer = boundIndexerAccess.Indexer; return GetInvocationEscapeScope(indexer, boundImplicitIndexerAccess.Receiver, boundIndexerAccess.InitialBindingReceiverIsSubjectToCloning, indexer.Parameters, boundIndexerAccess.Arguments, boundIndexerAccess.ArgumentRefKindsOpt, boundIndexerAccess.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.InlineArrayAccess: { BoundInlineArrayAccess elementAccess = (BoundInlineArrayAccess)expr; ImmutableArray arguments2; ImmutableArray refKinds2; SignatureOnlyMethodSymbol inlineArrayAccessEquivalentSignatureMethod = GetInlineArrayAccessEquivalentSignatureMethod(elementAccess, out arguments2, out refKinds2); return GetInvocationEscapeScope(inlineArrayAccessEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayAccessEquivalentSignatureMethod.Parameters, arguments2, refKinds2, default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)expr; return GetInvocationEscapeScope(boundPropertyAccess.PropertySymbol, boundPropertyAccess.ReceiverOpt, boundPropertyAccess.InitialBindingReceiverIsSubjectToCloning, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: false); } case BoundKind.ObjectCreationExpression: { BoundObjectCreationExpression boundObjectCreationExpression = (BoundObjectCreationExpression)expr; MethodSymbol constructor = boundObjectCreationExpression.Constructor; uint num = GetInvocationEscapeScope(constructor, null, (ThreeState)0, constructor.Parameters, boundObjectCreationExpression.Arguments, boundObjectCreationExpression.ArgumentRefKindsOpt, boundObjectCreationExpression.ArgsToParamsOpt, scopeOfTheContainingExpression, isRefEscape: false); BoundObjectInitializerExpressionBase initializerExpressionOpt = boundObjectCreationExpression.InitializerExpressionOpt; if (initializerExpressionOpt != null) { num = Math.Max(num, GetValEscape(initializerExpressionOpt, scopeOfTheContainingExpression)); } return num; } case BoundKind.WithExpression: { BoundWithExpression boundWithExpression = (BoundWithExpression)expr; return Math.Max(GetValEscape(boundWithExpression.Receiver, scopeOfTheContainingExpression), GetValEscape(boundWithExpression.InitializerExpression, scopeOfTheContainingExpression)); } case BoundKind.UnaryOperator: return GetValEscape(((BoundUnaryOperator)expr).Operand, scopeOfTheContainingExpression); case BoundKind.Conversion: { BoundConversion boundConversion = (BoundConversion)expr; if (boundConversion.ConversionKind == ConversionKind.InterpolatedStringHandler) { return GetInterpolatedStringHandlerConversionEscapeScope(boundConversion.Operand, scopeOfTheContainingExpression); } if (boundConversion.ConversionKind == ConversionKind.CollectionExpression) { if (!HasLocalScope((BoundCollectionExpression)boundConversion.Operand)) { return 0u; } return 2u; } if (boundConversion.Conversion.IsInlineArray) { ImmutableArray arguments; ImmutableArray refKinds; SignatureOnlyMethodSymbol inlineArrayConversionEquivalentSignatureMethod = GetInlineArrayConversionEquivalentSignatureMethod(boundConversion, out arguments, out refKinds); return GetInvocationEscapeScope(inlineArrayConversionEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayConversionEquivalentSignatureMethod.Parameters, arguments, refKinds, default(ImmutableArray), scopeOfTheContainingExpression, isRefEscape: false); } return GetValEscape(boundConversion.Operand, scopeOfTheContainingExpression); } case BoundKind.AssignmentOperator: return GetValEscape(((BoundAssignmentOperator)expr).Right, scopeOfTheContainingExpression); case BoundKind.IncrementOperator: return GetValEscape(((BoundIncrementOperator)expr).Operand, scopeOfTheContainingExpression); case BoundKind.CompoundAssignmentOperator: { BoundCompoundAssignmentOperator boundCompoundAssignmentOperator = (BoundCompoundAssignmentOperator)expr; return Math.Max(GetValEscape(boundCompoundAssignmentOperator.Left, scopeOfTheContainingExpression), GetValEscape(boundCompoundAssignmentOperator.Right, scopeOfTheContainingExpression)); } case BoundKind.BinaryOperator: { BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)expr; return Math.Max(GetValEscape(boundBinaryOperator.Left, scopeOfTheContainingExpression), GetValEscape(boundBinaryOperator.Right, scopeOfTheContainingExpression)); } case BoundKind.RangeExpression: { BoundRangeExpression boundRangeExpression = (BoundRangeExpression)expr; BoundExpression leftOperandOpt = boundRangeExpression.LeftOperandOpt; uint val = ((leftOperandOpt != null) ? GetValEscape(leftOperandOpt, scopeOfTheContainingExpression) : 0); BoundExpression rightOperandOpt = boundRangeExpression.RightOperandOpt; return Math.Max(val, (rightOperandOpt != null) ? GetValEscape(rightOperandOpt, scopeOfTheContainingExpression) : 0u); } case BoundKind.UserDefinedConditionalLogicalOperator: { BoundUserDefinedConditionalLogicalOperator boundUserDefinedConditionalLogicalOperator = (BoundUserDefinedConditionalLogicalOperator)expr; return Math.Max(GetValEscape(boundUserDefinedConditionalLogicalOperator.Left, scopeOfTheContainingExpression), GetValEscape(boundUserDefinedConditionalLogicalOperator.Right, scopeOfTheContainingExpression)); } case BoundKind.QueryClause: return GetValEscape(((BoundQueryClause)expr).Value, scopeOfTheContainingExpression); case BoundKind.RangeVariable: return GetValEscape(((BoundRangeVariable)expr).Value, scopeOfTheContainingExpression); case BoundKind.ObjectInitializerExpression: { BoundObjectInitializerExpression initExpr = (BoundObjectInitializerExpression)expr; return GetValEscapeOfObjectInitializer(initExpr, scopeOfTheContainingExpression); } case BoundKind.CollectionInitializerExpression: { BoundCollectionInitializerExpression boundCollectionInitializerExpression = (BoundCollectionInitializerExpression)expr; return GetValEscape(boundCollectionInitializerExpression.Initializers, scopeOfTheContainingExpression); } case BoundKind.CollectionElementInitializer: { BoundCollectionElementInitializer boundCollectionElementInitializer = (BoundCollectionElementInitializer)expr; return GetValEscape(boundCollectionElementInitializer.Arguments, scopeOfTheContainingExpression); } case BoundKind.ObjectInitializerMember: return scopeOfTheContainingExpression; case BoundKind.ObjectOrCollectionValuePlaceholder: case BoundKind.ImplicitReceiver: return scopeOfTheContainingExpression; case BoundKind.InterpolatedStringHandlerPlaceholder: return scopeOfTheContainingExpression; case BoundKind.DisposableValuePlaceholder: return scopeOfTheContainingExpression; case BoundKind.PointerIndirectionOperator: case BoundKind.PointerElementAccess: return 0u; case BoundKind.ArrayAccess: case BoundKind.AwaitExpression: case BoundKind.AsOperator: case BoundKind.ConditionalAccess: case BoundKind.ConditionalReceiver: return scopeOfTheContainingExpression; case BoundKind.UnconvertedSwitchExpression: case BoundKind.ConvertedSwitchExpression: { BoundSwitchExpression boundSwitchExpression = (BoundSwitchExpression)expr; return GetValEscape(ImmutableArrayExtensions.SelectAsArray(boundSwitchExpression.SwitchArms, (Func)((BoundSwitchExpressionArm a) => a.Value)), scopeOfTheContainingExpression); } default: return scopeOfTheContainingExpression; } } private bool HasLocalScope(BoundCollectionExpression expr) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Invalid comparison between Unknown and I4 //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Invalid comparison between Unknown and I4 TypeSymbol type = expr.Type; if ((object)type == null || !type.IsRefLikeType || expr.Elements.Length == 0) { return false; } TypeWithAnnotations elementType; CollectionExpressionTypeKind collectionExpressionTypeKind = ConversionsBase.GetCollectionExpressionTypeKind(_compilation, expr.Type, out elementType); switch (collectionExpressionTypeKind) { case CollectionExpressionTypeKind.ReadOnlySpan: return !LocalRewriter.ShouldUseRuntimeHelpersCreateSpan(expr, elementType.Type); case CollectionExpressionTypeKind.Span: return true; case CollectionExpressionTypeKind.CollectionBuilder: { MethodSymbol collectionBuilderMethod = expr.CollectionBuilderMethod; if ((object)collectionBuilderMethod != null) { ImmutableArray parameters = collectionBuilderMethod.Parameters; if (parameters.Length == 1) { ParameterSymbol parameterSymbol = parameters[0]; if ((object)parameterSymbol != null && (int)parameterSymbol.RefKind == 0) { if ((int)parameterSymbol.EffectiveScope == 2) { return false; } if (LocalRewriter.ShouldUseRuntimeHelpersCreateSpan(expr, ((NamedTypeSymbol)parameterSymbol.Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].Type)) { return false; } return true; } } } return true; } default: throw ExceptionUtilities.UnexpectedValue((object)collectionExpressionTypeKind); } } private uint GetTupleValEscape(ImmutableArray elements, uint scopeOfTheContainingExpression) { uint num = scopeOfTheContainingExpression; ImmutableArray.Enumerator enumerator = elements.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; num = Math.Max(num, GetValEscape(current, scopeOfTheContainingExpression)); } return num; } private uint GetValEscapeOfObjectInitializer(BoundObjectInitializerExpression initExpr, uint scopeOfTheContainingExpression) { uint num = 0u; ImmutableArray.Enumerator enumerator = initExpr.Initializers.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; if (current.Kind == BoundKind.AssignmentOperator) { BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)current; uint val = (boundAssignmentOperator.IsRef ? GetRefEscape(boundAssignmentOperator.Right, scopeOfTheContainingExpression) : GetValEscape(boundAssignmentOperator.Right, scopeOfTheContainingExpression)); num = Math.Max(num, val); BoundObjectInitializerMember boundObjectInitializerMember = (BoundObjectInitializerMember)boundAssignmentOperator.Left; num = Math.Max(num, GetValEscape(boundObjectInitializerMember.Arguments, scopeOfTheContainingExpression)); } else { num = Math.Max(num, GetValEscape(current, scopeOfTheContainingExpression)); } } return num; } private uint GetValEscape(ImmutableArray expressions, uint scopeOfTheContainingExpression) { uint num = 0u; ImmutableArray.Enumerator enumerator = expressions.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; num = Math.Max(num, GetValEscape(current, scopeOfTheContainingExpression)); } return num; } internal bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint escapeFrom, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_06c5: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_05cd: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0826: Unknown result type (might be due to invalid IL or missing references) if (escapeTo >= escapeFrom) { return true; } if (expr.HasAnyErrors) { return true; } if (expr.ConstantValueOpt != (ConstantValue)null) { return true; } TypeSymbol? type = expr.Type; if ((object)type == null || !type.IsRefLikeType) { return true; } bool inUnsafeRegion = _inUnsafeRegion; switch (expr.Kind) { case BoundKind.ThisReference: { ParameterSymbol thisParameter = _symbol.ThisParameter; return CheckParameterValEscape(node, thisParameter, escapeTo, diagnostics); } case BoundKind.DefaultLiteral: case BoundKind.DefaultExpression: case BoundKind.Utf8String: return true; case BoundKind.Parameter: return CheckParameterValEscape(node, ((BoundParameter)expr).ParameterSymbol, escapeTo, diagnostics); case BoundKind.TupleLiteral: case BoundKind.ConvertedTupleLiteral: { BoundTupleExpression boundTupleExpression = (BoundTupleExpression)expr; return CheckTupleValEscape(boundTupleExpression.Arguments, escapeFrom, escapeTo, diagnostics); } case BoundKind.MakeRefOperator: case BoundKind.RefValueOperator: return true; case BoundKind.DiscardExpression: return true; case BoundKind.DeconstructValuePlaceholder: case BoundKind.AwaitableValuePlaceholder: case BoundKind.InterpolatedStringArgumentPlaceholder: if (GetPlaceholderScope((BoundValuePlaceholderBase)expr) > escapeTo) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_EscapeVariable : ErrorCode.ERR_EscapeVariable, SyntaxNodeOrToken.op_Implicit(node), expr.Syntax); return inUnsafeRegion; } return true; case BoundKind.Local: { LocalSymbol localSymbol = ((BoundLocal)expr).LocalSymbol; if (GetLocalScopes(localSymbol).ValEscapeScope > escapeTo) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_EscapeVariable : ErrorCode.ERR_EscapeVariable, SyntaxNodeOrToken.op_Implicit(node), localSymbol); return inUnsafeRegion; } return true; } case BoundKind.CapturedReceiverPlaceholder: { BoundExpression receiver = ((BoundCapturedReceiverPlaceholder)expr).Receiver; return CheckValEscape(receiver.Syntax, receiver, escapeFrom, escapeTo, checkingReceiver, diagnostics); } case BoundKind.StackAllocArrayCreation: case BoundKind.ConvertedStackAllocExpression: if (escapeTo < 2) { Error(diagnostics, inUnsafeRegion ? ErrorCode.WRN_EscapeStackAlloc : ErrorCode.ERR_EscapeStackAlloc, SyntaxNodeOrToken.op_Implicit(node), expr.Type); return inUnsafeRegion; } return true; case BoundKind.UnconvertedConditionalOperator: { BoundUnconvertedConditionalOperator boundUnconvertedConditionalOperator = (BoundUnconvertedConditionalOperator)expr; if (CheckValEscape(boundUnconvertedConditionalOperator.Consequence.Syntax, boundUnconvertedConditionalOperator.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return CheckValEscape(boundUnconvertedConditionalOperator.Alternative.Syntax, boundUnconvertedConditionalOperator.Alternative, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } case BoundKind.ConditionalOperator: { BoundConditionalOperator boundConditionalOperator = (BoundConditionalOperator)expr; bool flag2 = CheckValEscape(boundConditionalOperator.Consequence.Syntax, boundConditionalOperator.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); if (!flag2 || boundConditionalOperator.IsRef) { return flag2; } return CheckValEscape(boundConditionalOperator.Alternative.Syntax, boundConditionalOperator.Alternative, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.NullCoalescingOperator: { BoundNullCoalescingOperator boundNullCoalescingOperator = (BoundNullCoalescingOperator)expr; if (CheckValEscape(boundNullCoalescingOperator.LeftOperand.Syntax, boundNullCoalescingOperator.LeftOperand, escapeFrom, escapeTo, checkingReceiver, diagnostics)) { return CheckValEscape(boundNullCoalescingOperator.RightOperand.Syntax, boundNullCoalescingOperator.RightOperand, escapeFrom, escapeTo, checkingReceiver, diagnostics); } return false; } case BoundKind.FieldAccess: { BoundFieldAccess boundFieldAccess = (BoundFieldAccess)expr; FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol; if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsRefLikeType) { return true; } return CheckValEscape(node, boundFieldAccess.ReceiverOpt, escapeFrom, escapeTo, checkingReceiver: true, diagnostics); } case BoundKind.Call: { BoundCall boundCall2 = (BoundCall)expr; MethodSymbol method2 = boundCall2.Method; return CheckInvocationEscape(boundCall2.Syntax, method2, boundCall2.ReceiverOpt, boundCall2.InitialBindingReceiverIsSubjectToCloning, method2.Parameters, boundCall2.Arguments, boundCall2.ArgumentRefKindsOpt, boundCall2.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.FunctionPointerInvocation: { BoundFunctionPointerInvocation boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)expr; FunctionPointerMethodSymbol signature = boundFunctionPointerInvocation.FunctionPointer.Signature; return CheckInvocationEscape(boundFunctionPointerInvocation.Syntax, signature, null, (ThreeState)0, signature.Parameters, boundFunctionPointerInvocation.Arguments, boundFunctionPointerInvocation.ArgumentRefKindsOpt, default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.IndexerAccess: { BoundIndexerAccess boundIndexerAccess2 = (BoundIndexerAccess)expr; PropertySymbol indexer2 = boundIndexerAccess2.Indexer; return CheckInvocationEscape(boundIndexerAccess2.Syntax, indexer2, boundIndexerAccess2.ReceiverOpt, boundIndexerAccess2.InitialBindingReceiverIsSubjectToCloning, indexer2.Parameters, boundIndexerAccess2.Arguments, boundIndexerAccess2.ArgumentRefKindsOpt, boundIndexerAccess2.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.ImplicitIndexerAccess: { BoundImplicitIndexerAccess boundImplicitIndexerAccess = (BoundImplicitIndexerAccess)expr; BoundExpression indexerOrSliceAccess = boundImplicitIndexerAccess.IndexerOrSliceAccess; if (!(indexerOrSliceAccess is BoundIndexerAccess boundIndexerAccess)) { if (!(indexerOrSliceAccess is BoundArrayAccess)) { if (indexerOrSliceAccess is BoundCall boundCall) { MethodSymbol method = boundCall.Method; return CheckInvocationEscape(boundCall.Syntax, method, boundImplicitIndexerAccess.Receiver, boundCall.InitialBindingReceiverIsSubjectToCloning, method.Parameters, boundCall.Arguments, boundCall.ArgumentRefKindsOpt, boundCall.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } throw ExceptionUtilities.UnexpectedValue((object)boundImplicitIndexerAccess.IndexerOrSliceAccess.Kind); } return false; } PropertySymbol indexer = boundIndexerAccess.Indexer; return CheckInvocationEscape(boundIndexerAccess.Syntax, indexer, boundImplicitIndexerAccess.Receiver, boundIndexerAccess.InitialBindingReceiverIsSubjectToCloning, indexer.Parameters, boundIndexerAccess.Arguments, boundIndexerAccess.ArgumentRefKindsOpt, boundIndexerAccess.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.InlineArrayAccess: { BoundInlineArrayAccess boundInlineArrayAccess = (BoundInlineArrayAccess)expr; ImmutableArray arguments; ImmutableArray refKinds; SignatureOnlyMethodSymbol inlineArrayAccessEquivalentSignatureMethod = GetInlineArrayAccessEquivalentSignatureMethod(boundInlineArrayAccess, out arguments, out refKinds); return CheckInvocationEscape(boundInlineArrayAccess.Syntax, inlineArrayAccessEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayAccessEquivalentSignatureMethod.Parameters, arguments, refKinds, default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.PropertyAccess: { BoundPropertyAccess boundPropertyAccess = (BoundPropertyAccess)expr; return CheckInvocationEscape(boundPropertyAccess.Syntax, boundPropertyAccess.PropertySymbol, boundPropertyAccess.ReceiverOpt, boundPropertyAccess.InitialBindingReceiverIsSubjectToCloning, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } case BoundKind.ObjectCreationExpression: { BoundObjectCreationExpression boundObjectCreationExpression = (BoundObjectCreationExpression)expr; MethodSymbol constructor = boundObjectCreationExpression.Constructor; bool flag = CheckInvocationEscape(boundObjectCreationExpression.Syntax, constructor, null, (ThreeState)0, constructor.Parameters, boundObjectCreationExpression.Arguments, boundObjectCreationExpression.ArgumentRefKindsOpt, boundObjectCreationExpression.ArgsToParamsOpt, checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); BoundObjectInitializerExpressionBase initializerExpressionOpt = boundObjectCreationExpression.InitializerExpressionOpt; if (initializerExpressionOpt != null) { flag = flag && CheckValEscape(initializerExpressionOpt.Syntax, initializerExpressionOpt, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return flag; } case BoundKind.WithExpression: { BoundWithExpression boundWithExpression = (BoundWithExpression)expr; bool num = CheckValEscape(node, boundWithExpression.Receiver, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); BoundObjectInitializerExpressionBase initializerExpression = boundWithExpression.InitializerExpression; if (num) { return CheckValEscape(initializerExpression.Syntax, initializerExpression, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } case BoundKind.UnaryOperator: { BoundUnaryOperator boundUnaryOperator = (BoundUnaryOperator)expr; return CheckValEscape(node, boundUnaryOperator.Operand, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.FromEndIndexExpression: return true; case BoundKind.Conversion: { BoundConversion boundConversion = (BoundConversion)expr; if (boundConversion.ConversionKind == ConversionKind.InterpolatedStringHandler) { return CheckInterpolatedStringHandlerConversionEscape(boundConversion.Operand, escapeFrom, escapeTo, diagnostics); } if (boundConversion.ConversionKind == ConversionKind.CollectionExpression) { if (HasLocalScope((BoundCollectionExpression)boundConversion.Operand) && escapeTo < 2) { Error(diagnostics, ErrorCode.ERR_CollectionExpressionEscape, SyntaxNodeOrToken.op_Implicit(node), expr.Type); return false; } return true; } if (boundConversion.Conversion.IsInlineArray) { ImmutableArray arguments2; ImmutableArray refKinds2; SignatureOnlyMethodSymbol inlineArrayConversionEquivalentSignatureMethod = GetInlineArrayConversionEquivalentSignatureMethod(boundConversion, out arguments2, out refKinds2); return CheckInvocationEscape(boundConversion.Syntax, inlineArrayConversionEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayConversionEquivalentSignatureMethod.Parameters, arguments2, refKinds2, default(ImmutableArray), checkingReceiver, escapeFrom, escapeTo, diagnostics, isRefEscape: false); } return CheckValEscape(node, boundConversion.Operand, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.AssignmentOperator: { BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)expr; return CheckValEscape(node, boundAssignmentOperator.Left, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.IncrementOperator: { BoundIncrementOperator boundIncrementOperator = (BoundIncrementOperator)expr; return CheckValEscape(node, boundIncrementOperator.Operand, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.CompoundAssignmentOperator: { BoundCompoundAssignmentOperator boundCompoundAssignmentOperator = (BoundCompoundAssignmentOperator)expr; if (CheckValEscape(boundCompoundAssignmentOperator.Left.Syntax, boundCompoundAssignmentOperator.Left, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return CheckValEscape(boundCompoundAssignmentOperator.Right.Syntax, boundCompoundAssignmentOperator.Right, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } case BoundKind.BinaryOperator: { BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)expr; if (boundBinaryOperator.OperatorKind == BinaryOperatorKind.Utf8Addition) { return true; } if (CheckValEscape(boundBinaryOperator.Left.Syntax, boundBinaryOperator.Left, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return CheckValEscape(boundBinaryOperator.Right.Syntax, boundBinaryOperator.Right, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } case BoundKind.RangeExpression: { BoundRangeExpression boundRangeExpression = (BoundRangeExpression)expr; BoundExpression leftOperandOpt = boundRangeExpression.LeftOperandOpt; if (leftOperandOpt != null && !CheckValEscape(leftOperandOpt.Syntax, leftOperandOpt, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return false; } BoundExpression rightOperandOpt = boundRangeExpression.RightOperandOpt; if (rightOperandOpt != null) { return CheckValEscape(rightOperandOpt.Syntax, rightOperandOpt, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return true; } case BoundKind.UserDefinedConditionalLogicalOperator: { BoundUserDefinedConditionalLogicalOperator boundUserDefinedConditionalLogicalOperator = (BoundUserDefinedConditionalLogicalOperator)expr; if (CheckValEscape(boundUserDefinedConditionalLogicalOperator.Left.Syntax, boundUserDefinedConditionalLogicalOperator.Left, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return CheckValEscape(boundUserDefinedConditionalLogicalOperator.Right.Syntax, boundUserDefinedConditionalLogicalOperator.Right, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } return false; } case BoundKind.QueryClause: { BoundExpression value3 = ((BoundQueryClause)expr).Value; return CheckValEscape(value3.Syntax, value3, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.RangeVariable: { BoundExpression value2 = ((BoundRangeVariable)expr).Value; return CheckValEscape(value2.Syntax, value2, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); } case BoundKind.ObjectInitializerExpression: { BoundObjectInitializerExpression initExpr = (BoundObjectInitializerExpression)expr; return CheckValEscapeOfObjectInitializer(initExpr, escapeFrom, escapeTo, diagnostics); } case BoundKind.CollectionInitializerExpression: { BoundCollectionInitializerExpression boundCollectionInitializerExpression = (BoundCollectionInitializerExpression)expr; return CheckValEscape(boundCollectionInitializerExpression.Initializers, escapeFrom, escapeTo, diagnostics); } case BoundKind.CollectionElementInitializer: { BoundCollectionElementInitializer boundCollectionElementInitializer = (BoundCollectionElementInitializer)expr; return CheckValEscape(boundCollectionElementInitializer.Arguments, escapeFrom, escapeTo, diagnostics); } case BoundKind.PointerElementAccess: { BoundExpression expression = ((BoundPointerElementAccess)expr).Expression; return CheckValEscape(expression.Syntax, expression, escapeFrom, escapeTo, checkingReceiver, diagnostics); } case BoundKind.PointerIndirectionOperator: { BoundExpression operand = ((BoundPointerIndirectionOperator)expr).Operand; return CheckValEscape(operand.Syntax, operand, escapeFrom, escapeTo, checkingReceiver, diagnostics); } case BoundKind.ArrayAccess: case BoundKind.AwaitExpression: case BoundKind.AsOperator: case BoundKind.ConditionalAccess: return false; case BoundKind.UnconvertedSwitchExpression: case BoundKind.ConvertedSwitchExpression: { ImmutableArray.Enumerator enumerator = ((BoundSwitchExpression)expr).SwitchArms.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression value = enumerator.Current.Value; if (!CheckValEscape(value.Syntax, value, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return false; } } return true; } default: diagnostics.Add(ErrorCode.ERR_InternalError, node.Location); return false; } } private SignatureOnlyMethodSymbol GetInlineArrayAccessEquivalentSignatureMethod(BoundInlineArrayAccess elementAccess, out ImmutableArray arguments, out ImmutableArray refKinds) { //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_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0077: Unknown result type (might be due to invalid IL or missing references) WellKnownMember getItemOrSliceHelper = elementAccess.GetItemOrSliceHelper; RefKind val; RefKind val2; if (((int)getItemOrSliceHelper == 400 || (int)getItemOrSliceHelper == 406) ? true : false) { if (elementAccess.IsValue) { val = (RefKind)0; val2 = (RefKind)0; } else { val = (RefKind)(((int)elementAccess.GetItemOrSliceHelper != 406) ? 1 : 3); val2 = val; } } else { getItemOrSliceHelper = elementAccess.GetItemOrSliceHelper; if (((int)getItemOrSliceHelper != 402 && (int)getItemOrSliceHelper != 408) || 1 == 0) { throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs", 4765); } val = (RefKind)0; val2 = (RefKind)(((int)elementAccess.GetItemOrSliceHelper != 408) ? 1 : 3); } SignatureOnlyMethodSymbol result = new SignatureOnlyMethodSymbol("", _symbol.ContainingType, (MethodKind)10, (CallingConvention)0, ImmutableArray.Empty, ImmutableArray.Create((ParameterSymbol)new SignatureOnlyParameterSymbol(TypeWithAnnotations.Create(elementAccess.Expression.Type), ImmutableArray.Empty, isParams: false, val2)), val, isInitOnly: false, isStatic: true, TypeWithAnnotations.Create(elementAccess.Type), ImmutableArray.Empty, ImmutableArray.Empty); arguments = ImmutableArray.Create(elementAccess.Expression); refKinds = ImmutableArray.Create(val2); return result; } private SignatureOnlyMethodSymbol GetInlineArrayConversionEquivalentSignatureMethod(BoundConversion conversion, out ImmutableArray arguments, out ImmutableArray refKinds) { return GetInlineArrayConversionEquivalentSignatureMethod(conversion.Operand, conversion.Type, out arguments, out refKinds); } private SignatureOnlyMethodSymbol GetInlineArrayConversionEquivalentSignatureMethod(BoundExpression inlineArray, TypeSymbol resultType, out ImmutableArray arguments, out ImmutableArray refKinds) { //IL_0023: 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_0092: Unknown result type (might be due to invalid IL or missing references) RefKind val = (RefKind)((!resultType.OriginalDefinition.Equals(_compilation.GetWellKnownType((WellKnownType)276), (TypeCompareKind)63)) ? 1 : 3); SignatureOnlyMethodSymbol result = new SignatureOnlyMethodSymbol("", _symbol.ContainingType, (MethodKind)10, (CallingConvention)0, ImmutableArray.Empty, ImmutableArray.Create((ParameterSymbol)new SignatureOnlyParameterSymbol(TypeWithAnnotations.Create(inlineArray.Type), ImmutableArray.Empty, isParams: false, val)), (RefKind)0, isInitOnly: false, isStatic: true, TypeWithAnnotations.Create(resultType), ImmutableArray.Empty, ImmutableArray.Empty); arguments = ImmutableArray.Create(inlineArray); refKinds = ImmutableArray.Create(val); return result; } private bool CheckTupleValEscape(ImmutableArray elements, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { ImmutableArray.Enumerator enumerator = elements.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; if (!CheckValEscape(current.Syntax, current, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return false; } } return true; } private bool CheckValEscapeOfObjectInitializer(BoundObjectInitializerExpression initExpr, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { ImmutableArray.Enumerator enumerator = initExpr.Initializers.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; if (current.Kind == BoundKind.AssignmentOperator) { BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)current; if (!(boundAssignmentOperator.IsRef ? CheckRefEscape(current.Syntax, boundAssignmentOperator.Right, escapeFrom, escapeTo, checkingReceiver: false, diagnostics) : CheckValEscape(current.Syntax, boundAssignmentOperator.Right, escapeFrom, escapeTo, checkingReceiver: false, diagnostics))) { return false; } BoundObjectInitializerMember boundObjectInitializerMember = (BoundObjectInitializerMember)boundAssignmentOperator.Left; if (!CheckValEscape(boundObjectInitializerMember.Arguments, escapeFrom, escapeTo, diagnostics)) { return false; } } else if (!CheckValEscape(current.Syntax, current, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return false; } } return true; } private bool CheckValEscape(ImmutableArray expressions, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { ImmutableArray.Enumerator enumerator = expressions.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; if (!CheckValEscape(current.Syntax, current, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { return false; } } return true; } private bool CheckInterpolatedStringHandlerConversionEscape(BoundExpression expression, uint escapeFrom, uint escapeTo, BindingDiagnosticBag diagnostics) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) InterpolatedStringHandlerData interpolatedStringHandlerData = expression.GetInterpolatedStringHandlerData(); CheckValEscape(expression.Syntax, interpolatedStringHandlerData.Construction, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); ArrayBuilder instance = ArrayBuilder.GetInstance(); GetInterpolatedStringHandlerArgumentsForEscape(expression, instance); bool result = true; Enumerator enumerator = instance.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; if (!CheckValEscape(current.Syntax, current, escapeFrom, escapeTo, checkingReceiver: false, diagnostics)) { result = false; break; } } instance.Free(); return result; } private void GetInterpolatedStringHandlerArgumentsForEscape(BoundExpression expression, ArrayBuilder arguments) { while (expression is BoundBinaryOperator boundBinaryOperator) { GetInterpolatedStringHandlerArgumentsForEscape(boundBinaryOperator.Right, arguments); expression = boundBinaryOperator.Left; } if (expression is BoundInterpolatedString interpolatedString) { getParts(interpolatedString); return; } throw ExceptionUtilities.UnexpectedValue((object)expression.Kind); void getParts(BoundInterpolatedString boundInterpolatedString) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 ImmutableArray.Enumerator enumerator = boundInterpolatedString.Parts.GetEnumerator(); while (enumerator.MoveNext()) { if (enumerator.Current is BoundCall boundCall) { MethodSymbol method = boundCall.Method; if ((object)method != null && method.Name == "AppendFormatted" && (!_useUpdatedEscapeRules || (int)boundCall.Method.Parameters[0].EffectiveScope != 2)) { arguments.Add(boundCall.Arguments[0]); } } } } } private void ValidateRefConditionalOperator(SyntaxNode node, BoundExpression trueExpr, BoundExpression falseExpr, BindingDiagnosticBag diagnostics) { uint localScopeDepth = _localScopeDepth; uint valEscape = GetValEscape(trueExpr, localScopeDepth); uint valEscape2 = GetValEscape(falseExpr, localScopeDepth); if (valEscape != valEscape2) { if (valEscape < valEscape2) { CheckValEscape(falseExpr.Syntax, falseExpr, localScopeDepth, valEscape, checkingReceiver: false, diagnostics); } else { CheckValEscape(trueExpr.Syntax, trueExpr, localScopeDepth, valEscape2, checkingReceiver: false, diagnostics); } diagnostics.Add(_inUnsafeRegion ? ErrorCode.WRN_MismatchedRefEscapeInTernary : ErrorCode.ERR_MismatchedRefEscapeInTernary, node.Location); } } private void ValidateAssignment(SyntaxNode node, BoundExpression op1, BoundExpression op2, bool isRef, BindingDiagnosticBag diagnostics) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) if (op1.HasAnyErrors) { return; } bool flag = false; if (isRef) { uint refEscape = GetRefEscape(op1, _localScopeDepth); uint refEscape2 = GetRefEscape(op2, _localScopeDepth); if (refEscape < refEscape2) { bool inUnsafeRegion = _inUnsafeRegion; ErrorCode errorCode = ((refEscape2 == 1) ? (inUnsafeRegion ? ErrorCode.WRN_RefAssignReturnOnly : ErrorCode.ERR_RefAssignReturnOnly) : (inUnsafeRegion ? ErrorCode.WRN_RefAssignNarrower : ErrorCode.ERR_RefAssignNarrower)); ErrorCode code = errorCode; Error(diagnostics, code, SyntaxNodeOrToken.op_Implicit(node), getName(op1), op2.Syntax); if (!_inUnsafeRegion) { flag = true; } } else { BoundKind kind = op1.Kind; if ((kind == BoundKind.Local || kind == BoundKind.Parameter) ? true : false) { uint valEscape = GetValEscape(op1, _localScopeDepth); refEscape2 = GetValEscape(op2, _localScopeDepth); if (valEscape > refEscape2) { ErrorCode code2 = (_inUnsafeRegion ? ErrorCode.WRN_RefAssignValEscapeWider : ErrorCode.ERR_RefAssignValEscapeWider); Error(diagnostics, code2, SyntaxNodeOrToken.op_Implicit(node), getName(op1), op2.Syntax); if (!_inUnsafeRegion) { flag = true; } } } } } if (!flag && op1.Type.IsRefLikeType) { uint valEscape2 = GetValEscape(op1, _localScopeDepth); ValidateEscape(op2, valEscape2, isByRef: false, diagnostics); } static object getName(BoundExpression expr) { Symbol expressionSymbol = expr.ExpressionSymbol; if ((object)expressionSymbol != null) { return expressionSymbol.Name; } if (expr is BoundArrayAccess) { return MessageID.IDS_ArrayAccess.Localize(); } if (expr is BoundPointerElementAccess) { return MessageID.IDS_PointerElementAccess.Localize(); } return ""; } } internal static void Analyze(CSharpCompilation compilation, MethodSymbol symbol, BoundNode node, BindingDiagnosticBag diagnostics) { RefSafetyAnalysis refSafetyAnalysis = new RefSafetyAnalysis(compilation, symbol, InUnsafeMethod(symbol), symbol.ContainingModule.UseUpdatedEscapeRules, diagnostics); try { refSafetyAnalysis.Visit(node); } catch (CancelledByStackGuardException ex) { ex.AddAnError(diagnostics); } } private static bool InUnsafeMethod(Symbol symbol) { if (symbol is SourceMemberMethodSymbol { IsUnsafe: not false }) { return true; } NamedTypeSymbol containingType = symbol.ContainingType; while ((object)containingType != null) { NamedTypeSymbol originalDefinition = containingType.OriginalDefinition; if (originalDefinition is SourceMemberContainerTypeSymbol { IsUnsafe: not false }) { return true; } containingType = originalDefinition.ContainingType; } return false; } private RefSafetyAnalysis(CSharpCompilation compilation, MethodSymbol symbol, bool inUnsafeRegion, bool useUpdatedEscapeRules, BindingDiagnosticBag diagnostics, Dictionary? localEscapeScopes = null) { _compilation = compilation; _symbol = symbol; _useUpdatedEscapeRules = useUpdatedEscapeRules; _diagnostics = diagnostics; _inUnsafeRegion = inUnsafeRegion; _localScopeDepth = 1u; _localEscapeScopes = localEscapeScopes; } private (uint RefEscapeScope, uint ValEscapeScope) GetLocalScopes(LocalSymbol local) { Dictionary? localEscapeScopes = _localEscapeScopes; if (localEscapeScopes == null || !localEscapeScopes.TryGetValue(local, out (uint, uint) value)) { return (RefEscapeScope: 0u, ValEscapeScope: 0u); } return value; } private void SetLocalScopes(LocalSymbol local, uint refEscapeScope, uint valEscapeScope) { AddOrSetLocalScopes(local, refEscapeScope, valEscapeScope); } private void AddPlaceholderScope(BoundValuePlaceholderBase placeholder, uint valEscapeScope) { if (_placeholderScopes == null) { _placeholderScopes = new Dictionary(); } _placeholderScopes[placeholder] = valEscapeScope; } private void RemovePlaceholderScope(BoundValuePlaceholderBase placeholder) { } private uint GetPlaceholderScope(BoundValuePlaceholderBase placeholder) { Dictionary? placeholderScopes = _placeholderScopes; if (placeholderScopes == null || !placeholderScopes.TryGetValue(placeholder, out var value)) { return 0u; } return value; } public override BoundNode? VisitBlock(BoundBlock node) { UnsafeRegion unsafeRegion = new UnsafeRegion(this, _inUnsafeRegion || node.HasUnsafeModifier); try { using (new LocalScope(this, node.Locals)) { return base.VisitBlock(node); } } finally { unsafeRegion.Dispose(); } } public override BoundNode? Visit(BoundNode? node) { return base.Visit(node); } public override BoundNode? VisitFieldEqualsValue(BoundFieldEqualsValue node) { throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs", 293); } public override BoundNode? VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { LocalFunctionSymbol symbol = node.Symbol; RefSafetyAnalysis refSafetyAnalysis = new RefSafetyAnalysis(_compilation, symbol, _inUnsafeRegion || symbol.IsUnsafe, _useUpdatedEscapeRules, _diagnostics, _localEscapeScopes); refSafetyAnalysis.Visit(node.BlockBody); refSafetyAnalysis.Visit(node.ExpressionBody); return null; } public override BoundNode? VisitLambda(BoundLambda node) { LambdaSymbol symbol = node.Symbol; new RefSafetyAnalysis(_compilation, symbol, _inUnsafeRegion, _useUpdatedEscapeRules, _diagnostics, _localEscapeScopes).Visit(node.Body); return null; } public override BoundNode? VisitConstructorMethodBody(BoundConstructorMethodBody node) { using (new LocalScope(this, node.Locals)) { return base.VisitConstructorMethodBody(node); } } public override BoundNode? VisitForStatement(BoundForStatement node) { using (new LocalScope(this, node.OuterLocals)) { using (new LocalScope(this, node.InnerLocals)) { return base.VisitForStatement(node); } } } public override BoundNode? VisitUsingStatement(BoundUsingStatement node) { using (new LocalScope(this, node.Locals)) { Visit(node.DeclarationsOpt); Visit(node.ExpressionOpt); ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); BoundAwaitableInfo awaitOpt = node.AwaitOpt; if (awaitOpt != null) { BoundExpression expressionOpt = node.ExpressionOpt; uint valEscapeScope = ((expressionOpt != null) ? GetValEscape(expressionOpt, _localScopeDepth) : _localScopeDepth); GetAwaitableInstancePlaceholders(instance, awaitOpt, valEscapeScope); } using (new PlaceholderRegion(this, instance)) { Visit(node.AwaitOpt); Visit(node.Body); return null; } } } public override BoundNode? VisitUsingLocalDeclarations(BoundUsingLocalDeclarations node) { ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); BoundAwaitableInfo awaitOpt = node.AwaitOpt; if (awaitOpt != null) { GetAwaitableInstancePlaceholders(instance, awaitOpt, _localScopeDepth); } using (new PlaceholderRegion(this, instance)) { return base.VisitUsingLocalDeclarations(node); } } public override BoundNode? VisitFixedStatement(BoundFixedStatement node) { using (new LocalScope(this, node.Locals)) { return base.VisitFixedStatement(node); } } public override BoundNode? VisitDoStatement(BoundDoStatement node) { using (new LocalScope(this, node.Locals)) { return base.VisitDoStatement(node); } } public override BoundNode? VisitWhileStatement(BoundWhileStatement node) { using (new LocalScope(this, node.Locals)) { return base.VisitWhileStatement(node); } } public override BoundNode? VisitSwitchStatement(BoundSwitchStatement node) { Visit(node.Expression); using (new LocalScope(this, node.InnerLocals)) { using (new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth))) { VisitList(node.SwitchSections); Visit(node.DefaultLabel); return null; } } } public override BoundNode? VisitConvertedSwitchExpression(BoundConvertedSwitchExpression node) { Visit(node.Expression); using (new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth))) { VisitList(node.SwitchArms); return null; } } public override BoundNode? VisitSwitchSection(BoundSwitchSection node) { using (new LocalScope(this, node.Locals)) { return base.VisitSwitchSection(node); } } public override BoundNode? VisitSwitchExpressionArm(BoundSwitchExpressionArm node) { using (new LocalScope(this, node.Locals)) { return base.VisitSwitchExpressionArm(node); } } public override BoundNode? VisitCatchBlock(BoundCatchBlock node) { using (new LocalScope(this, node.Locals)) { return base.VisitCatchBlock(node); } } public override BoundNode? VisitLocal(BoundLocal node) { return base.VisitLocal(node); } private void AddLocalScopes(LocalSymbol local, uint refEscapeScope, uint valEscapeScope) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 ScopedKind val = (ScopedKind)(_useUpdatedEscapeRules ? ((int)local.Scope) : 0); if ((int)val != 0) { refEscapeScope = (((int)val == 1) ? _localScopeDepth : 2u); valEscapeScope = (((int)val == 2) ? _localScopeDepth : 0u); } AddOrSetLocalScopes(local, refEscapeScope, valEscapeScope); } private void AddOrSetLocalScopes(LocalSymbol local, uint refEscapeScope, uint valEscapeScope) { if (_localEscapeScopes == null) { _localEscapeScopes = new Dictionary(); } _localEscapeScopes[local] = (refEscapeScope, valEscapeScope); } private void RemoveLocalScopes(LocalSymbol local) { } public override BoundNode? VisitLocalDeclaration(BoundLocalDeclaration node) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) base.VisitLocalDeclaration(node); BoundExpression initializerOpt = node.InitializerOpt; if (initializerOpt != null) { SourceLocalSymbol sourceLocalSymbol = (SourceLocalSymbol)node.LocalSymbol; uint refEscapeScope; uint escapeTo; (refEscapeScope, escapeTo) = GetLocalScopes(sourceLocalSymbol); if (_useUpdatedEscapeRules && (int)sourceLocalSymbol.Scope != 0) { BoundTypeExpression? declaredTypeOpt = node.DeclaredTypeOpt; if (declaredTypeOpt != null && declaredTypeOpt.Type.IsRefLikeType) { ValidateEscape(initializerOpt, escapeTo, isByRef: false, _diagnostics); } } else { SetLocalScopes(sourceLocalSymbol, _localScopeDepth, _localScopeDepth); escapeTo = GetValEscape(initializerOpt, _localScopeDepth); if ((int)sourceLocalSymbol.RefKind != 0) { refEscapeScope = GetRefEscape(initializerOpt, _localScopeDepth); } SetLocalScopes(sourceLocalSymbol, refEscapeScope, escapeTo); } } return null; } public override BoundNode? VisitReturnStatement(BoundReturnStatement node) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 base.VisitReturnStatement(node); BoundExpression expressionOpt = node.ExpressionOpt; if (expressionOpt != null && (object)expressionOpt.Type != null) { ValidateEscape(expressionOpt, 1u, (int)node.RefKind > 0, _diagnostics); } return null; } public override BoundNode? VisitYieldReturnStatement(BoundYieldReturnStatement node) { base.VisitYieldReturnStatement(node); BoundExpression expression = node.Expression; if (expression != null && (object)expression.Type != null) { ValidateEscape(expression, 1u, isByRef: false, _diagnostics); } return null; } public override BoundNode? VisitAssignmentOperator(BoundAssignmentOperator node) { base.VisitAssignmentOperator(node); if (node.Left.Kind != BoundKind.DiscardExpression) { ValidateAssignment(node.Syntax, node.Left, node.Right, node.IsRef, _diagnostics); } return null; } public override BoundNode? VisitIsPatternExpression(BoundIsPatternExpression node) { Visit(node.Expression); using (new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth))) { Visit(node.Pattern); return null; } } public override BoundNode? VisitDeclarationPattern(BoundDeclarationPattern node) { SetPatternLocalScopes(node); using (new PatternInput(this, getDeclarationValEscape(node.DeclaredType, _patternInputValEscape))) { return base.VisitDeclarationPattern(node); } static uint getDeclarationValEscape(BoundTypeExpression typeExpression, uint valEscape) { if (!typeExpression.Type.IsRefLikeType) { return 0u; } return valEscape; } } public override BoundNode? VisitListPattern(BoundListPattern node) { SetPatternLocalScopes(node); return base.VisitListPattern(node); } public override BoundNode? VisitRecursivePattern(BoundRecursivePattern node) { SetPatternLocalScopes(node); return base.VisitRecursivePattern(node); } public override BoundNode? VisitPositionalSubpattern(BoundPositionalSubpattern node) { using (new PatternInput(this, getPositionalValEscape(node.Symbol, _patternInputValEscape))) { return base.VisitPositionalSubpattern(node); } static uint getPositionalValEscape(Symbol? symbol, uint valEscape) { if ((object)symbol != null) { if (!symbol.GetTypeOrReturnType().IsRefLikeType()) { return 0u; } return valEscape; } return valEscape; } } public override BoundNode? VisitPropertySubpattern(BoundPropertySubpattern node) { using (new PatternInput(this, getMemberValEscape(node.Member, _patternInputValEscape))) { return base.VisitPropertySubpattern(node); } static uint getMemberValEscape(BoundPropertySubpatternMember? member, uint valEscape) { if (member == null) { return valEscape; } valEscape = getMemberValEscape(member.Receiver, valEscape); if (!member.Type.IsRefLikeType) { return 0u; } return valEscape; } } private void SetPatternLocalScopes(BoundObjectPattern pattern) { if (pattern.Variable is LocalSymbol local) { SetLocalScopes(local, _localScopeDepth, _patternInputValEscape); } } public override BoundNode? VisitConditionalOperator(BoundConditionalOperator node) { base.VisitConditionalOperator(node); if (node.IsRef) { ValidateRefConditionalOperator(node.Syntax, node.Consequence, node.Alternative, _diagnostics); } return null; } private void VisitArgumentsAndGetArgumentPlaceholders(BoundExpression? receiverOpt, ImmutableArray arguments) { for (int num = 0; num < arguments.Length; num++) { BoundExpression boundExpression = arguments[num]; BoundConversion boundConversion = boundExpression as BoundConversion; bool flag; if (boundConversion != null && boundConversion.ConversionKind == ConversionKind.InterpolatedStringHandler) { BoundExpression operand = boundConversion.Operand; if (operand is BoundInterpolatedString || operand is BoundBinaryOperator) { flag = true; goto IL_0040; } } flag = false; goto IL_0040; IL_0040: if (flag) { InterpolatedStringHandlerData interpolationData = boundConversion.Operand.GetInterpolatedStringHandlerData(); ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); GetInterpolatedStringPlaceholders(instance, in interpolationData, receiverOpt, num, arguments); new PlaceholderRegion(this, instance); } Visit(boundExpression); } } protected override void VisitArguments(BoundCall node) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) VisitArgumentsAndGetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); if (!node.HasErrors) { MethodSymbol method = node.Method; CheckInvocationArgMixing(node.Syntax, method, node.ReceiverOpt, node.InitialBindingReceiverIsSubjectToCloning, method.Parameters, node.Arguments, node.ArgumentRefKindsOpt, node.ArgsToParamsOpt, _localScopeDepth, _diagnostics); } } private void GetInterpolatedStringPlaceholders(ArrayBuilder<(BoundValuePlaceholderBase, uint)> placeholders, in InterpolatedStringHandlerData interpolationData, BoundExpression? receiver, int nArgumentsVisited, ImmutableArray arguments) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) placeholders.Add(((BoundValuePlaceholderBase)interpolationData.ReceiverPlaceholder, _localScopeDepth)); ImmutableArray.Enumerator enumerator = interpolationData.ArgumentPlaceholders.GetEnumerator(); while (enumerator.MoveNext()) { BoundInterpolatedStringArgumentPlaceholder current = enumerator.Current; int argumentIndex = current.ArgumentIndex; uint item; if (argumentIndex >= 0) { item = ((argumentIndex < nArgumentsVisited) ? GetValEscape(arguments[argumentIndex], _localScopeDepth) : 0u); } else { switch (argumentIndex) { case -1: break; default: throw ExceptionUtilities.UnexpectedValue((object)current.ArgumentIndex); case -3: case -2: continue; } item = ((receiver != null) ? (receiver.GetRefKind().IsWritableReference() ? GetRefEscape(receiver, _localScopeDepth) : GetValEscape(receiver, _localScopeDepth)) : 0u); } placeholders.Add(((BoundValuePlaceholderBase)current, item)); } } public override BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) { VisitObjectCreationExpressionBase(node); return null; } public override BoundNode? VisitDynamicObjectCreationExpression(BoundDynamicObjectCreationExpression node) { VisitObjectCreationExpressionBase(node); return null; } public override BoundNode? VisitNewT(BoundNewT node) { VisitObjectCreationExpressionBase(node); return null; } public override BoundNode? VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node) { VisitObjectCreationExpressionBase(node); return null; } private void VisitObjectCreationExpressionBase(BoundObjectCreationExpressionBase node) { VisitArgumentsAndGetArgumentPlaceholders(null, node.Arguments); Visit(node.InitializerExpressionOpt); if (!node.HasErrors) { MethodSymbol constructor = node.Constructor; if ((object)constructor != null) { CheckInvocationArgMixing(node.Syntax, constructor, null, (ThreeState)0, constructor.Parameters, node.Arguments, node.ArgumentRefKindsOpt, node.ArgsToParamsOpt, _localScopeDepth, _diagnostics); } } } public override BoundNode? VisitPropertyAccess(BoundPropertyAccess node) { return base.VisitPropertyAccess(node); } public override BoundNode? VisitIndexerAccess(BoundIndexerAccess node) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) Visit(node.ReceiverOpt); VisitArgumentsAndGetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); if (!node.HasErrors) { PropertySymbol indexer = node.Indexer; CheckInvocationArgMixing(node.Syntax, indexer, node.ReceiverOpt, node.InitialBindingReceiverIsSubjectToCloning, indexer.Parameters, node.Arguments, node.ArgumentRefKindsOpt, node.ArgsToParamsOpt, _localScopeDepth, _diagnostics); } return null; } public override BoundNode? VisitFunctionPointerInvocation(BoundFunctionPointerInvocation node) { VisitArgumentsAndGetArgumentPlaceholders(null, node.Arguments); if (!node.HasErrors) { FunctionPointerMethodSymbol signature = node.FunctionPointer.Signature; CheckInvocationArgMixing(node.Syntax, signature, null, (ThreeState)0, signature.Parameters, node.Arguments, node.ArgumentRefKindsOpt, default(ImmutableArray), _localScopeDepth, _diagnostics); } return null; } public override BoundNode? VisitAwaitExpression(BoundAwaitExpression node) { Visit(node.Expression); ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); GetAwaitableInstancePlaceholders(instance, node.AwaitableInfo, GetValEscape(node.Expression, _localScopeDepth)); using (new PlaceholderRegion(this, instance)) { Visit(node.AwaitableInfo); return null; } } private void GetAwaitableInstancePlaceholders(ArrayBuilder<(BoundValuePlaceholderBase, uint)> placeholders, BoundAwaitableInfo awaitableInfo, uint valEscapeScope) { BoundAwaitableValuePlaceholder awaitableInstancePlaceholder = awaitableInfo.AwaitableInstancePlaceholder; if (awaitableInstancePlaceholder != null) { placeholders.Add(((BoundValuePlaceholderBase)awaitableInstancePlaceholder, valEscapeScope)); } } public override BoundNode? VisitImplicitIndexerAccess(BoundImplicitIndexerAccess node) { base.VisitImplicitIndexerAccess(node); return null; } public override BoundNode? VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node) { base.VisitDeconstructionAssignmentOperator(node); BoundTupleExpression left = node.Left; BoundConversion right = node.Right; ArrayBuilder deconstructionAssignmentVariables = GetDeconstructionAssignmentVariables(left); VisitDeconstructionArguments(deconstructionAssignmentVariables, right.Syntax, right.Conversion, right.Operand); ArrayBuilderExtensions.FreeAll(deconstructionAssignmentVariables, (Func>)((DeconstructionVariable v) => v.NestedVariables)); return null; } private void VisitDeconstructionArguments(ArrayBuilder variables, SyntaxNode syntax, Conversion conversion, BoundExpression right) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (conversion.DeconstructionInfo.IsDefault || !(conversion.DeconstructionInfo.Invocation is BoundCall boundCall)) { return; } MethodSymbol method = boundCall.Method; if ((object)method == null) { return; } ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); instance.Add(((BoundValuePlaceholderBase)conversion.DeconstructionInfo.InputPlaceholder, GetValEscape(right, _localScopeDepth))); ImmutableArray parameters = method.Parameters; int count = variables.Count; int num = (boundCall.InvokedAsExtensionMethod ? 1 : 0); for (int i = 0; i < count; i++) { DeconstructionVariable deconstructionVariable = variables[i]; ArrayBuilder? nestedVariables = deconstructionVariable.NestedVariables; BoundDeconstructValuePlaceholder item = (BoundDeconstructValuePlaceholder)boundCall.Arguments[i + num]; uint item2 = ((nestedVariables == null) ? GetValEscape(deconstructionVariable.Expression, _localScopeDepth) : _localScopeDepth); instance.Add(((BoundValuePlaceholderBase)item, item2)); } using (new PlaceholderRegion(this, instance)) { CheckInvocationArgMixing(syntax, method, boundCall.ReceiverOpt, boundCall.InitialBindingReceiverIsSubjectToCloning, parameters, boundCall.Arguments, boundCall.ArgumentRefKindsOpt, boundCall.ArgsToParamsOpt, _localScopeDepth, _diagnostics); for (int j = 0; j < count; j++) { ArrayBuilder nestedVariables2 = variables[j].NestedVariables; if (nestedVariables2 != null) { (BoundValuePlaceholder? placeholder, BoundExpression? conversion) tuple = conversion.DeconstructConversionInfo[j]; Conversion conversion2 = BoundNode.GetConversion(placeholder: tuple.placeholder, conversion: tuple.conversion); VisitDeconstructionArguments(nestedVariables2, syntax, conversion2, boundCall.Arguments[j + num]); } } } } private ArrayBuilder GetDeconstructionAssignmentVariables(BoundTupleExpression tuple) { ImmutableArray arguments = tuple.Arguments; ArrayBuilder instance = ArrayBuilder.GetInstance(arguments.Length); ImmutableArray.Enumerator enumerator = arguments.GetEnumerator(); while (enumerator.MoveNext()) { BoundExpression current = enumerator.Current; instance.Add(getDeconstructionAssignmentVariable(current)); } return instance; DeconstructionVariable getDeconstructionAssignmentVariable(BoundExpression expr) { if (!(expr is BoundTupleExpression tuple2)) { return new DeconstructionVariable(expr, GetValEscape(expr, _localScopeDepth), null); } return new DeconstructionVariable(expr, uint.MaxValue, GetDeconstructionAssignmentVariables(tuple2)); } } private static ImmutableArray GetDeconstructionRightParts(BoundExpression expr) { if (!(expr is BoundTupleExpression boundTupleExpression)) { if (expr is BoundConversion { ConversionKind: var conversionKind } boundConversion && (conversionKind == ConversionKind.Identity || conversionKind == ConversionKind.ImplicitTupleLiteral)) { return GetDeconstructionRightParts(boundConversion.Operand); } throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs", 976); } return boundTupleExpression.Arguments; } public override BoundNode? VisitForEachStatement(BoundForEachStatement node) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) Visit(node.Expression); ForEachEnumeratorInfo enumeratorInfoOpt = node.EnumeratorInfoOpt; BoundExpression inlineArray; if (enumeratorInfoOpt != null && (int)enumeratorInfoOpt.InlineArraySpanType != 0 && !enumeratorInfoOpt.InlineArrayUsedAsValue) { if (node.Expression is BoundConversion { Conversion: { IsIdentity: not false }, ExplicitCastInCode: false } boundConversion) { BoundExpression operand = boundConversion.Operand; if (operand != null) { inlineArray = operand; goto IL_0078; } } inlineArray = node.Expression; goto IL_0078; } uint num = GetValEscape(node.Expression, _localScopeDepth); goto IL_00d4; IL_00d4: using (new LocalScope(this, ImmutableArray.Empty)) { ImmutableArray.Enumerator enumerator = node.IterationVariables.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current = enumerator.Current; AddLocalScopes(current, ((int)current.RefKind == 0) ? _localScopeDepth : num, num); } ArrayBuilder<(BoundValuePlaceholderBase, uint)> instance = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); BoundDeconstructValuePlaceholder boundDeconstructValuePlaceholder = node.DeconstructionOpt?.TargetPlaceholder; if (boundDeconstructValuePlaceholder != null) { instance.Add(((BoundValuePlaceholderBase)boundDeconstructValuePlaceholder, num)); } BoundAwaitableInfo awaitOpt = node.AwaitOpt; if (awaitOpt != null) { GetAwaitableInstancePlaceholders(instance, awaitOpt, num); } using (new PlaceholderRegion(this, instance)) { Visit(node.IterationVariableType); Visit(node.IterationErrorExpressionOpt); Visit(node.DeconstructionOpt); Visit(node.AwaitOpt); Visit(node.Body); enumerator = node.IterationVariables.GetEnumerator(); while (enumerator.MoveNext()) { LocalSymbol current2 = enumerator.Current; RemoveLocalScopes(current2); } return null; } } IL_0078: ImmutableArray arguments; ImmutableArray refKinds; SignatureOnlyMethodSymbol inlineArrayConversionEquivalentSignatureMethod = GetInlineArrayConversionEquivalentSignatureMethod(inlineArray, node.EnumeratorInfoOpt.GetEnumeratorInfo.Method.ContainingType, out arguments, out refKinds); num = GetInvocationEscapeScope(inlineArrayConversionEquivalentSignatureMethod, null, (ThreeState)0, inlineArrayConversionEquivalentSignatureMethod.Parameters, arguments, refKinds, default(ImmutableArray), _localScopeDepth, isRefEscape: false); goto IL_00d4; } private static void Error(BindingDiagnosticBag diagnostics, ErrorCode code, SyntaxNodeOrToken syntax, params object[] args) { Location location = ((SyntaxNodeOrToken)(ref syntax)).GetLocation(); Error(diagnostics, code, location, args); } private static void Error(BindingDiagnosticBag diagnostics, ErrorCode code, Location location, params object[] args) { ((BindingDiagnosticBag)diagnostics).Add((Diagnostic)(object)new CSDiagnostic((DiagnosticInfo)(object)new CSDiagnosticInfo(code, args), location)); } }