| File: Binder\Binder_Flags.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Symbols; using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { internal partial class Binder { /// <summary> /// Represents a small change from the enclosing/next binder. /// Can specify a BindingLocation and a ContainingMemberOrLambda. /// </summary> private sealed class BinderWithContainingMemberOrLambda : Binder { private readonly Symbol _containingMemberOrLambda; internal BinderWithContainingMemberOrLambda(Binder next, Symbol containingMemberOrLambda) : base(next) { Debug.Assert(containingMemberOrLambda != null); _containingMemberOrLambda = containingMemberOrLambda; } internal BinderWithContainingMemberOrLambda(Binder next, BinderFlags flags, Symbol containingMemberOrLambda) : base(next, flags) { Debug.Assert(containingMemberOrLambda != null); _containingMemberOrLambda = containingMemberOrLambda; } internal override Symbol ContainingMemberOrLambda { get { return _containingMemberOrLambda; } } } /// <summary> /// Represents a small change from the enclosing/next binder. /// Can specify a receiver Expression for containing conditional member access. /// </summary> private sealed class BinderWithConditionalReceiver : Binder { private readonly BoundExpression _receiverExpression; internal BinderWithConditionalReceiver(Binder next, BoundExpression receiverExpression) : base(next) { Debug.Assert(receiverExpression != null); _receiverExpression = receiverExpression; } internal override BoundExpression ConditionalReceiverExpression { get { return _receiverExpression; } } } internal Binder WithFlags(BinderFlags flags) { return this.Flags == flags ? this : new Binder(this, flags); } internal Binder WithAdditionalFlags(BinderFlags flags) { return this.Flags.Includes(flags) ? this : new Binder(this, this.Flags | flags); } internal Binder WithContainingMemberOrLambda(Symbol containing) { Debug.Assert((object)containing != null); return new BinderWithContainingMemberOrLambda(this, containing); } /// <remarks> /// It seems to be common to do both of these things at once, so provide a way to do so /// without adding two links to the binder chain. /// </remarks> internal Binder WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags flags, Symbol containing) { Debug.Assert((object)containing != null); return new BinderWithContainingMemberOrLambda(this, this.Flags | flags, containing); } internal Binder SetOrClearUnsafeRegionIfNecessary(SyntaxTokenList modifiers, bool isIteratorBody = false) { // In C# 13 and above, iterator bodies define a safe context even when nested in an unsafe context. // In C# 12 and below, we keep the (spec violating) behavior that iterator bodies inherit the safe/unsafe context // from their containing scope. Since there are errors for unsafe constructs directly in iterators, // this inherited unsafe context can be observed only in nested non-iterator local functions. var withoutUnsafe = isIteratorBody && this.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureRefUnsafeInIteratorAsync); if (this.Flags.Includes(BinderFlags.UnsafeRegion)) { return withoutUnsafe ? new Binder(this, this.Flags & ~BinderFlags.UnsafeRegion) : this; } // Under the updated memory safety rules, the `unsafe` modifier on a type or member declaration // does not introduce an unsafe context (no interior meaning). // `unsafe { }` blocks also introduce an unsafe context. return !withoutUnsafe && modifiers.Any(SyntaxKind.UnsafeKeyword) && !this.Compilation.SourceModule.UseUpdatedMemorySafetyRules ? new Binder(this, this.Flags | BinderFlags.UnsafeRegion) : this; } internal Binder WithCheckedOrUncheckedRegion(bool @checked) { Debug.Assert(!this.Flags.Includes(BinderFlags.UncheckedRegion | BinderFlags.CheckedRegion)); BinderFlags added = @checked ? BinderFlags.CheckedRegion : BinderFlags.UncheckedRegion; BinderFlags removed = @checked ? BinderFlags.UncheckedRegion : BinderFlags.CheckedRegion; return this.Flags.Includes(added) ? this : new Binder(this, (this.Flags & ~removed) | added); } } }