diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 7d7b48b2b..03e407fa4 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -850,6 +850,21 @@ Settings MainWindow::getCppcheckSettings() result.buildDir = (prjpath + '/' + buildDir).toStdString(); } } + + const QString platform = mProjectFile->getPlatform(); + if (platform.endsWith(".xml")) { + const QString applicationFilePath = QCoreApplication::applicationFilePath(); + const QString appPath = QFileInfo(applicationFilePath).canonicalPath(); + result.loadPlatformFile(appPath.toStdString().c_str(), platform.toStdString()); + } else { + for (int i = cppcheck::Platform::Native; i <= cppcheck::Platform::Unix64; i++) { + const cppcheck::Platform::PlatformType p = (cppcheck::Platform::PlatformType)i; + if (platform == cppcheck::Platform::platformString(p)) { + result.platform(p); + break; + } + } + } } // Include directories (and files) are searched in listed order. @@ -878,7 +893,8 @@ Settings MainWindow::getCppcheckSettings() result.jobs = mSettings->value(SETTINGS_CHECK_THREADS, 1).toInt(); result.inlineSuppressions = mSettings->value(SETTINGS_INLINE_SUPPRESSIONS, false).toBool(); result.inconclusive = mSettings->value(SETTINGS_INCONCLUSIVE_ERRORS, false).toBool(); - result.platformType = (Settings::PlatformType) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt(); + if (result.platformType == cppcheck::Platform::Unspecified) + result.platform((cppcheck::Platform::PlatformType) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt()); if (mSettings->value(SETTINGS_STD_CPP03, false).toBool()) result.standards.cpp = Standards::CPP03; else if (mSettings->value(SETTINGS_STD_CPP11, false).toBool()) @@ -894,7 +910,7 @@ Settings MainWindow::getCppcheckSettings() if (result.standards.posix) posix = tryLoadLibrary(&result.library, "posix.cfg"); bool windows = true; - if (result.platformType == Settings::Win32A || result.platformType == Settings::Win32W || result.platformType == Settings::Win64) + if (result.isWindowsPlatform()) windows = tryLoadLibrary(&result.library, "windows.cfg"); if (!std || !posix || !windows) diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index e90ddc6ac..ff0ed502e 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -50,6 +50,7 @@ static const char ExcludePathName[] = "path"; static const char ExcludePathNameAttrib[] = "name"; static const char LibrariesElementName[] = "libraries"; static const char LibraryElementName[] = "library"; +static const char PlatformElementName[] = "platform"; static const char SuppressionsElementName[] = "suppressions"; static const char SuppressionElementName[] = "suppression"; static const char AddonElementName[] = "addon"; @@ -84,6 +85,7 @@ void ProjectFile::clear() mPaths.clear(); mExcludedPaths.clear(); mLibraries.clear(); + mPlatform.clear(); mSuppressions.clear(); mAddons.clear(); mClangAnalyzer = mClangTidy = false; @@ -149,6 +151,9 @@ bool ProjectFile::read(const QString &filename) if (insideProject && xmlReader.name() == LibrariesElementName) readStringList(mLibraries, xmlReader,LibraryElementName); + if (insideProject && xmlReader.name() == PlatformElementName) + readPlatform(xmlReader); + // Find suppressions list from inside project element if (insideProject && xmlReader.name() == SuppressionsElementName) readStringList(mSuppressions, xmlReader,SuppressionElementName); @@ -434,6 +439,30 @@ void ProjectFile::readExcludes(QXmlStreamReader &reader) } while (!allRead); } +void ProjectFile::readPlatform(QXmlStreamReader &reader) +{ + do { + const QXmlStreamReader::TokenType type = reader.readNext(); + switch (type) { + case QXmlStreamReader::Characters: + mPlatform = reader.text().toString(); + case QXmlStreamReader::EndElement: + return; + // Not handled + case QXmlStreamReader::StartElement: + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::EndDocument: + case QXmlStreamReader::Comment: + case QXmlStreamReader::DTD: + case QXmlStreamReader::EntityReference: + case QXmlStreamReader::ProcessingInstruction: + break; + } + } while (1); +} + void ProjectFile::readStringList(QStringList &stringlist, QXmlStreamReader &reader, const char elementname[]) { @@ -498,6 +527,11 @@ void ProjectFile::setLibraries(const QStringList &libraries) mLibraries = libraries; } +void ProjectFile::setPlatform(const QString &platform) +{ + mPlatform = platform; +} + void ProjectFile::setSuppressions(const QStringList &suppressions) { mSuppressions = suppressions; @@ -535,6 +569,12 @@ bool ProjectFile::write(const QString &filename) xmlWriter.writeEndElement(); } + if (!mPlatform.isEmpty()) { + xmlWriter.writeStartElement(PlatformElementName); + xmlWriter.writeCharacters(mPlatform); + xmlWriter.writeEndElement(); + } + if (!mImportProject.isEmpty()) { xmlWriter.writeStartElement(ImportProjectElementName); xmlWriter.writeCharacters(mImportProject); diff --git a/gui/projectfile.h b/gui/projectfile.h index d0ae7aa5b..9bce66bc8 100644 --- a/gui/projectfile.h +++ b/gui/projectfile.h @@ -106,6 +106,14 @@ public: return mLibraries; } + /** + * @brief Get platform. + * @return Current platform. If it ends with .xml then it is a file. Otherwise it must match one of the return values from @sa cppcheck::Platform::platformString() ("win32A", "unix32", ..) + */ + QString getPlatform() const { + return mPlatform; + } + /** * @brief Get list suppressions. * @return list of suppressions. @@ -206,6 +214,12 @@ public: */ void setLibraries(const QStringList &libraries); + /** + * @brief Set platform. + * @param platform platform. + */ + void setPlatform(const QString &platform); + /** * @brief Set list of suppressions. * @param suppressions List of suppressions. @@ -282,6 +296,12 @@ protected: */ void readExcludes(QXmlStreamReader &reader); + /** + * @brief Read platform text. + * @param reader XML stream reader. + */ + void readPlatform(QXmlStreamReader &reader); + /** * @brief Read string list * @param stringlist destination string list @@ -359,6 +379,11 @@ private: */ QStringList mLibraries; + /** + * @brief Platform + */ + QString mPlatform; + /** * @brief List of suppressions. */ diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index b990f8af6..23c9da4da 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -33,6 +33,19 @@ #include "library.h" #include "cppcheck.h" #include "errorlogger.h" +#include "platforms.h" + +/** Platforms shown in the platform combobox */ +static const cppcheck::Platform::PlatformType builtinPlatforms[] = { + cppcheck::Platform::Native, + cppcheck::Platform::Win32A, + cppcheck::Platform::Win32W, + cppcheck::Platform::Win64, + cppcheck::Platform::Unix32, + cppcheck::Platform::Unix64 +}; + +static const int numberOfBuiltinPlatforms = sizeof(builtinPlatforms) / sizeof(builtinPlatforms[0]); ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent) : QDialog(parent) @@ -94,6 +107,32 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent) mLibraryCheckboxes << checkbox; } + // Platforms.. + Platforms p; + for (int i = 0; i < numberOfBuiltinPlatforms; i++) + mUI.mComboBoxPlatform->addItem(p.get(builtinPlatforms[i]).mTitle); + QStringList platformFiles; + foreach (QString sp, searchPaths) { + if (sp.endsWith("/cfg")) + sp = sp.mid(0,sp.length()-3) + "platforms"; + QDir dir(sp); + dir.setSorting(QDir::Name); + dir.setNameFilters(QStringList("*.xml")); + dir.setFilter(QDir::Files | QDir::NoDotAndDotDot); + foreach (QFileInfo item, dir.entryInfoList()) { + const QString platformFile = item.fileName(); + + cppcheck::Platform p; + if (!p.loadPlatformFile(appPath.toStdString().c_str(), platformFile.toStdString())) + continue; + + if (platformFiles.indexOf(platformFile) == -1) + platformFiles << platformFile; + } + } + qSort(platformFiles); + mUI.mComboBoxPlatform->addItems(platformFiles); + mUI.mEditTags->setValidator(new QRegExpValidator(QRegExp("[a-zA-Z0-9 ;]*"),this)); connect(mUI.mButtons, &QDialogButtonBox::accepted, this, &ProjectFileDialog::ok); @@ -156,6 +195,33 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) mUI.mChkAllVsConfigs->setChecked(projectFile->getAnalyzeAllVsConfigs()); setExcludedPaths(projectFile->getExcludedPaths()); setLibraries(projectFile->getLibraries()); + const QString platform = projectFile->getPlatform(); + if (platform.endsWith(".xml")) { + int i; + for (i = numberOfBuiltinPlatforms; i < mUI.mComboBoxPlatform->count(); ++i) { + if (mUI.mComboBoxPlatform->itemText(i) == platform) + break; + } + if (i < mUI.mComboBoxPlatform->count()) + mUI.mComboBoxPlatform->setCurrentIndex(i); + else { + mUI.mComboBoxPlatform->addItem(platform); + mUI.mComboBoxPlatform->setCurrentIndex(i); + } + } else { + int i; + for (i = 0; i < numberOfBuiltinPlatforms; ++i) { + const cppcheck::Platform::PlatformType p = builtinPlatforms[i]; + if (platform == cppcheck::Platform::platformString(p)) + break; + } + if (i < numberOfBuiltinPlatforms) + mUI.mComboBoxPlatform->setCurrentIndex(i); + else + mUI.mComboBoxPlatform->setCurrentIndex(-1); + } + + mUI.mComboBoxPlatform->setCurrentText(projectFile->getPlatform()); setSuppressions(projectFile->getSuppressions()); QSettings settings; @@ -193,6 +259,15 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const projectFile->setCheckPaths(getCheckPaths()); projectFile->setExcludedPaths(getExcludedPaths()); projectFile->setLibraries(getLibraries()); + if (mUI.mComboBoxPlatform->currentText().endsWith(".xml")) + projectFile->setPlatform(mUI.mComboBoxPlatform->currentText()); + else { + int i = mUI.mComboBoxPlatform->currentIndex(); + if (i < numberOfBuiltinPlatforms) + projectFile->setPlatform(cppcheck::Platform::platformString(builtinPlatforms[i])); + else + projectFile->setPlatform(QString()); + } projectFile->setSuppressions(getSuppressions()); QStringList list; if (mUI.mAddonThreadSafety->isChecked()) diff --git a/gui/projectfiledialog.ui b/gui/projectfiledialog.ui index 406adb48c..a84ca9a16 100644 --- a/gui/projectfiledialog.ui +++ b/gui/projectfiledialog.ui @@ -268,35 +268,11 @@ - + - Project + Checking - - - - - Root path: - - - - - - - - - - - - Warning tags (separated by semicolon) - - - - - - - - + @@ -316,6 +292,18 @@ + + + + Platform + + + + + + + + @@ -338,6 +326,143 @@ + + + + Qt::Vertical + + + + 20 + 96 + + + + + + + + + Warning options + + + + + + Root path: + + + + + + + + + + + + Warning tags (separated by semicolon) + + + + + + + + + + + + Exclude paths + + + + + + + + + + + Add... + + + + + + + Edit + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Suppressions + + + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + @@ -353,151 +478,76 @@ - + - Exclude - - - - - - Paths: - - - - - - - - - - - - - - Add... - - - - - - - Edit - - - - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - Suppressions - - - - - - Suppression list: - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Add - - - - - - - Remove - - - - - - - - - - Addons + Addons and tools - - - Y2038 + + + Addons + + + + + Y2038 + + + + + + + Thread safety + + + + + + + Coding standards + + + + + + + Cert + + + + + + + MISRA C 2012 + + + + - - - Thread safety - - - - - - - Coding standards - - - - - - - Cert - - - - - - - MISRA C 2012 + + + External tools + + + + + Clang-tidy + + + + + + + Clang analyzer + + + + @@ -515,47 +565,6 @@ - - - Extra Tools - - - - - - It is common best practice to use several tools. - - - - - - - Clang analyzer - - - - - - - Clang-tidy - - - - - - - Qt::Vertical - - - - 20 - 310 - - - - - - @@ -572,10 +581,6 @@ mButtons - mListExcludedPaths - mBtnAddIgnorePath - mBtnEditIgnorePath - mBtnRemoveIgnorePath diff --git a/lib/platform.h b/lib/platform.h index 4970f5f58..ddb63bffd 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -122,7 +122,11 @@ namespace cppcheck { } const char *platformString() const { - switch (platformType) { + return platformString(platformType); + } + + static const char *platformString(PlatformType pt) { + switch (pt) { case Unspecified: return "Unspecified"; case Native: