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
```
This commit is contained in:
Daniel Marjamäki 2023-08-29 12:00:52 +02:00 committed by GitHub
parent 4d18f3e68b
commit 276f017fbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1434 additions and 23 deletions

View File

@ -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

View File

@ -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=<file>\n"
" Write a report of all the active checkers to the given file.\n"
" --clang=<path> 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"

View File

@ -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=<filename> 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

View File

@ -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<std::string> mActiveCheckers;
/**
* True if there are critical errors
*/
std::string mCriticalErrors;
};
#endif // CPPCHECKEXECUTOR_H

View File

@ -527,18 +527,7 @@ void ResultsView::stopAnalysis()
void ResultsView::handleCriticalError(const ErrorItem &item)
{
const QSet<QString> 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);

View File

@ -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);
}

View File

@ -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;
/**

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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) {

View File

@ -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()) {

View File

@ -280,6 +280,8 @@ static std::vector<ValueFlow::Value> 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<std::string, std::list<const CTU::FileInfo::CallBase *>> callsMap = ctu->getCallsMap();
for (const Check::FileInfo* fi1 : fileInfo) {
@ -1015,6 +1032,7 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::map<std::string, std::l
void CheckBufferOverrun::objectIndex()
{
logChecker("CheckBufferOverrun::objectIndex");
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
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())

View File

@ -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<int, const Token*> 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<Function>::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<const Function *> 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<const Function *, std::list<const Token *>> 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<C
std::unordered_map<std::string, MyFileInfo::NameLoc> all;
CheckClass dummy(nullptr, &settings, &errorLogger);
dummy.
logChecker("CheckClass::analyseWholeProgram");
for (const Check::FileInfo* fi1 : fileInfo) {
const MyFileInfo *fi = dynamic_cast<const MyFileInfo*>(fi1);
if (!fi)

View File

@ -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()) {

478
lib/checkers.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <string>
#include <vector>
namespace checkers {
static std::map<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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"}}
};
}

View File

@ -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;

View File

@ -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;

View File

@ -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<int, Filepointer> 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;

View File

@ -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.

View File

@ -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

View File

@ -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:

View File

@ -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<std::string, std::list<const CTU::FileInfo::CallBase *>> callsMap = ctu->getCallsMap();
for (const Check::FileInfo* fi1 : fileInfo) {

View File

@ -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<int, std::string> 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<const Variable*> 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<int, bool> inconclusive;
std::map<int, std::string> 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()) {

View File

@ -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();

View File

@ -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) {

View File

@ -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);

View File

@ -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<nonneg int> checkedVars;
for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) {

View File

@ -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()) {

View File

@ -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<<y)
if (mTokenizer->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;

View File

@ -93,6 +93,8 @@ bool CheckUninitVar::diag(const Token* tok)
void CheckUninitVar::check()
{
logChecker("CheckUninitVar::check");
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
std::set<std::string> 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<nonneg int> ids;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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")

View File

@ -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;

View File

@ -39,6 +39,17 @@
#include <tinyxml2.h>
const std::set<std::string> ErrorLogger::mCriticalErrorIds{
"cppcheckError",
"cppcheckLimit",
"internalAstError",
"instantiationError",
"internalError",
"preprocessorErrorDirective",
"syntaxError",
"unknownMacro"
};
ErrorMessage::ErrorMessage()
: severity(Severity::none), cwe(0U), certainty(Certainty::normal), hash(0)
{}

View File

@ -27,6 +27,7 @@
#include <cstddef>
#include <list>
#include <set>
#include <string>
#include <utility>
#include <vector>
@ -263,6 +264,13 @@ public:
"</dict>\r\n"
"</plist>";
}
static bool isCriticalErrorId(const std::string& id) {
return mCriticalErrorIds.count(id) != 0;
}
private:
static const std::set<std::string> mCriticalErrorIds;
};
/** Replace substring. Example replaceStr("1,NR,3", "NR", "2") => "1,2,3" */

View File

@ -130,6 +130,9 @@ public:
/** @brief The maximum time in seconds for the checks of a single file */
int checksMaxTime{};
/** @brief --checkers-report=<filename> : Generate report of executed checkers */
std::string checkersReportFilename;
/** @brief check unknown function return values */
std::set<std::string> checkUnknownFunctionReturn;

View File

@ -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:

View File

@ -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

View File

@ -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;

329
tools/get_checkers.py Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <string>
#include <vector>
namespace checkers {
static std::map<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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"}}
};
}
""")