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:
parent
5f25f2c6e6
commit
dd666b7c1b
|
@ -83,6 +83,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
_exitAfterPrint = true;
|
_exitAfterPrint = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag used for various purposes during debugging
|
// Flag used for various purposes during debugging
|
||||||
else if (strcmp(argv[i], "--debug") == 0)
|
else if (strcmp(argv[i], "--debug") == 0)
|
||||||
_settings->debug = _settings->debugwarnings = true;
|
_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)
|
else if (strcmp(argv[i], "--debug-warnings") == 0)
|
||||||
_settings->debugwarnings = true;
|
_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
|
// Enable all checks - will be removed in future
|
||||||
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
|
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,6 +82,73 @@ unsigned int CppCheck::check(const std::string &path, const std::string &content
|
||||||
return retval;
|
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()
|
unsigned int CppCheck::processFile()
|
||||||
{
|
{
|
||||||
exitcode = 0;
|
exitcode = 0;
|
||||||
|
@ -186,7 +253,18 @@ unsigned int CppCheck::processFile()
|
||||||
if (!appendCode.empty())
|
if (!appendCode.empty())
|
||||||
Preprocessor::preprocessWhitespaces(appendCode);
|
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;
|
++checkCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,6 +282,8 @@ unsigned int CppCheck::processFile()
|
||||||
return exitcode;
|
return exitcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CppCheck::checkFunctionUsage()
|
void CppCheck::checkFunctionUsage()
|
||||||
{
|
{
|
||||||
// This generates false positives - especially for libraries
|
// This generates false positives - especially for libraries
|
||||||
|
@ -409,6 +489,13 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
if (errmsg.empty())
|
if (errmsg.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (_settings.debugFalsePositive)
|
||||||
|
{
|
||||||
|
// Don't print out error
|
||||||
|
_errorList.push_back(errmsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Alert only about unique errors
|
// Alert only about unique errors
|
||||||
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
|
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -158,6 +158,19 @@ private:
|
||||||
*/
|
*/
|
||||||
virtual void reportOut(const std::string &outmsg);
|
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;
|
unsigned int exitcode;
|
||||||
std::list<std::string> _errorList;
|
std::list<std::string> _errorList;
|
||||||
std::ostringstream _errout;
|
std::ostringstream _errout;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
{
|
{
|
||||||
debug = debugwarnings = false;
|
debug = debugwarnings = false;
|
||||||
|
debugFalsePositive = false;
|
||||||
_errorsOnly = false;
|
_errorsOnly = false;
|
||||||
_inlineSuppressions = false;
|
_inlineSuppressions = false;
|
||||||
_verbose = false;
|
_verbose = false;
|
||||||
|
|
|
@ -55,6 +55,9 @@ public:
|
||||||
/** @brief Is --debug-warnings given? */
|
/** @brief Is --debug-warnings given? */
|
||||||
bool debugwarnings;
|
bool debugwarnings;
|
||||||
|
|
||||||
|
/** @brief Is --debug-fp given? */
|
||||||
|
bool debugFalsePositive;
|
||||||
|
|
||||||
/** @brief Inconclusive checks */
|
/** @brief Inconclusive checks */
|
||||||
bool inconclusive;
|
bool inconclusive;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue