From 174bcc8d3429227c047e5ee9f5e34d8f374e2581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 14 Apr 2017 10:46:35 +0200 Subject: [PATCH] Misra: Add rule 16.3 --- addons/misra-test.c | 14 ++++++++++++++ addons/misra.py | 22 ++++++++++++++++++++++ lib/cppcheck.cpp | 44 ++++++++++++++++++++++---------------------- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/addons/misra-test.c b/addons/misra-test.c index fc9075538..ddd75fec9 100644 --- a/addons/misra-test.c +++ b/addons/misra-test.c @@ -122,3 +122,17 @@ void misra_16_2() { break; } } + +void misra_16_3() { + switch (x) { + case 1: + case 2: + a=1; + case 3: // 16.3 + a=2; + // fallthrough + case 5: + break; + default: break; + } +} diff --git a/addons/misra.py b/addons/misra.py index fbe5dbac7..d319ab0e7 100644 --- a/addons/misra.py +++ b/addons/misra.py @@ -419,6 +419,26 @@ def misra_16_2(data): if token.str == 'case' and token.scope.type != 'Switch': reportError(token, 16, 2) +# The goal is handle comments/annotations by other tools +def misra_16_3(rawTokens): + # state: 0=no, 1=break is seen but not its ';', 2=after 'break;', 'comment', '{' + state = 0 + for token in rawTokens: + if token.str == 'break': + state = 1 + elif token.str == ';': + if state == 1: + state = 2 + else: + state = 0 + elif token.str.startswith('/*') or token.str.startswith('//'): + if token.str.lower().find('fallthrough')>0: + state = 2 + elif token.str == '{': + state = 2 + elif token.str == 'case' and state != 2: + reportError(token, 16, 3) + for arg in sys.argv[1:]: print('Checking ' + arg + '...') data = cppcheckdata.parsedump(arg) @@ -455,4 +475,6 @@ for arg in sys.argv[1:]: misra_15_6(data.rawTokens) misra_15_7(cfg) misra_16_2(cfg) + if cfgNumber == 1: + misra_16_3(data.rawTokens) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index ef01a6f1b..55d631d15 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -135,6 +135,28 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin simplecpp::TokenList tokens1(fileStream, files, filename, &outputList); preprocessor.loadFiles(tokens1, files); + // write dump file xml prolog + std::ofstream fdump; + if (_settings.dump) { + const std::string dumpfile(filename + ".dump"); + fdump.open(dumpfile.c_str()); + if (fdump.is_open()) { + fdump << "" << std::endl; + fdump << "" << std::endl; + fdump << " " << std::endl; + for (unsigned int i = 0; i < files.size(); ++i) + fdump << " " << std::endl; + for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { + fdump << " location.fileIndex << "\" " + << "linenr=\"" << tok->location.line << "\" " + << "str=\"" << ErrorLogger::toxml(tok->str) << "\"" + << "/>" << std::endl; + } + fdump << " " << std::endl; + } + } + // Parse comments and then remove them preprocessor.inlineSuppressions(tokens1); tokens1.removeComments(); @@ -209,28 +231,6 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin } } - // write dump file xml prolog - std::ofstream fdump; - if (_settings.dump) { - const std::string dumpfile(filename + ".dump"); - fdump.open(dumpfile.c_str()); - if (fdump.is_open()) { - fdump << "" << std::endl; - fdump << "" << std::endl; - fdump << " " << std::endl; - for (unsigned int i = 0; i < files.size(); ++i) - fdump << " " << std::endl; - for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { - fdump << " location.fileIndex << "\" " - << "linenr=\"" << tok->location.line << "\" " - << "str=\"" << ErrorLogger::toxml(tok->str) << "\"" - << "/>" << std::endl; - } - fdump << " " << std::endl; - } - } - std::set checksums; unsigned int checkCount = 0; for (std::set::const_iterator it = configurations.begin(); it != configurations.end(); ++it) {