protected override bool LocalFunctionEnd( LocalFunctionState savedState, LocalFunctionState currentState, ref LocalState stateAtReturn ) { if (currentState.CapturedMask.IsNull) { currentState.CapturedMask = GetCapturedBitmask(); currentState.InvertedCapturedMask = currentState.CapturedMask.Clone(); currentState.InvertedCapturedMask.Invert(); } // Filter the modified state variables to only captured variables stateAtReturn.Assigned.IntersectWith(currentState.CapturedMask); if (NonMonotonicState.HasValue) { var state = NonMonotonicState.Value; state.Assigned.UnionWith(currentState.InvertedCapturedMask); NonMonotonicState = state; } // Build a list of variables that are both captured and read before assignment var capturedAndRead = currentState.ReadVars; capturedAndRead.IntersectWith(currentState.CapturedMask); // Union and check to see if there are any changes return(savedState.ReadVars.UnionWith(capturedAndRead)); }
/// <summary> /// State changes are handled by the base class. We override to find captured variables that /// have been read before they were assigned and determine if the set has changed. /// </summary> protected override bool LocalFunctionEnd( LocalFunctionState savedState, LocalFunctionState currentState, ref LocalState stateAtReturn) { // Build a list of variables that are both captured and read before assignment var capturedMask = GetCapturedBitmask(ref currentState.ReadVars); var capturedAndRead = currentState.ReadVars; capturedAndRead.IntersectWith(capturedMask); // Union and check to see if there are any changes return(savedState.ReadVars.UnionWith(capturedAndRead)); }
protected override LocalFunctionState LocalFunctionStart(LocalFunctionState startState) { // 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. var savedState = new LocalFunctionState(UnreachableState()); savedState.ReadVars = startState.ReadVars.Clone(); startState.ReadVars.Clear(); return(savedState); }
/// <summary> /// At the local function's use site, checks that all variables read are assigned. /// </summary> protected override void VisitLocalFunctionUse(LocalFunctionSymbol localFunc, LocalFunctionState localFunctionState, SyntaxNode syntax) { _usedLocalFunctions.Add(localFunc); var reads = localFunctionState.ReadVars; // Start at slot 1 (slot 0 just indicates reachability) for (int slot = 1; slot < reads.Capacity; slot++) { if (reads[slot]) { var symbol = variableBySlot[slot].Symbol; CheckIfAssignedDuringLocalFunctionReplay(symbol, syntax, slot); } } }
protected override void VisitLocalFunctionUse( LocalFunctionSymbol localFunc, LocalFunctionState localFunctionState, SyntaxNode syntax, bool isCall) { _usedLocalFunctions.Add(localFunc); // Check variables that were read before being definitely assigned. var reads = localFunctionState.ReadVars; // Start at slot 1 (slot 0 just indicates reachability) for (int slot = 1; slot < reads.Capacity; slot++) { if (reads[slot]) { var symbol = variableBySlot[slot].Symbol; CheckIfAssignedDuringLocalFunctionReplay(symbol, syntax, slot); } } base.VisitLocalFunctionUse(localFunc, localFunctionState, syntax, isCall); }