diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index ec52843ff..55ef4ed6a 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -946,6 +946,20 @@ Settings MainWindow::getCppcheckSettings()
json += " }";
result.addons.push_back(json.toStdString());
}
+
+ if (isCppcheckPremium()) {
+ QString premiumArgs;
+ if (mProjectFile->getBughunting())
+ premiumArgs += " --bughunting";
+ if (mProjectFile->getCertIntPrecision() > 0)
+ premiumArgs += " --cert-c-int-precision=" + QString::number(mProjectFile->getCertIntPrecision());
+ if (mProjectFile->getAddons().contains("misra"))
+ premiumArgs += " --misra-c-2012";
+ for (const QString& c: mProjectFile->getCodingStandards()) {
+ premiumArgs += " --" + c;
+ }
+ result.premiumArgs = premiumArgs.mid(1).toStdString();
+ }
}
// Include directories (and files) are searched in listed order.
@@ -1664,7 +1678,7 @@ void MainWindow::newProjectFile()
mProjectFile->setFilename(filepath);
mProjectFile->setBuildDir(filename.left(filename.indexOf(".")) + "-cppcheck-build-dir");
- ProjectFileDialog dlg(mProjectFile, this);
+ ProjectFileDialog dlg(mProjectFile, isCppcheckPremium(), this);
if (dlg.exec() == QDialog::Accepted) {
addProjectMRU(filepath);
analyzeProject(mProjectFile);
@@ -1695,7 +1709,7 @@ void MainWindow::editProjectFile()
return;
}
- ProjectFileDialog dlg(mProjectFile, this);
+ ProjectFileDialog dlg(mProjectFile, isCppcheckPremium(), this);
if (dlg.exec() == QDialog::Accepted) {
mProjectFile->write();
analyzeProject(mProjectFile);
@@ -1864,3 +1878,7 @@ void MainWindow::suppressIds(QStringList ids)
mProjectFile->setSuppressions(suppressions);
mProjectFile->write();
}
+
+bool MainWindow::isCppcheckPremium() const {
+ return mCppcheckCfgProductName.startsWith("Cppcheck Premium ");
+}
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
index 5621ca12e..564674079 100644
--- a/gui/mainwindow.h
+++ b/gui/mainwindow.h
@@ -230,6 +230,8 @@ protected slots:
private:
+ bool isCppcheckPremium() const;
+
/** Get filename for last results */
QString getLastResults() const;
diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp
index 3eb49ca73..cb7d2e41b 100644
--- a/gui/projectfile.cpp
+++ b/gui/projectfile.cpp
@@ -74,6 +74,11 @@ void ProjectFile::clear()
mVsConfigurations.clear();
mTags.clear();
mWarningTags.clear();
+
+ // Premium
+ mBughunting = false;
+ mCertIntPrecision = 0;
+ mCodingStandards.clear();
}
bool ProjectFile::read(const QString &filename)
@@ -195,6 +200,15 @@ bool ProjectFile::read(const QString &filename)
// VSConfiguration
if (xmlReader.name() == QString(CppcheckXml::VSConfigurationElementName))
readVsConfigurations(xmlReader);
+
+ // Cppcheck Premium
+ if (xmlReader.name() == QString(CppcheckXml::BughuntingElementName))
+ mBughunting = true;
+ if (xmlReader.name() == QString(CppcheckXml::CodingStandardsElementName))
+ readStringList(mAddons, xmlReader, CppcheckXml::CodingStandardElementName);
+ if (xmlReader.name() == QString(CppcheckXml::CertIntPrecisionElementName))
+ mCertIntPrecision = readInt(xmlReader, 0);
+
break;
case QXmlStreamReader::EndElement:
@@ -928,6 +942,23 @@ bool ProjectFile::write(const QString &filename)
}
}
+ // Cppcheck Premium
+ if (mBughunting) {
+ xmlWriter.writeStartElement(CppcheckXml::BughuntingElementName);
+ xmlWriter.writeEndElement();
+ }
+
+ writeStringList(xmlWriter,
+ mCodingStandards,
+ CppcheckXml::CodingStandardsElementName,
+ CppcheckXml::CodingStandardElementName);
+
+ if (mCertIntPrecision > 0) {
+ xmlWriter.writeStartElement(CppcheckXml::CertIntPrecisionElementName);
+ xmlWriter.writeCharacters(QString::number(mCertIntPrecision));
+ xmlWriter.writeEndElement();
+ }
+
xmlWriter.writeEndDocument();
file.close();
return true;
diff --git a/gui/projectfile.h b/gui/projectfile.h
index 8951a4f94..92abca02a 100644
--- a/gui/projectfile.h
+++ b/gui/projectfile.h
@@ -333,6 +333,36 @@ public:
/** Get tags for a warning */
QString getWarningTags(std::size_t hash) const;
+ /** Bughunting (Cppcheck Premium) */
+ void setBughunting(bool bughunting) {
+ mBughunting = bughunting;
+ }
+ bool getBughunting() const {
+ return mBughunting;
+ }
+
+ /** @brief Get list of coding standards (checked by Cppcheck Premium). */
+ QStringList getCodingStandards() const {
+ return mCodingStandards;
+ }
+
+ /**
+ * @brief Set list of coding standards (checked by Cppcheck Premium).
+ * @param codingStandards List of coding standards.
+ */
+ void setCodingStandards(QStringList codingStandards) {
+ mCodingStandards = std::move(codingStandards);
+ }
+
+ /** Cert C: int precision */
+ void setCertIntPrecision(int p) {
+ mCertIntPrecision = p;
+ }
+ int getCertIntPrecision() const {
+ return mCertIntPrecision;
+ }
+
+
/**
* @brief Write project file (to disk).
* @param filename Filename to use.
@@ -543,6 +573,15 @@ private:
*/
QStringList mAddons;
+ bool mBughunting;
+
+ /**
+ * @brief List of coding standards, checked by Cppcheck Premium.
+ */
+ QStringList mCodingStandards;
+
+ int mCertIntPrecision;
+
/** @brief Execute clang analyzer? */
bool mClangAnalyzer;
diff --git a/gui/projectfile.ui b/gui/projectfile.ui
index f35f54daa..96384385b 100644
--- a/gui/projectfile.ui
+++ b/gui/projectfile.ui
@@ -773,24 +773,26 @@
+
+
+
+ -
+
+
+ Coding standards
+
+
-
-
+
- Coding standards
+ Misra C 2012
-
-
-
- MISRA C 2012
-
-
-
- -
-
+
-
-
+
MISRA rule texts
@@ -812,6 +814,57 @@
+ -
+
+
+ Cert C
+
+
+
+ -
+
+
-
+
+
+ CERT-INT35-C: int precision (if size equals precision, you can leave empty)
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Misra C++ 2008
+
+
+
+ -
+
+
+ Autosar
+
+
+
+
+
+
+ -
+
+
+ Bug hunting
+
+
+
-
+
+
+ Bug hunting
+
+
+
diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp
index 33cc88aeb..d3d242460 100644
--- a/gui/projectfiledialog.cpp
+++ b/gui/projectfiledialog.cpp
@@ -40,6 +40,11 @@
#include
#include
+static const char ADDON_MISRA[] = "misra";
+static const char CODING_STANDARD_MISRA_CPP_2008[] = "misra-cpp-2008";
+static const char CODING_STANDARD_CERT_C[] = "cert-c-2016";
+static const char CODING_STANDARD_AUTOSAR[] = "autosar";
+
class QModelIndex;
/** Return paths from QListWidget */
@@ -79,10 +84,11 @@ QStringList ProjectFileDialog::getProjectConfigs(const QString &fileName)
return ret;
}
-ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent)
+ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, bool premium, QWidget *parent)
: QDialog(parent)
, mUI(new Ui::ProjectFile)
, mProjectFile(projectFile)
+ , mPremium(premium)
{
mUI->setupUi(this);
@@ -191,6 +197,9 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent)
platformFiles.sort();
mUI->mComboBoxPlatform->addItems(platformFiles);
+ // integer. allow empty.
+ mUI->mEditCertIntPrecision->setValidator(new QRegularExpressionValidator(QRegularExpression("[0-9]*"),this));
+
mUI->mEditTags->setValidator(new QRegularExpressionValidator(QRegularExpression("[a-zA-Z0-9 ;]*"),this));
const QRegularExpression undefRegExp("\\s*([a-zA-Z_][a-zA-Z0-9_]*[; ]*)*");
@@ -340,15 +349,36 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
const QString dataDir = getDataDir();
updateAddonCheckBox(mUI->mAddonThreadSafety, projectFile, dataDir, "threadsafety");
updateAddonCheckBox(mUI->mAddonY2038, projectFile, dataDir, "y2038");
- updateAddonCheckBox(mUI->mAddonMisra, projectFile, dataDir, "misra");
+ updateAddonCheckBox(mUI->mMisraC2012, projectFile, dataDir, ADDON_MISRA);
const QString &misraFile = settings.value(SETTINGS_MISRA_FILE, QString()).toString();
mUI->mEditMisraFile->setText(misraFile);
- if (!mUI->mAddonMisra->isEnabled()) {
+ if (mPremium) {
+ mUI->mLabelMisraFile->setVisible(false);
+ mUI->mEditMisraFile->setVisible(false);
+ mUI->mBtnBrowseMisraFile->setVisible(false);
+ } else if (!mUI->mMisraC2012->isEnabled()) {
mUI->mEditMisraFile->setEnabled(false);
mUI->mBtnBrowseMisraFile->setEnabled(false);
}
+ mUI->mPremiumCertC->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_CERT_C));
+ mUI->mMisraCpp2008->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_MISRA_CPP_2008));
+ mUI->mAutosar->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_AUTOSAR));
+
+ if (projectFile->getCertIntPrecision() <= 0)
+ mUI->mEditCertIntPrecision->setText(QString());
+ else
+ mUI->mEditCertIntPrecision->setText(QString::number(projectFile->getCertIntPrecision()));
+
+ mUI->mPremiumCertC->setVisible(mPremium);
+ mUI->mMisraCpp2008->setVisible(mPremium);
+ mUI->mAutosar->setVisible(mPremium);
+ mUI->mLabelCertIntPrecision->setVisible(mPremium);
+ mUI->mEditCertIntPrecision->setVisible(mPremium);
+ mUI->mBughunting->setChecked(projectFile->getBughunting());
+ mUI->mGroupboxBughunting->setVisible(mPremium);
+
mUI->mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
mUI->mToolClangTidy->setChecked(projectFile->getClangTidy());
if (CheckThread::clangTidyCmd().isEmpty()) {
@@ -405,14 +435,23 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
projectFile->setSafeChecks(safeChecks);
*/
// Addons
- QStringList list;
+ QStringList addons;
if (mUI->mAddonThreadSafety->isChecked())
- list << "threadsafety";
+ addons << "threadsafety";
if (mUI->mAddonY2038->isChecked())
- list << "y2038";
- if (mUI->mAddonMisra->isChecked())
- list << "misra";
- projectFile->setAddons(list);
+ addons << "y2038";
+ if (mUI->mMisraC2012->isChecked())
+ addons << ADDON_MISRA;
+ projectFile->setAddons(addons);
+ QStringList codingStandards;
+ if (mUI->mPremiumCertC->isChecked())
+ codingStandards << CODING_STANDARD_CERT_C;
+ if (mUI->mMisraCpp2008->isChecked())
+ codingStandards << CODING_STANDARD_MISRA_CPP_2008;
+ if (mUI->mAutosar->isChecked())
+ codingStandards << CODING_STANDARD_AUTOSAR;
+ projectFile->setCodingStandards(codingStandards);
+ projectFile->setCertIntPrecision(mUI->mEditCertIntPrecision->text().toInt());
projectFile->setClangAnalyzer(mUI->mToolClangAnalyzer->isChecked());
projectFile->setClangTidy(mUI->mToolClangTidy->isChecked());
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
@@ -874,8 +913,8 @@ void ProjectFileDialog::browseMisraFile()
mUI->mEditMisraFile->setText(fileName);
settings.setValue(SETTINGS_MISRA_FILE, fileName);
- mUI->mAddonMisra->setText("MISRA C 2012");
- mUI->mAddonMisra->setEnabled(true);
- updateAddonCheckBox(mUI->mAddonMisra, nullptr, getDataDir(), "misra");
+ mUI->mMisraC2012->setText("MISRA C 2012");
+ mUI->mMisraC2012->setEnabled(true);
+ updateAddonCheckBox(mUI->mMisraC2012, nullptr, getDataDir(), ADDON_MISRA);
}
}
diff --git a/gui/projectfiledialog.h b/gui/projectfiledialog.h
index 449d3c661..18c8deece 100644
--- a/gui/projectfiledialog.h
+++ b/gui/projectfiledialog.h
@@ -44,7 +44,7 @@ class ProjectFile;
class ProjectFileDialog : public QDialog {
Q_OBJECT
public:
- explicit ProjectFileDialog(ProjectFile *projectFile, QWidget *parent = nullptr);
+ explicit ProjectFileDialog(ProjectFile *projectFile, bool premium, QWidget *parent = nullptr);
~ProjectFileDialog() override;
private:
@@ -325,6 +325,9 @@ private:
*/
ProjectFile *mProjectFile;
+ /** Is this Cppcheck Premium? */
+ bool mPremium;
+
QString getExistingDirectory(const QString &caption, bool trailingSlash);
QList mSuppressions;
diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp
index 951acb563..949693cfe 100644
--- a/lib/cppcheck.cpp
+++ b/lib/cppcheck.cpp
@@ -89,7 +89,7 @@ namespace {
std::string args; // special extra arguments
std::string python; // script interpreter
bool ctu = false;
- std::string runScript{};
+ std::string runScript;
static std::string getFullPath(const std::string &fileName, const std::string &exename) {
if (Path::fileExists(fileName))
@@ -275,6 +275,7 @@ static void createDumpFile(const Settings& settings,
static std::string executeAddon(const AddonInfo &addonInfo,
const std::string &defaultPythonExe,
const std::string &file,
+ const std::string &premiumArgs,
std::function,std::string,std::string*)> executeCommand)
{
const std::string redirect = "2>&1";
@@ -308,6 +309,8 @@ static std::string executeAddon(const AddonInfo &addonInfo,
if (addonInfo.executable.empty())
args = cmdFileName(addonInfo.runScript) + " " + cmdFileName(addonInfo.scriptFile);
args += std::string(args.empty() ? "" : " ") + "--cli" + addonInfo.args;
+ if (!premiumArgs.empty() && !addonInfo.executable.empty())
+ args += " " + premiumArgs;
const std::string fileArg = (endsWith(file, FILELIST, sizeof(FILELIST)-1) ? " --file-list " : " ") + cmdFileName(file);
args += fileArg;
@@ -1366,7 +1369,7 @@ void CppCheck::executeAddons(const std::vector& files)
continue;
const std::string results =
- executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mExecuteCommand);
+ executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mSettings.premiumArgs, mExecuteCommand);
std::istringstream istr(results);
std::string line;
diff --git a/lib/importproject.h b/lib/importproject.h
index 5dc87b5d2..a6eb37ba5 100644
--- a/lib/importproject.h
+++ b/lib/importproject.h
@@ -178,6 +178,11 @@ namespace CppcheckXml {
const char Name[] = "name";
const char VSConfigurationElementName[] = "vs-configurations";
const char VSConfigurationName[] = "config";
+ // Cppcheck Premium
+ const char BughuntingElementName[] = "bug-hunting";
+ const char CodingStandardsElementName[] = "coding-standards";
+ const char CodingStandardElementName[] = "coding-standard";
+ const char CertIntPrecisionElementName[] = "cert-c-int-precision";
}
/// @}
diff --git a/lib/settings.h b/lib/settings.h
index 51fbb8dd5..ee8cf28f8 100644
--- a/lib/settings.h
+++ b/lib/settings.h
@@ -239,6 +239,9 @@ public:
/** @brief plist output (--plist-output=<dir>) */
std::string plistOutput;
+ /** @brief Extra arguments for Cppcheck Premium addon */
+ std::string premiumArgs;
+
/** @brief Using -E for debugging purposes */
bool preprocessOnly;