public RunScope Clone(bool?canBreak = null, bool?canContinue = null) { var scope = new RunScope(_ca, _funcDef, _funcOffset) { _returned = _returned, _canBreak = _canBreak, _canContinue = _canContinue, _suppressInitializedCheck = _suppressInitializedCheck }; if (canBreak.HasValue) { scope._canBreak = canBreak.Value; } if (canContinue.HasValue) { scope._canContinue = canContinue.Value; } foreach (var v in _vars) { scope._vars[v.Key] = v.Value.Clone(); } return(scope); }
public void Merge(RunScope scope, bool promoteBreak = true, bool promoteContinue = true) { if (scope.Returned > _returned) { _returned = scope.Returned; } if (promoteBreak && scope.Breaked > _breaked) { _breaked = scope.Breaked; } if (promoteContinue && scope.Continued > _continued) { _continued = scope.Continued; } foreach (var myVar in _vars.Values) { Variable otherVar; if (scope._vars.TryGetValue(myVar.Name, out otherVar)) { if (scope.Returned != TriState.True) // Don't initialize variables if the branch returned before this point { if (otherVar.IsInitialized > myVar.IsInitialized) { myVar.IsInitialized = otherVar.IsInitialized; } } if (otherVar.IsUsed) { myVar.IsUsed = true; } } } }
private void AnalyzeFunction(CodeModel.PreprocessorModel.LocalFunction func) { var body = _fullSource.Substring(func.StartPos, func.EndPos - func.StartPos); if (body.EndsWith("}")) { body = body.Substring(0, body.Length - 1); // End pos is just after the closing brace } _read = new ReadParams { CodeAnalyzer = this, Code = new CodeParser(body), FuncOffset = func.StartPos, FuncDef = func.Definition }; _scope = new RunScope(this, func.Definition, func.StartPos); _stmts = new List <Statement>(); // Parse the function body while (!_read.Code.EndOfFile) { var stmt = Statement.Read(_read); if (stmt == null) { break; } _stmts.Add(stmt); } foreach (var arg in func.Arguments) { if (!string.IsNullOrEmpty(arg.Name)) { _scope.AddVariable(new Variable(arg, arg.Name, arg.DataType, Value.CreateUnknownFromDataType(arg.DataType), true, TriState.True, true)); } } foreach (var v in func.Variables) { _scope.AddVariable(new Variable(v, v.Name, v.DataType, Value.CreateUnknownFromDataType(v.DataType), false, TriState.False, false)); } foreach (var v in _prepModel.DefinitionProvider.GetGlobalFromFile <VariableDefinition>()) { _scope.AddVariable(new Variable(v, v.Name, v.DataType, Value.CreateUnknownFromDataType(v.DataType), false, TriState.True, true)); } foreach (var stmt in _stmts) { stmt.Execute(_scope); } if (func.Definition.DataType.ValueType != ValType.Void && _scope.Returned != TriState.True && func.Definition.Name != "staticinitialize") { ReportErrorAbsolute(func.NameSpan, CAError.CA0017); // Function does not return a value. } foreach (var v in _scope.Variables) { if (!v.IsUsed) { if (v.IsInitialized != TriState.False) { var def = v.Definition; ReportErrorLocal(def.SourceFileName, new Span(def.SourceStartPos, def.SourceStartPos + def.Name.Length), false, null, CAError.CA0111, v.Name); // Variable '{0}' is assigned a value, but is never used. } else { var def = v.Definition; ReportErrorLocal(def.SourceFileName, new Span(def.SourceStartPos, def.SourceStartPos + def.Name.Length), false, null, CAError.CA0112, v.Name); // Variable '{0}' is not used. } } } }