📄 cppcheck.cpp
字号:
"Example usage:\n" " # Recursively check the current folder. Print the progress on the screen and\n" " write errors in a file:\n" " cppcheck . 2> err.txt\n" " # Recursively check ../myproject/ and print only most fatal errors:\n" " cppcheck --quiet ../myproject/\n" " # Check only files one.cpp and two.cpp and give all information there is:\n" " cppcheck -v -a -s one.cpp two.cpp\n" " # Check f.cpp and search include files from inc1/ and inc2/:\n" " cppcheck -I inc1/ -I inc2/ f.cpp\n"; return oss.str(); } else if (_filenames.empty()) { return "cppcheck: No C or C++ source files found.\n"; } return "";}unsigned int CppCheck::check(){ _checkFunctionUsage.setErrorLogger(this); std::sort(_filenames.begin(), _filenames.end()); for (unsigned int c = 0; c < _filenames.size(); c++) { _errout.str(""); std::string fname = _filenames[c]; if (_settings._errorsOnly == false) _errorLogger->reportOut(std::string("Checking ") + fname + std::string("...")); Preprocessor preprocessor; std::list<std::string> configurations; std::string filedata = ""; if (_fileContents.size() > 0 && _fileContents.find(_filenames[c]) != _fileContents.end()) { // File content was given as a string std::istringstream iss(_fileContents[ _filenames[c] ]); preprocessor.preprocess(iss, filedata, configurations, fname, _includePaths); } else { // Only file name was given, read the content from file std::ifstream fin(fname.c_str()); preprocessor.preprocess(fin, filedata, configurations, fname, _includePaths); } int checkCount = 0; for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // Check only 12 first configurations, after that bail out, unless --force // was used. if (!_settings._force && checkCount > 11) { if (_settings._errorsOnly == false) _errorLogger->reportOut(std::string("Bailing out from checking ") + fname + ": Too many configurations. Recheck this file with --force if you want to check them all."); break; } cfg = *it; std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it); // If only errors are printed, print filename after the check if (_settings._errorsOnly == false && it != configurations.begin()) _errorLogger->reportOut(std::string("Checking ") + fname + ": " + cfg + std::string("...")); checkFile(codeWithoutCfg, _filenames[c].c_str()); ++checkCount; } _errorLogger->reportStatus(c + 1, _filenames.size()); } // This generates false positives - especially for libraries _settings._verbose = false; if (_settings._unusedFunctions) { _errout.str(""); if (_settings._errorsOnly == false) _errorLogger->reportOut("Checking usage of global functions (this may take several minutes).."); _checkFunctionUsage.check(); } unsigned int result = static_cast<unsigned int>(_errorList.size()); _errorList.clear(); return result;}//---------------------------------------------------------------------------// CppCheck - A function that checks a specified file//---------------------------------------------------------------------------void CppCheck::checkFile(const std::string &code, const char FileName[]){ Tokenizer _tokenizer; // Tokenize the file { std::istringstream istr(code); _tokenizer.tokenize(istr, FileName); } // Set variable id _tokenizer.setVarId(); _tokenizer.fillFunctionList(); // Check that the memsets are valid. // The 'memset' function can do dangerous things if used wrong. // Important: The checking doesn't work on simplified tokens list. CheckClass checkClass(&_tokenizer, _settings, this); if (ErrorLogger::memsetClass()) checkClass.noMemset(); // Coding style checks that must be run before the simplifyTokenList CheckOther checkOther(&_tokenizer, _settings, this); // Check for unsigned divisions where one operand is signed if (ErrorLogger::udivWarning(_settings) || ErrorLogger::udivError()) checkOther.CheckUnsignedDivision(); // Give warning when using char variable as array index if (ErrorLogger::charArrayIndex(_settings) || ErrorLogger::charBitOp(_settings)) checkOther.CheckCharVariable(); _tokenizer.simplifyTokenList(); // Write simplified token list to a file.. //std::cout << _tokenizer.tokens()->stringifyList(true) << std::endl; if (_settings._unusedFunctions) _checkFunctionUsage.parseTokens(_tokenizer); // Class for detecting buffer overruns and related problems CheckBufferOverrunClass checkBufferOverrun(&_tokenizer, _settings, this); // Class for checking functions that should not be used CheckDangerousFunctionsClass checkDangerousFunctions(&_tokenizer, _settings, this); // Memory leak CheckMemoryLeakClass checkMemoryLeak(&_tokenizer, _settings, this); if (ErrorLogger::memleak() || ErrorLogger::mismatchAllocDealloc()) checkMemoryLeak.CheckMemoryLeak(); // Check that all class constructors are ok. if (ErrorLogger::noConstructor(_settings) || ErrorLogger::uninitVar(_settings)) checkClass.constructors(); // Check that all base classes have virtual destructors if (ErrorLogger::virtualDestructor()) checkClass.virtualDestructor(); // Array index out of bounds / Buffer overruns.. if (ErrorLogger::arrayIndexOutOfBounds(_settings) || ErrorLogger::bufferOverrun(_settings)) checkBufferOverrun.bufferOverrun(); // Warning upon c-style pointer casts if (ErrorLogger::cstyleCast(_settings)) { const char *ext = strrchr(FileName, '.'); if (ext && strcmp(ext, ".cpp") == 0) checkOther.WarningOldStylePointerCast(); } // if (a) delete a; if (ErrorLogger::redundantIfDelete0(_settings)) checkOther.WarningRedundantCode(); // strtol and strtoul usage if (ErrorLogger::dangerousUsageStrtol() || ErrorLogger::sprintfOverlappingData()) checkOther.InvalidFunctionUsage(); // Check that all private functions are called. if (ErrorLogger::unusedPrivateFunction(_settings)) checkClass.privateFunctions(); // 'operator=' should return something.. if (ErrorLogger::operatorEq(_settings)) checkClass.operatorEq(); // if (condition); if (ErrorLogger::ifNoAction(_settings) || ErrorLogger::conditionAlwaysTrueFalse(_settings)) checkOther.WarningIf(); // Unused struct members.. if (ErrorLogger::unusedStructMember(_settings)) checkOther.CheckStructMemberUsage(); // Check if a constant function parameter is passed by value if (ErrorLogger::passedByValue(_settings)) checkOther.CheckConstantFunctionParameter(); // Variable scope (check if the scope could be limited) if (ErrorLogger::variableScope()) checkOther.CheckVariableScope(); // Check for various types of incomplete statements that could for example // mean that an ';' has been added by accident if (ErrorLogger::constStatement(_settings)) checkOther.CheckIncompleteStatement(); // Unusual pointer arithmetic if (ErrorLogger::strPlusChar()) checkOther.strPlusChar(); CheckStl checkStl(&_tokenizer, this); if (ErrorLogger::iteratorUsage()) checkStl.iterators(); if (ErrorLogger::stlOutOfBounds()) checkStl.stlOutOfBounds(); if (ErrorLogger::erase()) checkStl.erase(); if (ErrorLogger::pushback()) checkStl.pushback();}Settings CppCheck::settings() const{ return _settings;}//---------------------------------------------------------------------------void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg){ std::string errmsg = msg.toText(); // Alert only about unique errors if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end()) return; _errorList.push_back(errmsg); std::string errmsg2(errmsg); if (_settings._verbose) { errmsg2 += "\n Defines=\'" + cfg + "\'\n"; } _errorLogger->reportErr(msg); _errout << errmsg2 << std::endl;}void CppCheck::reportOut(const std::string & /*outmsg*/){ // This is currently never called. It is here just to comply with // the interface.}const std::vector<std::string> &CppCheck::filenames() const{ return _filenames;}void CppCheck::reportStatus(unsigned int /*index*/, unsigned int /*max*/){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -