Skip to content

fix #13730: Report type: cppcheck severity is shown for misra directive even though --report-type=misra-c-2023 is used #7595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,8 +1309,12 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
mSettings.reportType = ReportType::certC;
} else if (typeStr == "cert-cpp-2016") {
mSettings.reportType = ReportType::certCpp;
} else if (typeStr == "misra-c-2012" || typeStr == "misra-c-2023") {
mSettings.reportType = ReportType::misraC;
} else if (typeStr == "misra-c-2012") {
mSettings.reportType = ReportType::misraC2012;
} else if (typeStr == "misra-c-2023") {
mSettings.reportType = ReportType::misraC2023;
} else if (typeStr == "misra-c-2025") {
mSettings.reportType = ReportType::misraC2025;
} else if (typeStr == "misra-cpp-2008") {
mSettings.reportType = ReportType::misraCpp2008;
} else if (typeStr == "misra-cpp-2023") {
Expand Down Expand Up @@ -1963,6 +1967,7 @@ void CmdLineParser::printHelp() const
" * cert-cpp-2016 Cert C++ 2016\n"
" * misra-c-2012 Misra C 2012\n"
" * misra-c-2023 Misra C 2023\n"
" * misra-c-2025 Misra C 2025\n"
" * misra-cpp-2008 Misra C++ 2008\n"
" * misra-cpp-2023 Misra C++ 2023\n"
" --rule=<rule> Match regular expression.\n"
Expand Down
17 changes: 14 additions & 3 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,9 @@ void MainWindow::loadSettings()
mUI->mActionReportAutosar->setChecked(reportType == ReportType::autosar);
mUI->mActionReportCertC->setChecked(reportType == ReportType::certC);
mUI->mActionReportCertCpp->setChecked(reportType == ReportType::certCpp);
mUI->mActionReportMisraC->setChecked(reportType == ReportType::misraC);
mUI->mActionReportMisraC->setChecked(reportType == ReportType::misraC2012 ||
reportType == ReportType::misraC2023 ||
reportType == ReportType::misraC2025);
mUI->mActionReportMisraCpp2008->setChecked(reportType == ReportType::misraCpp2008);
mUI->mActionReportMisraCpp2023->setChecked(reportType == ReportType::misraCpp2023);

Expand Down Expand Up @@ -470,6 +472,15 @@ void MainWindow::loadSettings()
}
}

static ReportType getMisraCReportType(const QStringList &standards)
{
if (standards.contains(CODING_STANDARD_MISRA_C_2023))
return ReportType::misraC2023;
if (standards.contains(CODING_STANDARD_MISRA_C_2025))
return ReportType::misraC2025;
return ReportType::misraC2012;
}

void MainWindow::saveSettings() const
{
// Window/dialog sizes
Expand All @@ -480,7 +491,7 @@ void MainWindow::saveSettings() const
const ReportType reportType = mUI->mActionReportAutosar->isChecked() ? ReportType::autosar :
mUI->mActionReportCertC->isChecked() ? ReportType::certC :
mUI->mActionReportCertCpp->isChecked() ? ReportType::certCpp :
mUI->mActionReportMisraC->isChecked() ? ReportType::misraC :
mUI->mActionReportMisraC->isChecked() ? (mProjectFile ? getMisraCReportType(mProjectFile->getCodingStandards()) : ReportType::misraC2012) :
mUI->mActionReportMisraCpp2008->isChecked() ? ReportType::misraCpp2008 :
mUI->mActionReportMisraCpp2023->isChecked() ? ReportType::misraCpp2023 :
ReportType::normal;
Expand Down Expand Up @@ -2283,7 +2294,7 @@ void MainWindow::changeReportType() {
const ReportType reportType = mUI->mActionReportAutosar->isChecked() ? ReportType::autosar :
mUI->mActionReportCertC->isChecked() ? ReportType::certC :
mUI->mActionReportCertCpp->isChecked() ? ReportType::certCpp :
mUI->mActionReportMisraC->isChecked() ? ReportType::misraC :
mUI->mActionReportMisraC->isChecked() ? (mProjectFile ? getMisraCReportType(mProjectFile->getCodingStandards()) : ReportType::misraC2012) :
mUI->mActionReportMisraCpp2008->isChecked() ? ReportType::misraCpp2008 :
mUI->mActionReportMisraCpp2023->isChecked() ? ReportType::misraCpp2023 :
ReportType::normal;
Expand Down
16 changes: 8 additions & 8 deletions gui/projectfiledialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@
#include <QSpinBox>
#include <QVariant>

static constexpr char ADDON_MISRA[] = "misra";
static constexpr char CODING_STANDARD_MISRA_C_2023[] = "misra-c-2023";
static constexpr char CODING_STANDARD_MISRA_C_2025[] = "misra-c-2025";
static constexpr char CODING_STANDARD_MISRA_CPP_2008[] = "misra-cpp-2008";
static constexpr char CODING_STANDARD_MISRA_CPP_2023[] = "misra-cpp-2023";
static constexpr char CODING_STANDARD_CERT_C[] = "cert-c-2016";
static constexpr char CODING_STANDARD_CERT_CPP[] = "cert-cpp-2016";
static constexpr char CODING_STANDARD_AUTOSAR[] = "autosar";
const char ADDON_MISRA[] = "misra";
const char CODING_STANDARD_MISRA_C_2023[] = "misra-c-2023";
const char CODING_STANDARD_MISRA_C_2025[] = "misra-c-2025";
const char CODING_STANDARD_MISRA_CPP_2008[] = "misra-cpp-2008";
const char CODING_STANDARD_MISRA_CPP_2023[] = "misra-cpp-2023";
const char CODING_STANDARD_CERT_C[] = "cert-c-2016";
const char CODING_STANDARD_CERT_CPP[] = "cert-cpp-2016";
const char CODING_STANDARD_AUTOSAR[] = "autosar";

/** Return paths from QListWidget */
static QStringList getPaths(const QListWidget *list)
Expand Down
9 changes: 9 additions & 0 deletions gui/projectfiledialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ namespace Ui {
class ProjectFile;
}

extern const char ADDON_MISRA[];
extern const char CODING_STANDARD_MISRA_C_2023[];
extern const char CODING_STANDARD_MISRA_C_2025[];
extern const char CODING_STANDARD_MISRA_CPP_2008[];
extern const char CODING_STANDARD_MISRA_CPP_2023[];
extern const char CODING_STANDARD_CERT_C[];
extern const char CODING_STANDARD_CERT_CPP[];
extern const char CODING_STANDARD_AUTOSAR[];

/// @addtogroup GUI
/// @{

Expand Down
4 changes: 3 additions & 1 deletion gui/resultstree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,9 @@ bool ResultsTree::isCertReport() const {

bool ResultsTree::isAutosarMisraReport() const {
return mReportType == ReportType::autosar ||
mReportType == ReportType::misraC ||
mReportType == ReportType::misraC2012 ||
mReportType == ReportType::misraC2023 ||
mReportType == ReportType::misraC2025 ||
mReportType == ReportType::misraCpp2008 ||
mReportType == ReportType::misraCpp2023;
}
4 changes: 2 additions & 2 deletions gui/test/resultstree/testresultstree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void TestResultsTree::testReportType() const
QCOMPARE(report.output, "id1,,\nunusedVariable,,");

// switch to Misra C report and check that "id1" is not shown
tree.setReportType(ReportType::misraC);
tree.setReportType(ReportType::misraC2012);
tree.saveResults(&report);
QCOMPARE(report.output, "unusedVariable,Advisory,2.8");

Expand Down Expand Up @@ -187,7 +187,7 @@ void TestResultsTree::testGetGuidelineError() const

// normal report with 2 errors
ResultsTree tree(nullptr);
tree.setReportType(ReportType::misraC);
tree.setReportType(ReportType::misraC2012);
tree.addErrorItem(createErrorItem(Severity::error, "id1")); // error severity => guideline 1.3
tree.saveResults(&report);
QCOMPARE(report.output, "id1,Required,1.3");
Expand Down
4 changes: 3 additions & 1 deletion lib/checkers.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ enum class ReportType : std::uint8_t {
autosar = 1,
certC = 2,
certCpp = 3,
misraC = 4,
misraC2012 = 4,
misraCpp2008 = 5,
misraCpp2023 = 6,
misraC2023 = 7,
misraC2025 = 8,
};

namespace checkers {
Expand Down
45 changes: 34 additions & 11 deletions lib/errorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -945,24 +945,40 @@ std::string getClassification(const std::string &guideline, ReportType reportTyp
return getClassification(checkers::certCInfo, guideline);
case ReportType::certCpp:
return getClassification(checkers::certCppInfo, guideline);
case ReportType::misraC:
case ReportType::misraC2012:
case ReportType::misraC2023:
case ReportType::misraC2025:
{
auto components = splitString(guideline, '.');
const bool isDirective = guideline.rfind("Dir ", 0) == 0;

const std::size_t offset = isDirective ? 4 : 0;
auto components = splitString(guideline.substr(offset), '.');
if (components.size() != 2)
return "";

const int a = std::stoi(components[0]);
const int b = std::stoi(components[1]);

const std::vector<checkers::MisraInfo> &info = checkers::misraC2012Rules;
const auto it = std::find_if(info.cbegin(), info.cend(), [&](const checkers::MisraInfo &i) {
const std::vector<checkers::MisraInfo> *info = nullptr;
switch (reportType) {
case ReportType::misraC2012:
info = isDirective ? &checkers::misraC2012Directives : &checkers::misraC2012Rules;
break;
case ReportType::misraC2023:
info = isDirective ? &checkers::misraC2023Directives : &checkers::misraC2023Rules;
break;
case ReportType::misraC2025:
info = isDirective ? &checkers::misraC2025Directives : &checkers::misraC2025Rules;
break;
default:
cppcheck::unreachable();
}

const auto it = std::find_if(info->cbegin(), info->cend(), [&](const checkers::MisraInfo &i) {
return i.a == a && i.b == b;
});

if (it == info.cend())
return "";

return it->str;
return it == info->cend() ? "" : it->str;
}
case ReportType::misraCpp2008:
case ReportType::misraCpp2023:
Expand Down Expand Up @@ -1022,7 +1038,9 @@ std::string getGuideline(const std::string &errId, ReportType reportType,
guideline.begin(), static_cast<int (*)(int)>(std::toupper));
}
break;
case ReportType::misraC:
case ReportType::misraC2012:
case ReportType::misraC2023:
case ReportType::misraC2025:
if (errId.rfind("misra-c20", 0) == 0 || errId.rfind("premium-misra-c-20", 0) == 0)
guideline = errId.substr(errId.rfind('-') + 1);
break;
Expand All @@ -1038,8 +1056,11 @@ std::string getGuideline(const std::string &errId, ReportType reportType,
break;
}

if (!guideline.empty())
if (!guideline.empty()) {
if (errId.find("-dir-") != std::string::npos)
guideline = "Dir " + guideline;
return guideline;
}

auto it = guidelineMapping.find(errId);

Expand Down Expand Up @@ -1074,7 +1095,9 @@ std::map<std::string, std::string> createGuidelineMapping(ReportType reportType)
idMapping1 = &checkers::idMappingCertC;
ext1 = "-C";
break;
case ReportType::misraC:
case ReportType::misraC2012:
case ReportType::misraC2023:
case ReportType::misraC2025:
idMapping1 = &checkers::idMappingMisraC;
break;
case ReportType::misraCpp2008:
Expand Down
1 change: 1 addition & 0 deletions man/cppcheck.1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ There are false positives with this option. Each result must be carefully invest
<glossentry><glossterm>cert-cpp-2016</glossterm><glossdef><para>Cert C++ 2016</para></glossdef></glossentry>
<glossentry><glossterm>misra-c-2012</glossterm><glossdef><para>Misra C 2012</para></glossdef></glossentry>
<glossentry><glossterm>misra-c-2023</glossterm><glossdef><para>Misra C 2023</para></glossdef></glossentry>
<glossentry><glossterm>misra-c-2025</glossterm><glossdef><para>Misra C 2025</para></glossdef></glossentry>
<glossentry><glossterm>misra-cpp-2008</glossterm><glossdef><para>Misra C++ 2008</para></glossdef></glossentry>
<glossentry><glossterm>misra-cpp-2023</glossterm><glossdef><para>Misra C++ 2023</para></glossdef></glossentry>
</glosslist>
Expand Down
12 changes: 10 additions & 2 deletions test/testcmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ class TestCmdlineParser : public TestFixture {
TEST_CASE(reportTypeCertC);
TEST_CASE(reportTypeMisraC2012);
TEST_CASE(reportTypeMisraC2023);
TEST_CASE(reportTypeMisraC2025);
TEST_CASE(reportTypeMisraCpp2008);
TEST_CASE(reportTypeMisraCpp2023);
TEST_CASE(invalidReportType);
Expand Down Expand Up @@ -3456,14 +3457,21 @@ class TestCmdlineParser : public TestFixture {
REDIRECT;
const char *const argv[] = { "cppcheck", "--report-type=misra-c-2012", "file.cpp" };
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv));
ASSERT_EQUALS_ENUM(ReportType::misraC, settings->reportType);
ASSERT_EQUALS_ENUM(ReportType::misraC2012, settings->reportType);
}

void reportTypeMisraC2023() {
REDIRECT;
const char *const argv[] = { "cppcheck", "--report-type=misra-c-2023", "file.cpp" };
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv));
ASSERT_EQUALS_ENUM(ReportType::misraC, settings->reportType);
ASSERT_EQUALS_ENUM(ReportType::misraC2023, settings->reportType);
}

void reportTypeMisraC2025() {
REDIRECT;
const char *const argv[] = { "cppcheck", "--report-type=misra-c-2025", "file.cpp" };
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv));
ASSERT_EQUALS_ENUM(ReportType::misraC2025, settings->reportType);
}

void reportTypeMisraCpp2008() {
Expand Down
16 changes: 15 additions & 1 deletion test/testerrorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class TestErrorLogger : public TestFixture {
TEST_CASE(isCriticalErrorId);

TEST_CASE(ErrorMessageReportTypeMisraC);
TEST_CASE(ErrorMessageReportTypeMisraCDirective);
TEST_CASE(ErrorMessageReportTypeCertC);
}

Expand Down Expand Up @@ -317,7 +318,7 @@ class TestErrorLogger : public TestFixture {

void ErrorMessageReportTypeMisraC() const {
std::list<ErrorMessage::FileLocation> locs = { fooCpp5 };
const auto reportType = ReportType::misraC;
const auto reportType = ReportType::misraC2012;
const auto mapping = createGuidelineMapping(reportType);
const std::string format = "{severity} {id}";
ErrorMessage msg(std::move(locs), emptyString, Severity::error, "", "unusedVariable", Certainty::normal);
Expand All @@ -328,6 +329,19 @@ class TestErrorLogger : public TestFixture {
ASSERT_EQUALS("Advisory 2.8", msg.toString(true, format, ""));
}

void ErrorMessageReportTypeMisraCDirective() const {
std::list<ErrorMessage::FileLocation> locs = { fooCpp5 };
const auto reportType = ReportType::misraC2012;
const auto mapping = createGuidelineMapping(reportType);
const std::string format = "{severity} {id}";
ErrorMessage msg(std::move(locs), emptyString, Severity::style, "", "premium-misra-c-2012-dir-4.6", Certainty::normal);
msg.guideline = getGuideline(msg.id, reportType, mapping, msg.severity);
msg.classification = getClassification(msg.guideline, reportType);
ASSERT_EQUALS("Advisory", msg.classification);
ASSERT_EQUALS("Dir 4.6", msg.guideline);
ASSERT_EQUALS("Advisory Dir 4.6", msg.toString(true, format, ""));
}

void ErrorMessageReportTypeCertC() const {
std::list<ErrorMessage::FileLocation> locs = { fooCpp5 };
const auto reportType = ReportType::certC;
Expand Down
Loading