From 276f017fbe214b0e8aa0334fea2950782eab2965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 29 Aug 2023 12:00:52 +0200 Subject: [PATCH] Partial fix for #11897 (Safety: show what checks are enabled/disabled) (#5372) Example output on stdout: ``` $ ./cppcheck m1.cpp Checking m1.cpp ... Active checkers: 59/177 ``` --- Makefile | 2 +- cli/cmdlineparser.cpp | 5 + cli/cppcheckexecutor.cpp | 191 ++++++++++++++ cli/cppcheckexecutor.h | 15 ++ gui/resultsview.cpp | 13 +- lib/check.cpp | 6 + lib/check.h | 3 + lib/check64bit.cpp | 2 + lib/checkassert.cpp | 2 + lib/checkautovariables.cpp | 5 + lib/checkbool.cpp | 18 ++ lib/checkboost.cpp | 1 + lib/checkbufferoverrun.cpp | 19 ++ lib/checkclass.cpp | 40 +++ lib/checkcondition.cpp | 30 +++ lib/checkers.h | 478 +++++++++++++++++++++++++++++++++++ lib/checkexceptionsafety.cpp | 13 + lib/checkfunctions.cpp | 19 ++ lib/checkio.cpp | 6 + lib/checkleakautovar.cpp | 2 + lib/checkmemoryleak.cpp | 12 +- lib/checkmemoryleak.h | 4 +- lib/checknullpointer.cpp | 8 + lib/checkother.cpp | 79 +++++- lib/checkother.h | 6 +- lib/checkpostfixoperator.cpp | 2 + lib/checksizeof.cpp | 17 ++ lib/checkstl.cpp | 41 ++- lib/checkstring.cpp | 12 + lib/checktype.cpp | 10 + lib/checkuninitvar.cpp | 4 + lib/checkunusedfunctions.cpp | 3 + lib/checkunusedvar.cpp | 4 + lib/checkvaarg.cpp | 5 + lib/cppcheck.cpp | 5 + lib/errorlogger.cpp | 11 + lib/errorlogger.h | 8 + lib/settings.h | 3 + test/cli/test-helloworld.py | 20 ++ test/cli/testutils.py | 2 + test/fixture.cpp | 2 + tools/get_checkers.py | 329 ++++++++++++++++++++++++ 42 files changed, 1434 insertions(+), 23 deletions(-) create mode 100644 lib/checkers.h create mode 100644 tools/get_checkers.py diff --git a/Makefile b/Makefile index 98646493d..8cc4ead63 100644 --- a/Makefile +++ b/Makefile @@ -638,7 +638,7 @@ $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathli cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h +cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/utils.h diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index fecc6b682..54a2e8af7 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -253,6 +253,9 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.checkLibrary = true; } + else if (std::strncmp(argv[i], "--checkers-report=", 18) == 0) + mSettings.checkersReportFilename = argv[i] + 18; + else if (std::strncmp(argv[i], "--checks-max-time=", 18) == 0) { if (!parseNumberArg(argv[i], 18, mSettings.checksMaxTime, true)) return false; @@ -1115,6 +1118,8 @@ void CmdLineParser::printHelp() " The default choice is 'normal'.\n" " --check-library Show information messages when library files have\n" " incomplete info.\n" + " --checkers-report=\n" + " Write a report of all the active checkers to the given file.\n" " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" " parser. Takes the executable as optional parameter and\n" " defaults to `clang`. Cppcheck will run the given Clang\n" diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 8f640c06e..041c051dc 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -19,6 +19,7 @@ #include "cppcheckexecutor.h" #include "analyzerinfo.h" +#include "checkers.h" #include "cmdlineparser.h" #include "color.h" #include "config.h" @@ -296,6 +297,9 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) AnalyzerInformation::writeFilesTxt(settings.buildDir, fileNames, settings.userDefines, settings.project.fileSettings); } + if (!settings.checkersReportFilename.empty()) + std::remove(settings.checkersReportFilename.c_str()); + unsigned int returnValue = 0; if (settings.useSingleJob()) { // Single process @@ -326,11 +330,186 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) reportErr(ErrorMessage::getXMLFooter()); } + writeCheckersReport(settings); + if (returnValue) return settings.exitCode; return 0; } +static bool isCppcheckPremium(const Settings& settings) { + return (settings.cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0); +} + +static std::string getMisraRuleSeverity(const std::string& rule) { + if (checkers::misraRuleSeverity.count(rule) > 0) + return checkers::misraRuleSeverity.at(rule); + return "style"; +} + +static bool isMisraRuleInconclusive(const std::string& rule) { + return rule == "8.3"; +} + +static bool isMisraRuleActive(const std::string& rule, int amendment, const std::string& severity, const Settings& settings) { + if (!isCppcheckPremium(settings) && amendment >= 3) + return false; + const bool inconclusive = isMisraRuleInconclusive(rule); + if (inconclusive && !settings.certainty.isEnabled(Certainty::inconclusive)) + return false; + if (severity == "warning") + return settings.severity.isEnabled(Severity::warning); + if (severity == "style") + return settings.severity.isEnabled(Severity::style); + return true; // error severity +} + +void CppCheckExecutor::writeCheckersReport(const Settings& settings) const +{ + if (!settings.quiet) { + int activeCheckers = 0; + int totalCheckers = 0; + for (const auto& checkReq: checkers::allCheckers) { + if (mActiveCheckers.count(checkReq.first) > 0) + ++activeCheckers; + ++totalCheckers; + } + if (isCppcheckPremium(settings)) { + for (const auto& checkReq: checkers::premiumCheckers) { + if (mActiveCheckers.count(checkReq.first) > 0) + ++activeCheckers; + ++totalCheckers; + } + } + if (mSettings->premiumArgs.find("misra-c-") != std::string::npos || mSettings->addons.count("misra")) { + for (const checkers::MisraInfo& info: checkers::misraC2012Rules) { + const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b); + const std::string severity = getMisraRuleSeverity(rule); + const bool active = isMisraRuleActive(rule, info.amendment, severity, settings); + if (active) + ++activeCheckers; + ++totalCheckers; + } + } + + const std::string extra = settings.verbose ? " (use --checkers-report= to see details)" : ""; + if (mCriticalErrors.empty()) + std::cout << "Active checkers: " << activeCheckers << "/" << totalCheckers << extra << std::endl; + else + std::cout << "Active checkers: There was critical errors" << extra << std::endl; + } + + if (settings.checkersReportFilename.empty()) + return; + + std::ofstream fout(settings.checkersReportFilename); + if (!fout.is_open()) + return; + + fout << "Critical errors" << std::endl; + fout << "---------------" << std::endl; + if (!mCriticalErrors.empty()) { + fout << "There was critical errors (" << mCriticalErrors << ")" << std::endl; + fout << "All checking is skipped for a file with such error" << std::endl; + } else { + fout << "No critical errors, all files were checked." << std::endl; + fout << "Important: Analysis is still not guaranteed to be 'complete' it is possible there are false negatives." << std::endl; + } + + fout << std::endl << std::endl; + fout << "Open source checkers" << std::endl; + fout << "--------------------" << std::endl; + + int maxCheckerSize = 0; + for (const auto& checkReq: checkers::allCheckers) { + const std::string& checker = checkReq.first; + if (checker.size() > maxCheckerSize) + maxCheckerSize = checker.size(); + } + for (const auto& checkReq: checkers::allCheckers) { + const std::string& checker = checkReq.first; + const bool active = mActiveCheckers.count(checkReq.first) > 0; + const std::string& req = checkReq.second; + fout << (active ? "Yes " : "No ") << checker; + if (!active && !req.empty()) + fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req; + fout << std::endl; + } + + const bool cppcheckPremium = isCppcheckPremium(settings); + + if (cppcheckPremium) { + fout << std::endl << std::endl; + fout << "Premium checkers" << std::endl; + fout << "----------------" << std::endl; + + maxCheckerSize = 0; + for (const auto& checkReq: checkers::premiumCheckers) { + const std::string& checker = checkReq.first; + if (checker.size() > maxCheckerSize) + maxCheckerSize = checker.size(); + } + for (const auto& checkReq: checkers::premiumCheckers) { + const std::string& checker = checkReq.first; + std::string req = checkReq.second; + bool active = cppcheckPremium; + if (req == "warning") + active &= mSettings->severity.isEnabled(Severity::warning); + else if (req == "style") + active &= mSettings->severity.isEnabled(Severity::style); + fout << (active ? "Yes " : "No ") << checker; + if (!req.empty()) + req = "premium," + req; + else + req = "premium"; + if (!active) + fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req; + fout << std::endl; + } + } + + int misra = 0; + if (mSettings->premiumArgs.find("misra-c-2012") != std::string::npos) + misra = 2012; + else if (mSettings->premiumArgs.find("misra-c-2023") != std::string::npos) + misra = 2023; + else if (mSettings->addons.count("misra")) + misra = 2012; + + if (misra == 0) { + fout << std::endl << std::endl; + fout << "Misra C" << std::endl; + fout << "-------" << std::endl; + fout << "Misra is not enabled" << std::endl; + } else { + fout << std::endl << std::endl; + fout << "Misra C " << misra << std::endl; + fout << "------------" << std::endl; + for (const checkers::MisraInfo& info: checkers::misraC2012Rules) { + const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b); + const std::string severity = getMisraRuleSeverity(rule); + const bool active = isMisraRuleActive(rule, info.amendment, severity, settings); + const bool inconclusive = isMisraRuleInconclusive(rule); + fout << (active ? "Yes " : "No ") << rule; + std::string extra; + if (misra == 2012 && info.amendment >= 1) + extra = " amendment:" + std::to_string(info.amendment); + std::string reqs; + if (info.amendment >= 3) + reqs += ",premium"; + if (severity != "error") + reqs += "," + severity; + if (inconclusive) + reqs += ",inconclusive"; + if (!active && !reqs.empty()) + extra += " require:" + reqs.substr(1); + if (!extra.empty()) + fout << std::string(7 - rule.size(), ' ') << extra; + fout << '\n'; + } + } +} + bool CppCheckExecutor::loadLibraries(Settings& settings) { if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) { @@ -428,10 +607,22 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg) { assert(mSettings != nullptr); + if (msg.severity == Severity::none && msg.id == "logChecker") { + const std::string& checker = msg.shortMessage(); + mActiveCheckers.emplace(checker); + return; + } + // Alert only about unique errors if (!mShownErrors.insert(msg.toString(mSettings->verbose)).second) return; + if (ErrorLogger::isCriticalErrorId(msg.id) && mCriticalErrors.find(msg.id) == std::string::npos) { + if (!mCriticalErrors.empty()) + mCriticalErrors += ", "; + mCriticalErrors += msg.id; + } + if (mSettings->xml) reportErr(msg.toXML()); else diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index e5577396d..47660c9dd 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -153,6 +153,11 @@ private: */ bool loadLibraries(Settings& settings); + /** + * @brief Write the checkers report + */ + void writeCheckersReport(const Settings& settings) const; + /** * Pointer to current settings; set while check() is running for reportError(). */ @@ -182,6 +187,16 @@ private: * Error output */ std::ofstream* mErrorOutput{}; + + /** + * Checkers that has been executed + */ + std::set mActiveCheckers; + + /** + * True if there are critical errors + */ + std::string mCriticalErrors; }; #endif // CPPCHECKEXECUTOR_H diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp index 942ab5974..e1cea8833 100644 --- a/gui/resultsview.cpp +++ b/gui/resultsview.cpp @@ -527,18 +527,7 @@ void ResultsView::stopAnalysis() void ResultsView::handleCriticalError(const ErrorItem &item) { - const QSet criticalErrors{ - "cppcheckError", - "cppcheckLimit", - "internalAstError", - "instantiationError", - "internalError", - "preprocessorErrorDirective", - "syntaxError", - "unknownMacro" - }; - - if (criticalErrors.contains(item.errorId)) { + if (ErrorLogger::isCriticalErrorId(item.errorId.toStdString())) { QString msg = tr("There was a critical error with id '%1'").arg(item.errorId); if (!item.file0.isEmpty()) msg += ", " + tr("when checking %1").arg(item.file0); diff --git a/lib/check.cpp b/lib/check.cpp index de7b3892c..114ca8d71 100644 --- a/lib/check.cpp +++ b/lib/check.cpp @@ -125,3 +125,9 @@ ErrorPath Check::getErrorPath(const Token* errtok, const ValueFlow::Value* value } return errorPath; } + +void Check::logChecker(const char id[]) +{ + reportError(nullptr, Severity::none, "logChecker", id); +} + diff --git a/lib/check.h b/lib/check.h index 5421c64a7..1a6c57faa 100644 --- a/lib/check.h +++ b/lib/check.h @@ -155,6 +155,9 @@ protected: void reportError(const ErrorPath &errorPath, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty); + /** log checker */ + void logChecker(const char id[]); + ErrorPath getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const; /** diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index a70e94a21..c43eb9db2 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -46,6 +46,8 @@ void Check64BitPortability::pointerassignment() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("Check64BitPortability::pointerassignment"); // portability + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // Check return values diff --git a/lib/checkassert.cpp b/lib/checkassert.cpp index 41fe45574..c6eae27c4 100644 --- a/lib/checkassert.cpp +++ b/lib/checkassert.cpp @@ -44,6 +44,8 @@ void CheckAssert::assertWithSideEffects() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckAssert::assertWithSideEffects"); // warning + for (const Token* tok = mTokenizer->list.front(); tok; tok = tok->next()) { if (!Token::simpleMatch(tok, "assert (")) continue; diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 6e4322ebf..61d070fc4 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -213,6 +213,8 @@ void CheckAutoVariables::assignFunctionArg() if (!printStyle && !printWarning) return; + logChecker("CheckAutoVariables::assignFunctionArg"); // style,warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -261,6 +263,8 @@ static bool hasOverloadedAssignment(const Token* tok, bool c, bool& inconclusive void CheckAutoVariables::autoVariables() { + logChecker("CheckAutoVariables::autoVariables"); + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -674,6 +678,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token void CheckAutoVariables::checkVarLifetime() { + logChecker("CheckAutoVariables::checkVarLifetime"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { if (!scope->function) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 970cd7d70..4de26ea28 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -53,6 +53,8 @@ void CheckBool::checkIncrementBoolean() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckBool::checkIncrementBoolean"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -96,6 +98,8 @@ void CheckBool::checkBitwiseOnBoolean() if (!mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckBool::checkBitwiseOnBoolean"); // style,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -149,6 +153,8 @@ void CheckBool::checkComparisonOfBoolWithInt() if (!mSettings->severity.isEnabled(Severity::warning) || !mTokenizer->isCPP()) return; + logChecker("CheckBool::checkComparisonOfBoolWithInt"); // warning,c++ + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -201,6 +207,8 @@ void CheckBool::checkComparisonOfFuncReturningBool() if (!mTokenizer->isCPP()) return; + logChecker("CheckBool::checkComparisonOfFuncReturningBool"); // style,c++ + const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); auto getFunctionTok = [](const Token* tok) -> const Token* { while (Token::simpleMatch(tok, "!") || (tok && tok->isCast() && !isCPPCast(tok))) @@ -265,6 +273,8 @@ void CheckBool::checkComparisonOfBoolWithBool() if (!mTokenizer->isCPP()) return; + logChecker("CheckBool::checkComparisonOfBoolWithBool"); // style,c++ + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -308,6 +318,7 @@ void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::strin //----------------------------------------------------------------------------- void CheckBool::checkAssignBoolToPointer() { + logChecker("CheckBool::checkAssignBoolToPointer"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -331,6 +342,8 @@ void CheckBool::checkComparisonOfBoolExpressionWithInt() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckBool::checkComparisonOfBoolExpressionWithInt"); // warning + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -397,6 +410,8 @@ void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool no void CheckBool::pointerArithBool() { + logChecker("CheckBool::pointerArithBool"); + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -451,6 +466,7 @@ void CheckBool::checkAssignBoolToFloat() return; if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckBool::checkAssignBoolToFloat"); // style,c++ const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -472,6 +488,8 @@ void CheckBool::returnValueOfFunctionReturningBool() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckBool::returnValueOfFunctionReturningBool"); // style + const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { diff --git a/lib/checkboost.cpp b/lib/checkboost.cpp index 9974f5e6d..5ddea9945 100644 --- a/lib/checkboost.cpp +++ b/lib/checkboost.cpp @@ -33,6 +33,7 @@ static const CWE CWE664(664); void CheckBoost::checkBoostForeachModification() { + logChecker("CheckBoost::checkBoostForeachModification"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart->next(); tok && tok != scope->bodyEnd; tok = tok->next()) { diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index cf5ec86fd..7470a340a 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -280,6 +280,8 @@ static std::vector getOverrunIndexValues(const Token* tok, void CheckBufferOverrun::arrayIndex() { + logChecker("CheckBufferOverrun::arrayIndex"); + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "[") continue; @@ -461,6 +463,8 @@ void CheckBufferOverrun::pointerArithmetic() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("CheckBufferOverrun::pointerArithmetic"); // portability + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!Token::Match(tok, "+|-")) continue; @@ -626,6 +630,8 @@ static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::Mi void CheckBufferOverrun::bufferOverflow() { + logChecker("CheckBufferOverrun::bufferOverflow"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -691,6 +697,8 @@ void CheckBufferOverrun::arrayIndexThenCheck() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("CheckBufferOverrun::arrayIndexThenCheck"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * const scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -746,6 +754,9 @@ void CheckBufferOverrun::stringNotZeroTerminated() // this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3 if (!mSettings->severity.isEnabled(Severity::warning) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + + logChecker("CheckBufferOverrun::stringNotZeroTerminated"); // warning,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * const scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -810,6 +821,8 @@ void CheckBufferOverrun::argumentSize() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckBufferOverrun::argumentSize"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * const scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -957,6 +970,10 @@ bool CheckBufferOverrun::analyseWholeProgram(const CTU::FileInfo *ctu, const std bool foundErrors = false; (void)settings; // This argument is unused + CheckBufferOverrun dummy(nullptr, &settings, &errorLogger); + dummy. + logChecker("CheckBufferOverrun::analyseWholeProgram"); + const std::map> callsMap = ctu->getCallsMap(); for (const Check::FileInfo* fi1 : fileInfo) { @@ -1015,6 +1032,7 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::mapgetSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -1122,6 +1140,7 @@ static bool isVLAIndex(const Token* tok) void CheckBufferOverrun::negativeArraySize() { + logChecker("CheckBufferOverrun::negativeArraySize"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->isArray()) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 29a94f024..dd15ca066 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -131,6 +131,8 @@ void CheckClass::constructors() if (!printStyle && !printWarnings) return; + logChecker("CheckClass::checkConstructors"); // style,warning + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { if (mSettings->hasLib("vcl") && isVclTypeInit(scope->definedType)) @@ -338,6 +340,8 @@ void CheckClass::checkExplicitConstructors() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckClass::checkExplicitConstructors"); // style + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // Do not perform check, if the class/struct has not any constructors if (scope->numConstructors == 0) @@ -405,6 +409,8 @@ void CheckClass::copyconstructors() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::checkCopyConstructors"); // warning + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { std::map allocatedVars; @@ -1115,6 +1121,8 @@ void CheckClass::initializationListUsage() if (!mSettings->severity.isEnabled(Severity::performance)) return; + logChecker("CheckClass::initializationListUsage"); // performance + for (const Scope *scope : mSymbolDatabase->functionScopes) { // Check every constructor if (!scope->function || !scope->function->isConstructor()) @@ -1255,6 +1263,8 @@ void CheckClass::privateFunctions() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckClass::privateFunctions"); // style + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // do not check borland classes with properties.. @@ -1325,6 +1335,7 @@ static const Scope* findFunctionOf(const Scope* scope) void CheckClass::checkMemset() { + logChecker("CheckClass::checkMemset"); const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); for (const Scope *scope : mSymbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -1541,6 +1552,8 @@ void CheckClass::operatorEqRetRefThis() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckClass::operatorEqRetRefThis"); // style + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { for (std::list::const_iterator func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) { if (func->type == Function::eOperatorEqual && func->hasBody()) { @@ -1683,6 +1696,8 @@ void CheckClass::operatorEqToSelf() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::operatorEqToSelf"); // warning + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // skip classes with multiple inheritance if (scope->definedType->derivedFrom.size() > 1) @@ -1881,6 +1896,8 @@ void CheckClass::virtualDestructor() std::list inconclusiveErrors; + logChecker("CheckClass::virtualDestructor"); + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // Skip base classes (unless inconclusive) @@ -2028,6 +2045,8 @@ void CheckClass::thisSubtraction() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::thisSubtraction"); // warning + const Token *tok = mTokenizer->tokens(); for (;;) { tok = Token::findmatch(tok, "this - %name%"); @@ -2059,6 +2078,8 @@ void CheckClass::checkConst() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckClass::checkConst"); // style,inconclusive + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { for (const Function &func : scope->functionList) { // does the function have a body? @@ -2609,6 +2630,8 @@ void CheckClass::initializerListOrder() if (!mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckClass::initializerListOrder"); // style,inconclusive + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // iterate through all member functions looking for constructors @@ -2671,6 +2694,8 @@ void CheckClass::initializerListError(const Token *tok1, const Token *tok2, cons void CheckClass::checkSelfInitialization() { + logChecker("CheckClass::checkSelfInitialization"); + for (const Scope *scope : mSymbolDatabase->functionScopes) { const Function* function = scope->function; if (!function || !function->isConstructor()) @@ -2710,6 +2735,7 @@ void CheckClass::checkVirtualFunctionCallInConstructor() { if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::checkVirtualFunctionCallInConstructor"); // warning std::map> virtualFunctionCallsMap; for (const Scope *scope : mSymbolDatabase->functionScopes) { if (scope->function == nullptr || !scope->function->hasBody() || @@ -2878,6 +2904,8 @@ void CheckClass::checkDuplInheritedMembers() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::checkDuplInheritedMembers"); // warning + // Iterate over all classes for (const Type &classIt : mSymbolDatabase->typeList) { // Iterate over the parent classes @@ -3009,6 +3037,8 @@ void CheckClass::checkCopyCtorAndEqOperator() if ((true) || !mSettings->severity.isEnabled(Severity::warning)) // NOLINT(readability-simplify-boolean-expr) return; + // logChecker + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { const bool hasNonStaticVars = std::any_of(scope->varlist.begin(), scope->varlist.end(), [](const Variable& var) { @@ -3068,6 +3098,7 @@ void CheckClass::checkOverride() return; if (mSettings->standards.cpp < Standards::CPP11) return; + logChecker("CheckClass::checkMissingOverride"); // style,c++03 for (const Scope * classScope : mSymbolDatabase->classAndStructScopes) { if (!classScope->definedType || classScope->definedType->derivedFrom.empty()) continue; @@ -3166,6 +3197,8 @@ void CheckClass::checkUselessOverride() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckClass::checkUselessOverride"); // style + for (const Scope* classScope : mSymbolDatabase->classAndStructScopes) { if (!classScope->definedType || classScope->definedType->derivedFrom.size() != 1) continue; @@ -3223,6 +3256,8 @@ void CheckClass::checkThisUseAfterFree() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::checkThisUseAfterFree"); // warning + for (const Scope * classScope : mSymbolDatabase->classAndStructScopes) { for (const Variable &var : classScope->varlist) { @@ -3320,6 +3355,7 @@ void CheckClass::checkUnsafeClassRefMember() { if (!mSettings->safeChecks.classes || !mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckClass::checkUnsafeClassRefMember"); // warning,safeChecks for (const Scope * classScope : mSymbolDatabase->classAndStructScopes) { for (const Function &func : classScope->functionList) { if (!func.hasBody() || !func.isConstructor()) @@ -3467,6 +3503,10 @@ bool CheckClass::analyseWholeProgram(const CTU::FileInfo *ctu, const std::list all; + CheckClass dummy(nullptr, &settings, &errorLogger); + dummy. + logChecker("CheckClass::analyseWholeProgram"); + for (const Check::FileInfo* fi1 : fileInfo) { const MyFileInfo *fi = dynamic_cast(fi1); if (!fi) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 226e6c993..fa7700707 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -89,6 +89,8 @@ void CheckCondition::assignIf() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::assignIf"); // style + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "=") continue; @@ -306,6 +308,8 @@ void CheckCondition::checkBadBitmaskCheck() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::checkBadBitmaskCheck"); // style + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() == "|" && tok->astOperand1() && tok->astOperand2() && tok->astParent()) { const Token* parent = tok->astParent(); @@ -352,6 +356,8 @@ void CheckCondition::comparison() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::comparison"); // style + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->isComparisonOp()) continue; @@ -470,6 +476,8 @@ void CheckCondition::duplicateCondition() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::duplicateCondition"); // style + const SymbolDatabase *const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -519,6 +527,8 @@ void CheckCondition::multiCondition() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::multiCondition"); // style + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -605,6 +615,8 @@ void CheckCondition::multiCondition2() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckCondition::multiCondition2"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -1114,6 +1126,8 @@ void CheckCondition::checkIncorrectLogicOperator() return; const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); + logChecker("CheckCondition::checkIncorrectLogicOperator"); // style,warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -1347,6 +1361,8 @@ void CheckCondition::checkModuloAlwaysTrueFalse() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckCondition::checkModuloAlwaysTrueFalse"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -1403,6 +1419,8 @@ void CheckCondition::clarifyCondition() const bool isC = mTokenizer->isC(); + logChecker("CheckCondition::clarifyCondition"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -1465,6 +1483,8 @@ void CheckCondition::alwaysTrueFalse() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::alwaysTrueFalse"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -1627,6 +1647,8 @@ void CheckCondition::checkInvalidTestForOverflow() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckCondition::checkInvalidTestForOverflow"); // warning + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!Token::Match(tok, "<|<=|>=|>") || !tok->isBinaryOp()) continue; @@ -1716,6 +1738,8 @@ void CheckCondition::checkPointerAdditionResultNotNull() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckCondition::checkPointerAdditionResultNotNull"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -1761,6 +1785,8 @@ void CheckCondition::checkDuplicateConditionalAssign() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::checkDuplicateConditionalAssign"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -1838,6 +1864,8 @@ void CheckCondition::checkAssignmentInCondition() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckCondition::checkAssignmentInCondition"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -1887,6 +1915,8 @@ void CheckCondition::checkCompareValueOutOfTypeRange() mSettings->platform.type == cppcheck::Platform::Type::Unspecified) return; + logChecker("CheckCondition::checkCompareValueOutOfTypeRange"); // style,platform + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { diff --git a/lib/checkers.h b/lib/checkers.h new file mode 100644 index 000000000..5cc61a518 --- /dev/null +++ b/lib/checkers.h @@ -0,0 +1,478 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2023 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace checkers { + + static std::map allCheckers{ + {"CheckBool::checkIncrementBoolean","style"}, + {"CheckBool::checkBitwiseOnBoolean","style,inconclusive"}, + {"CheckBool::checkComparisonOfBoolWithInt","warning,c++"}, + {"CheckBool::checkComparisonOfFuncReturningBool","style,c++"}, + {"CheckBool::checkComparisonOfBoolWithBool","style,c++"}, + {"CheckBool::checkAssignBoolToPointer",""}, + {"CheckBool::checkComparisonOfBoolExpressionWithInt","warning"}, + {"CheckBool::pointerArithBool",""}, + {"CheckBool::checkAssignBoolToFloat","style,c++"}, + {"CheckBool::returnValueOfFunctionReturningBool","style"}, + {"CheckPostfixOperator::postfixOperator","performance"}, + {"CheckSizeof::checkSizeofForNumericParameter","warning"}, + {"CheckSizeof::checkSizeofForArrayParameter","warning"}, + {"CheckSizeof::checkSizeofForPointerSize","warning"}, + {"CheckSizeof::sizeofsizeof","warning"}, + {"CheckSizeof::sizeofCalculation","warning"}, + {"CheckSizeof::sizeofFunction","warning"}, + {"CheckSizeof::suspiciousSizeofCalculation","warning,inconclusive"}, + {"CheckSizeof::sizeofVoid","portability"}, + {"Check64BitPortability::pointerassignment","portability"}, + {"CheckStl::outOfBounds",""}, + {"CheckStl::outOfBoundsIndexExpression",""}, + {"CheckStl::iterators",""}, + {"CheckStl::misMatchingContainers",""}, + {"CheckStl::misMatchingContainerIterator",""}, + {"CheckStl::invalidContainer",""}, + {"CheckStl::stlOutOfBounds",""}, + {"CheckStl::negativeIndex",""}, + {"CheckStl::erase",""}, + {"CheckStl::stlBoundaries",""}, + {"CheckStl::if_find","warning,performance"}, + {"CheckStl::checkFindInsert","performance"}, + {"CheckStl::size","performance,c++03"}, + {"CheckStl::redundantCondition","style"}, + {"CheckStl::missingComparison","warning"}, + {"CheckStl::string_c_str",""}, + {"CheckStl::uselessCalls","performance,warning"}, + {"CheckStl::checkDereferenceInvalidIterator","warning"}, + {"CheckStl::checkDereferenceInvalidIterator2",""}, + {"CheckStl::useStlAlgorithm","style"}, + {"CheckStl::knownEmptyContainer","style"}, + {"CheckStl::checkMutexes","warning"}, + {"CheckBoost::checkBoostForeachModification",""}, + {"CheckNullPointer::nullPointer",""}, + {"CheckNullPointer::nullConstantDereference",""}, + {"CheckNullPointer::aithmetic",""}, + {"CheckNullPointer::analyseWholeProgram","unusedfunctions"}, + {"CheckBufferOverrun::arrayIndex",""}, + {"CheckBufferOverrun::pointerArithmetic","portability"}, + {"CheckBufferOverrun::bufferOverflow",""}, + {"CheckBufferOverrun::arrayIndexThenCheck",""}, + {"CheckBufferOverrun::stringNotZeroTerminated","warning,inconclusive"}, + {"CheckBufferOverrun::argumentSize","warning"}, + {"CheckBufferOverrun::analyseWholeProgram",""}, + {"CheckBufferOverrun::objectIndex",""}, + {"CheckBufferOverrun::negativeArraySize",""}, + {"CheckUninitVar::check",""}, + {"CheckUninitVar::valueFlowUninit",""}, + {"CheckOther::checkCastIntToCharAndBack","warning"}, + {"CheckOther::clarifyCalculation","style"}, + {"CheckOther::clarifyStatement","warning"}, + {"CheckOther::checkSuspiciousSemicolon","warning,inconclusive"}, + {"CheckOther::warningOldStylePointerCast","style,c++"}, + {"CheckOther::invalidPointerCast","portability"}, + {"CheckOther::checkRedundantAssignment","style"}, + {"CheckOther::redundantBitwiseOperationInSwitch","warning"}, + {"CheckOther::checkSuspiciousCaseInSwitch","warning,inconclusive"}, + {"CheckOther::checkUnreachableCode","style"}, + {"CheckOther::checkVariableScope","style,notclang"}, + {"CheckOther::checkPassByReference","performance,c++"}, + {"CheckOther::checkConstPointer","style"}, + {"CheckOther::checkCharVariable","warning,portability"}, + {"CheckOther::checkIncompleteStatement","warning"}, + {"CheckOther::checkZeroDivision",""}, + {"CheckOther::checkNanInArithmeticExpression","style"}, + {"CheckOther::checkMisusedScopedObject","style,c++"}, + {"CheckOther::checkDuplicateBranch","style,inconclusive"}, + {"CheckOther::checkInvalidFree",""}, + {"CheckOther::checkDuplicateExpression","style,warning"}, + {"CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse","warning"}, + {"CheckOther::checkSignOfUnsignedVariable","style"}, + {"CheckOther::checkRedundantCopy","c++,performance,inconclusive"}, + {"CheckOther::checkNegativeBitwiseShift",""}, + {"CheckOther::checkIncompleteArrayFill","warning,portability,inconclusive"}, + {"CheckOther::checkVarFuncNullUB","portability"}, + {"CheckOther::checkRedundantPointerOp","style"}, + {"CheckOther::checkInterlockedDecrement","windows-platform"}, + {"CheckOther::checkUnusedLabel","style,warning"}, + {"CheckOther::checkEvaluationOrder","C/C++03"}, + {"CheckOther::checkAccessOfMovedVariable","c++11,warning"}, + {"CheckOther::checkFuncArgNamesDifferent","style,warning,inconclusive"}, + {"CheckOther::checkShadowVariables","style"}, + {"CheckOther::checkKnownArgument","style"}, + {"CheckOther::checkKnownPointerToBool","style"}, + {"CheckOther::checkComparePointers",""}, + {"CheckOther::checkModuloOfOne","style"}, + {"CheckOther::checkOverlappingWrite",""}, + {"CheckClass::checkConstructors","style,warning"}, + {"CheckClass::checkExplicitConstructors","style"}, + {"CheckClass::checkCopyConstructors","warning"}, + {"CheckClass::initializationListUsage","performance"}, + {"CheckClass::privateFunctions","style"}, + {"CheckClass::checkMemset",""}, + {"CheckClass::operatorEqRetRefThis","style"}, + {"CheckClass::operatorEqToSelf","warning"}, + {"CheckClass::virtualDestructor",""}, + {"CheckClass::thisSubtraction","warning"}, + {"CheckClass::checkConst","style,inconclusive"}, + {"CheckClass::initializerListOrder","style,inconclusive"}, + {"CheckClass::checkSelfInitialization",""}, + {"CheckClass::checkVirtualFunctionCallInConstructor","warning"}, + {"CheckClass::checkDuplInheritedMembers","warning"}, + {"CheckClass::checkMissingOverride","style,c++03"}, + {"CheckClass::checkUselessOverride","style"}, + {"CheckClass::checkThisUseAfterFree","warning"}, + {"CheckClass::checkUnsafeClassRefMember","warning,safeChecks"}, + {"CheckClass::analyseWholeProgram",""}, + {"CheckUnusedVar::checkFunctionVariableUsage","style"}, + {"CheckUnusedVar::checkStructMemberUsage","style"}, + {"CheckIO::checkCoutCerrMisusage","c"}, + {"CheckIO::checkFileUsage",""}, + {"CheckIO::checkWrongPrintfScanfArguments",""}, + {"CheckCondition::assignIf","style"}, + {"CheckCondition::checkBadBitmaskCheck","style"}, + {"CheckCondition::comparison","style"}, + {"CheckCondition::duplicateCondition","style"}, + {"CheckCondition::multiCondition","style"}, + {"CheckCondition::multiCondition2","warning"}, + {"CheckCondition::checkIncorrectLogicOperator","style,warning"}, + {"CheckCondition::checkModuloAlwaysTrueFalse","warning"}, + {"CheckCondition::clarifyCondition","style"}, + {"CheckCondition::alwaysTrueFalse","style"}, + {"CheckCondition::checkInvalidTestForOverflow","warning"}, + {"CheckCondition::checkPointerAdditionResultNotNull","warning"}, + {"CheckCondition::checkDuplicateConditionalAssign","style"}, + {"CheckCondition::checkAssignmentInCondition","style"}, + {"CheckCondition::checkCompareValueOutOfTypeRange","style,platform"}, + {"CheckFunctions::checkProhibitedFunctions",""}, + {"CheckFunctions::invalidFunctionUsage",""}, + {"CheckFunctions::checkIgnoredReturnValue","style,warning"}, + {"CheckFunctions::checkMissingReturn",""}, + {"CheckFunctions::checkMathFunctions","style,warning,c99,c++11"}, + {"CheckFunctions::memsetZeroBytes","warning"}, + {"CheckFunctions::memsetInvalid2ndParam","warning,portability"}, + {"CheckFunctions::returnLocalStdMove","performance,c++11"}, + {"CheckFunctions::useStandardLibrary","style"}, + {"CheckVaarg::va_start_argument",""}, + {"CheckVaarg::va_list_usage","notclang"}, + {"CheckUnusedFunctions::analyseWholeProgram","unusedFunctions"}, + {"CheckType::checkTooBigBitwiseShift","platform"}, + {"CheckType::checkIntegerOverflow","platform"}, + {"CheckType::checkSignConversion","warning"}, + {"CheckType::checkLongCast","style"}, + {"CheckType::checkFloatToIntegerOverflow",""}, + {"CheckString::stringLiteralWrite",""}, + {"CheckString::checkAlwaysTrueOrFalseStringCompare","warning"}, + {"CheckString::checkSuspiciousStringCompare","warning"}, + {"CheckString::strPlusChar",""}, + {"CheckString::checkIncorrectStringCompare","warning"}, + {"CheckString::overlappingStrcmp","warning"}, + {"CheckString::sprintfOverlappingData",""}, + {"CheckAssert::assertWithSideEffects","warning"}, + {"CheckExceptionSafety::destructors","warning"}, + {"CheckExceptionSafety::deallocThrow","warning"}, + {"CheckExceptionSafety::checkRethrowCopy","style"}, + {"CheckExceptionSafety::checkCatchExceptionByValue","style"}, + {"CheckExceptionSafety::nothrowThrows",""}, + {"CheckExceptionSafety::unhandledExceptionSpecification","style,inconclusive"}, + {"CheckExceptionSafety::rethrowNoCurrentException",""}, + {"CheckAutoVariables::assignFunctionArg","style,warning"}, + {"CheckAutoVariables::autoVariables",""}, + {"CheckAutoVariables::checkVarLifetime",""}, + {"CheckLeakAutoVar::check","notclang"}, + {"CheckMemoryLeakInFunction::checkReallocUsage",""}, + {"CheckMemoryLeakInClass::check",""}, + {"CheckMemoryLeakStructMember::check",""}, + {"CheckMemoryLeakNoVar::check",""}, + }; + + + static std::map premiumCheckers{ + {"CheckBufferOverrun::addressOfPointerArithmetic","warning"}, + {"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"}, + {"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"}, + {"CheckHang::infiniteLoop",""}, + {"CheckHang::infiniteLoopContinue",""}, + {"CheckOther::arrayPointerComparison","style"}, + {"CheckOther::knownResult","style"}, + {"CheckOther::lossOfPrecision","style"}, + {"CheckOther::pointerCast","style"}, + {"CheckOther::reassignInLoop","style"}, + {"CheckOther::unreachableCode","style"}, + {"CheckStrictAlias::strictAliasCondition","warning"}, + {"CheckUninitVar::uninitvar",""}, + {"CheckUninitVar::uninitmember",""}, + {"CheckUnusedVar::unreadVariable","style"}, + {"CheckUnusedVar::unusedPrivateMember","style"}, + }; + + + + struct MisraInfo { + int a; + int b; + const char* str; + int amendment; + }; + + const char Req[] = "Required"; + const char Adv[] = "Advisory"; + const char Man[] = "Mandatory"; + + const MisraInfo misraC2012Rules[] = + { + {1,1,Req,0}, + {1,2,Adv,0}, + {1,3,Req,0}, + {1,4,Req,2}, // amendment 2 + {1,5,Req,3}, // Amendment 3 + {2,1,Req,0}, + {2,2,Req,0}, + {2,3,Adv,0}, + {2,4,Adv,0}, + {2,5,Adv,0}, + {2,6,Adv,0}, + {2,7,Adv,0}, + {2,8,Adv,0}, + {3,1,Req,0}, + {3,2,Req,0}, + {4,1,Req,0}, + {4,2,Adv,0}, + {5,1,Req,0}, + {5,2,Req,0}, + {5,3,Req,0}, + {5,4,Req,0}, + {5,5,Req,0}, + {5,6,Req,0}, + {5,7,Req,0}, + {5,8,Req,0}, + {5,9,Adv,0}, + {6,1,Req,0}, + {6,2,Req,0}, + {6,3,Req,0}, + {7,1,Req,0}, + {7,2,Req,0}, + {7,3,Req,0}, + {7,4,Req,0}, + {7,5,Man,0}, + {7,6,Req,0}, + {8,1,Req,0}, + {8,2,Req,0}, + {8,3,Req,0}, + {8,4,Req,0}, + {8,5,Req,0}, + {8,6,Req,0}, + {8,7,Adv,0}, + {8,8,Req,0}, + {8,9,Adv,0}, + {8,10,Req,0}, + {8,11,Adv,0}, + {8,12,Req,0}, + {8,13,Adv,0}, + {8,14,Req,0}, + {8,15,Req,0}, + {8,16,Adv,0}, + {8,17,Adv,0}, + {9,1,Man,0}, + {9,2,Req,0}, + {9,3,Req,0}, + {9,4,Req,0}, + {9,5,Req,0}, + {9,6,Req,0}, + {9,7,Man,0}, + {10,1,Req,0}, + {10,2,Req,0}, + {10,3,Req,0}, + {10,4,Req,0}, + {10,5,Adv,0}, + {10,6,Req,0}, + {10,7,Req,0}, + {10,8,Req,0}, + {11,1,Req,0}, + {11,2,Req,0}, + {11,3,Req,0}, + {11,4,Adv,0}, + {11,5,Adv,0}, + {11,6,Req,0}, + {11,7,Req,0}, + {11,8,Req,0}, + {11,9,Req,0}, + {11,10,Req,0}, + {12,1,Adv,0}, + {12,2,Req,0}, + {12,3,Adv,0}, + {12,4,Adv,0}, + {12,5,Man,1}, // amendment 1 + {12,6,Req,4}, // amendment 4 + {13,1,Req,0}, + {13,2,Req,0}, + {13,3,Adv,0}, + {13,4,Adv,0}, + {13,5,Req,0}, + {13,6,Man,0}, + {14,1,Req,0}, + {14,2,Req,0}, + {14,3,Req,0}, + {14,4,Req,0}, + {15,1,Adv,0}, + {15,2,Req,0}, + {15,3,Req,0}, + {15,4,Adv,0}, + {15,5,Adv,0}, + {15,6,Req,0}, + {15,7,Req,0}, + {16,1,Req,0}, + {16,2,Req,0}, + {16,3,Req,0}, + {16,4,Req,0}, + {16,5,Req,0}, + {16,6,Req,0}, + {16,7,Req,0}, + {17,1,Req,0}, + {17,2,Req,0}, + {17,3,Man,0}, + {17,4,Man,0}, + {17,5,Adv,0}, + {17,6,Man,0}, + {17,7,Req,0}, + {17,8,Adv,0}, + {17,9,Man,0}, + {17,10,Req,0}, + {17,11,Adv,0}, + {17,12,Adv,0}, + {17,13,Req,0}, + {18,1,Req,0}, + {18,2,Req,0}, + {18,3,Req,0}, + {18,4,Adv,0}, + {18,5,Adv,0}, + {18,6,Req,0}, + {18,7,Req,0}, + {18,8,Req,0}, + {18,9,Req,0}, + {18,10,Man,0}, + {19,1,Man,0}, + {19,2,Adv,0}, + {20,1,Adv,0}, + {20,2,Req,0}, + {20,3,Req,0}, + {20,4,Req,0}, + {20,5,Adv,0}, + {20,6,Req,0}, + {20,7,Req,0}, + {20,8,Req,0}, + {20,9,Req,0}, + {20,10,Adv,0}, + {20,11,Req,0}, + {20,12,Req,0}, + {20,13,Req,0}, + {20,14,Req,0}, + {21,1,Req,0}, + {21,2,Req,0}, + {21,3,Req,0}, + {21,4,Req,0}, + {21,5,Req,0}, + {21,6,Req,0}, + {21,7,Req,0}, + {21,8,Req,0}, + {21,9,Req,0}, + {21,10,Req,0}, + {21,11,Req,0}, + {21,12,Adv,0}, + {21,13,Man,1}, // Amendment 1 + {21,14,Req,1}, // Amendment 1 + {21,15,Req,1}, // Amendment 1 + {21,16,Req,1}, // Amendment 1 + {21,17,Req,1}, // Amendment 1 + {21,18,Man,1}, // Amendment 1 + {21,19,Man,1}, // Amendment 1 + {21,20,Man,1}, // Amendment 1 + {21,21,Req,3}, // Amendment 3 + {21,22,Man,3}, // Amendment 3 + {21,23,Req,3}, // Amendment 3 + {21,24,Req,3}, // Amendment 3 + {21,25,Req,4}, // Amendment 4 + {21,26,Req,4}, // Amendment 4 + {22,1,Req,0}, + {22,2,Man,0}, + {22,3,Req,0}, + {22,4,Man,0}, + {22,5,Man,0}, + {22,6,Man,0}, + {22,7,Req,1}, // Amendment 1 + {22,8,Req,1}, // Amendment 1 + {22,9,Req,1}, // Amendment 1 + {22,10,Req,1}, // Amendment 1 + {22,11,Req,4}, // Amendment 4 + {22,12,Man,4}, // Amendment 4 + {22,13,Req,4}, // Amendment 4 + {22,14,Man,4}, // Amendment 4 + {22,15,Req,4}, // Amendment 4 + {22,16,Req,4}, // Amendment 4 + {22,17,Req,4}, // Amendment 4 + {22,18,Req,4}, // Amendment 4 + {22,19,Req,4}, // Amendment 4 + {22,20,Man,4}, // Amendment 4 + {23,1,Adv,3}, // Amendment 3 + {23,2,Req,3}, // Amendment 3 + {23,3,Adv,3}, // Amendment 3 + {23,4,Req,3}, // Amendment 3 + {23,5,Adv,3}, // Amendment 3 + {23,6,Req,3}, // Amendment 3 + {23,7,Adv,3}, // Amendment 3 + {23,8,Req,3}, // Amendment 3 + }; + + static std::map misraRuleSeverity{ + {"1.1", "error"}, //{"syntaxError", "unknownMacro"}}, + {"1.3", "error"}, //most "error" + {"2.1", "style"}, //{"alwaysFalse", "duplicateBreak"}}, + {"2.2", "style"}, //{"alwaysTrue", "redundantCondition", "redundantAssignment", "redundantAssignInSwitch", "unreadVariable"}}, + {"2.6", "style"}, //{"unusedLabel"}}, + {"2.8", "style"}, //{"unusedVariable"}}, + {"5.3", "style"}, //{"shadowVariable"}}, + {"8.3", "style"}, //{"funcArgNamesDifferent"}}, // inconclusive + {"8.13", "style"}, //{"constPointer"}}, + {"9.1", "error"}, //{"uninitvar"}}, + {"14.3", "style"}, //{"alwaysTrue", "alwaysFalse", "compareValueOutOfTypeRangeError", "knownConditionTrueFalse"}}, + {"13.2", "error"}, //{"unknownEvaluationOrder"}}, + {"13.6", "style"}, //{"sizeofCalculation"}}, + {"17.4", "error"}, //{"missingReturn"}}, + {"17.5", "warning"}, //{"argumentSize"}}, + {"18.1", "error"}, //{"pointerOutOfBounds"}}, + {"18.2", "error"}, //{"comparePointers"}}, + {"18.3", "error"}, //{"comparePointers"}}, + {"18.6", "error"}, //{"danglingLifetime"}}, + {"19.1", "error"}, //{"overlappingWriteUnion", "overlappingWriteFunction"}}, + {"20.6", "error"}, //{"preprocessorErrorDirective"}}, + {"21.13", "error"}, //{"invalidFunctionArg"}}, + {"21.17", "error"}, //{"bufferAccessOutOfBounds"}}, + {"21.18", "error"}, //{"bufferAccessOutOfBounds"}}, + {"22.1", "error"}, //{"memleak", "resourceLeak", "memleakOnRealloc", "leakReturnValNotUsed", "leakNoVarFunctionCall"}}, + {"22.2", "error"}, //{"autovarInvalidDeallocation"}}, + {"22.3", "error"}, //{"incompatibleFileOpen"}}, + {"22.4", "error"}, //{"writeReadOnlyFile"}}, + {"22.6", "error"}, //{"useClosedFile"}} + }; + +} + + diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index 5a6b233e9..a77eddc16 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -48,6 +48,8 @@ void CheckExceptionSafety::destructors() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckExceptionSafety::destructors"); // warning + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); // Perform check.. @@ -95,6 +97,8 @@ void CheckExceptionSafety::deallocThrow() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckExceptionSafety::deallocThrow"); // warning + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -168,6 +172,8 @@ void CheckExceptionSafety::checkRethrowCopy() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckExceptionSafety::checkRethrowCopy"); // style + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -210,6 +216,8 @@ void CheckExceptionSafety::checkCatchExceptionByValue() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckExceptionSafety::checkCatchExceptionByValue"); // style + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -278,6 +286,8 @@ static const Token * functionThrows(const Function * function) //-------------------------------------------------------------------------- void CheckExceptionSafety::nothrowThrows() { + logChecker("CheckExceptionSafety::nothrowThrows"); + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -322,6 +332,8 @@ void CheckExceptionSafety::unhandledExceptionSpecification() if (!mSettings->severity.isEnabled(Severity::style) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckExceptionSafety::unhandledExceptionSpecification"); // style,inconclusive + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -359,6 +371,7 @@ void CheckExceptionSafety::unhandledExceptionSpecificationError(const Token * co //-------------------------------------------------------------------------- void CheckExceptionSafety::rethrowNoCurrentException() { + logChecker("CheckExceptionSafety::rethrowNoCurrentException"); const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { const Function* function = scope->function; diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 2232c2be6..73f109f37 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -58,6 +58,8 @@ void CheckFunctions::checkProhibitedFunctions() { const bool checkAlloca = mSettings->severity.isEnabled(Severity::warning) && ((mSettings->standards.c >= Standards::C99 && mTokenizer->isC()) || mSettings->standards.cpp >= Standards::CPP11); + logChecker("CheckFunctions::checkProhibitedFunctions"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -101,6 +103,7 @@ void CheckFunctions::checkProhibitedFunctions() //--------------------------------------------------------------------------- void CheckFunctions::invalidFunctionUsage() { + logChecker("CheckFunctions::invalidFunctionUsage"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -242,6 +245,8 @@ void CheckFunctions::checkIgnoredReturnValue() if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckFunctions::checkIgnoredReturnValue"); // style,warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -302,6 +307,7 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib void CheckFunctions::checkMissingReturn() { + logChecker("CheckFunctions::checkMissingReturn"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { const Function *function = scope->function; @@ -418,6 +424,11 @@ void CheckFunctions::checkMathFunctions() const bool styleC99 = mSettings->severity.isEnabled(Severity::style) && mSettings->standards.c != Standards::C89 && mSettings->standards.cpp != Standards::CPP03; const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); + if (!styleC99 && !printWarnings) + return; + + logChecker("CheckFunctions::checkMathFunctions"); // style,warning,c99,c++11 + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -500,6 +511,8 @@ void CheckFunctions::memsetZeroBytes() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckFunctions::memsetZeroBytes"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -539,6 +552,8 @@ void CheckFunctions::memsetInvalid2ndParam() if (!printWarning && !printPortability) return; + logChecker("CheckFunctions::memsetInvalid2ndParam"); // warning,portability + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok && (tok != scope->bodyEnd); tok = tok->next()) { @@ -670,6 +685,8 @@ void CheckFunctions::returnLocalStdMove() if (!mSettings->severity.isEnabled(Severity::performance)) return; + logChecker("CheckFunctions::returnLocalStdMove"); // performance,c++11 + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { // Expect return by-value @@ -704,6 +721,8 @@ void CheckFunctions::useStandardLibrary() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckFunctions::useStandardLibrary"); // style + for (const Scope& scope: mTokenizer->getSymbolDatabase()->scopeList) { if (scope.type != Scope::ScopeType::eFor) continue; diff --git a/lib/checkio.cpp b/lib/checkio.cpp index dc14c0832..e52f19871 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -66,6 +66,8 @@ void CheckIO::checkCoutCerrMisusage() if (mTokenizer->isC()) return; + logChecker("CheckIO::checkCoutCerrMisusage"); // c + const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -128,6 +130,8 @@ void CheckIO::checkFileUsage() std::map filepointers; + logChecker("CheckIO::checkFileUsage"); + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->declarationId() || var->isArray() || !Token::simpleMatch(var->typeStartToken(), "FILE *")) @@ -521,6 +525,8 @@ void CheckIO::checkWrongPrintfScanfArguments() const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); const bool isWindows = mSettings->platform.isWindows(); + logChecker("CheckIO::checkWrongPrintfScanfArguments"); + for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (!tok->isName()) continue; diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index ae53485d7..f4142a58e 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -195,6 +195,8 @@ void CheckLeakAutoVar::check() if (mSettings->clang) return; + logChecker("CheckLeakAutoVar::check"); // notclang + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // Local variables that are known to be non-zero. diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 7612091c2..2026e18d6 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -422,8 +422,10 @@ static bool ifvar(const Token *tok, nonneg int varid, const std::string &comp, c // a = malloc(10); a = realloc(a, 100); //--------------------------------------------------------------------------- -void CheckMemoryLeakInFunction::checkReallocUsage() const +void CheckMemoryLeakInFunction::checkReallocUsage() { + logChecker("CheckMemoryLeakInFunction::checkReallocUsage"); + // only check functions const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -498,6 +500,8 @@ void CheckMemoryLeakInFunction::checkReallocUsage() const void CheckMemoryLeakInClass::check() { + logChecker("CheckMemoryLeakInClass::check"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // only check classes and structures @@ -675,11 +679,13 @@ void CheckMemoryLeakInClass::publicAllocationError(const Token *tok, const std:: } -void CheckMemoryLeakStructMember::check() const +void CheckMemoryLeakStructMember::check() { if (mSettings->clang) return; + logChecker("CheckMemoryLeakStructMember::check"); + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || (!var->isLocal() && !(var->isArgument() && var->scope())) || var->isStatic()) @@ -922,6 +928,8 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari void CheckMemoryLeakNoVar::check() { + logChecker("CheckMemoryLeakNoVar::check"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // only check functions diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 435530a8f..ca2adde63 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -180,7 +180,7 @@ public: /** * Checking for a memory leak caused by improper realloc usage. */ - void checkReallocUsage() const; + void checkReallocUsage(); private: /** Report all possible errors (for the --errorlist) */ @@ -274,7 +274,7 @@ public: checkMemoryLeak.check(); } - void check() const; + void check(); private: diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 3e767ce7a..4110426f1 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -319,6 +319,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() void CheckNullPointer::nullPointer() { + logChecker("CheckNullPointer::nullPointer"); nullPointerByDeRefAndChec(); } @@ -332,6 +333,8 @@ namespace { /** Dereferencing null constant (simplified token list) */ void CheckNullPointer::nullConstantDereference() { + logChecker("CheckNullPointer::nullConstantDereference"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -464,6 +467,7 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var void CheckNullPointer::arithmetic() { + logChecker("CheckNullPointer::aithmetic"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -588,6 +592,10 @@ bool CheckNullPointer::analyseWholeProgram(const CTU::FileInfo *ctu, const std:: bool foundErrors = false; (void)settings; // This argument is unused + CheckNullPointer dummy(nullptr, &settings, &errorLogger); + dummy. + logChecker("CheckNullPointer::analyseWholeProgram"); // unusedfunctions + const std::map> callsMap = ctu->getCallsMap(); for (const Check::FileInfo* fi1 : fileInfo) { diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 05801b4ad..e75688e95 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -86,6 +86,8 @@ void CheckOther::checkCastIntToCharAndBack() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkCastIntToCharAndBack"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { std::map vars; @@ -154,6 +156,8 @@ void CheckOther::clarifyCalculation() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::clarifyCalculation"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -223,6 +227,8 @@ void CheckOther::clarifyStatement() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::clarifyStatement"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { @@ -259,6 +265,8 @@ void CheckOther::checkSuspiciousSemicolon() const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); + logChecker("CheckOther::checkSuspiciousSemicolon"); // warning,inconclusive + // Look for "if(); {}", "for(); {}" or "while(); {}" for (const Scope &scope : symbolDatabase->scopeList) { if (scope.type == Scope::eIf || scope.type == Scope::eElse || scope.type == Scope::eWhile || scope.type == Scope::eFor) { @@ -290,6 +298,8 @@ void CheckOther::warningOldStylePointerCast() if (!mSettings->severity.isEnabled(Severity::style) || !mTokenizer->isCPP()) return; + logChecker("CheckOther::warningOldStylePointerCast"); // style,c++ + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { const Token* tok; @@ -341,6 +351,8 @@ void CheckOther::invalidPointerCast() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("CheckOther::invalidPointerCast"); // portability + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -391,6 +403,9 @@ void CheckOther::checkRedundantAssignment() { if (!mSettings->severity.isEnabled(Severity::style)) return; + + logChecker("CheckOther::checkRedundantAssignment"); // style + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { if (!scope->bodyStart) @@ -553,11 +568,13 @@ static inline bool isFunctionOrBreakPattern(const Token *tok) return Token::Match(tok, "%name% (") || Token::Match(tok, "break|continue|return|exit|goto|throw"); } -void CheckOther::checkRedundantAssignmentInSwitch() +void CheckOther::redundantBitwiseOperationInSwitchError() { if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::redundantBitwiseOperationInSwitch"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // Find the beginning of a switch. E.g.: @@ -685,6 +702,8 @@ void CheckOther::checkSuspiciousCaseInSwitch() if (!mSettings->certainty.isEnabled(Certainty::inconclusive) || !mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkSuspiciousCaseInSwitch"); // warning,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope & scope : symbolDatabase->scopeList) { @@ -729,6 +748,9 @@ void CheckOther::checkUnreachableCode() { if (!mSettings->severity.isEnabled(Severity::style)) return; + + logChecker("CheckOther::checkUnreachableCode"); // style + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -888,6 +910,8 @@ void CheckOther::checkVariableScope() if (mSettings->daca && mTokenizer->isC()) return; + logChecker("CheckOther::checkVariableScope"); // style,notclang + for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->isLocal() || var->isConst()) continue; @@ -1122,6 +1146,8 @@ void CheckOther::checkCommaSeparatedReturn() if ((true) || !mSettings->severity.isEnabled(Severity::style)) // NOLINT(readability-simplify-boolean-expr) return; + // logChecker + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() == "return") { tok = tok->next(); @@ -1314,6 +1340,8 @@ void CheckOther::checkPassByReference() if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC()) return; + logChecker("CheckOther::checkPassByReference"); // performance,c++ + const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { @@ -1565,6 +1593,8 @@ void CheckOther::checkConstPointer() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkConstPointer"); // style + std::vector pointers, nonConstPointers; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { const Variable* const var = tok->variable(); @@ -1734,6 +1764,8 @@ void CheckOther::checkCharVariable() if (!warning && !portability) return; + logChecker("CheckOther::checkCharVariable"); // warning,portability + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -1956,6 +1988,8 @@ void CheckOther::checkIncompleteStatement() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkIncompleteStatement"); // warning + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { const Scope *scope = tok->scope(); if (scope && !scope->isExecutable()) @@ -2058,6 +2092,8 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type, //--------------------------------------------------------------------------- void CheckOther::checkZeroDivision() { + logChecker("CheckOther::checkZeroDivision"); + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand2() || !tok->astOperand1()) continue; @@ -2079,7 +2115,7 @@ void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value) { if (!tok && !value) { reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, Certainty::normal); - reportError(tok, Severity::error, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(nullptr) + " or there is division by zero.", CWE369, Certainty::normal); + reportError(tok, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(nullptr) + " or there is division by zero.", CWE369, Certainty::normal); return; } @@ -2108,6 +2144,7 @@ void CheckOther::checkNanInArithmeticExpression() { if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkNanInArithmeticExpression"); // style for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "/") continue; @@ -2138,6 +2175,8 @@ void CheckOther::checkMisusedScopedObject() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkMisusedScopedObject"); // style,c++ + auto getConstructorTok = [](const Token* tok, std::string& typeStr) -> const Token* { if (!Token::Match(tok, "[;{}] %name%") || tok->next()->isKeyword()) return nullptr; @@ -2242,6 +2281,8 @@ void CheckOther::checkDuplicateBranch() if (!mSettings->severity.isEnabled(Severity::style) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckOther::checkDuplicateBranch"); // style,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope & scope : symbolDatabase->scopeList) { @@ -2328,6 +2369,8 @@ void CheckOther::checkInvalidFree() std::map inconclusive; std::map allocation; + logChecker("CheckOther::checkInvalidFree"); + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -2445,6 +2488,8 @@ void CheckOther::checkDuplicateExpression() if (!styleEnabled && !warningEnabled) return; + logChecker("CheckOther::checkDuplicateExpression"); // style,warning + // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -2713,6 +2758,8 @@ void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -2756,6 +2803,8 @@ void CheckOther::checkSignOfUnsignedVariable() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkSignOfUnsignedVariable"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -2877,6 +2926,8 @@ void CheckOther::checkRedundantCopy() if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC() || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckOther::checkRedundantCopy"); // c++,performance,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { @@ -2949,6 +3000,8 @@ void CheckOther::checkNegativeBitwiseShift() { const bool portability = mSettings->severity.isEnabled(Severity::portability); + logChecker("CheckOther::checkNegativeBitwiseShift"); + for (const Token* tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand1() || !tok->astOperand2()) continue; @@ -3006,6 +3059,8 @@ void CheckOther::checkIncompleteArrayFill() if (!printPortability && !printWarning) return; + logChecker("CheckOther::checkIncompleteArrayFill"); // warning,portability,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3066,6 +3121,8 @@ void CheckOther::checkVarFuncNullUB() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("CheckOther::checkVarFuncNullUB"); // portability + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -3149,6 +3206,8 @@ void CheckOther::checkRedundantPointerOp() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkRedundantPointerOp"); // style + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->isExpandedMacro() && tok->str() == "(") tok = tok->link(); @@ -3194,6 +3253,8 @@ void CheckOther::checkInterlockedDecrement() return; } + logChecker("CheckOther::checkInterlockedDecrement"); // windows-platform + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->isName() && Token::Match(tok, "InterlockedDecrement ( & %name% ) ; if ( %name%|!|0")) { const Token* interlockedVarTok = tok->tokAt(3); @@ -3237,6 +3298,8 @@ void CheckOther::checkUnusedLabel() if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkUnusedLabel"); // style,warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { const bool hasIfdef = mTokenizer->hasIfdef(scope->bodyStart, scope->bodyEnd); @@ -3285,6 +3348,8 @@ void CheckOther::checkEvaluationOrder() if (mTokenizer->isCPP() && mSettings->standards.cpp >= Standards::CPP11) return; + logChecker("CheckOther::checkEvaluationOrder"); // C/C++03 + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * functionScope : symbolDatabase->functionScopes) { for (const Token* tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -3362,6 +3427,7 @@ void CheckOther::checkAccessOfMovedVariable() { if (!mTokenizer->isCPP() || mSettings->standards.cpp < Standards::CPP11 || !mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckOther::checkAccessOfMovedVariable"); // c++11,warning const bool reportInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3440,6 +3506,8 @@ void CheckOther::checkFuncArgNamesDifferent() if (!(warning || (style && inconclusive))) return; + logChecker("CheckOther::checkFuncArgNamesDifferent"); // style,warning,inconclusive + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // check every function for (const Scope *scope : symbolDatabase->functionScopes) { @@ -3578,6 +3646,7 @@ void CheckOther::checkShadowVariables() { if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkShadowVariables"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope & scope : symbolDatabase->scopeList) { if (!scope.isExecutable() || scope.type == Scope::eLambda) @@ -3659,6 +3728,7 @@ void CheckOther::checkKnownArgument() { if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkKnownArgument"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -3747,6 +3817,7 @@ void CheckOther::checkKnownPointerToBool() { if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkKnownPointerToBool"); // style const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* functionScope : symbolDatabase->functionScopes) { for (const Token* tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -3787,6 +3858,7 @@ void CheckOther::knownPointerToBoolError(const Token* tok, const ValueFlow::Valu void CheckOther::checkComparePointers() { + logChecker("CheckOther::checkComparePointers"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -3845,6 +3917,8 @@ void CheckOther::checkModuloOfOne() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckOther::checkModuloOfOne"); // style + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand2() || !tok->astOperand1()) continue; @@ -3906,6 +3980,7 @@ static bool getBufAndOffset(const Token *expr, const Token **buf, MathLib::bigin void CheckOther::checkOverlappingWrite() { + logChecker("CheckOther::checkOverlappingWrite"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { diff --git a/lib/checkother.h b/lib/checkother.h index 69a62b9b1..35aad044e 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -64,7 +64,7 @@ public: checkOther.invalidPointerCast(); checkOther.checkCharVariable(); checkOther.checkRedundantAssignment(); - checkOther.checkRedundantAssignmentInSwitch(); + checkOther.redundantBitwiseOperationInSwitchError(); checkOther.checkSuspiciousCaseInSwitch(); checkOther.checkDuplicateBranch(); checkOther.checkDuplicateExpression(); @@ -150,8 +150,8 @@ public: /** @brief copying to memory or assigning to a variable twice */ void checkRedundantAssignment(); - /** @brief %Check for assigning to the same variable twice in a switch statement*/ - void checkRedundantAssignmentInSwitch(); + /** @brief %Check for redundant bitwise operation in switch statement*/ + void redundantBitwiseOperationInSwitchError(); /** @brief %Check for code like 'case A||B:'*/ void checkSuspiciousCaseInSwitch(); diff --git a/lib/checkpostfixoperator.cpp b/lib/checkpostfixoperator.cpp index f491e58b2..d8e60a3d4 100644 --- a/lib/checkpostfixoperator.cpp +++ b/lib/checkpostfixoperator.cpp @@ -48,6 +48,8 @@ void CheckPostfixOperator::postfixOperator() if (!mSettings->severity.isEnabled(Severity::performance)) return; + logChecker("CheckPostfixOperator::postfixOperator"); // performance + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index 281f02a6a..c49527d1f 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -50,6 +50,8 @@ void CheckSizeof::checkSizeofForNumericParameter() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckSizeof::checkSizeofForNumericParameter"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -77,6 +79,9 @@ void CheckSizeof::checkSizeofForArrayParameter() { if (!mSettings->severity.isEnabled(Severity::warning)) return; + + logChecker("CheckSizeof::checkSizeofForArrayParameter"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -116,6 +121,8 @@ void CheckSizeof::checkSizeofForPointerSize() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckSizeof::checkSizeofForPointerSize"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -282,6 +289,8 @@ void CheckSizeof::sizeofsizeof() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckSizeof::sizeofsizeof"); // warning + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof (| sizeof")) { sizeofsizeofError(tok); @@ -306,6 +315,8 @@ void CheckSizeof::sizeofCalculation() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckSizeof::sizeofCalculation"); // warning + const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { @@ -350,6 +361,8 @@ void CheckSizeof::sizeofFunction() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckSizeof::sizeofFunction"); // warning + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof (")) { @@ -391,6 +404,8 @@ void CheckSizeof::suspiciousSizeofCalculation() if (!mSettings->severity.isEnabled(Severity::warning) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; + logChecker("CheckSizeof::suspiciousSizeofCalculation"); // warning,inconclusive + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof (")) { const Token* lPar = tok->astParent(); @@ -433,6 +448,8 @@ void CheckSizeof::sizeofVoid() if (!mSettings->severity.isEnabled(Severity::portability)) return; + logChecker("CheckSizeof::sizeofVoid"); // portability + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof ( void )")) { sizeofVoidError(tok); diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 6f7d6fa04..4c6a1224f 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -133,6 +133,8 @@ static const Token* getContainerFromSize(const Library::Container* container, co void CheckStl::outOfBounds() { + logChecker("CheckStl::outOfBounds"); + for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { const Library::Container *container = getLibraryContainer(tok); @@ -318,6 +320,7 @@ bool CheckStl::isContainerSizeGE(const Token * containerToken, const Token *expr void CheckStl::outOfBoundsIndexExpression() { + logChecker("CheckStl::outOfBoundsIndexExpression"); for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { if (!tok->isName() || !tok->valueType()) @@ -461,6 +464,8 @@ static bool isVector(const Token* tok) void CheckStl::iterators() { + logChecker("CheckStl::iterators"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // Filling map of iterators id and their scope begin @@ -763,6 +768,8 @@ struct ArgIteratorInfo { void CheckStl::mismatchingContainers() { + logChecker("CheckStl::misMatchingContainers"); + // Check if different containers are used in various calls of standard functions const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -821,6 +828,8 @@ void CheckStl::mismatchingContainers() void CheckStl::mismatchingContainerIterator() { + logChecker("CheckStl::misMatchingContainerIterator"); + // Check if different containers are used in various calls of standard functions const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -1062,6 +1071,7 @@ static const Token* endOfExpression(const Token* tok) void CheckStl::invalidContainer() { + logChecker("CheckStl::invalidContainer"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); const Library& library = mSettings->library; InvalidContainerAnalyzer analyzer; @@ -1204,6 +1214,8 @@ void CheckStl::invalidContainerReferenceError(const Token* tok, const Token* con void CheckStl::stlOutOfBounds() { + logChecker("CheckStl::stlOutOfBounds"); + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); // Scan through all scopes.. @@ -1296,6 +1308,8 @@ void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, con void CheckStl::negativeIndex() { + logChecker("CheckStl::negativeIndex"); + // Negative index is out of bounds.. const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -1332,6 +1346,8 @@ void CheckStl::negativeIndexError(const Token *tok, const ValueFlow::Value &inde void CheckStl::erase() { + logChecker("CheckStl::erase"); + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -1395,6 +1411,8 @@ void CheckStl::eraseCheckLoopVar(const Scope &scope, const Variable *var) void CheckStl::stlBoundaries() { + logChecker("CheckStl::stlBoundaries"); + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->scope() || !var->scope()->isExecutable()) @@ -1452,6 +1470,8 @@ void CheckStl::if_find() if (!printWarning && !printPerformance) return; + logChecker("CheckStl::if_find"); // warning,performance + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -1628,6 +1648,8 @@ void CheckStl::checkFindInsert() if (!mSettings->severity.isEnabled(Severity::performance)) return; + logChecker("CheckStl::checkFindInsert"); // performance + const SymbolDatabase *const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -1707,6 +1729,8 @@ void CheckStl::size() if (mSettings->standards.cpp >= Standards::CPP11) return; + logChecker("CheckStl::size"); // performance,c++03 + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -1763,6 +1787,8 @@ void CheckStl::redundantCondition() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckStl::redundantCondition"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -1802,6 +1828,8 @@ void CheckStl::missingComparison() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckStl::missingComparison"); // warning + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { @@ -1898,6 +1926,8 @@ void CheckStl::string_c_str() const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); + logChecker("CheckStl::string_c_str"); + // Find all functions that take std::string as argument struct StrArg { nonneg int n; // cppcheck-suppress unusedStructMember // FP used through iterator/pair @@ -2166,6 +2196,8 @@ void CheckStl::uselessCalls() if (!printPerformance && !printWarning) return; + logChecker("CheckStl::uselessCalls"); // performance,warning + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -2288,6 +2320,8 @@ void CheckStl::checkDereferenceInvalidIterator() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckStl::checkDereferenceInvalidIterator"); // warning + // Iterate over "if", "while", and "for" conditions where there may // be an iterator that is dereferenced before being checked for validity. for (const Scope &scope : mTokenizer->getSymbolDatabase()->scopeList) { @@ -2349,6 +2383,8 @@ void CheckStl::checkDereferenceInvalidIterator2() { const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive)); + logChecker("CheckStl::checkDereferenceInvalidIterator2"); + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof|decltype|typeid|typeof (")) { tok = tok->next()->link(); @@ -2806,6 +2842,8 @@ void CheckStl::useStlAlgorithm() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckStl::useStlAlgorithm"); // style + auto checkAssignee = [](const Token* tok) { if (astIsBool(tok)) // std::accumulate is not a good fit for bool values, std::all/any/none_of return early return false; @@ -3033,6 +3071,7 @@ void CheckStl::knownEmptyContainer() { if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckStl::knownEmptyContainer"); // style for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { @@ -3110,7 +3149,7 @@ void CheckStl::checkMutexes() { if (!mSettings->severity.isEnabled(Severity::warning)) return; - + logChecker("CheckStl::checkMutexes"); // warning for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { std::set checkedVars; for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { diff --git a/lib/checkstring.cpp b/lib/checkstring.cpp index 055dac642..11164bd65 100644 --- a/lib/checkstring.cpp +++ b/lib/checkstring.cpp @@ -54,6 +54,7 @@ static const struct CWE CWE758(758U); // Reliance on Undefined, Unspecified, o //--------------------------------------------------------------------------- void CheckString::stringLiteralWrite() { + logChecker("CheckString::stringLiteralWrite"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -99,6 +100,8 @@ void CheckString::checkAlwaysTrueOrFalseStringCompare() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckString::checkAlwaysTrueOrFalseStringCompare"); // warning + for (const Token* tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->isName() && tok->strAt(1) == "(" && Token::Match(tok, "memcmp|strncmp|strcmp|stricmp|strverscmp|bcmp|strcmpi|strcasecmp|strncasecmp|strncasecmp_l|strcasecmp_l|wcsncasecmp|wcscasecmp|wmemcmp|wcscmp|wcscasecmp_l|wcsncasecmp_l|wcsncmp|_mbscmp|_mbscmp_l|_memicmp|_memicmp_l|_stricmp|_wcsicmp|_mbsicmp|_stricmp_l|_wcsicmp_l|_mbsicmp_l")) { if (Token::Match(tok->tokAt(2), "%str% , %str% ,|)")) { @@ -166,6 +169,8 @@ void CheckString::checkSuspiciousStringCompare() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckString::checkSuspiciousStringCompare"); // warning + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -223,6 +228,7 @@ static bool isChar(const Variable* var) void CheckString::strPlusChar() { + logChecker("CheckString::strPlusChar"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -270,6 +276,8 @@ void CheckString::checkIncorrectStringCompare() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckString::checkIncorrectStringCompare"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -336,6 +344,8 @@ void CheckString::overlappingStrcmp() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckString::overlappingStrcmp"); // warning + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { @@ -410,6 +420,8 @@ void CheckString::overlappingStrcmpError(const Token *eq0, const Token *ne0) //--------------------------------------------------------------------------- void CheckString::sprintfOverlappingData() { + logChecker("CheckString::sprintfOverlappingData"); + const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { diff --git a/lib/checktype.cpp b/lib/checktype.cpp index a15064122..c0ddd639c 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -60,6 +60,8 @@ void CheckType::checkTooBigBitwiseShift() if (mSettings->platform.type == cppcheck::Platform::Type::Unspecified) return; + logChecker("CheckType::checkTooBigBitwiseShift"); // platform + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { // C++ and macro: OUT(x<isCPP() && Token::Match(tok, "[;{}] %name% (") && Token::simpleMatch(tok->linkAt(2), ") ;") && tok->next()->isUpperCaseName() && !tok->next()->function()) @@ -164,6 +166,8 @@ void CheckType::checkIntegerOverflow() if (mSettings->platform.type == cppcheck::Platform::Type::Unspecified || mSettings->platform.int_bit >= MathLib::bigint_bits) return; + logChecker("CheckType::checkIntegerOverflow"); // platform + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->isArithmeticalOp()) continue; @@ -235,6 +239,8 @@ void CheckType::checkSignConversion() if (!mSettings->severity.isEnabled(Severity::warning)) return; + logChecker("CheckType::checkSignConversion"); // warning + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->isArithmeticalOp() || Token::Match(tok,"+|-")) continue; @@ -315,6 +321,8 @@ void CheckType::checkLongCast() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckType::checkLongCast"); // style + // Assignments.. for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "=" || !Token::Match(tok->astOperand2(), "*|<<") || tok->astOperand2()->isUnaryOp("*")) @@ -415,6 +423,8 @@ void CheckType::longCastReturnError(const Token *tok, const ValueType* src, cons void CheckType::checkFloatToIntegerOverflow() { + logChecker("CheckType::checkFloatToIntegerOverflow"); + for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { const ValueType *vtint, *vtfloat; diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 623c30596..2ff5be3c0 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -93,6 +93,8 @@ bool CheckUninitVar::diag(const Token* tok) void CheckUninitVar::check() { + logChecker("CheckUninitVar::check"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); std::set arrayTypeDefs; @@ -1592,6 +1594,8 @@ static bool isLeafDot(const Token* tok) void CheckUninitVar::valueFlowUninit() { + logChecker("CheckUninitVar::valueFlowUninit"); + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); std::unordered_set ids; diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 4319b927c..b1dff174d 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -373,6 +373,9 @@ bool CheckUnusedFunctions::analyseWholeProgram(const CTU::FileInfo *ctu, const s { (void)ctu; (void)fileInfo; + CheckUnusedFunctions dummy(nullptr, &settings, &errorLogger); + dummy. + logChecker("CheckUnusedFunctions::analyseWholeProgram"); // unusedFunctions return check(&errorLogger, settings); } diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index ab41ef548..b853785eb 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1154,6 +1154,8 @@ void CheckUnusedVar::checkFunctionVariableUsage() if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->checkLibrary) return; + logChecker("CheckUnusedVar::checkFunctionVariableUsage"); // style + // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1440,6 +1442,8 @@ void CheckUnusedVar::checkStructMemberUsage() if (!mSettings->severity.isEnabled(Severity::style)) return; + logChecker("CheckUnusedVar::checkStructMemberUsage"); // style + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index cca96abbc..247f8b926 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -51,6 +51,8 @@ void CheckVaarg::va_start_argument() const std::size_t functions = symbolDatabase->functionScopes.size(); const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); + logChecker("CheckVaarg::va_start_argument"); + for (std::size_t i = 0; i < functions; ++i) { const Scope* scope = symbolDatabase->functionScopes[i]; const Function* function = scope->function; @@ -98,6 +100,9 @@ void CheckVaarg::va_list_usage() { if (mSettings->clang) return; + + logChecker("CheckVaarg::va_list_usage"); // notclang + const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || var->isPointer() || var->isReference() || var->isArray() || !var->scope() || var->typeStartToken()->str() != "va_list") diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 3d45a21be..fe9b60050 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1605,6 +1605,11 @@ void CppCheck::purgedConfigurationMessage(const std::string &file, const std::st void CppCheck::reportErr(const ErrorMessage &msg) { + if (msg.severity == Severity::none && msg.id == "logChecker") { + mErrorLogger.reportErr(msg); + return; + } + if (!mSettings.library.reportErrors(msg.file0)) return; diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index efe893088..5b69bd489 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -39,6 +39,17 @@ #include +const std::set ErrorLogger::mCriticalErrorIds{ + "cppcheckError", + "cppcheckLimit", + "internalAstError", + "instantiationError", + "internalError", + "preprocessorErrorDirective", + "syntaxError", + "unknownMacro" +}; + ErrorMessage::ErrorMessage() : severity(Severity::none), cwe(0U), certainty(Certainty::normal), hash(0) {} diff --git a/lib/errorlogger.h b/lib/errorlogger.h index d9983df1b..ae0466ce5 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -263,6 +264,13 @@ public: "\r\n" ""; } + + static bool isCriticalErrorId(const std::string& id) { + return mCriticalErrorIds.count(id) != 0; + } + +private: + static const std::set mCriticalErrorIds; }; /** Replace substring. Example replaceStr("1,NR,3", "NR", "2") => "1,2,3" */ diff --git a/lib/settings.h b/lib/settings.h index afb7e981f..5cc034ffa 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -130,6 +130,9 @@ public: /** @brief The maximum time in seconds for the checks of a single file */ int checksMaxTime{}; + /** @brief --checkers-report= : Generate report of executed checkers */ + std::string checkersReportFilename; + /** @brief check unknown function return values */ std::set checkUnknownFunctionReturn; diff --git a/test/cli/test-helloworld.py b/test/cli/test-helloworld.py index 5bdf62945..211271368 100644 --- a/test/cli/test-helloworld.py +++ b/test/cli/test-helloworld.py @@ -199,6 +199,26 @@ def test_build_dir_dump_output(): assert(len(filelist) == 0) +def test_checkers_report(): + with tempfile.TemporaryDirectory() as tempdir: + filename = os.path.join(tempdir, '1.txt') + args = f'--checkers-report={filename} helloworld' + + cppcheck(args.split()) + + with open(filename, 'rt') as f: + data = f.read() + assert 'No CheckAutoVariables::assignFunctionArg' in data + assert 'Yes CheckAutoVariables::autoVariables' in data + + args = '--enable=style ' + args + cppcheck(args.split()) + with open(filename, 'rt') as f: + data = f.read() + # checker has been activated by --enable=style + assert 'Yes CheckAutoVariables::assignFunctionArg' in data + + def __test_missing_include_system(use_j): args = ['--enable=missingInclude', '--suppress=zerodiv', '--template={file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]', 'helloworld'] if use_j: diff --git a/test/cli/testutils.py b/test/cli/testutils.py index 5b94b15a4..c1a1455ea 100644 --- a/test/cli/testutils.py +++ b/test/cli/testutils.py @@ -72,4 +72,6 @@ def cppcheck(args): comm = p.communicate() stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') + if stdout.find('\nActive checkers:') > 0: + stdout = stdout[:1 + stdout.find('\nActive checkers:')] return p.returncode, stdout, stderr diff --git a/test/fixture.cpp b/test/fixture.cpp index 1eb9d5936..af1860169 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -379,6 +379,8 @@ void TestFixture::reportOut(const std::string & outmsg, Color /*c*/) void TestFixture::reportErr(const ErrorMessage &msg) { + if (msg.severity == Severity::none && msg.id == "logChecker") + return; const std::string errormessage(msg.toString(mVerbose, mTemplateFormat, mTemplateLocation)); if (errout.str().find(errormessage) == std::string::npos) errout << errormessage << std::endl; diff --git a/tools/get_checkers.py b/tools/get_checkers.py new file mode 100644 index 000000000..b43e457a0 --- /dev/null +++ b/tools/get_checkers.py @@ -0,0 +1,329 @@ +import glob +import re + +print("""/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2023 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace checkers { + +static std::map allCheckers{""") + +for filename in glob.glob('../lib/*.cpp'): + for line in open(filename,'rt'): + res = re.match(r'[ \t]*logChecker\(\s*"([:_a-zA-Z0-9]+)"\s*\);.*', line) + if res is None: + continue + req = '' + if line.find('//')>0: + req = line[line.find('//')+2:].strip() + print(' {"%s","%s"},' % (res.group(1), req)) +print("};\n\n") + +print('static std::map premiumCheckers{') + +premium_checkers = """ +$ grep logChecker *.cpp | sed 's/.*logChecker/logChecker/' +logChecker("CheckBufferOverrun::addressOfPointerArithmetic"); // warning +logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning +logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning +logChecker("CheckHang::infiniteLoop"); +logChecker("CheckHang::infiniteLoopContinue"); +logChecker("CheckOther::arrayPointerComparison"); // style +logChecker("CheckOther::knownResult"); // style +logChecker("CheckOther::lossOfPrecision"); // style +logChecker("CheckOther::pointerCast"); // style +logChecker("CheckOther::reassignInLoop"); // style +logChecker("CheckOther::unreachableCode"); // style +logChecker("CheckStrictAlias::strictAliasCondition"); // warning +logChecker("CheckUninitVar::uninitvar"); +logChecker("CheckUninitVar::uninitmember"); +logChecker("CheckUnusedVar::unreadVariable"); // style +logChecker("CheckUnusedVar::unusedPrivateMember"); // style +""" + +for line in premium_checkers.split('\n'): + res = re.match(r'logChecker\("([:_a-zA-Z0-9]+)"\);.*', line) + if res is None: + continue + if line.find('//') > 0: + req = line[line.find('//')+2:].strip() + else: + req = '' + print(' {"%s","%s"},' % (res.group(1), req)) + +print('};\n\n') + +print(""" +struct MisraInfo { + int a; + int b; + const char* str; + int amendment; +}; + +const char Req[] = "Required"; +const char Adv[] = "Advisory"; +const char Man[] = "Mandatory"; + +const MisraInfo misraC2012Rules[] = +{ + {1,1,Req,0}, + {1,2,Adv,0}, + {1,3,Req,0}, + {1,4,Req,2}, // amendment 2 + {1,5,Req,3}, // Amendment 3 + {2,1,Req,0}, + {2,2,Req,0}, + {2,3,Adv,0}, + {2,4,Adv,0}, + {2,5,Adv,0}, + {2,6,Adv,0}, + {2,7,Adv,0}, + {2,8,Adv,0}, + {3,1,Req,0}, + {3,2,Req,0}, + {4,1,Req,0}, + {4,2,Adv,0}, + {5,1,Req,0}, + {5,2,Req,0}, + {5,3,Req,0}, + {5,4,Req,0}, + {5,5,Req,0}, + {5,6,Req,0}, + {5,7,Req,0}, + {5,8,Req,0}, + {5,9,Adv,0}, + {6,1,Req,0}, + {6,2,Req,0}, + {6,3,Req,0}, + {7,1,Req,0}, + {7,2,Req,0}, + {7,3,Req,0}, + {7,4,Req,0}, + {7,5,Man,0}, + {7,6,Req,0}, + {8,1,Req,0}, + {8,2,Req,0}, + {8,3,Req,0}, + {8,4,Req,0}, + {8,5,Req,0}, + {8,6,Req,0}, + {8,7,Adv,0}, + {8,8,Req,0}, + {8,9,Adv,0}, + {8,10,Req,0}, + {8,11,Adv,0}, + {8,12,Req,0}, + {8,13,Adv,0}, + {8,14,Req,0}, + {8,15,Req,0}, + {8,16,Adv,0}, + {8,17,Adv,0}, + {9,1,Man,0}, + {9,2,Req,0}, + {9,3,Req,0}, + {9,4,Req,0}, + {9,5,Req,0}, + {9,6,Req,0}, + {9,7,Man,0}, + {10,1,Req,0}, + {10,2,Req,0}, + {10,3,Req,0}, + {10,4,Req,0}, + {10,5,Adv,0}, + {10,6,Req,0}, + {10,7,Req,0}, + {10,8,Req,0}, + {11,1,Req,0}, + {11,2,Req,0}, + {11,3,Req,0}, + {11,4,Adv,0}, + {11,5,Adv,0}, + {11,6,Req,0}, + {11,7,Req,0}, + {11,8,Req,0}, + {11,9,Req,0}, + {11,10,Req,0}, + {12,1,Adv,0}, + {12,2,Req,0}, + {12,3,Adv,0}, + {12,4,Adv,0}, + {12,5,Man,1}, // amendment 1 + {12,6,Req,4}, // amendment 4 + {13,1,Req,0}, + {13,2,Req,0}, + {13,3,Adv,0}, + {13,4,Adv,0}, + {13,5,Req,0}, + {13,6,Man,0}, + {14,1,Req,0}, + {14,2,Req,0}, + {14,3,Req,0}, + {14,4,Req,0}, + {15,1,Adv,0}, + {15,2,Req,0}, + {15,3,Req,0}, + {15,4,Adv,0}, + {15,5,Adv,0}, + {15,6,Req,0}, + {15,7,Req,0}, + {16,1,Req,0}, + {16,2,Req,0}, + {16,3,Req,0}, + {16,4,Req,0}, + {16,5,Req,0}, + {16,6,Req,0}, + {16,7,Req,0}, + {17,1,Req,0}, + {17,2,Req,0}, + {17,3,Man,0}, + {17,4,Man,0}, + {17,5,Adv,0}, + {17,6,Man,0}, + {17,7,Req,0}, + {17,8,Adv,0}, + {17,9,Man,0}, + {17,10,Req,0}, + {17,11,Adv,0}, + {17,12,Adv,0}, + {17,13,Req,0}, + {18,1,Req,0}, + {18,2,Req,0}, + {18,3,Req,0}, + {18,4,Adv,0}, + {18,5,Adv,0}, + {18,6,Req,0}, + {18,7,Req,0}, + {18,8,Req,0}, + {18,9,Req,0}, + {18,10,Man,0}, + {19,1,Man,0}, + {19,2,Adv,0}, + {20,1,Adv,0}, + {20,2,Req,0}, + {20,3,Req,0}, + {20,4,Req,0}, + {20,5,Adv,0}, + {20,6,Req,0}, + {20,7,Req,0}, + {20,8,Req,0}, + {20,9,Req,0}, + {20,10,Adv,0}, + {20,11,Req,0}, + {20,12,Req,0}, + {20,13,Req,0}, + {20,14,Req,0}, + {21,1,Req,0}, + {21,2,Req,0}, + {21,3,Req,0}, + {21,4,Req,0}, + {21,5,Req,0}, + {21,6,Req,0}, + {21,7,Req,0}, + {21,8,Req,0}, + {21,9,Req,0}, + {21,10,Req,0}, + {21,11,Req,0}, + {21,12,Adv,0}, + {21,13,Man,1}, // Amendment 1 + {21,14,Req,1}, // Amendment 1 + {21,15,Req,1}, // Amendment 1 + {21,16,Req,1}, // Amendment 1 + {21,17,Req,1}, // Amendment 1 + {21,18,Man,1}, // Amendment 1 + {21,19,Man,1}, // Amendment 1 + {21,20,Man,1}, // Amendment 1 + {21,21,Req,3}, // Amendment 3 + {21,22,Man,3}, // Amendment 3 + {21,23,Req,3}, // Amendment 3 + {21,24,Req,3}, // Amendment 3 + {21,25,Req,4}, // Amendment 4 + {21,26,Req,4}, // Amendment 4 + {22,1,Req,0}, + {22,2,Man,0}, + {22,3,Req,0}, + {22,4,Man,0}, + {22,5,Man,0}, + {22,6,Man,0}, + {22,7,Req,1}, // Amendment 1 + {22,8,Req,1}, // Amendment 1 + {22,9,Req,1}, // Amendment 1 + {22,10,Req,1}, // Amendment 1 + {22,11,Req,4}, // Amendment 4 + {22,12,Man,4}, // Amendment 4 + {22,13,Req,4}, // Amendment 4 + {22,14,Man,4}, // Amendment 4 + {22,15,Req,4}, // Amendment 4 + {22,16,Req,4}, // Amendment 4 + {22,17,Req,4}, // Amendment 4 + {22,18,Req,4}, // Amendment 4 + {22,19,Req,4}, // Amendment 4 + {22,20,Man,4}, // Amendment 4 + {23,1,Adv,3}, // Amendment 3 + {23,2,Req,3}, // Amendment 3 + {23,3,Adv,3}, // Amendment 3 + {23,4,Req,3}, // Amendment 3 + {23,5,Adv,3}, // Amendment 3 + {23,6,Req,3}, // Amendment 3 + {23,7,Adv,3}, // Amendment 3 + {23,8,Req,3}, // Amendment 3 +}; + +static std::map misraRuleSeverity{ + {"1.1", "error"}, //{"syntaxError", "unknownMacro"}}, + {"1.3", "error"}, //most "error" + {"2.1", "style"}, //{"alwaysFalse", "duplicateBreak"}}, + {"2.2", "style"}, //{"alwaysTrue", "redundantCondition", "redundantAssignment", "redundantAssignInSwitch", "unreadVariable"}}, + {"2.6", "style"}, //{"unusedLabel"}}, + {"2.8", "style"}, //{"unusedVariable"}}, + {"5.3", "style"}, //{"shadowVariable"}}, + {"8.3", "style"}, //{"funcArgNamesDifferent"}}, // inconclusive + {"8.13", "style"}, //{"constPointer"}}, + {"9.1", "error"}, //{"uninitvar"}}, + {"14.3", "style"}, //{"alwaysTrue", "alwaysFalse", "compareValueOutOfTypeRangeError", "knownConditionTrueFalse"}}, + {"13.2", "error"}, //{"unknownEvaluationOrder"}}, + {"13.6", "style"}, //{"sizeofCalculation"}}, + {"17.4", "error"}, //{"missingReturn"}}, + {"17.5", "warning"}, //{"argumentSize"}}, + {"18.1", "error"}, //{"pointerOutOfBounds"}}, + {"18.2", "error"}, //{"comparePointers"}}, + {"18.3", "error"}, //{"comparePointers"}}, + {"18.6", "error"}, //{"danglingLifetime"}}, + {"19.1", "error"}, //{"overlappingWriteUnion", "overlappingWriteFunction"}}, + {"20.6", "error"}, //{"preprocessorErrorDirective"}}, + {"21.13", "error"}, //{"invalidFunctionArg"}}, + {"21.17", "error"}, //{"bufferAccessOutOfBounds"}}, + {"21.18", "error"}, //{"bufferAccessOutOfBounds"}}, + {"22.1", "error"}, //{"memleak", "resourceLeak", "memleakOnRealloc", "leakReturnValNotUsed", "leakNoVarFunctionCall"}}, + {"22.2", "error"}, //{"autovarInvalidDeallocation"}}, + {"22.3", "error"}, //{"incompatibleFileOpen"}}, + {"22.4", "error"}, //{"writeReadOnlyFile"}}, + {"22.6", "error"}, //{"useClosedFile"}} +}; + +} + +""") + +