diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index fecc6b6821c..f97e2880686 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1017,6 +1017,20 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } } + if (!mSettings.severity.isEnabled(Severity::style)) { + std::string std; + if (mSettings.premiumArgs.find("misra") != std::string::npos || mSettings.addons.count("misra")) + std = "misra"; + else if (mSettings.premiumArgs.find("autosar") != std::string::npos) + std = "autosar"; + else if (mSettings.premiumArgs.find("cert") != std::string::npos) + std = "cert"; + if (!std.empty()) { + printError("When " + std + " is used, you must enable style messages: --enable=style"); + return false; + } + } + mSettings.loadCppcheckCfg(); // Default template format.. diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 8f640c06e13..25f1c5a11ce 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -67,6 +67,18 @@ #include #endif +static const std::set criticalErrors{ + "cppcheckError", + "cppcheckLimit", + "internalAstError", + "instantiationError", + "internalError", + "preprocessorErrorDirective", + "syntaxError", + "unknownMacro" +}; + + class XMLErrorMessagesLogger : public ErrorLogger { void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override @@ -296,6 +308,7 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) AnalyzerInformation::writeFilesTxt(settings.buildDir, fileNames, settings.userDefines, settings.project.fileSettings); } + std::set criticalErrors; unsigned int returnValue = 0; if (settings.useSingleJob()) { // Single process @@ -326,6 +339,17 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) reportErr(ErrorMessage::getXMLFooter()); } + if (!mCriticalErrors.empty()) { + std::string err; + for (const std::string& id: mCriticalErrors) + err += "," + id; + reportOut("Checking was not successful. Checking was aborted because of critical errors (" + err.substr(1) + ").", Color::FgRed); + } + + if (settings.terminated()) { + reportOut("Checking was not successful. Checking was stopped.", Color::FgRed); + } + if (returnValue) return settings.exitCode; return 0; @@ -428,6 +452,9 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg) { assert(mSettings != nullptr); + if (criticalErrors.count(msg.id)) + mCriticalErrors.insert(msg.id); + // Alert only about unique errors if (!mShownErrors.insert(msg.toString(mSettings->verbose)).second) return; diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index e5577396d75..20c8991894c 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -163,6 +163,11 @@ class CppCheckExecutor : public ErrorLogger { */ std::set mShownErrors; + /** + * @brief Critical errors that has been reported. + */ + std::set mCriticalErrors; + /** * Filename associated with size of file */ diff --git a/gui/compliancereportdialog.cpp b/gui/compliancereportdialog.cpp index 10ab0b424de..57fbbba269d 100644 --- a/gui/compliancereportdialog.cpp +++ b/gui/compliancereportdialog.cpp @@ -191,13 +191,7 @@ void ComplianceReportDialog::save() "--project-version=" + projectVersion, "--output-file=" + outFile}; - if (std.startsWith("misra-c-")) { - args << "--misra-c" - << "--compliant=misra-c2012-1.1" - << "--compliant=misra-c2012-1.2"; - } else { - args << ("--" + std); - } + args << ("--" + std); if (files) args << "--files=" + tempFiles.fileName(); diff --git a/gui/compliancereportdialog.ui b/gui/compliancereportdialog.ui index b65ef626eed..b756ec7eab5 100644 --- a/gui/compliancereportdialog.ui +++ b/gui/compliancereportdialog.ui @@ -47,7 +47,7 @@ - Misra C 2023 + Misra C diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index aa377098b7a..f12b6937a34 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -1020,11 +1020,10 @@ Settings MainWindow::getCppcheckSettings() 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()) { + for (const QString& c: mProjectFile->getCodingStandards()) premiumArgs += " --" + c; - } + if (!premiumArgs.contains("misra") && mProjectFile->getAddons().contains("misra")) + premiumArgs += " --misra-c-2012"; result.premiumArgs = premiumArgs.mid(1).toStdString(); } } @@ -1495,16 +1494,24 @@ void MainWindow::save() void MainWindow::complianceReport() { - if (isCppcheckPremium() && mProjectFile && mProjectFile->getAddons().contains("misra")) { - QTemporaryFile tempResults; - tempResults.open(); - tempResults.close(); + if (!mUI->mResults->isSuccess()) { + QMessageBox m(QMessageBox::Critical, + tr("Cppcheck"), + tr("Cannot generate a compliance report right now, an analysis must finish successfully. Try to reanalyze the code and ensure there are no critical errors."), + QMessageBox::Ok, + this); + m.exec(); + return; + } - mUI->mResults->save(tempResults.fileName(), Report::XMLV2); + QTemporaryFile tempResults; + tempResults.open(); + tempResults.close(); - ComplianceReportDialog dlg(mProjectFile, tempResults.fileName()); - dlg.exec(); - } + mUI->mResults->save(tempResults.fileName(), Report::XMLV2); + + ComplianceReportDialog dlg(mProjectFile, tempResults.fileName()); + dlg.exec(); } void MainWindow::resultsAdded() @@ -1574,6 +1581,7 @@ void MainWindow::aboutToShowViewMenu() void MainWindow::stopAnalysis() { mThread->stop(); + mUI->mResults->stopAnalysis(); mUI->mResults->disableProgressbar(); const QString &lastResults = getLastResults(); if (!lastResults.isEmpty()) { diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp index b26d22be484..454aca13478 100644 --- a/gui/resultsview.cpp +++ b/gui/resultsview.cpp @@ -90,6 +90,7 @@ void ResultsView::initialize(QSettings *settings, ApplicationList *list, ThreadH { mUI->mProgress->setMinimum(0); mUI->mProgress->setVisible(false); + mUI->mLabelCriticalErrors->setVisible(false); CodeEditorStyle theStyle(CodeEditorStyle::loadSettings(settings)); mUI->mCode->setStyle(theStyle); @@ -120,6 +121,8 @@ void ResultsView::clear(bool results) mUI->mProgress->setMaximum(PROGRESS_MAX); mUI->mProgress->setValue(0); mUI->mProgress->setFormat("%p%"); + + mUI->mLabelCriticalErrors->setVisible(false); } void ResultsView::clear(const QString &filename) @@ -145,6 +148,8 @@ void ResultsView::progress(int value, const QString& description) void ResultsView::error(const ErrorItem &item) { + handleCriticalError(item); + if (mUI->mTree->addErrorItem(item)) { emit gotResults(); mStatistics->addItem(item.tool(), ShowTypes::SeverityToShowType(item.severity)); @@ -285,6 +290,8 @@ void ResultsView::checkingStarted(int count) void ResultsView::checkingFinished() { + mSuccess = !mUI->mLabelCriticalErrors->isVisible(); + mUI->mProgress->setVisible(false); mUI->mProgress->setFormat("%p%"); @@ -377,6 +384,7 @@ void ResultsView::readErrorsXml(const QString &filename) } for (const ErrorItem& item : errors) { + handleCriticalError(item); mUI->mTree->addErrorItem(item); } @@ -506,3 +514,36 @@ void ResultsView::on_mListLog_customContextMenuRequested(const QPoint &pos) contextMenu.exec(globalPos); } + +void ResultsView::stopAnalysis() +{ + mUI->mLabelCriticalErrors->setText(tr("Analysis was stopped")); + mUI->mLabelCriticalErrors->setVisible(true); +} + +void ResultsView::handleCriticalError(const ErrorItem &item) +{ + const QSet criticalErrors{ + "cppcheckError", + "cppcheckLimit", + "internalAstError", + "instantiationError", + "internalError", + "preprocessorErrorDirective", + "syntaxError", + "unknownMacro" + }; + + if (criticalErrors.contains(item.errorId)) { + QString msg = tr("There was a critical error with id '%1'").arg(item.errorId); + if (!item.file0.isEmpty()) + msg += ", " + tr("when checking %1").arg(item.file0); + msg += ". " + tr("Analysis was aborted."); + mUI->mLabelCriticalErrors->setText(msg); + mUI->mLabelCriticalErrors->setVisible(true); + } +} + +bool ResultsView::isSuccess() const { + return mSuccess && !mUI->mLabelCriticalErrors->isVisible(); +} diff --git a/gui/resultsview.h b/gui/resultsview.h index b44adfd0782..4a66dbc0930 100644 --- a/gui/resultsview.h +++ b/gui/resultsview.h @@ -176,6 +176,17 @@ class ResultsView : public QWidget { */ void translate(); + /** + * @brief This function should be called when analysis is stopped + */ + void stopAnalysis(); + + /** + * @brief Are there successful results? + * @return true if analysis finished without critical errors etc + */ + bool isSuccess() const; + void disableProgressbar(); /** @@ -340,7 +351,11 @@ public slots: */ void logCopyComplete(); -protected: +private: + + void handleCriticalError(const ErrorItem& item); + bool mHasCriticalError = false; + /** * @brief Should we show a "No errors found dialog" every time no errors were found? */ @@ -350,6 +365,11 @@ public slots: CheckStatistics *mStatistics; + /** + * Set to true when checking finish successfully. Set to false whenever analysis starts. + */ + bool mSuccess = false; + private slots: /** * @brief Custom context menu for Analysis Log diff --git a/gui/resultsview.ui b/gui/resultsview.ui index 9e22e561eaa..7ab18fffc9c 100644 --- a/gui/resultsview.ui +++ b/gui/resultsview.ui @@ -51,6 +51,16 @@ + + + + color: red; + + + Critical errors + + +