diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml
index 1adcc540cf9..389e39371ba 100644
--- a/.github/workflows/selfcheck.yml
+++ b/.github/workflows/selfcheck.yml
@@ -121,7 +121,7 @@ jobs:
- name: Self check (unusedFunction / no test / no gui)
run: |
- supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1660 --suppress=unusedFunction:lib/importproject.cpp:1684"
+ supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1665 --suppress=unusedFunction:lib/importproject.cpp:1689"
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
env:
DISABLE_VALUEFLOW: 1
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index 161eec381b3..c3ca1672768 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -1126,6 +1126,8 @@ bool MainWindow::getCppcheckSettings(Settings& settings, Suppressions& supprs)
for (const QString& undefine : undefines)
settings.userUndefs.insert(undefine.toStdString());
+ settings.userIncludes.push_back(mProjectFile->getUserInclude().toStdString());
+
const QStringList libraries = mProjectFile->getLibraries();
for (const QString& library : libraries) {
settings.libraries.emplace_back(library.toStdString());
diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp
index b807723ceeb..ce2d066fd71 100644
--- a/gui/projectfile.cpp
+++ b/gui/projectfile.cpp
@@ -63,6 +63,7 @@ void ProjectFile::clear()
mIncludeDirs.clear();
mDefines.clear();
mUndefines.clear();
+ mUserInclude.clear();
mPaths.clear();
mExcludedPaths.clear();
mLibraries.clear();
@@ -166,6 +167,9 @@ bool ProjectFile::read(const QString &filename)
if (xmlReader.name() == QString(CppcheckXml::UndefinesElementName))
readStringList(mUndefines, xmlReader, CppcheckXml::UndefineName);
+ if (xmlReader.name() == QString(CppcheckXml::UserIncludeElementName))
+ mUserInclude = readString(xmlReader);
+
// Find exclude list from inside project element
if (xmlReader.name() == QString(CppcheckXml::ExcludeElementName))
readExcludes(xmlReader);
@@ -347,15 +351,13 @@ bool ProjectFile::readBool(QXmlStreamReader &reader)
int ProjectFile::readInt(QXmlStreamReader &reader, int defaultValue)
{
- int ret = defaultValue;
do {
const QXmlStreamReader::TokenType type = reader.readNext();
switch (type) {
case QXmlStreamReader::Characters:
- ret = reader.text().toString().toInt();
- FALLTHROUGH;
+ return reader.text().toString().toInt();
case QXmlStreamReader::EndElement:
- return ret;
+ return defaultValue;
// Not handled
case QXmlStreamReader::StartElement:
case QXmlStreamReader::NoToken:
@@ -373,15 +375,13 @@ int ProjectFile::readInt(QXmlStreamReader &reader, int defaultValue)
QString ProjectFile::readString(QXmlStreamReader &reader)
{
- QString ret;
do {
const QXmlStreamReader::TokenType type = reader.readNext();
switch (type) {
case QXmlStreamReader::Characters:
- ret = reader.text().toString();
- FALLTHROUGH;
+ return reader.text().toString();
case QXmlStreamReader::EndElement:
- return ret;
+ return {};
// Not handled
case QXmlStreamReader::StartElement:
case QXmlStreamReader::NoToken:
@@ -910,6 +910,12 @@ bool ProjectFile::write(const QString &filename)
xmlWriter.writeEndElement();
}
+ if (!mUserInclude.isEmpty()) {
+ xmlWriter.writeStartElement(CppcheckXml::UserIncludeElementName);
+ xmlWriter.writeCharacters(mUserInclude);
+ xmlWriter.writeEndElement();
+ }
+
if (!mVsConfigurations.isEmpty()) {
writeStringList(xmlWriter,
mVsConfigurations,
diff --git a/gui/projectfile.h b/gui/projectfile.h
index e7f8d342180..f46374b74fa 100644
--- a/gui/projectfile.h
+++ b/gui/projectfile.h
@@ -141,6 +141,14 @@ class ProjectFile : public QObject {
return mUndefines;
}
+ const QString& getUserInclude() const {
+ return mUserInclude;
+ }
+
+ void setUserInclude(const QString& userInclude) {
+ mUserInclude = userInclude;
+ }
+
/**
* @brief Get list of paths to check.
* @return list of paths.
@@ -601,6 +609,9 @@ class ProjectFile : public QObject {
*/
QStringList mUndefines;
+ /** @brief --include file */
+ QString mUserInclude;
+
/**
* @brief List of paths to check.
*/
diff --git a/gui/projectfile.ui b/gui/projectfile.ui
index 4bd01339d83..5543e67910c 100644
--- a/gui/projectfile.ui
+++ b/gui/projectfile.ui
@@ -7,7 +7,7 @@
0
0
940
- 701
+ 741
@@ -80,7 +80,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -95,7 +95,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -117,7 +117,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -151,7 +151,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -199,7 +199,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -269,7 +269,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -284,7 +284,7 @@
-
- QAbstractItemView::SelectRows
+ QAbstractItemView::SelectionBehavior::SelectRows
@@ -314,7 +314,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -342,10 +342,38 @@
+ -
+
+
-
+
+
+ Include file
+
+
+ mEditUserInclude
+
+
+
+ -
+
+
+ <html><head/><body><p><span style=" font-family:'monospace'; color:#000000; background-color:#ffffff;">Force inclusion of a header file</span></p></body></html>
+
+
+
+ -
+
+
+ Browse..
+
+
+
+
+
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -552,7 +580,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -586,7 +614,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -701,7 +729,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -744,7 +772,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -769,7 +797,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -856,7 +884,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -919,7 +947,7 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
@@ -1018,7 +1046,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -1035,10 +1063,10 @@
-
- Qt::Horizontal
+ Qt::Orientation::Horizontal
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+ QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok
diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp
index d46eb5c3489..82fc0aac7c4 100644
--- a/gui/projectfiledialog.cpp
+++ b/gui/projectfiledialog.cpp
@@ -235,6 +235,7 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, bool premium, QWi
connect(mUI->mBtnBrowseBuildDir, &QPushButton::clicked, this, &ProjectFileDialog::browseBuildDir);
connect(mUI->mBtnClearImportProject, &QPushButton::clicked, this, &ProjectFileDialog::clearImportProject);
connect(mUI->mBtnBrowseImportProject, &QPushButton::clicked, this, &ProjectFileDialog::browseImportProject);
+ connect(mUI->mBtnBrowseUserInclude, &QPushButton::clicked, this, &ProjectFileDialog::browseUserInclude);
connect(mUI->mBtnAddCheckPath, SIGNAL(clicked()), this, SLOT(addCheckPath()));
connect(mUI->mBtnEditCheckPath, &QPushButton::clicked, this, &ProjectFileDialog::editCheckPath);
connect(mUI->mBtnRemoveCheckPath, &QPushButton::clicked, this, &ProjectFileDialog::removeCheckPath);
@@ -303,6 +304,7 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
setIncludepaths(projectFile->getIncludeDirs());
setDefines(projectFile->getDefines());
setUndefines(projectFile->getUndefines());
+ mUI->mEditUserInclude->setText(projectFile->getUserInclude());
setCheckPaths(projectFile->getCheckPaths());
setImportProject(projectFile->getImportProject());
mUI->mChkAllVsConfigs->setChecked(projectFile->getAnalyzeAllVsConfigs());
@@ -481,6 +483,7 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
projectFile->setIncludes(getIncludePaths());
projectFile->setDefines(getDefines());
projectFile->setUndefines(getUndefines());
+ projectFile->setUserInclude(mUI->mEditUserInclude->text());
projectFile->setCheckPaths(getCheckPaths());
projectFile->setExcludedPaths(getExcludedPaths());
projectFile->setLibraries(getLibraries());
@@ -643,6 +646,21 @@ void ProjectFileDialog::browseImportProject()
}
}
+void ProjectFileDialog::browseUserInclude()
+{
+ const QFileInfo inf(mProjectFile->getFilename());
+ const QDir &dir = inf.absoluteDir();
+ QMap filters;
+ filters[tr("C/C++ header")] = "*.h";
+ filters[tr("All files")] = "*.*";
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Include file"),
+ dir.canonicalPath(),
+ toFilterString(filters));
+ if (!fileName.isEmpty()) {
+ mUI->mEditUserInclude->setText(dir.relativeFilePath(fileName));
+ }
+}
+
QStringList ProjectFileDialog::getProjectConfigurations() const
{
QStringList configs;
diff --git a/gui/projectfiledialog.h b/gui/projectfiledialog.h
index 68f62ea83e5..231d1f26ef3 100644
--- a/gui/projectfiledialog.h
+++ b/gui/projectfiledialog.h
@@ -201,6 +201,11 @@ private slots:
*/
void browseImportProject();
+ /**
+ * @brief Browse for include file
+ */
+ void browseUserInclude();
+
/**
* @brief Add new path to check.
*/
diff --git a/lib/importproject.cpp b/lib/importproject.cpp
index 401f1334b81..ac19db922ed 100644
--- a/lib/importproject.cpp
+++ b/lib/importproject.cpp
@@ -1484,6 +1484,10 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
else if (strcmp(name, CppcheckXml::UndefinesElementName) == 0) {
for (const std::string &u : readXmlStringList(node, "", CppcheckXml::UndefineName, nullptr))
temp.userUndefs.insert(u);
+ } else if (strcmp(name, CppcheckXml::UserIncludeElementName) == 0) {
+ const char* i = node->GetText();
+ if (i)
+ temp.userIncludes.emplace_back(i);
} else if (strcmp(name, CppcheckXml::ImportProjectElementName) == 0) {
const std::string t_str = empty_if_null(node->GetText());
if (!t_str.empty())
@@ -1605,6 +1609,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
settings.includePaths = temp.includePaths; // TODO: append instead of overwrite
settings.userDefines = temp.userDefines; // TODO: append instead of overwrite
settings.userUndefs = temp.userUndefs; // TODO: append instead of overwrite
+ settings.userIncludes = temp.userIncludes; // TODO: append instead of overwrite
for (const std::string &addon : temp.addons)
settings.addons.emplace(addon);
settings.clang = temp.clang;
diff --git a/lib/importproject.h b/lib/importproject.h
index 4a6e318c02d..fb724b5b454 100644
--- a/lib/importproject.h
+++ b/lib/importproject.h
@@ -151,6 +151,7 @@ namespace CppcheckXml {
static constexpr char DefineNameAttrib[] = "name";
static constexpr char UndefinesElementName[] = "undefines";
static constexpr char UndefineName[] = "undefine";
+ static constexpr char UserIncludeElementName[] = "user-include";
static constexpr char PathsElementName[] = "paths";
static constexpr char PathName[] = "dir";
static constexpr char PathNameAttrib[] = "name";
diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp
index f7c53f3d3a6..6f8633dbeea 100644
--- a/test/testimportproject.cpp
+++ b/test/testimportproject.cpp
@@ -482,6 +482,7 @@ class TestImportProject : public TestFixture {
" \n"
" \n"
" \n"
+ " gcc-macros.h\n"
" \n"
" \n"
" \n"
@@ -497,6 +498,8 @@ class TestImportProject : public TestFixture {
ASSERT_EQUALS("cli/", project.guiProject.pathNames[0]);
ASSERT_EQUALS(1, s.includePaths.size());
ASSERT_EQUALS("lib/", s.includePaths.front());
+ ASSERT_EQUALS(1, s.userIncludes.size());
+ ASSERT_EQUALS("gcc-macros.h", s.userIncludes.front());
ASSERT_EQUALS(true, s.inlineSuppressions);
}