예제 #1
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var oldCurrentFunction = _F.CurrentFunction;

            _F.CurrentFunction = node.Symbol;
            var result = base.VisitLocalFunctionStatement(node);

            _F.CurrentFunction = oldCurrentFunction;
            return(result);
        }
예제 #2
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            if (IsInside && !node.WasCompilerGenerated)
            {
                foreach (var parameter in node.Symbol.Parameters)
                {
                    _variablesDeclared.Add(parameter);
                }
            }

            return(base.VisitLocalFunctionStatement(node));
        }
예제 #3
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var outerLocalFunction = _staticLocalFunction;

            if (node.Symbol.IsStaticLocalFunction)
            {
                _staticLocalFunction = node.Symbol;
            }
            var result = base.VisitLocalFunctionStatement(node);

            _staticLocalFunction = outerLocalFunction;
            return(result);
        }
            public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
            {
                var origLabels    = this.currentLabels;
                var origSeenAwait = _seenAwait;

                this.currentLabels = null;
                _seenAwait         = false;

                base.VisitLocalFunctionStatement(node);

                this.currentLabels = origLabels;
                _seenAwait         = origSeenAwait;

                return(null);
            }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var oldContainingSymbol  = _F.CurrentFunction;
            var oldAwaitFinallyFrame = _currentAwaitFinallyFrame;

            _F.CurrentFunction        = node.Symbol;
            _currentAwaitFinallyFrame = new AwaitFinallyFrame();

            var result = base.VisitLocalFunctionStatement(node);

            _F.CurrentFunction        = oldContainingSymbol;
            _currentAwaitFinallyFrame = oldAwaitFinallyFrame;

            return(result);
        }
예제 #6
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            CheckRefReadOnlySymbols(node.Symbol);

            var typeParameters = node.Symbol.TypeParameters;

            if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
            }

            bool constraintsNeedNullableAttribute = typeParameters.Any(
                typeParameter => (typeParameter.HasReferenceTypeConstraint && typeParameter.ReferenceTypeConstraintIsNullable != null) ||
                typeParameter.ConstraintTypesNoUseSiteDiagnostics.Any(
                    typeConstraint => typeConstraint.NeedsNullableAttribute()));

            bool returnTypeNeedsNullableAttribute = node.Symbol.ReturnType.NeedsNullableAttribute();
            bool parametersNeedNullableAttribute  = node.Symbol.ParameterTypes.Any(parameter => parameter.NeedsNullableAttribute());

            if (constraintsNeedNullableAttribute || returnTypeNeedsNullableAttribute || parametersNeedNullableAttribute)
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists();
            }

            var oldContainingSymbol = _factory.CurrentFunction;

            try
            {
                _factory.CurrentFunction = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
            }
        }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     return(VisitLocalFunctionOrLambda(node.Body));
 }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     MakeSlots(node.Symbol.Parameters);
     return(base.VisitLocalFunctionStatement(node));
 }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldSymbol       = this.currentSymbol;
            var localFuncSymbol = localFunc.Symbol;

            this.currentSymbol = localFuncSymbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // SPEC: The entry point to a local function is always reachable.
            // Captured variables are definitely assigned if they are definitely assigned on
            // all branches into the local function.

            var savedState = this.State;

            this.State = this.TopState();

            if (!localFunc.WasCompilerGenerated)
            {
                EnterParameters(localFuncSymbol.Parameters);
            }

            // Captured variables are definitely assigned if they are assigned on
            // all branches into the local function, so we store all reads from
            // possibly unassigned captured variables and later report definite
            // assignment errors if any of the captured variables is not assigned
            // on a particular branch.
            //
            // Assignments to captured variables are also recorded, as calls to local functions
            // definitely assign captured variables if the variables are definitely assigned at
            // all branches out of the local function.

            var usages   = GetOrCreateLocalFuncUsages(localFuncSymbol);
            var oldReads = usages.ReadVars.Clone();

            usages.ReadVars.Clear();

            var oldPending2 = SavePending();

            // If this is an iterator, there's an implicit branch before the first statement
            // of the function where the enumerable is returned.
            if (localFuncSymbol.IsIterator)
            {
                PendingBranches.Add(new PendingBranch(null, this.State, null));
            }

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray <PendingBranch> pendingReturns = RemoveReturns();

            RestorePending(oldPending);

            Location location = null;

            if (!localFuncSymbol.Locations.IsDefaultOrEmpty)
            {
                location = localFuncSymbol.Locations[0];
            }

            LeaveParameters(localFuncSymbol.Parameters, localFunc.Syntax, location);

            // Intersect the state of all branches out of the local function
            LocalState stateAtReturn = this.State;

            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;

                // Pass the local function identifier as a location if the branch
                // is null or compiler generated.
                LeaveParameters(localFuncSymbol.Parameters,
                                branch?.Syntax,
                                branch?.WasCompilerGenerated == false ? null : location);

                Join(ref stateAtReturn, ref this.State);
            }

            // Check for changes to the possibly unassigned and assigned sets
            // of captured variables
            if (RecordChangedVars(ref usages.WrittenVars,
                                  ref stateAtReturn,
                                  ref oldReads,
                                  ref usages.ReadVars) &&
                usages.LocalFuncVisited)
            {
                // If the sets have changed and we already used the results
                // of this local function in another computation, the previous
                // calculations may be invalid. We need to analyze until we
                // reach a fixed-point. The previous writes are always valid,
                // so they are stored in usages.WrittenVars, while the reads
                // may be invalidated by new writes, so we throw the results out.
                stateChangedAfterUse    = true;
                usages.LocalFuncVisited = false;
            }

            this.State         = savedState;
            this.currentSymbol = oldSymbol;

            return(null);
        }