Verification; Updated report
This commit is contained in:
parent
147cf9319f
commit
4b4f7ea60b
|
@ -192,6 +192,8 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
// Experimental: Verify
|
// Experimental: Verify
|
||||||
else if (std::strcmp(argv[i], "--verify") == 0)
|
else if (std::strcmp(argv[i], "--verify") == 0)
|
||||||
mSettings->verification = true;
|
mSettings->verification = true;
|
||||||
|
else if (std::strcmp(argv[i], "--verify-report") == 0)
|
||||||
|
mSettings->verification = mSettings->verificationReport = true;
|
||||||
else if (std::strcmp(argv[i], "--debug-verify") == 0)
|
else if (std::strcmp(argv[i], "--debug-verify") == 0)
|
||||||
mSettings->debugVerification = true;
|
mSettings->debugVerification = true;
|
||||||
|
|
||||||
|
|
|
@ -79,13 +79,14 @@
|
||||||
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;
|
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;
|
||||||
|
|
||||||
CppCheckExecutor::CppCheckExecutor()
|
CppCheckExecutor::CppCheckExecutor()
|
||||||
: mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mShowAllErrors(false)
|
: mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mVerificationOutput(nullptr), mShowAllErrors(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CppCheckExecutor::~CppCheckExecutor()
|
CppCheckExecutor::~CppCheckExecutor()
|
||||||
{
|
{
|
||||||
delete mErrorOutput;
|
delete mErrorOutput;
|
||||||
|
delete mVerificationOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[])
|
bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[])
|
||||||
|
@ -1063,6 +1064,13 @@ void CppCheckExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppCheckExecutor::reportVerification(const std::string &str)
|
||||||
|
{
|
||||||
|
if (!mVerificationOutput)
|
||||||
|
mVerificationOutput = new std::ofstream("verification-report.txt");
|
||||||
|
(*mVerificationOutput) << str << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::setExceptionOutput(FILE* exceptionOutput)
|
void CppCheckExecutor::setExceptionOutput(FILE* exceptionOutput)
|
||||||
{
|
{
|
||||||
mExceptionOutput = exceptionOutput;
|
mExceptionOutput = exceptionOutput;
|
||||||
|
|
|
@ -81,6 +81,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void reportInfo(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
void reportInfo(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
||||||
|
|
||||||
|
void reportVerification(const std::string &str) OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about how many files have been checked
|
* Information about how many files have been checked
|
||||||
*
|
*
|
||||||
|
@ -187,6 +189,11 @@ private:
|
||||||
*/
|
*/
|
||||||
std::ofstream *mErrorOutput;
|
std::ofstream *mErrorOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verification report
|
||||||
|
*/
|
||||||
|
std::ostream *mVerificationOutput;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has --errorlist been given?
|
* Has --errorlist been given?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -348,6 +348,11 @@ void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg)
|
||||||
writeToPipe(REPORT_INFO, msg.serialize());
|
writeToPipe(REPORT_INFO, msg.serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThreadExecutor::reportVerification(const std::string &str)
|
||||||
|
{
|
||||||
|
writeToPipe(REPORT_VERIFICATION, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(THREADING_MODEL_WIN)
|
#elif defined(THREADING_MODEL_WIN)
|
||||||
|
|
||||||
void ThreadExecutor::addFileContent(const std::string &path, const std::string &content)
|
void ThreadExecutor::addFileContent(const std::string &path, const std::string &content)
|
||||||
|
@ -490,7 +495,12 @@ void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
|
|
||||||
void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg)
|
void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg)
|
||||||
{
|
{
|
||||||
report(msg, MessageType::REPORT_INFO);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadExecutor::reportVerification(const std::string &/*str*/)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadExecutor::report(const ErrorLogger::ErrorMessage &msg, MessageType msgType)
|
void ThreadExecutor::report(const ErrorLogger::ErrorMessage &msg, MessageType msgType)
|
||||||
|
@ -551,4 +561,8 @@ void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &/*msg*/)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThreadExecutor::reportVerification(const std::string &/*str*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
void reportOut(const std::string &outmsg) OVERRIDE;
|
void reportOut(const std::string &outmsg) OVERRIDE;
|
||||||
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
||||||
void reportInfo(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
void reportInfo(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
||||||
|
void reportVerification(const std::string &str) OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add content to a file, to be used in unit testing.
|
* @brief Add content to a file, to be used in unit testing.
|
||||||
|
@ -75,7 +76,7 @@ private:
|
||||||
/** @brief Key is file name, and value is the content of the file */
|
/** @brief Key is file name, and value is the content of the file */
|
||||||
std::map<std::string, std::string> mFileContents;
|
std::map<std::string, std::string> mFileContents;
|
||||||
private:
|
private:
|
||||||
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', REPORT_INFO='3', CHILD_END='4'};
|
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', REPORT_INFO='3', REPORT_VERIFICATION='4', CHILD_END='5'};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read from the pipe, parse and handle what ever is in there.
|
* Read from the pipe, parse and handle what ever is in there.
|
||||||
|
|
|
@ -12,10 +12,11 @@ NewSuppressionDialog::NewSuppressionDialog(QWidget *parent) :
|
||||||
|
|
||||||
class QErrorLogger : public ErrorLogger {
|
class QErrorLogger : public ErrorLogger {
|
||||||
public:
|
public:
|
||||||
virtual void reportOut(const std::string &/*outmsg*/) {}
|
void reportOut(const std::string &/*outmsg*/) override {}
|
||||||
virtual void reportErr(const ErrorLogger::ErrorMessage &msg) {
|
void reportErr(const ErrorLogger::ErrorMessage &msg) override {
|
||||||
errorIds << QString::fromStdString(msg.id);
|
errorIds << QString::fromStdString(msg.id);
|
||||||
}
|
}
|
||||||
|
void reportVerification(const std::string &/*str*/) override {}
|
||||||
QStringList errorIds;
|
QStringList errorIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void reportOut(const std::string &outmsg) override;
|
void reportOut(const std::string &outmsg) override;
|
||||||
void reportErr(const ErrorLogger::ErrorMessage &msg) override;
|
void reportErr(const ErrorLogger::ErrorMessage &msg) override;
|
||||||
|
void reportVerification(const std::string &/*str*/) override {}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
|
@ -766,9 +766,8 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verification using ExprEngine..
|
// Verification using ExprEngine..
|
||||||
if (mSettings.verification) {
|
if (mSettings.verification)
|
||||||
ExprEngine::runChecks(this, &tokenizer, &mSettings);
|
ExprEngine::runChecks(this, &tokenizer, &mSettings);
|
||||||
}
|
|
||||||
|
|
||||||
// Analyse the tokens..
|
// Analyse the tokens..
|
||||||
|
|
||||||
|
@ -1202,6 +1201,11 @@ void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppCheck::reportVerification(const std::string &str)
|
||||||
|
{
|
||||||
|
mErrorLogger.reportVerification(str);
|
||||||
|
}
|
||||||
|
|
||||||
void CppCheck::getErrorMessages()
|
void CppCheck::getErrorMessages()
|
||||||
{
|
{
|
||||||
Settings s(mSettings);
|
Settings s(mSettings);
|
||||||
|
|
|
@ -195,6 +195,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void reportOut(const std::string &outmsg) OVERRIDE;
|
void reportOut(const std::string &outmsg) OVERRIDE;
|
||||||
|
|
||||||
|
void reportVerification(const std::string &str) OVERRIDE;
|
||||||
|
|
||||||
std::list<std::string> mErrorList;
|
std::list<std::string> mErrorList;
|
||||||
Settings mSettings;
|
Settings mSettings;
|
||||||
|
|
||||||
|
|
|
@ -401,6 +401,8 @@ public:
|
||||||
reportErr(msg);
|
reportErr(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void reportVerification(const std::string &str) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report unmatched suppressions
|
* Report unmatched suppressions
|
||||||
* @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
|
* @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "exprengine.h"
|
#include "exprengine.h"
|
||||||
#include "astutils.h"
|
#include "astutils.h"
|
||||||
|
#include "path.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
@ -1455,12 +1456,12 @@ static void execute(const Token *start, const Token *end, Data &data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprEngine::executeAllFunctions(const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, std::ostream &trace)
|
void ExprEngine::executeAllFunctions(const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, std::ostream &report)
|
||||||
{
|
{
|
||||||
const SymbolDatabase *symbolDatabase = tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = tokenizer->getSymbolDatabase();
|
||||||
for (const Scope *functionScope : symbolDatabase->functionScopes) {
|
for (const Scope *functionScope : symbolDatabase->functionScopes) {
|
||||||
try {
|
try {
|
||||||
executeFunction(functionScope, tokenizer, settings, callbacks, trace);
|
executeFunction(functionScope, tokenizer, settings, callbacks, report);
|
||||||
} catch (const VerifyException &e) {
|
} catch (const VerifyException &e) {
|
||||||
// FIXME.. there should not be exceptions
|
// FIXME.. there should not be exceptions
|
||||||
std::string functionName = functionScope->function->name();
|
std::string functionName = functionScope->function->name();
|
||||||
|
@ -1549,7 +1550,7 @@ static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data)
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, std::ostream &trace)
|
void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, std::ostream &report)
|
||||||
{
|
{
|
||||||
if (!functionScope->bodyStart)
|
if (!functionScope->bodyStart)
|
||||||
return;
|
return;
|
||||||
|
@ -1576,14 +1577,24 @@ void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *to
|
||||||
call(callbacks, tok, bailoutValue, &data);
|
call(callbacks, tok, bailoutValue, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings->debugVerification) {
|
if (settings->debugVerification && !trackExecution.isAllOk()) {
|
||||||
// TODO generate better output!!
|
if (settings->verificationReport)
|
||||||
trackExecution.print(trace);
|
report << "[debug]" << std::endl;
|
||||||
|
trackExecution.print(report);
|
||||||
|
if (settings->verificationReport)
|
||||||
|
report << "[details]" << std::endl;
|
||||||
|
trackExecution.report(report, functionScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a verification report
|
// Write a verification report
|
||||||
//if (!trackExecution.isAllOk())
|
if (settings->verificationReport) {
|
||||||
// trackExecution.report(trace, functionScope);
|
report << "[function-report] "
|
||||||
|
<< Path::stripDirectoryPart(tokenizer->list.getFiles().at(functionScope->bodyStart->fileIndex())) << ":"
|
||||||
|
<< functionScope->bodyStart->linenr() << ":"
|
||||||
|
<< function->name()
|
||||||
|
<< (trackExecution.isAllOk() ? " is safe" : " is not safe")
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings)
|
void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings)
|
||||||
|
@ -1752,5 +1763,9 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
#ifdef VERIFY_INTEGEROVERFLOW
|
#ifdef VERIFY_INTEGEROVERFLOW
|
||||||
callbacks.push_back(integerOverflow);
|
callbacks.push_back(integerOverflow);
|
||||||
#endif
|
#endif
|
||||||
ExprEngine::executeAllFunctions(tokenizer, settings, callbacks, std::cout);
|
|
||||||
|
std::ostringstream report;
|
||||||
|
ExprEngine::executeAllFunctions(tokenizer, settings, callbacks, report);
|
||||||
|
if (errorLogger && settings->verificationReport && !report.str().empty())
|
||||||
|
errorLogger->reportVerification(report.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,8 +297,8 @@ namespace ExprEngine {
|
||||||
typedef std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback;
|
typedef std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback;
|
||||||
|
|
||||||
/** Execute all functions */
|
/** Execute all functions */
|
||||||
void CPPCHECKLIB executeAllFunctions(const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &trace);
|
void CPPCHECKLIB executeAllFunctions(const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &report);
|
||||||
void executeFunction(const Scope *functionScope, const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &trace);
|
void executeFunction(const Scope *functionScope, const Tokenizer *tokenizer, const Settings *settings, const std::vector<Callback> &callbacks, std::ostream &report);
|
||||||
|
|
||||||
void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings);
|
void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ Settings::Settings()
|
||||||
force(false),
|
force(false),
|
||||||
inconclusive(false),
|
inconclusive(false),
|
||||||
verification(false),
|
verification(false),
|
||||||
|
verificationReport(false),
|
||||||
debugVerification(false),
|
debugVerification(false),
|
||||||
inlineSuppressions(false),
|
inlineSuppressions(false),
|
||||||
jobs(1),
|
jobs(1),
|
||||||
|
|
|
@ -191,6 +191,10 @@ public:
|
||||||
/** @brief Enable verification analysis */
|
/** @brief Enable verification analysis */
|
||||||
bool verification;
|
bool verification;
|
||||||
|
|
||||||
|
/** @brief Generate verification report */
|
||||||
|
bool verificationReport;
|
||||||
|
|
||||||
|
/** @brief Generate verification debug output */
|
||||||
bool debugVerification;
|
bool debugVerification;
|
||||||
|
|
||||||
/** @brief check unknown function return values */
|
/** @brief check unknown function return values */
|
||||||
|
|
|
@ -37,8 +37,8 @@ private:
|
||||||
public:
|
public:
|
||||||
std::list<std::string> id;
|
std::list<std::string> id;
|
||||||
|
|
||||||
void reportOut(const std::string & /*outmsg*/) OVERRIDE {
|
void reportOut(const std::string & /*outmsg*/) OVERRIDE {}
|
||||||
}
|
void reportVerification(const std::string & /*str*/) OVERRIDE {}
|
||||||
|
|
||||||
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE {
|
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE {
|
||||||
id.push_back(msg.id);
|
id.push_back(msg.id);
|
||||||
|
|
|
@ -103,8 +103,8 @@ private:
|
||||||
};
|
};
|
||||||
std::vector<ExprEngine::Callback> callbacks;
|
std::vector<ExprEngine::Callback> callbacks;
|
||||||
callbacks.push_back(f);
|
callbacks.push_back(f);
|
||||||
std::ostringstream dummy;
|
std::ostringstream trace;
|
||||||
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, dummy);
|
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, trace);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ private:
|
||||||
};
|
};
|
||||||
std::vector<ExprEngine::Callback> callbacks;
|
std::vector<ExprEngine::Callback> callbacks;
|
||||||
callbacks.push_back(f);
|
callbacks.push_back(f);
|
||||||
std::ostringstream dummy;
|
std::ostringstream trace;
|
||||||
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, dummy);
|
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, trace);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ private:
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
std::vector<ExprEngine::Callback> dummy;
|
std::vector<ExprEngine::Callback> callbacks;
|
||||||
std::ostringstream ret;
|
std::ostringstream ret;
|
||||||
ExprEngine::executeAllFunctions(&tokenizer, &settings, dummy, ret);
|
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, ret);
|
||||||
return ret.str();
|
return ret.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ protected:
|
||||||
|
|
||||||
void processOptions(const options& args);
|
void processOptions(const options& args);
|
||||||
public:
|
public:
|
||||||
|
void reportVerification(const std::string &/*str*/) OVERRIDE {}
|
||||||
void reportOut(const std::string &outmsg) OVERRIDE;
|
void reportOut(const std::string &outmsg) OVERRIDE;
|
||||||
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
|
||||||
void run(const std::string &str);
|
void run(const std::string &str);
|
||||||
|
|
Loading…
Reference in New Issue