diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 4674c550c..dda75d80f 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -158,16 +158,6 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strcmp(argv[i], "--dump") == 0) mSettings->dump = true; - // TODO: These options are about removing code. Instead of having lots of different options - // can we create one option that is customizable somehow. - // --check-headers=no - else if (std::strcmp(argv[i], "--check-headers=no") == 0) - mSettings->checkHeaders = false; - else if (std::strcmp(argv[i], "--remove-unused-templates") == 0) - mSettings->removeUnusedTemplates = true; - else if (std::strcmp(argv[i], "--remove-unused-included-templates") == 0) - mSettings->removeUnusedIncludedTemplates = true; - // max ctu depth else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0) mSettings->maxCtuDepth = std::atoi(argv[i] + 16); @@ -931,8 +921,6 @@ void CmdLineParser::printHelp() " incremental analysis, distributed analysis.\n" " --check-config Check cppcheck configuration. The normal code\n" " analysis is disabled by this flag.\n" - " --check-headers=no Turn off checking of included files, to make the\n" - " analysis faster.\n" " --check-library Show information messages when library files have\n" " incomplete info.\n" " --config-exclude=\n" @@ -1088,10 +1076,6 @@ void CmdLineParser::printHelp() " using e.g. ~ for home folder does not work. It is\n" " currently only possible to apply the base paths to\n" " files that are on a lower level in the directory tree.\n" - " --remove-unused-templates\n" - " Remove unused templates.\n" - " --remove-unused-included-templates\n" - " Remove unused templates in included files.\n" " --report-progress Report progress messages while checking a file.\n" #ifdef HAVE_RULES " --rule= Match regular expression.\n" diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index c03da51fc..cab500312 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -892,6 +892,10 @@ Settings MainWindow::getCppcheckSettings() } } } + + result.maxCtuDepth = mProjectFile->getMaxCtuDepth(); + result.checkHeaders = mProjectFile->getCheckHeaders(); + result.checkUnusedTemplates = mProjectFile->getCheckUnusedTemplates(); } // Include directories (and files) are searched in listed order. diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index 922001bf7..025f5c2a9 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -61,6 +61,9 @@ static const char ToolElementName[] = "tool"; static const char ToolsElementName[] = "tools"; static const char TagsElementName[] = "tags"; static const char TagElementName[] = "tag"; +static constexpr char CheckHeadersElementName[] = "check-headers"; +static constexpr char CheckUnusedTemplatesElementName[] = "check-unused-templates"; +static constexpr char MaxCtuDepthElementName[] = "max-ctu-depth"; ProjectFile::ProjectFile(QObject *parent) : QObject(parent) @@ -92,6 +95,10 @@ void ProjectFile::clear() mSuppressions.clear(); mAddons.clear(); mClangAnalyzer = mClangTidy = false; + mAnalyzeAllVsConfigs = false; + mCheckHeaders = true; + mCheckUnusedTemplates = false; + mMaxCtuDepth = 10; } bool ProjectFile::read(const QString &filename) @@ -131,7 +138,13 @@ bool ProjectFile::read(const QString &filename) readImportProject(xmlReader); if (insideProject && xmlReader.name() == AnalyzeAllVsConfigsElementName) - readAnalyzeAllVsConfigs(xmlReader); + mAnalyzeAllVsConfigs = readBool(xmlReader); + + if (insideProject && xmlReader.name() == CheckHeadersElementName) + mCheckHeaders = readBool(xmlReader); + + if (insideProject && xmlReader.name() == CheckUnusedTemplatesElementName) + mCheckUnusedTemplates = readBool(xmlReader); // Find include directory from inside project element if (insideProject && xmlReader.name() == IncludeDirElementName) @@ -180,6 +193,9 @@ bool ProjectFile::read(const QString &filename) if (insideProject && xmlReader.name() == TagsElementName) readStringList(mTags, xmlReader, TagElementName); + if (insideProject && xmlReader.name() == MaxCtuDepthElementName) + mMaxCtuDepth = readInt(xmlReader, mMaxCtuDepth); + break; case QXmlStreamReader::EndElement: @@ -263,15 +279,41 @@ void ProjectFile::readImportProject(QXmlStreamReader &reader) } while (1); } -void ProjectFile::readAnalyzeAllVsConfigs(QXmlStreamReader &reader) +bool ProjectFile::readBool(QXmlStreamReader &reader) { + bool ret = false; do { const QXmlStreamReader::TokenType type = reader.readNext(); switch (type) { case QXmlStreamReader::Characters: - mAnalyzeAllVsConfigs = (reader.text().toString() == "true"); + ret = (reader.text().toString() == "true"); case QXmlStreamReader::EndElement: - return; + return ret; + // 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); +} + +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(); + case QXmlStreamReader::EndElement: + return ret; // Not handled case QXmlStreamReader::StartElement: case QXmlStreamReader::NoToken: @@ -642,6 +684,18 @@ bool ProjectFile::write(const QString &filename) xmlWriter.writeCharacters(mAnalyzeAllVsConfigs ? "true" : "false"); xmlWriter.writeEndElement(); + xmlWriter.writeStartElement(CheckHeadersElementName); + xmlWriter.writeCharacters(mCheckHeaders ? "true" : "false"); + xmlWriter.writeEndElement(); + + xmlWriter.writeStartElement(CheckUnusedTemplatesElementName); + xmlWriter.writeCharacters(mCheckUnusedTemplates ? "true" : "false"); + xmlWriter.writeEndElement(); + + xmlWriter.writeStartElement(MaxCtuDepthElementName); + xmlWriter.writeCharacters(QString::number(mMaxCtuDepth)); + xmlWriter.writeEndElement(); + if (!mIncludeDirs.isEmpty()) { xmlWriter.writeStartElement(IncludeDirElementName); foreach (QString incdir, mIncludeDirs) { diff --git a/gui/projectfile.h b/gui/projectfile.h index a08cd81a5..def99eaee 100644 --- a/gui/projectfile.h +++ b/gui/projectfile.h @@ -68,6 +68,22 @@ public: return mAnalyzeAllVsConfigs; } + bool getCheckHeaders() const { + return mCheckHeaders; + } + + void setCheckHeaders(bool b) { + mCheckHeaders = b; + } + + bool getCheckUnusedTemplates() const { + return mCheckUnusedTemplates; + } + + void setCheckUnusedTemplates(bool b) { + mCheckUnusedTemplates = b; + } + /** * @brief Get list of include directories. * @return list of directories. @@ -166,6 +182,14 @@ public: return mTags; } + int getMaxCtuDepth() const { + return mMaxCtuDepth; + } + + void setMaxCtuDepth(int maxCtuDepth) { + mMaxCtuDepth = maxCtuDepth; + } + /** * @brief Get filename for the project file. * @return file name. @@ -286,7 +310,9 @@ protected: */ void readImportProject(QXmlStreamReader &reader); - void readAnalyzeAllVsConfigs(QXmlStreamReader &reader); + bool readBool(QXmlStreamReader &reader); + + int readInt(QXmlStreamReader &reader, int defaultValue); /** * @brief Read list of include directories from XML. @@ -376,6 +402,12 @@ private: */ bool mAnalyzeAllVsConfigs; + /** Check code in headers */ + bool mCheckHeaders; + + /** Check code in unused templates */ + bool mCheckUnusedTemplates; + /** * @brief List of include directories used to search include files. */ @@ -431,6 +463,9 @@ private: * @brief Warning tags */ QStringList mTags; + + /** Max CTU depth */ + int mMaxCtuDepth; }; /// @} #endif // PROJECT_FILE_H diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index 059c0adcd..00dcf7034 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -240,6 +240,9 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) setCheckPaths(projectFile->getCheckPaths()); setImportProject(projectFile->getImportProject()); mUI.mChkAllVsConfigs->setChecked(projectFile->getAnalyzeAllVsConfigs()); + mUI.mCheckHeaders->setChecked(projectFile->getCheckHeaders()); + mUI.mCheckUnusedTemplates->setChecked(projectFile->getCheckUnusedTemplates()); + mUI.mMaxCtuDepth->setValue(projectFile->getMaxCtuDepth()); setExcludedPaths(projectFile->getExcludedPaths()); setLibraries(projectFile->getLibraries()); const QString platform = projectFile->getPlatform(); @@ -304,6 +307,9 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const projectFile->setBuildDir(getBuildDir()); projectFile->setImportProject(getImportProject()); projectFile->setAnalyzeAllVsConfigs(mUI.mChkAllVsConfigs->isChecked()); + projectFile->setCheckHeaders(mUI.mCheckHeaders->isChecked()); + projectFile->setCheckUnusedTemplates(mUI.mCheckUnusedTemplates->isChecked()); + projectFile->setMaxCtuDepth(mUI.mMaxCtuDepth->value()); projectFile->setIncludes(getIncludePaths()); projectFile->setDefines(getDefines()); projectFile->setUndefines(getUndefines()); diff --git a/gui/projectfiledialog.ui b/gui/projectfiledialog.ui index 31e515a35..7e9373ef4 100644 --- a/gui/projectfiledialog.ui +++ b/gui/projectfiledialog.ui @@ -325,6 +325,59 @@ + + + + Analysis + + + + + + Check code in headers (slower analysis, more results) + + + true + + + + + + + Check code in unused templates (slower and less accurate analysis) + + + + + + + + + Max CTU depth + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/lib/settings.cpp b/lib/settings.cpp index 1845f29ce..2a9fb7def 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -51,8 +51,7 @@ Settings::Settings() checkConfiguration(false), checkLibrary(false), checkHeaders(true), - removeUnusedTemplates(false), - removeUnusedIncludedTemplates(false) + checkUnusedTemplates(false) { } diff --git a/lib/settings.h b/lib/settings.h index 429c765ad..d2ffb6031 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -290,11 +290,8 @@ public: * be turned off to save CPU */ bool checkHeaders; - /** Remove unused templates in all files */ - bool removeUnusedTemplates; - - /** Remove unused included templates */ - bool removeUnusedIncludedTemplates; + /** Check unused templates */ + bool checkUnusedTemplates; /** Struct contains standards settings */ Standards standards; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 21d56968e..49b55c965 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4767,15 +4767,15 @@ void Tokenizer::simplifyHeaders() // TODO : can we remove anything in headers here? Like unused declarations. // Maybe if --dump is used we want to have _everything_. - if (mSettings->checkHeaders && !mSettings->removeUnusedTemplates && !mSettings->removeUnusedIncludedTemplates) + if (mSettings->checkHeaders && mSettings->checkUnusedTemplates) // Default=full analysis. All information in the headers are kept. return; const bool checkHeaders = mSettings->checkHeaders; - const bool removeUnusedIncludedFunctions = mSettings->checkHeaders; - const bool removeUnusedIncludedClasses = mSettings->checkHeaders; - const bool removeUnusedTemplates = mSettings->removeUnusedTemplates; - const bool removeUnusedIncludedTemplates = mSettings->checkHeaders || mSettings->removeUnusedIncludedTemplates; + const bool removeUnusedIncludedFunctions = !mSettings->checkHeaders; + const bool removeUnusedIncludedClasses = !mSettings->checkHeaders; + const bool removeUnusedIncludedTemplates = !mSettings->checkUnusedTemplates || !mSettings->checkHeaders; + const bool removeUnusedTemplates = !mSettings->checkUnusedTemplates; // We want to remove selected stuff from the headers but not *everything*. // The intention here is to not damage the analysis of the source file.