Add command line option: --debug-fp ... If used, cppcheck will print out the code generating error into output stream.

This is ment to be used for debugging false positive errors in Cppcheck.
Current implementation tries two alternatives. Without all headers or with all headers and prints out the option with
less code. In future versions this could try with individual headers or group of header files.
This commit is contained in:
Reijo Tomperi 2011-08-16 22:58:27 +03:00
parent 5f25f2c6e6
commit dd666b7c1b
5 changed files with 110 additions and 1 deletions

View File

@ -83,6 +83,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
_exitAfterPrint = true;
return true;
}
// Flag used for various purposes during debugging
else if (strcmp(argv[i], "--debug") == 0)
_settings->debug = _settings->debugwarnings = true;
@ -91,6 +92,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
else if (strcmp(argv[i], "--debug-warnings") == 0)
_settings->debugwarnings = true;
// Print out code that triggers false positive
else if (strcmp(argv[i], "--debug-fp") == 0)
_settings->debugFalsePositive = true;
// Enable all checks - will be removed in future
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
{

View File

@ -82,6 +82,73 @@ unsigned int CppCheck::check(const std::string &path, const std::string &content
return retval;
}
std::string CppCheck::replaceAll(std::string code, const std::string &from, const std::string &to)
{
size_t pos = 0;
while ((pos = code.find(from, pos)) != std::string::npos)
{
code.replace(pos, from.length(), to);
pos += to.length();
}
return code;
}
bool CppCheck::findError(std::string code, const char FileName[])
{
// First make sure that error occurs with the original code
checkFile(code, FileName);
if (_errorList.empty())
{
// Error does not occur with this code
return false;
}
std::string previousCode = code;
std::string error = _errorList.front();
for (;;)
{
// Try to remove included files from the source
size_t found=previousCode.rfind("\n#endfile");
if (found == std::string::npos)
{
// No modifications can be done to the code
}
else
{
// Modify code and re-check it to see if error
// is still there.
code = previousCode.substr(found+9);
_errorList.clear();
checkFile(code, FileName);
}
if (_errorList.empty())
{
// Latest code didn't fail anymore. Fall back
// to previous code
code = previousCode;
}
else
{
error = _errorList.front();
}
// Add '\n' so that "\n#file" on first line would be found
code = "// " + error + "\n" + code;
code = replaceAll(code, "\n#file", "\n// #file");
code = replaceAll(code, "\n#endfile", "\n// #endfile");
// We have reduced the code as much as we can. Print out
// the code and quit.
_errorLogger.reportOut(code);
break;
}
return true;
}
unsigned int CppCheck::processFile()
{
exitcode = 0;
@ -186,7 +253,18 @@ unsigned int CppCheck::processFile()
if (!appendCode.empty())
Preprocessor::preprocessWhitespaces(appendCode);
checkFile(codeWithoutCfg + appendCode, _filename.c_str());
if (_settings.debugFalsePositive)
{
if (findError(codeWithoutCfg + appendCode, _filename.c_str()))
{
return exitcode;
}
}
else
{
checkFile(codeWithoutCfg + appendCode, _filename.c_str());
}
++checkCount;
}
}
@ -204,6 +282,8 @@ unsigned int CppCheck::processFile()
return exitcode;
}
void CppCheck::checkFunctionUsage()
{
// This generates false positives - especially for libraries
@ -409,6 +489,13 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
if (errmsg.empty())
return;
if (_settings.debugFalsePositive)
{
// Don't print out error
_errorList.push_back(errmsg);
return;
}
// Alert only about unique errors
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
return;

View File

@ -158,6 +158,19 @@ private:
*/
virtual void reportOut(const std::string &outmsg);
/**
* @brief Check given code. If error is found, return true
* and print out source of the file. Try to reduce the code
* while still showing the error.
*/
bool findError(std::string code, const char FileName[]);
/**
* @brief Replace "from" strings with "to" strings in "code"
* and return it.
*/
std::string replaceAll(std::string code, const std::string &from, const std::string &to);
unsigned int exitcode;
std::list<std::string> _errorList;
std::ostringstream _errout;

View File

@ -31,6 +31,7 @@
Settings::Settings()
{
debug = debugwarnings = false;
debugFalsePositive = false;
_errorsOnly = false;
_inlineSuppressions = false;
_verbose = false;

View File

@ -55,6 +55,9 @@ public:
/** @brief Is --debug-warnings given? */
bool debugwarnings;
/** @brief Is --debug-fp given? */
bool debugFalsePositive;
/** @brief Inconclusive checks */
bool inconclusive;