Fixed #7502 (Correct exit code if never used function is found) (#1026)

This commit is contained in:
Ivan Maidanski 2018-01-12 10:24:01 +03:00 committed by Daniel Marjamäki
parent 03603c85cf
commit 97ffec85c0
10 changed files with 34 additions and 15 deletions

View File

@ -888,7 +888,8 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
c++; c++;
} }
} }
cppcheck.analyseWholeProgram(); if (cppcheck.analyseWholeProgram())
returnValue++;
} else if (!ThreadExecutor::isEnabled()) { } else if (!ThreadExecutor::isEnabled()) {
std::cout << "No thread support yet implemented for this platform." << std::endl; std::cout << "No thread support yet implemented for this platform." << std::endl;
} else { } else {

View File

@ -109,10 +109,12 @@ public:
return nullptr; return nullptr;
} }
virtual void analyseWholeProgram(const std::list<FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) { // Return true if an error is reported.
virtual bool analyseWholeProgram(const std::list<FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) {
(void)fileInfo; (void)fileInfo;
(void)settings; (void)settings;
(void)errorLogger; (void)errorLogger;
return false;
} }
protected: protected:

View File

@ -2022,8 +2022,9 @@ Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLEle
} }
void CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings&, ErrorLogger &errorLogger) bool CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings&, ErrorLogger &errorLogger)
{ {
bool errors = false;
// Merge all fileInfo // Merge all fileInfo
MyFileInfo all; MyFileInfo all;
for (std::list<Check::FileInfo*>::const_iterator it = fileInfo.begin(); it != fileInfo.end(); ++it) { for (std::list<Check::FileInfo*>::const_iterator it = fileInfo.begin(); it != fileInfo.end(); ++it) {
@ -2069,8 +2070,10 @@ void CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &
"arrayIndexOutOfBounds", "arrayIndexOutOfBounds",
CWE788, false); CWE788, false);
errorLogger.reportErr(errmsg); errorLogger.reportErr(errmsg);
errors = true;
} }
} }
return errors;
} }
unsigned int CheckBufferOverrun::sizeOfType(const Token *type) const unsigned int CheckBufferOverrun::sizeOfType(const Token *type) const

View File

@ -244,7 +244,7 @@ public:
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const; Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const;
/** @brief Analyse all file infos for all TU */ /** @brief Analyse all file infos for all TU */
void analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger); bool analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger);
/** /**
* Calculates sizeof value for given type. * Calculates sizeof value for given type.

View File

@ -237,8 +237,9 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const char Fi
void CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings& settings) bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings& settings)
{ {
bool errors = false;
for (std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it) { for (std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it) {
const FunctionUsage &func = it->second; const FunctionUsage &func = it->second;
if (func.usedOtherFile || func.filename.empty()) if (func.usedOtherFile || func.filename.empty())
@ -252,15 +253,18 @@ void CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings
if (func.filename != "+") if (func.filename != "+")
filename = func.filename; filename = func.filename;
unusedFunctionError(errorLogger, filename, func.lineNumber, it->first); unusedFunctionError(errorLogger, filename, func.lineNumber, it->first);
errors = true;
} else if (! func.usedOtherFile) { } else if (! func.usedOtherFile) {
/** @todo add error message "function is only used in <file> it can be static" */ /** @todo add error message "function is only used in <file> it can be static" */
/* /*
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage."; errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage.";
_errorLogger->reportErr( errmsg.str() ); _errorLogger->reportErr( errmsg.str() );
errors = true;
*/ */
} }
} }
return errors;
} }
void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger, void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger,
@ -291,10 +295,10 @@ Check::FileInfo *CheckUnusedFunctions::getFileInfo(const Tokenizer *tokenizer, c
return nullptr; return nullptr;
} }
void CheckUnusedFunctions::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) bool CheckUnusedFunctions::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger)
{ {
(void)fileInfo; (void)fileInfo;
check(&errorLogger, settings); return check(&errorLogger, settings);
} }
CheckUnusedFunctions::FunctionDecl::FunctionDecl(const Function *f) CheckUnusedFunctions::FunctionDecl::FunctionDecl(const Function *f)

View File

@ -55,13 +55,14 @@ public:
// * What functions are declared // * What functions are declared
void parseTokens(const Tokenizer &tokenizer, const char FileName[], const Settings *settings, bool clear=true); void parseTokens(const Tokenizer &tokenizer, const char FileName[], const Settings *settings, bool clear=true);
void check(ErrorLogger * const errorLogger, const Settings& settings); // Return true if an error is reported.
bool check(ErrorLogger * const errorLogger, const Settings& settings);
/** @brief Parse current TU and extract file info */ /** @brief Parse current TU and extract file info */
Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const; Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const;
/** @brief Analyse all file infos for all TU */ /** @brief Analyse all file infos for all TU */
void analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger); bool analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger);
static CheckUnusedFunctions instance; static CheckUnusedFunctions instance;

View File

@ -809,11 +809,13 @@ void CppCheck::getErrorMessages()
Preprocessor::getErrorMessages(this, &s); Preprocessor::getErrorMessages(this, &s);
} }
void CppCheck::analyseWholeProgram() bool CppCheck::analyseWholeProgram()
{ {
bool errors = false;
// Analyse the tokens // Analyse the tokens
for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it)
(*it)->analyseWholeProgram(fileInfo, _settings, *this); errors |= (*it)->analyseWholeProgram(fileInfo, _settings, *this);
return errors;
} }
void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files) void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files)

View File

@ -131,9 +131,10 @@ public:
/** Analyse whole program, run this after all TUs has been scanned. /** Analyse whole program, run this after all TUs has been scanned.
* This is deprecated and the plan is to remove this when * This is deprecated and the plan is to remove this when
* .analyzeinfo is good enough * .analyzeinfo is good enough.
* Return true if an error is reported.
*/ */
void analyseWholeProgram(); bool analyseWholeProgram();
/** analyse whole program use .analyzeinfo files */ /** analyse whole program use .analyzeinfo files */
void analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files); void analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files);

View File

@ -161,7 +161,8 @@ private:
for (std::map<std::string, std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { for (std::map<std::string, std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
exitCode |= cppCheck.check(file->first, file->second); exitCode |= cppCheck.check(file->first, file->second);
} }
cppCheck.analyseWholeProgram(); if (cppCheck.analyseWholeProgram())
exitCode |= settings.exitCode;
reportSuppressions(settings, files); reportSuppressions(settings, files);

View File

@ -77,7 +77,11 @@ private:
// Check for unused functions.. // Check for unused functions..
CheckUnusedFunctions checkUnusedFunctions(&tokenizer, &settings, this); CheckUnusedFunctions checkUnusedFunctions(&tokenizer, &settings, this);
checkUnusedFunctions.parseTokens(tokenizer, "someFile.c", &settings); checkUnusedFunctions.parseTokens(tokenizer, "someFile.c", &settings);
checkUnusedFunctions.check(this, settings); // check() returns error if and only if errout is not empty.
if (checkUnusedFunctions.check(this, settings))
ASSERT(errout.str() != "");
else
ASSERT_EQUALS("", errout.str());
} }
void incondition() { void incondition() {