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 => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute()); bool returnTypeNeedsNullableAttribute = node.Symbol.ReturnTypeWithAnnotations.NeedsNullableAttribute(); bool parametersNeedNullableAttribute = node.Symbol.ParameterTypesWithAnnotations.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) { if (IsInside) { _interactsWithLocalFunction = true; } MakeSlots(node.Symbol.Parameters); return(base.VisitLocalFunctionStatement(node)); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { var oldCurrentFunction = _F.CurrentFunction; _F.CurrentFunction = node.Symbol; var result = base.VisitLocalFunctionStatement(node); _F.CurrentFunction = oldCurrentFunction; return(result); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { if (IsInside && !node.WasCompilerGenerated) { foreach (var parameter in node.Symbol.Parameters) { _variablesDeclared.Add(parameter); } } return base.VisitLocalFunctionStatement(node); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { if (IsInside && !node.WasCompilerGenerated) { foreach (var parameter in node.Symbol.Parameters) { _variablesDeclared.Add(parameter); } } return(base.VisitLocalFunctionStatement(node)); }
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) { _sawLocalFunctions = true; var oldContainingSymbol = _factory.CurrentMethod; try { _factory.CurrentMethod = node.Symbol; return(base.VisitLocalFunctionStatement(node)); } finally { _factory.CurrentMethod = oldContainingSymbol; } }
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); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { ExecutableCodeBinder.ValidateIteratorMethod(_compilation, node.Symbol, _diagnostics); var outerLocalFunction = _staticLocalFunction; if (node.Symbol.IsStatic) { _staticLocalFunction = node.Symbol; } var result = base.VisitLocalFunctionStatement(node); _staticLocalFunction = outerLocalFunction; return(result); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { _sawLocalFunctions = true; var localFunction = node.Symbol; CheckRefReadOnlySymbols(localFunction); var typeParameters = localFunction.TypeParameters; if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint)) { _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists(); } if (_factory.CompilationState.Compilation.ShouldEmitNullableAttributes(localFunction)) { bool constraintsNeedNullableAttribute = typeParameters.Any( typeParameter => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute()); bool returnTypeNeedsNullableAttribute = localFunction.ReturnTypeWithAnnotations.NeedsNullableAttribute(); bool parametersNeedNullableAttribute = localFunction.ParameterTypesWithAnnotations.Any(parameter => parameter.NeedsNullableAttribute()); if (constraintsNeedNullableAttribute || returnTypeNeedsNullableAttribute || parametersNeedNullableAttribute) { _factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists(); } } var oldContainingSymbol = _factory.CurrentFunction; var oldInstrumenter = _instrumenter; try { _factory.CurrentFunction = localFunction; if (localFunction.IsDirectlyExcludedFromCodeCoverage) { _instrumenter = RemoveDynamicAnalysisInjectors(oldInstrumenter); } return(base.VisitLocalFunctionStatement(node)); } finally { _factory.CurrentFunction = oldContainingSymbol; _instrumenter = oldInstrumenter; } }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { _sawLocalFunctions = true; CheckRefReadOnlySymbols(node.Symbol); var oldContainingSymbol = _factory.CurrentFunction; try { _factory.CurrentFunction = node.Symbol; return(base.VisitLocalFunctionStatement(node)); } finally { _factory.CurrentFunction = oldContainingSymbol; } }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { _sawLocalFunctions = true; CheckRefReadOnlySymbols(node.Symbol); if (node.Symbol.TypeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint)) { _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists(); } var oldContainingSymbol = _factory.CurrentFunction; try { _factory.CurrentFunction = node.Symbol; return(base.VisitLocalFunctionStatement(node)); } finally { _factory.CurrentFunction = oldContainingSymbol; } }
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 hasConstraintsWithNullableReferenceTypes = typeParameters.Any( typeParameter => typeParameter.ReferenceTypeConstraintIsNullable == true || typeParameter.ConstraintTypesNoUseSiteDiagnostics.Any( typeConstraint => typeConstraint.ContainsNullableReferenceTypes())); bool hasReturnTypeWithNullableReferenceTypes = node.Symbol.ReturnType.ContainsNullableReferenceTypes(); bool hasParametersWithNullableReferenceTypes = node.Symbol.ParameterTypes.Any(parameter => parameter.ContainsNullableReferenceTypes()); if (hasConstraintsWithNullableReferenceTypes || hasReturnTypeWithNullableReferenceTypes || hasParametersWithNullableReferenceTypes) { _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 localFunc) { var oldMethodOrLambda = this.currentMethodOrLambda; this.currentMethodOrLambda = localFunc.Symbol; var oldPending = SavePending(); // we do not support branches into a lambda // Local functions don't affect outer state and are analyzed // with everything unassigned and reachable var savedState = this.State; this.State = this.ReachableState(); var usages = GetOrCreateLocalFuncUsages(localFunc.Symbol); var oldReads = usages.ReadVars; usages.ReadVars = BitVector.Empty; if (!localFunc.WasCompilerGenerated) { EnterParameters(localFunc.Symbol.Parameters); } var oldPending2 = SavePending(); VisitAlways(localFunc.Body); RestorePending(oldPending2); // process any forward branches within the lambda body ImmutableArray <PendingBranch> pendingReturns = RemoveReturns(); RestorePending(oldPending); Location location = null; if (!localFunc.Symbol.Locations.IsDefaultOrEmpty) { location = localFunc.Symbol.Locations[0]; } LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, location); LocalState stateAtReturn = this.State; foreach (PendingBranch pending in pendingReturns) { this.State = pending.State; BoundNode branch = pending.Branch; if (branch.Kind == BoundKind.ReturnStatement) { // ensure out parameters are definitely assigned at each return LeaveParameters(localFunc.Symbol.Parameters, branch.Syntax, branch.WasCompilerGenerated ? location : null); IntersectWith(ref stateAtReturn, ref this.State); } else { // other ways of branching out of a lambda are errors, previously reported in control-flow analysis } } // Check for changes to the read and write sets if (RecordChangedVars(ref usages.WrittenVars, ref stateAtReturn.Assigned, ref oldReads, ref usages.ReadVars) && usages.LocalFuncVisited) { stateChangedAfterUse = true; usages.LocalFuncVisited = false; } this.State = savedState; this.currentMethodOrLambda = oldMethodOrLambda; return(null); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { MakeSlots(node.Symbol.Parameters); return(base.VisitLocalFunctionStatement(node)); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc) { return(null); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { MakeSlots(node.Symbol.Parameters); return base.VisitLocalFunctionStatement(node); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { VariableScope[node.Symbol] = _currentScope; return VisitLambdaOrFunction(node); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { return VisitLocalFunctionOrLambda(node.Body); }
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) { // Do not recurse into nested lambdas; we don't want their returns. return null; }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { return(VisitLocalFunctionOrLambda(node.Body)); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { var oldContainingSymbol = _F.CurrentMethod; var oldAwaitFinallyFrame = _currentAwaitFinallyFrame; _F.CurrentMethod = node.Symbol; _currentAwaitFinallyFrame = new AwaitFinallyFrame(); var result = base.VisitLocalFunctionStatement(node); _F.CurrentMethod = oldContainingSymbol; _currentAwaitFinallyFrame = oldAwaitFinallyFrame; return result; }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) => VisitClosure(node.Symbol.OriginalDefinition, node.Body);
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); } // State changes to captured variables are recorded, as calls to local functions // transition the state of captured variables if the variables have state changes // across all branches leaving the local function var localFunctionState = GetOrCreateLocalFuncUsages(localFuncSymbol); var savedLocalFunctionState = LocalFunctionStart(localFunctionState); 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 var 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); } // Record any changes to the state of captured variables if (RecordStateChange( savedLocalFunctionState, localFunctionState, ref stateAtReturn) && localFunctionState.Visited) { // 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. stateChangedAfterUse = true; localFunctionState.Visited = false; } this.State = savedState; this.CurrentSymbol = oldSymbol; return(null); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc) { var oldMethodOrLambda = this.currentMethodOrLambda; this.currentMethodOrLambda = localFunc.Symbol; var oldPending = SavePending(); // we do not support branches into a lambda // Local functions don't affect outer state and are analyzed // with everything unassigned and reachable var savedState = this.State; this.State = this.ReachableState(); var usages = GetOrCreateLocalFuncUsages(localFunc.Symbol); var oldReads = usages.ReadVars; usages.ReadVars = BitVector.Empty; if (!localFunc.WasCompilerGenerated) EnterParameters(localFunc.Symbol.Parameters); 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 (localFunc.Symbol.IsIterator) { PendingBranches.Add(new PendingBranch(null, this.State)); } VisitAlways(localFunc.Body); RestorePending(oldPending2); // process any forward branches within the lambda body ImmutableArray<PendingBranch> pendingReturns = RemoveReturns(); RestorePending(oldPending); Location location = null; if (!localFunc.Symbol.Locations.IsDefaultOrEmpty) { location = localFunc.Symbol.Locations[0]; } LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, location); LocalState stateAtReturn = this.State; foreach (PendingBranch pending in pendingReturns) { this.State = pending.State; BoundNode branch = pending.Branch; LeaveParameters(localFunc.Symbol.Parameters, branch?.Syntax, branch?.WasCompilerGenerated == true ? location : null); IntersectWith(ref stateAtReturn, ref this.State); } // Check for changes to the read and write sets if (RecordChangedVars(ref usages.WrittenVars, ref stateAtReturn.Assigned, ref oldReads, ref usages.ReadVars) && usages.LocalFuncVisited) { stateChangedAfterUse = true; usages.LocalFuncVisited = false; } this.State = savedState; this.currentMethodOrLambda = oldMethodOrLambda; return null; }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc) { var oldMethodOrLambda = this.currentMethodOrLambda; var localFuncSymbol = localFunc.Symbol; this.currentMethodOrLambda = localFuncSymbol; var oldPending = SavePending(); // we do not support branches into a lambda // Local functions don't affect outer state and are analyzed // with everything unassigned and reachable var savedState = this.State; this.State = this.ReachableState(); var usages = GetOrCreateLocalFuncUsages(localFuncSymbol); var oldReads = usages.ReadVars; usages.ReadVars = BitVector.Empty; if (!localFunc.WasCompilerGenerated) { EnterParameters(localFuncSymbol.Parameters); } 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)); } 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); LocalState stateAtReturn = this.State; foreach (PendingBranch pending in pendingReturns) { this.State = pending.State; BoundNode branch = pending.Branch; LeaveParameters(localFuncSymbol.Parameters, branch?.Syntax, branch?.WasCompilerGenerated == true ? location : null); IntersectWith(ref stateAtReturn, ref this.State); } // Check for changes to the read and write sets if (RecordChangedVars(ref usages.WrittenVars, ref stateAtReturn, ref oldReads, ref usages.ReadVars) && usages.LocalFuncVisited) { stateChangedAfterUse = true; usages.LocalFuncVisited = false; } this.State = savedState; this.currentMethodOrLambda = oldMethodOrLambda; return(null); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { // Do not recurse into nested lambdas; we don't want their returns. return(null); }
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); }
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { VariableScope[node.Symbol] = _currentScope; return(VisitLambdaOrFunction(node)); }