Skip to content

Commit

Permalink
Verification; Updated report
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar committed Dec 27, 2019
1 parent 147cf93 commit 4b4f7ea
Show file tree
Hide file tree
Showing 17 changed files with 89 additions and 26 deletions.
2 changes: 2 additions & 0 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// Experimental: Verify
else if (std::strcmp(argv[i], "--verify") == 0)
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)
mSettings->debugVerification = true;

Expand Down
10 changes: 9 additions & 1 deletion cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;

CppCheckExecutor::CppCheckExecutor()
: mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mShowAllErrors(false)
: mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mVerificationOutput(nullptr), mShowAllErrors(false)
{
}

CppCheckExecutor::~CppCheckExecutor()
{
delete mErrorOutput;
delete mVerificationOutput;
}

bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[])
Expand Down Expand Up @@ -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)
{
mExceptionOutput = exceptionOutput;
Expand Down
7 changes: 7 additions & 0 deletions cli/cppcheckexecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class CppCheckExecutor : public ErrorLogger {
*/
void reportInfo(const ErrorLogger::ErrorMessage &msg) OVERRIDE;

void reportVerification(const std::string &str) OVERRIDE;

/**
* Information about how many files have been checked
*
Expand Down Expand Up @@ -187,6 +189,11 @@ class CppCheckExecutor : public ErrorLogger {
*/
std::ofstream *mErrorOutput;

/**
* Verification report
*/
std::ostream *mVerificationOutput;

/**
* Has --errorlist been given?
*/
Expand Down
16 changes: 15 additions & 1 deletion cli/threadexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg)
writeToPipe(REPORT_INFO, msg.serialize());
}

void ThreadExecutor::reportVerification(const std::string &str)
{
writeToPipe(REPORT_VERIFICATION, str.c_str());
}

#elif defined(THREADING_MODEL_WIN)

void ThreadExecutor::addFileContent(const std::string &path, const std::string &content)
Expand Down Expand Up @@ -490,7 +495,12 @@ void ThreadExecutor::reportErr(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)
Expand Down Expand Up @@ -551,4 +561,8 @@ void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &/*msg*/)

}

void ThreadExecutor::reportVerification(const std::string &/*str*/)
{
}

#endif
3 changes: 2 additions & 1 deletion cli/threadexecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class ThreadExecutor : public ErrorLogger {
void reportOut(const std::string &outmsg) OVERRIDE;
void reportErr(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.
Expand All @@ -75,7 +76,7 @@ class ThreadExecutor : public ErrorLogger {
/** @brief Key is file name, and value is the content of the file */
std::map<std::string, std::string> mFileContents;
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.
Expand Down
5 changes: 3 additions & 2 deletions gui/newsuppressiondialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ NewSuppressionDialog::NewSuppressionDialog(QWidget *parent) :

class QErrorLogger : public ErrorLogger {
public:
virtual void reportOut(const std::string &/*outmsg*/) {}
virtual void reportErr(const ErrorLogger::ErrorMessage &msg) {
void reportOut(const std::string &/*outmsg*/) override {}
void reportErr(const ErrorLogger::ErrorMessage &msg) override {
errorIds << QString::fromStdString(msg.id);
}
void reportVerification(const std::string &/*str*/) override {}
QStringList errorIds;
};

Expand Down
1 change: 1 addition & 0 deletions gui/threadresult.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class ThreadResult : public QObject, public ErrorLogger {
*/
void reportOut(const std::string &outmsg) override;
void reportErr(const ErrorLogger::ErrorMessage &msg) override;
void reportVerification(const std::string &/*str*/) override {}

public slots:

Expand Down
8 changes: 6 additions & 2 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,9 +766,8 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
}

// Verification using ExprEngine..
if (mSettings.verification) {
if (mSettings.verification)
ExprEngine::runChecks(this, &tokenizer, &mSettings);
}

// Analyse the tokens..

Expand Down Expand Up @@ -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()
{
Settings s(mSettings);
Expand Down
2 changes: 2 additions & 0 deletions lib/cppcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ class CPPCHECKLIB CppCheck : ErrorLogger {
*/
void reportOut(const std::string &outmsg) OVERRIDE;

void reportVerification(const std::string &str) OVERRIDE;

std::list<std::string> mErrorList;
Settings mSettings;

Expand Down
2 changes: 2 additions & 0 deletions lib/errorlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ class CPPCHECKLIB ErrorLogger {
reportErr(msg);
}

virtual void reportVerification(const std::string &str) = 0;

/**
* Report unmatched suppressions
* @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
Expand Down
33 changes: 24 additions & 9 deletions lib/exprengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "exprengine.h"
#include "astutils.h"
#include "path.h"
#include "settings.h"
#include "symboldatabase.h"
#include "tokenize.h"
Expand Down Expand Up @@ -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();
for (const Scope *functionScope : symbolDatabase->functionScopes) {
try {
executeFunction(functionScope, tokenizer, settings, callbacks, trace);
executeFunction(functionScope, tokenizer, settings, callbacks, report);
} catch (const VerifyException &e) {
// FIXME.. there should not be exceptions
std::string functionName = functionScope->function->name();
Expand Down Expand Up @@ -1549,7 +1550,7 @@ static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data)
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)
return;
Expand All @@ -1576,14 +1577,24 @@ void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *to
call(callbacks, tok, bailoutValue, &data);
}

if (settings->debugVerification) {
// TODO generate better output!!
trackExecution.print(trace);
if (settings->debugVerification && !trackExecution.isAllOk()) {
if (settings->verificationReport)
report << "[debug]" << std::endl;
trackExecution.print(report);
if (settings->verificationReport)
report << "[details]" << std::endl;
trackExecution.report(report, functionScope);
}

// Write a verification report
//if (!trackExecution.isAllOk())
// trackExecution.report(trace, functionScope);
if (settings->verificationReport) {
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)
Expand Down Expand Up @@ -1752,5 +1763,9 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
#ifdef VERIFY_INTEGEROVERFLOW
callbacks.push_back(integerOverflow);
#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());
}
4 changes: 2 additions & 2 deletions lib/exprengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ namespace ExprEngine {
typedef std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback;

/** Execute all functions */
void CPPCHECKLIB executeAllFunctions(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 &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 &report);

void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings);
}
Expand Down
1 change: 1 addition & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Settings::Settings()
force(false),
inconclusive(false),
verification(false),
verificationReport(false),
debugVerification(false),
inlineSuppressions(false),
jobs(1),
Expand Down
4 changes: 4 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ class CPPCHECKLIB Settings : public cppcheck::Platform {
/** @brief Enable verification analysis */
bool verification;

/** @brief Generate verification report */
bool verificationReport;

/** @brief Generate verification debug output */
bool debugVerification;

/** @brief check unknown function return values */
Expand Down
4 changes: 2 additions & 2 deletions test/testcppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class TestCppcheck : public TestFixture {
public:
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 {
id.push_back(msg.id);
Expand Down
12 changes: 6 additions & 6 deletions test/testexprengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ class TestExprEngine : public TestFixture {
};
std::vector<ExprEngine::Callback> callbacks;
callbacks.push_back(f);
std::ostringstream dummy;
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, dummy);
std::ostringstream trace;
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, trace);
return ret;
}

Expand All @@ -126,8 +126,8 @@ class TestExprEngine : public TestFixture {
};
std::vector<ExprEngine::Callback> callbacks;
callbacks.push_back(f);
std::ostringstream dummy;
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, dummy);
std::ostringstream trace;
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, trace);
return ret;
}

Expand All @@ -139,9 +139,9 @@ class TestExprEngine : public TestFixture {
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
std::vector<ExprEngine::Callback> dummy;
std::vector<ExprEngine::Callback> callbacks;
std::ostringstream ret;
ExprEngine::executeAllFunctions(&tokenizer, &settings, dummy, ret);
ExprEngine::executeAllFunctions(&tokenizer, &settings, callbacks, ret);
return ret.str();
}

Expand Down
1 change: 1 addition & 0 deletions test/testsuite.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class TestFixture : public ErrorLogger {

void processOptions(const options& args);
public:
void reportVerification(const std::string &/*str*/) OVERRIDE {}
void reportOut(const std::string &outmsg) OVERRIDE;
void reportErr(const ErrorLogger::ErrorMessage &msg) OVERRIDE;
void run(const std::string &str);
Expand Down

0 comments on commit 4b4f7ea

Please sign in to comment.