Fix #11897 (Safety: show what checks are enabled/disabled) (#5378)

This primarily adds the corresponding report in the GUI that we have in
the command line already
This commit is contained in:
Daniel Marjamäki 2023-08-31 18:28:47 +02:00 committed by GitHub
parent 22547beaaf
commit 44c149e51b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 562 additions and 304 deletions

View File

@ -200,6 +200,7 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \
$(libcppdir)/checkbufferoverrun.o \ $(libcppdir)/checkbufferoverrun.o \
$(libcppdir)/checkclass.o \ $(libcppdir)/checkclass.o \
$(libcppdir)/checkcondition.o \ $(libcppdir)/checkcondition.o \
$(libcppdir)/checkersreport.o \
$(libcppdir)/checkexceptionsafety.o \ $(libcppdir)/checkexceptionsafety.o \
$(libcppdir)/checkfunctions.o \ $(libcppdir)/checkfunctions.o \
$(libcppdir)/checkinternal.o \ $(libcppdir)/checkinternal.o \
@ -488,6 +489,9 @@ $(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/
$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/astutils.h lib/check.h lib/checkcondition.h lib/checkother.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/astutils.h lib/check.h lib/checkcondition.h lib/checkother.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp
$(libcppdir)/checkersreport.o: lib/checkersreport.cpp lib/checkers.h lib/checkersreport.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp
$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp
@ -638,7 +642,7 @@ $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathli
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp
cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/utils.h cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/utils.h

View File

@ -14,9 +14,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup Label="HeaderFiles"> <ItemGroup Label="HeaderFiles">
<ClInclude Include="..\lib\config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmdlineparser.h"> <ClInclude Include="cmdlineparser.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -44,6 +41,9 @@
<ClInclude Include="stacktrace.h"> <ClInclude Include="stacktrace.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="singleexecutor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup Label="SourceFiles"> <ItemGroup Label="SourceFiles">
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
@ -76,6 +76,9 @@
<ClCompile Include="stacktrace.cpp"> <ClCompile Include="stacktrace.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="singleexecutor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc"> <ResourceCompile Include="version.rc">

View File

@ -20,6 +20,7 @@
#include "analyzerinfo.h" #include "analyzerinfo.h"
#include "checkers.h" #include "checkers.h"
#include "checkersreport.h"
#include "cmdlineparser.h" #include "cmdlineparser.h"
#include "color.h" #include "color.h"
#include "config.h" #include "config.h"
@ -337,60 +338,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
return 0; return 0;
} }
static bool isCppcheckPremium(const Settings& settings) {
return (settings.cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0);
}
static std::string getMisraRuleSeverity(const std::string& rule) {
if (checkers::misraRuleSeverity.count(rule) > 0)
return checkers::misraRuleSeverity.at(rule);
return "style";
}
static bool isMisraRuleInconclusive(const std::string& rule) {
return rule == "8.3";
}
static bool isMisraRuleActive(const std::string& rule, int amendment, const std::string& severity, const Settings& settings) {
if (!isCppcheckPremium(settings) && amendment >= 3)
return false;
const bool inconclusive = isMisraRuleInconclusive(rule);
if (inconclusive && !settings.certainty.isEnabled(Certainty::inconclusive))
return false;
if (severity == "warning")
return settings.severity.isEnabled(Severity::warning);
if (severity == "style")
return settings.severity.isEnabled(Severity::style);
return true; // error severity
}
void CppCheckExecutor::writeCheckersReport(const Settings& settings) const void CppCheckExecutor::writeCheckersReport(const Settings& settings) const
{ {
CheckersReport checkersReport(settings, mActiveCheckers);
if (!settings.quiet) { if (!settings.quiet) {
int activeCheckers = 0; const int activeCheckers = checkersReport.getActiveCheckersCount();
int totalCheckers = 0; const int totalCheckers = checkersReport.getAllCheckersCount();
for (const auto& checkReq: checkers::allCheckers) {
if (mActiveCheckers.count(checkReq.first) > 0)
++activeCheckers;
++totalCheckers;
}
if (isCppcheckPremium(settings)) {
for (const auto& checkReq: checkers::premiumCheckers) {
if (mActiveCheckers.count(checkReq.first) > 0)
++activeCheckers;
++totalCheckers;
}
}
if (mSettings->premiumArgs.find("misra-c-") != std::string::npos || mSettings->addons.count("misra")) {
for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
const std::string severity = getMisraRuleSeverity(rule);
const bool active = isMisraRuleActive(rule, info.amendment, severity, settings);
if (active)
++activeCheckers;
++totalCheckers;
}
}
const std::string extra = settings.verbose ? " (use --checkers-report=<filename> to see details)" : ""; const std::string extra = settings.verbose ? " (use --checkers-report=<filename> to see details)" : "";
if (mCriticalErrors.empty()) if (mCriticalErrors.empty())
@ -403,111 +357,9 @@ void CppCheckExecutor::writeCheckersReport(const Settings& settings) const
return; return;
std::ofstream fout(settings.checkersReportFilename); std::ofstream fout(settings.checkersReportFilename);
if (!fout.is_open()) if (fout.is_open())
return; fout << checkersReport.getReport(mCriticalErrors);
fout << "Critical errors" << std::endl;
fout << "---------------" << std::endl;
if (!mCriticalErrors.empty()) {
fout << "There was critical errors (" << mCriticalErrors << ")" << std::endl;
fout << "All checking is skipped for a file with such error" << std::endl;
} else {
fout << "No critical errors, all files were checked." << std::endl;
fout << "Important: Analysis is still not guaranteed to be 'complete' it is possible there are false negatives." << std::endl;
}
fout << std::endl << std::endl;
fout << "Open source checkers" << std::endl;
fout << "--------------------" << std::endl;
int maxCheckerSize = 0;
for (const auto& checkReq: checkers::allCheckers) {
const std::string& checker = checkReq.first;
if (checker.size() > maxCheckerSize)
maxCheckerSize = checker.size();
}
for (const auto& checkReq: checkers::allCheckers) {
const std::string& checker = checkReq.first;
const bool active = mActiveCheckers.count(checkReq.first) > 0;
const std::string& req = checkReq.second;
fout << (active ? "Yes " : "No ") << checker;
if (!active && !req.empty())
fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
fout << std::endl;
}
const bool cppcheckPremium = isCppcheckPremium(settings);
if (cppcheckPremium) {
fout << std::endl << std::endl;
fout << "Premium checkers" << std::endl;
fout << "----------------" << std::endl;
maxCheckerSize = 0;
for (const auto& checkReq: checkers::premiumCheckers) {
const std::string& checker = checkReq.first;
if (checker.size() > maxCheckerSize)
maxCheckerSize = checker.size();
}
for (const auto& checkReq: checkers::premiumCheckers) {
const std::string& checker = checkReq.first;
std::string req = checkReq.second;
bool active = cppcheckPremium;
if (req == "warning")
active &= mSettings->severity.isEnabled(Severity::warning);
else if (req == "style")
active &= mSettings->severity.isEnabled(Severity::style);
fout << (active ? "Yes " : "No ") << checker;
if (!req.empty())
req = "premium," + req;
else
req = "premium";
if (!active)
fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
fout << std::endl;
}
}
int misra = 0;
if (mSettings->premiumArgs.find("misra-c-2012") != std::string::npos)
misra = 2012;
else if (mSettings->premiumArgs.find("misra-c-2023") != std::string::npos)
misra = 2023;
else if (mSettings->addons.count("misra"))
misra = 2012;
if (misra == 0) {
fout << std::endl << std::endl;
fout << "Misra C" << std::endl;
fout << "-------" << std::endl;
fout << "Misra is not enabled" << std::endl;
} else {
fout << std::endl << std::endl;
fout << "Misra C " << misra << std::endl;
fout << "------------" << std::endl;
for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
const std::string severity = getMisraRuleSeverity(rule);
const bool active = isMisraRuleActive(rule, info.amendment, severity, settings);
const bool inconclusive = isMisraRuleInconclusive(rule);
fout << (active ? "Yes " : "No ") << rule;
std::string extra;
if (misra == 2012 && info.amendment >= 1)
extra = " amendment:" + std::to_string(info.amendment);
std::string reqs;
if (info.amendment >= 3)
reqs += ",premium";
if (severity != "error")
reqs += "," + severity;
if (inconclusive)
reqs += ",inconclusive";
if (!active && !reqs.empty())
extra += " require:" + reqs.substr(1);
if (!extra.empty())
fout << std::string(7 - rule.size(), ' ') << extra;
fout << '\n';
}
}
} }
bool CppCheckExecutor::loadLibraries(Settings& settings) bool CppCheckExecutor::loadLibraries(Settings& settings)
@ -607,7 +459,7 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg)
{ {
assert(mSettings != nullptr); assert(mSettings != nullptr);
if (msg.severity == Severity::none && msg.id == "logChecker") { if (msg.severity == Severity::none && (msg.id == "logChecker" || endsWith(msg.id, "-logChecker"))) {
const std::string& checker = msg.shortMessage(); const std::string& checker = msg.shortMessage();
mActiveCheckers.emplace(checker); mActiveCheckers.emplace(checker);
return; return;

View File

@ -65,6 +65,11 @@ void CheckStatistics::addItem(const QString &tool, ShowTypes::ShowType type)
} }
} }
void CheckStatistics::addChecker(const QString &checker)
{
mActiveCheckers.insert(checker.toStdString());
}
void CheckStatistics::clear() void CheckStatistics::clear()
{ {
mStyle.clear(); mStyle.clear();
@ -73,6 +78,8 @@ void CheckStatistics::clear()
mPortability.clear(); mPortability.clear();
mInformation.clear(); mInformation.clear();
mError.clear(); mError.clear();
mActiveCheckers.clear();
mCheckersReport.clear();
} }
unsigned CheckStatistics::getCount(const QString &tool, ShowTypes::ShowType type) const unsigned CheckStatistics::getCount(const QString &tool, ShowTypes::ShowType type) const

View File

@ -23,9 +23,13 @@
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
#include <QSet>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <set>
#include <string>
/// @addtogroup GUI /// @addtogroup GUI
/// @{ /// @{
@ -44,6 +48,11 @@ public:
*/ */
void addItem(const QString &tool, ShowTypes::ShowType type); void addItem(const QString &tool, ShowTypes::ShowType type);
/**
* @brief Add checker to statistics
*/
void addChecker(const QString& checker);
/** /**
* @brief Clear the statistics. * @brief Clear the statistics.
* *
@ -59,9 +68,24 @@ public:
*/ */
unsigned getCount(const QString &tool, ShowTypes::ShowType type) const; unsigned getCount(const QString &tool, ShowTypes::ShowType type) const;
std::set<std::string> getActiveCheckers() const {
return mActiveCheckers;
}
int getNumberOfActiveCheckers() const {
return mActiveCheckers.size();
}
/** Get tools with results */ /** Get tools with results */
QStringList getTools() const; QStringList getTools() const;
void setCheckersReport(QString report) {
mCheckersReport = std::move(report);
}
QString getCheckersReport() const {
return mCheckersReport;
}
private: private:
QMap<QString, unsigned> mStyle; QMap<QString, unsigned> mStyle;
QMap<QString, unsigned> mWarning; QMap<QString, unsigned> mWarning;
@ -69,6 +93,8 @@ private:
QMap<QString, unsigned> mPortability; QMap<QString, unsigned> mPortability;
QMap<QString, unsigned> mInformation; QMap<QString, unsigned> mInformation;
QMap<QString, unsigned> mError; QMap<QString, unsigned> mError;
std::set<std::string> mActiveCheckers;
QString mCheckersReport;
}; };
/// @} /// @}

View File

@ -540,6 +540,7 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons
} }
mThread->setProject(p); mThread->setProject(p);
mThread->check(checkSettings); mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
} }
void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration) void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration)
@ -603,6 +604,7 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
mThread->setCheckFiles(true); mThread->setCheckFiles(true);
mThread->check(checkSettings); mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
} }
void MainWindow::analyzeCode(const QString& code, const QString& filename) void MainWindow::analyzeCode(const QString& code, const QString& filename)
@ -1208,7 +1210,9 @@ void MainWindow::reAnalyzeSelected(const QStringList& files)
// considered in "Modified Files Check" performed after "Selected Files Check" // considered in "Modified Files Check" performed after "Selected Files Check"
// TODO: Should we store per file CheckStartTime? // TODO: Should we store per file CheckStartTime?
QDateTime saveCheckStartTime = mThread->getCheckStartTime(); QDateTime saveCheckStartTime = mThread->getCheckStartTime();
mThread->check(getCppcheckSettings()); const Settings& checkSettings = getCppcheckSettings();
mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
mThread->setCheckStartTime(saveCheckStartTime); mThread->setCheckStartTime(saveCheckStartTime);
} }
@ -1232,7 +1236,9 @@ void MainWindow::reAnalyze(bool all)
qDebug() << "Rechecking project file" << mProjectFile->getFilename(); qDebug() << "Rechecking project file" << mProjectFile->getFilename();
mThread->setCheckFiles(all); mThread->setCheckFiles(all);
mThread->check(getCppcheckSettings()); const Settings& checkSettings = getCppcheckSettings();
mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
} }
void MainWindow::clearResults() void MainWindow::clearResults()

View File

@ -193,7 +193,7 @@ public slots:
/** @brief Slot for showing the library editor */ /** @brief Slot for showing the library editor */
void showLibraryEditor(); void showLibraryEditor();
protected slots: private slots:
/** @brief Slot for checkthread's done signal */ /** @brief Slot for checkthread's done signal */
void analysisDone(); void analysisDone();

View File

@ -19,6 +19,7 @@
#include "resultsview.h" #include "resultsview.h"
#include "checkstatistics.h" #include "checkstatistics.h"
#include "checkersreport.h"
#include "codeeditor.h" #include "codeeditor.h"
#include "codeeditorstyle.h" #include "codeeditorstyle.h"
#include "common.h" #include "common.h"
@ -105,6 +106,7 @@ void ResultsView::initialize(QSettings *settings, ApplicationList *list, ThreadH
ResultsView::~ResultsView() ResultsView::~ResultsView()
{ {
delete mUI; delete mUI;
delete mCheckSettings;
} }
void ResultsView::clear(bool results) void ResultsView::clear(bool results)
@ -116,6 +118,8 @@ void ResultsView::clear(bool results)
mUI->mDetails->setText(QString()); mUI->mDetails->setText(QString());
mStatistics->clear(); mStatistics->clear();
delete mCheckSettings;
mCheckSettings = nullptr;
//Clear the progressbar //Clear the progressbar
mUI->mProgress->setMaximum(PROGRESS_MAX); mUI->mProgress->setMaximum(PROGRESS_MAX);
@ -150,6 +154,11 @@ void ResultsView::progress(int value, const QString& description)
void ResultsView::error(const ErrorItem &item) void ResultsView::error(const ErrorItem &item)
{ {
if (item.severity == Severity::none && (item.errorId == "logChecker" || item.errorId.endsWith("-logChecker"))) {
mStatistics->addChecker(item.message);
return;
}
handleCriticalError(item); handleCriticalError(item);
if (mUI->mTree->addErrorItem(item)) { if (mUI->mTree->addErrorItem(item)) {
@ -282,6 +291,13 @@ QString ResultsView::getCheckDirectory()
return mUI->mTree->getCheckDirectory(); return mUI->mTree->getCheckDirectory();
} }
void ResultsView::setCheckSettings(const Settings &settings)
{
delete mCheckSettings;
mCheckSettings = new Settings;
*mCheckSettings = settings;
}
void ResultsView::checkingStarted(int count) void ResultsView::checkingStarted(int count)
{ {
mSuccess = true; mSuccess = true;
@ -296,6 +312,13 @@ void ResultsView::checkingFinished()
mUI->mProgress->setVisible(false); mUI->mProgress->setVisible(false);
mUI->mProgress->setFormat("%p%"); mUI->mProgress->setFormat("%p%");
{
Settings checkSettings;
const std::set<std::string> activeCheckers = mStatistics->getActiveCheckers();
CheckersReport checkersReport(mCheckSettings ? *mCheckSettings : checkSettings, activeCheckers);
mStatistics->setCheckersReport(QString::fromStdString(checkersReport.getReport(mCriticalErrors.toStdString())));
}
// TODO: Items can be mysteriously hidden when checking is finished, this function // TODO: Items can be mysteriously hidden when checking is finished, this function
// call should be redundant but it "unhides" the wrongly hidden items. // call should be redundant but it "unhides" the wrongly hidden items.
mUI->mTree->refreshTree(); mUI->mTree->refreshTree();
@ -528,6 +551,11 @@ void ResultsView::stopAnalysis()
void ResultsView::handleCriticalError(const ErrorItem &item) void ResultsView::handleCriticalError(const ErrorItem &item)
{ {
if (ErrorLogger::isCriticalErrorId(item.errorId.toStdString())) { if (ErrorLogger::isCriticalErrorId(item.errorId.toStdString())) {
if (!mCriticalErrors.contains(item.errorId)) {
if (!mCriticalErrors.isEmpty())
mCriticalErrors += ",";
mCriticalErrors += item.errorId;
}
QString msg = tr("There was a critical error with id '%1'").arg(item.errorId); QString msg = tr("There was a critical error with id '%1'").arg(item.errorId);
if (!item.file0.isEmpty()) if (!item.file0.isEmpty())
msg += ", " + tr("when checking %1").arg(item.file0); msg += ", " + tr("when checking %1").arg(item.file0);

View File

@ -29,6 +29,7 @@
#include <QWidget> #include <QWidget>
class ErrorItem; class ErrorItem;
class Settings;
class ApplicationList; class ApplicationList;
class ThreadHandler; class ThreadHandler;
class QModelIndex; class QModelIndex;
@ -136,6 +137,11 @@ public:
QString getCheckDirectory(); QString getCheckDirectory();
/**
* Set settings used in checking
*/
void setCheckSettings(const Settings& settings);
/** /**
* @brief Inform the view that checking has started * @brief Inform the view that checking has started
* *
@ -368,11 +374,16 @@ private:
CheckStatistics *mStatistics; CheckStatistics *mStatistics;
Settings* mCheckSettings = nullptr;
/** /**
* Set to true when checking finish successfully. Set to false whenever analysis starts. * Set to true when checking finish successfully. Set to false whenever analysis starts.
*/ */
bool mSuccess = false; bool mSuccess = false;
/** Critical error ids */
QString mCriticalErrors;
private slots: private slots:
/** /**
* @brief Custom context menu for Analysis Log * @brief Custom context menu for Analysis Log

View File

@ -75,6 +75,10 @@ StatsDialog::StatsDialog(QWidget *parent)
{ {
mUI->setupUi(this); mUI->setupUi(this);
QFont font("courier");
font.setStyleHint(QFont::Monospace);
mUI->mCheckersReport->setFont(font);
setWindowFlags(Qt::Window); setWindowFlags(Qt::Window);
connect(mUI->mCopyToClipboard, &QPushButton::pressed, this, &StatsDialog::copyToClipboard); connect(mUI->mCopyToClipboard, &QPushButton::pressed, this, &StatsDialog::copyToClipboard);
@ -366,12 +370,14 @@ void StatsDialog::copyToClipboard()
void StatsDialog::setStatistics(const CheckStatistics *stats) void StatsDialog::setStatistics(const CheckStatistics *stats)
{ {
mStatistics = stats; mStatistics = stats;
mUI->mLblErrors->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowErrors))); mUI->mLblErrors->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowErrors)));
mUI->mLblWarnings->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowWarnings))); mUI->mLblWarnings->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowWarnings)));
mUI->mLblStyle->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowStyle))); mUI->mLblStyle->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowStyle)));
mUI->mLblPortability->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowPortability))); mUI->mLblPortability->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowPortability)));
mUI->mLblPerformance->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowPerformance))); mUI->mLblPerformance->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowPerformance)));
mUI->mLblInformation->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowInformation))); mUI->mLblInformation->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowInformation)));
mUI->mLblActiveCheckers->setText(QString::number(stats->getNumberOfActiveCheckers()));
mUI->mCheckersReport->setPlainText(stats->getCheckersReport());
} }
#ifdef QT_CHARTS_LIB #ifdef QT_CHARTS_LIB

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>502</width> <width>500</width>
<height>274</height> <height>414</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -247,114 +247,150 @@
<attribute name="title"> <attribute name="title">
<string>Statistics</string> <string>Statistics</string>
</attribute> </attribute>
<layout class="QFormLayout" name="formLayout"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5"> <widget class="QLabel" name="label">
<item> <property name="text">
<widget class="QLabel" name="label"> <string>Errors:</string>
<property name="text"> </property>
<string>Errors:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblErrors"> <item row="0" column="1">
<property name="text"> <widget class="QLabel" name="mLblErrors">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <widget class="QLabel" name="label_2">
<item> <property name="text">
<widget class="QLabel" name="label_2"> <string>Warnings:</string>
<property name="text"> </property>
<string>Warnings:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblWarnings"> <item row="1" column="1">
<property name="text"> <widget class="QLabel" name="mLblWarnings">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <widget class="QLabel" name="label_3">
<item> <property name="text">
<widget class="QLabel" name="label_3"> <string>Stylistic warnings:</string>
<property name="text"> </property>
<string>Stylistic warnings:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblStyle"> <item row="2" column="1">
<property name="text"> <widget class="QLabel" name="mLblStyle">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_8"> <widget class="QLabel" name="label_6">
<item> <property name="text">
<widget class="QLabel" name="label_6"> <string>Portability warnings:</string>
<property name="text"> </property>
<string>Portability warnings:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblPortability"> <item row="3" column="1">
<property name="text"> <widget class="QLabel" name="mLblPortability">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4"> <widget class="QLabel" name="label_4">
<item> <property name="text">
<widget class="QLabel" name="label_4"> <string>Performance issues:</string>
<property name="text"> </property>
<string>Performance issues:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblPerformance"> <item row="4" column="1">
<property name="text"> <widget class="QLabel" name="mLblPerformance">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout>
</item> </item>
<item row="5" column="0"> <item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_6"> <widget class="QLabel" name="label_5">
<item> <property name="text">
<widget class="QLabel" name="label_5"> <string>Information messages:</string>
<property name="text"> </property>
<string>Information messages:</string> <property name="alignment">
</property> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget> </property>
</item> </widget>
<item> </item>
<widget class="QLabel" name="mLblInformation"> <item row="5" column="1">
<property name="text"> <widget class="QLabel" name="mLblInformation">
<string notr="true">TextLabel</string> <property name="text">
</property> <string notr="true">TextLabel</string>
</widget> </property>
</item> </widget>
</layout> </item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Active checkers:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="mLblActiveCheckers">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mCheckersTab">
<attribute name="title">
<string>Checkers</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QPlainTextEdit" name="mCheckersReport">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<family>Courier 10 Pitch</family>
</font>
</property>
<property name="undoRedoEnabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -206,22 +206,21 @@ namespace checkers {
static std::map<std::string, std::string> premiumCheckers{ static std::map<std::string, std::string> premiumCheckers{
{"CheckBufferOverrun::addressOfPointerArithmetic","warning"}, {"PremiumCheckBufferOverrun::addressOfPointerArithmetic","warning"},
{"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"}, {"PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
{"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"}, {"PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
{"CheckHang::infiniteLoop",""}, {"PremiumCheckHang::infiniteLoop",""},
{"CheckHang::infiniteLoopContinue",""}, {"PremiumCheckHang::infiniteLoopContinue",""},
{"CheckOther::arrayPointerComparison","style"}, {"PremiumCheckOther::arrayPointerComparison","style"},
{"CheckOther::knownResult","style"}, {"PremiumCheckOther::knownResult","style"},
{"CheckOther::lossOfPrecision","style"}, {"PremiumCheckOther::lossOfPrecision","style"},
{"CheckOther::pointerCast","style"}, {"PremiumCheckOther::pointerCast","style"},
{"CheckOther::reassignInLoop","style"}, {"PremiumCheckOther::reassignInLoop","style"},
{"CheckOther::unreachableCode","style"}, {"PremiumCheckOther::unreachableCode","style"},
{"CheckStrictAlias::strictAliasCondition","warning"}, {"PremiumCheckUninitVar::uninitvar",""},
{"CheckUninitVar::uninitvar",""}, {"PremiumCheckUninitVar::uninitmember",""},
{"CheckUninitVar::uninitmember",""}, {"PremiumCheckUnusedVar::unreadVariable","style"},
{"CheckUnusedVar::unreadVariable","style"}, {"PremiumCheckUnusedVar::unusedPrivateMember","style"},
{"CheckUnusedVar::unusedPrivateMember","style"},
}; };

207
lib/checkersreport.cpp Normal file
View File

@ -0,0 +1,207 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2023 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "checkersreport.h"
#include "checkers.h"
#include <sstream>
static bool isCppcheckPremium(const Settings& settings) {
return (settings.cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0);
}
static std::string getMisraRuleSeverity(const std::string& rule) {
if (checkers::misraRuleSeverity.count(rule) > 0)
return checkers::misraRuleSeverity.at(rule);
return "style";
}
static bool isMisraRuleInconclusive(const std::string& rule) {
return rule == "8.3";
}
static bool isMisraRuleActive(const std::string& rule, int amendment, const std::string& severity, const Settings& settings) {
if (!isCppcheckPremium(settings) && amendment >= 3)
return false;
const bool inconclusive = isMisraRuleInconclusive(rule);
if (inconclusive && !settings.certainty.isEnabled(Certainty::inconclusive))
return false;
if (severity == "warning")
return settings.severity.isEnabled(Severity::warning);
if (severity == "style")
return settings.severity.isEnabled(Severity::style);
return true; // error severity
}
CheckersReport::CheckersReport(const Settings& settings, const std::set<std::string>& activeCheckers)
: mSettings(settings), mActiveCheckers(activeCheckers)
{}
int CheckersReport::getActiveCheckersCount()
{
if (mAllCheckersCount == 0) {
countCheckers();
}
return mActiveCheckersCount;
}
int CheckersReport::getAllCheckersCount()
{
if (mAllCheckersCount == 0) {
countCheckers();
}
return mAllCheckersCount;
}
void CheckersReport::countCheckers()
{
mActiveCheckersCount = mAllCheckersCount = 0;
for (const auto& checkReq: checkers::allCheckers) {
if (mActiveCheckers.count(checkReq.first) > 0)
++mActiveCheckersCount;
++mAllCheckersCount;
}
for (const auto& checkReq: checkers::premiumCheckers) {
if (mActiveCheckers.count(checkReq.first) > 0)
++mActiveCheckersCount;
++mAllCheckersCount;
}
if (mSettings.premiumArgs.find("misra-c-") != std::string::npos || mSettings.addons.count("misra")) {
for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
const std::string severity = getMisraRuleSeverity(rule);
const bool active = isMisraRuleActive(rule, info.amendment, severity, mSettings);
if (active)
++mActiveCheckersCount;
++mAllCheckersCount;
}
}
}
std::string CheckersReport::getReport(const std::string& criticalErrors) const
{
std::ostringstream fout;
fout << "Critical errors" << std::endl;
fout << "---------------" << std::endl;
if (!criticalErrors.empty()) {
fout << "There was critical errors (" << criticalErrors << ")" << std::endl;
fout << "All checking is skipped for a file with such error" << std::endl;
} else {
fout << "No critical errors, all files were checked." << std::endl;
fout << "Important: Analysis is still not guaranteed to be 'complete' it is possible there are false negatives." << std::endl;
}
fout << std::endl << std::endl;
fout << "Open source checkers" << std::endl;
fout << "--------------------" << std::endl;
int maxCheckerSize = 0;
for (const auto& checkReq: checkers::allCheckers) {
const std::string& checker = checkReq.first;
if (checker.size() > maxCheckerSize)
maxCheckerSize = checker.size();
}
for (const auto& checkReq: checkers::allCheckers) {
const std::string& checker = checkReq.first;
const bool active = mActiveCheckers.count(checkReq.first) > 0;
const std::string& req = checkReq.second;
fout << (active ? "Yes " : "No ") << checker;
if (!active && !req.empty())
fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
fout << std::endl;
}
const bool cppcheckPremium = isCppcheckPremium(mSettings);
fout << std::endl << std::endl;
fout << "Premium checkers" << std::endl;
fout << "----------------" << std::endl;
if (!cppcheckPremium) {
fout << "Cppcheck Premium is not used" << std::endl;
} else {
maxCheckerSize = 0;
for (const auto& checkReq: checkers::premiumCheckers) {
const std::string& checker = checkReq.first;
if (checker.size() > maxCheckerSize)
maxCheckerSize = checker.size();
}
for (const auto& checkReq: checkers::premiumCheckers) {
const std::string& checker = checkReq.first;
std::string req = checkReq.second;
bool active = cppcheckPremium && mActiveCheckers.count(checkReq.first) > 0;
if (req == "warning")
active &= mSettings.severity.isEnabled(Severity::warning);
else if (req == "style")
active &= mSettings.severity.isEnabled(Severity::style);
else if (!req.empty())
active = false; // FIXME: handle req
fout << (active ? "Yes " : "No ") << checker;
if (!req.empty())
req = "premium," + req;
else
req = "premium";
if (!active)
fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
fout << std::endl;
}
}
int misra = 0;
if (mSettings.premiumArgs.find("misra-c-2012") != std::string::npos)
misra = 2012;
else if (mSettings.premiumArgs.find("misra-c-2023") != std::string::npos)
misra = 2023;
else if (mSettings.addons.count("misra"))
misra = 2012;
if (misra == 0) {
fout << std::endl << std::endl;
fout << "Misra C" << std::endl;
fout << "-------" << std::endl;
fout << "Misra is not enabled" << std::endl;
} else {
fout << std::endl << std::endl;
fout << "Misra C " << misra << std::endl;
fout << "------------" << std::endl;
for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
const std::string severity = getMisraRuleSeverity(rule);
const bool active = isMisraRuleActive(rule, info.amendment, severity, mSettings);
const bool inconclusive = isMisraRuleInconclusive(rule);
fout << (active ? "Yes " : "No ") << rule;
std::string extra;
if (misra == 2012 && info.amendment >= 1)
extra = " amendment:" + std::to_string(info.amendment);
std::string reqs;
if (info.amendment >= 3)
reqs += ",premium";
if (severity != "error")
reqs += "," + severity;
if (inconclusive)
reqs += ",inconclusive";
if (!active && !reqs.empty())
extra += " require:" + reqs.substr(1);
if (!extra.empty())
fout << std::string(7 - rule.size(), ' ') << extra;
fout << '\n';
}
}
return fout.str();
}

44
lib/checkersreport.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2023 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "settings.h"
#include <set>
#include <string>
class CPPCHECKLIB CheckersReport {
public:
CheckersReport(const Settings& settings, const std::set<std::string>& activeCheckers);
int getActiveCheckersCount();
int getAllCheckersCount();
std::string getReport(const std::string& criticalErrors) const;
private:
const Settings& mSettings;
const std::set<std::string>& mActiveCheckers;
void countCheckers();
int mActiveCheckersCount = 0;
int mAllCheckersCount = 0;
};

View File

@ -1492,9 +1492,11 @@ void CppCheck::executeAddons(const std::vector<std::string>& files)
errmsg.setmsg(text); errmsg.setmsg(text);
const std::string severity = obj["severity"].get<std::string>(); const std::string severity = obj["severity"].get<std::string>();
errmsg.severity = Severity::fromString(severity); errmsg.severity = Severity::fromString(severity);
if (errmsg.severity == Severity::SeverityType::none) if (errmsg.severity == Severity::SeverityType::none) {
continue; if (!endsWith(errmsg.id, "-logChecker"))
if (!mSettings.severity.isEnabled(errmsg.severity)) continue;
}
else if (!mSettings.severity.isEnabled(errmsg.severity))
continue; continue;
errmsg.file0 = ((files.size() == 1) ? files[0] : ""); errmsg.file0 = ((files.size() == 1) ? files[0] : "");
@ -1596,7 +1598,7 @@ void CppCheck::purgedConfigurationMessage(const std::string &file, const std::st
void CppCheck::reportErr(const ErrorMessage &msg) void CppCheck::reportErr(const ErrorMessage &msg)
{ {
if (msg.severity == Severity::none && msg.id == "logChecker") { if (msg.severity == Severity::none && (msg.id == "logChecker" || endsWith(msg.id, "-logChecker"))) {
mErrorLogger.reportErr(msg); mErrorLogger.reportErr(msg);
return; return;
} }

View File

@ -56,6 +56,7 @@
<ClCompile Include="checkbufferoverrun.cpp" /> <ClCompile Include="checkbufferoverrun.cpp" />
<ClCompile Include="checkclass.cpp" /> <ClCompile Include="checkclass.cpp" />
<ClCompile Include="checkcondition.cpp" /> <ClCompile Include="checkcondition.cpp" />
<ClCompile Include="checkersreport.cpp" />
<ClCompile Include="checkexceptionsafety.cpp" /> <ClCompile Include="checkexceptionsafety.cpp" />
<ClCompile Include="checkfunctions.cpp" /> <ClCompile Include="checkfunctions.cpp" />
<ClCompile Include="checkinternal.cpp" /> <ClCompile Include="checkinternal.cpp" />
@ -122,6 +123,7 @@
<ClInclude Include="checkbufferoverrun.h" /> <ClInclude Include="checkbufferoverrun.h" />
<ClInclude Include="checkclass.h" /> <ClInclude Include="checkclass.h" />
<ClInclude Include="checkcondition.h" /> <ClInclude Include="checkcondition.h" />
<ClInclude Include="checkersreport.h" />
<ClInclude Include="checkexceptionsafety.h" /> <ClInclude Include="checkexceptionsafety.h" />
<ClInclude Include="checkfunctions.h" /> <ClInclude Include="checkfunctions.h" />
<ClInclude Include="checkinternal.h" /> <ClInclude Include="checkinternal.h" />

View File

@ -194,6 +194,12 @@
<ClCompile Include="vfvalue.cpp"> <ClCompile Include="vfvalue.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="checkersreport.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="keywords.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup Label="HeaderFiles"> <ItemGroup Label="HeaderFiles">
<ClInclude Include="checkbufferoverrun.h"> <ClInclude Include="checkbufferoverrun.h">
@ -406,6 +412,15 @@
<ClInclude Include="vfvalue.h"> <ClInclude Include="vfvalue.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="keywords.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="checkersreport.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc" /> <ResourceCompile Include="version.rc" />

View File

@ -45,6 +45,7 @@ const std::set<std::string> ErrorLogger::mCriticalErrorIds{
"internalAstError", "internalAstError",
"instantiationError", "instantiationError",
"internalError", "internalError",
"premium-internalError",
"preprocessorErrorDirective", "preprocessorErrorDirective",
"syntaxError", "syntaxError",
"unknownMacro" "unknownMacro"

View File

@ -16,6 +16,7 @@ HEADERS += $${PWD}/analyzer.h \
$${PWD}/checkbufferoverrun.h \ $${PWD}/checkbufferoverrun.h \
$${PWD}/checkclass.h \ $${PWD}/checkclass.h \
$${PWD}/checkcondition.h \ $${PWD}/checkcondition.h \
$${PWD}/checkersreport.h \
$${PWD}/checkexceptionsafety.h \ $${PWD}/checkexceptionsafety.h \
$${PWD}/checkfunctions.h \ $${PWD}/checkfunctions.h \
$${PWD}/checkinternal.h \ $${PWD}/checkinternal.h \
@ -85,6 +86,7 @@ SOURCES += $${PWD}/analyzerinfo.cpp \
$${PWD}/checkbufferoverrun.cpp \ $${PWD}/checkbufferoverrun.cpp \
$${PWD}/checkclass.cpp \ $${PWD}/checkclass.cpp \
$${PWD}/checkcondition.cpp \ $${PWD}/checkcondition.cpp \
$${PWD}/checkersreport.cpp \
$${PWD}/checkexceptionsafety.cpp \ $${PWD}/checkexceptionsafety.cpp \
$${PWD}/checkfunctions.cpp \ $${PWD}/checkfunctions.cpp \
$${PWD}/checkinternal.cpp \ $${PWD}/checkinternal.cpp \

View File

@ -10,8 +10,12 @@ Improved checking:
- constParameter*/constVariable* checks find more instances of pointers/references that can be const, e.g. when calling library functions - constParameter*/constVariable* checks find more instances of pointers/references that can be const, e.g. when calling library functions
GUI: GUI:
- Show in statistics which checkers have been activated in latest analysis
- Make it more visible if there has been critical errors that caused checkers to be skipped
Changed interface: Changed interface:
- Write how many checkers was activated after a run
- Added --checkers-report that can be used to generate a report in a file that shows what checkers was activated and disabled
Deprecations: Deprecations:
- The qmake build system has been deprecated and will be removed in a future version. - The qmake build system has been deprecated and will be removed in a future version.

View File

@ -256,6 +256,9 @@
<ClCompile Include="testsingleexecutor.cpp"> <ClCompile Include="testsingleexecutor.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="testcheck.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup Label="HeaderFiles"> <ItemGroup Label="HeaderFiles">
<ClInclude Include="options.h"> <ClInclude Include="options.h">

View File

@ -44,22 +44,22 @@ print('static std::map<std::string, std::string> premiumCheckers{')
premium_checkers = """ premium_checkers = """
$ grep logChecker *.cpp | sed 's/.*logChecker/logChecker/' $ grep logChecker *.cpp | sed 's/.*logChecker/logChecker/'
logChecker("CheckBufferOverrun::addressOfPointerArithmetic"); // warning logChecker("PremiumCheckBufferOverrun::addressOfPointerArithmetic"); // warning
logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning logChecker("PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning logChecker("PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
logChecker("CheckHang::infiniteLoop"); logChecker("PremiumCheckHang::infiniteLoop");
logChecker("CheckHang::infiniteLoopContinue"); logChecker("PremiumCheckHang::infiniteLoopContinue");
logChecker("CheckOther::arrayPointerComparison"); // style logChecker("PremiumCheckOther::arrayPointerComparison"); // style
logChecker("CheckOther::knownResult"); // style logChecker("PremiumCheckOther::knownResult"); // style
logChecker("CheckOther::lossOfPrecision"); // style logChecker("PremiumCheckOther::lossOfPrecision"); // style
logChecker("CheckOther::pointerCast"); // style logChecker("PremiumCheckOther::pointerCast"); // style
logChecker("CheckOther::reassignInLoop"); // style logChecker("PremiumCheckOther::reassignInLoop"); // style
logChecker("CheckOther::unreachableCode"); // style logChecker("PremiumCheckOther::unreachableCode"); // style
logChecker("CheckStrictAlias::strictAliasCondition"); // warning logChecker("PremiumCheckStrictAlias::strictAliasCondition"); // warning
logChecker("CheckUninitVar::uninitvar"); logChecker("PremiumCheckUninitVar::uninitvar");
logChecker("CheckUninitVar::uninitmember"); logChecker("PremiumCheckUninitVar::uninitmember");
logChecker("CheckUnusedVar::unreadVariable"); // style logChecker("PremiumCheckUnusedVar::unreadVariable"); // style
logChecker("CheckUnusedVar::unusedPrivateMember"); // style logChecker("PremiumCheckUnusedVar::unusedPrivateMember"); // style
""" """
for line in premium_checkers.split('\n'): for line in premium_checkers.split('\n'):