Esempio n. 1
0
        /// <summary>
        /// Check that the given variable is definitely assigned.  If not, produce an error.
        /// </summary>
        /// <param name="local"></param>
        /// <param name="node"></param>
        protected void CheckAssigned(Symbol local, SyntaxNode node)
        {
            if (local != null && state.Reachable && !state.IsAssigned(VariableSlot(local)))
            {
                ReportUnassigned(local, node);
            }

            NoteRead(local);
        }
Esempio n. 2
0
        /// <summary>
        /// Perform a single pass of flow analysis.  Note that after this pass,
        /// this.backwardBranchChanged indicates if a further pass is required.
        /// </summary>
        protected virtual void Scan()
        {
            // the entry point of a method is assumed reachable
            state = FlowAnalysisLocalState.ReachableState();

            // label out parameters as not assigned.
            foreach (var parameter in method.Parameters)
            {
                if (parameter.RefKind == RefKind.Out)
                {
                    SetSlotState(MakeSlot(parameter), initiallyAssignedVariables != null && initiallyAssignedVariables.Contains(parameter));
                }
                else
                {
                    // this code has no effect except in the region analysis APIs, which assign
                    // variable slots to all parameters.
                    int slot = VariableSlot(parameter);
                    SetSlotState(slot, true);
                }
            }

            // TODO: if this is the body of an initial struct constructor, mark "this" as unassigned.
            this.backwardBranchChanged = false;
            if (this.Diagnostics != null)
            {
                this.Diagnostics.Free();
            }
            this.Diagnostics     = DiagnosticBag.GetInstance(); // clear reported diagnostics
            this.alreadyReported = BitArray.Empty;              // no variables yet reported unassigned
            VisitStatement(block);

            // check that each local variable is used somewhere (or warn if it isn't)
            foreach (var symbol in variableBySlot)
            {
                if (symbol != null && symbol.Kind == SymbolKind.Local && !readVariables.Contains(symbol))
                {
                    Diagnostics.Add(writtenVariables.Contains(symbol) ? ErrorCode.WRN_UnreferencedVarAssg : ErrorCode.WRN_UnreferencedVar, symbol.Locations[0], symbol.Name);
                }
            }

            // check that each out parameter is definitely assigned at the end of the method if
            // there's more than one location, then the method is partial and we prefer to report an
            // out parameter in partial method error
            if (method.Locations.Count == 1)
            {
                foreach (ParameterSymbol parameter in method.Parameters)
                {
                    if (parameter.RefKind == RefKind.Out)
                    {
                        var slot = VariableSlot(parameter);
                        if (!state.IsAssigned(slot))
                        {
                            ReportUnassignedOutParameter(parameter, null, method.Locations[0]);
                        }

                        foreach (PendingBranch returnBranch in pendingBranches)
                        {
                            if (!returnBranch.State.IsAssigned(slot))
                            {
                                ReportUnassignedOutParameter(parameter, returnBranch.Branch.Syntax, null);
                            }
                        }
                    }
                }
            }
            // TODO: handle "this" in struct constructor.
        }
Esempio n. 3
0
        /// <summary>
        /// Perform a single pass of flow analysis.  Note that after this pass,
        /// this.backwardBranchChanged indicates if a further pass is required.
        /// </summary>
        protected virtual void Scan()
        {
            // the entry point of a method is assumed reachable
            state = FlowAnalysisLocalState.ReachableState();

            // label out parameters as not assigned.
            foreach (var parameter in method.Parameters)
            {
                if (parameter.RefKind == RefKind.Out)
                {
                    SetSlotState(MakeSlot(parameter), initiallyAssignedVariables != null && initiallyAssignedVariables.Contains(parameter));
                }
                else
                {
                    // this code has no effect except in the region analysis APIs, which assign
                    // variable slots to all parameters.
                    int slot = VariableSlot(parameter);
                    SetSlotState(slot, true);
                }
            }

            // TODO: if this is the body of an initial struct constructor, mark "this" as unassigned.
            this.backwardBranchChanged = false;
            if (this.Diagnostics != null)
                this.Diagnostics.Free();
            this.Diagnostics = DiagnosticBag.GetInstance();  // clear reported diagnostics
            this.alreadyReported = BitArray.Empty;           // no variables yet reported unassigned
            VisitStatement(block);

            // check that each local variable is used somewhere (or warn if it isn't)
            foreach (var symbol in variableBySlot)
            {
                if (symbol != null && symbol.Kind == SymbolKind.Local && !readVariables.Contains(symbol))
                {
                    Diagnostics.Add(writtenVariables.Contains(symbol) ? ErrorCode.WRN_UnreferencedVarAssg : ErrorCode.WRN_UnreferencedVar, symbol.Locations[0], symbol.Name);
                }
            }

            // check that each out parameter is definitely assigned at the end of the method if
            // there's more than one location, then the method is partial and we prefer to report an
            // out parameter in partial method error
            if (method.Locations.Count == 1)
            {
                foreach (ParameterSymbol parameter in method.Parameters)
                {
                    if (parameter.RefKind == RefKind.Out)
                    {
                        var slot = VariableSlot(parameter);
                        if (!state.IsAssigned(slot))
                        {
                            ReportUnassignedOutParameter(parameter, null, method.Locations[0]);
                        }

                        foreach (PendingBranch returnBranch in pendingBranches)
                        {
                            if (!returnBranch.State.IsAssigned(slot))
                            {
                                ReportUnassignedOutParameter(parameter, returnBranch.Branch.Syntax, null);
                            }
                        }
                    }
                }
            }
            // TODO: handle "this" in struct constructor.
        }