From 13d55c7060bf183f34e343d2dd92c8680293697e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 7 Jul 2021 15:16:53 +0200 Subject: [PATCH] misra; implement rule 2.3 --- addons/cppcheckdata.py | 2 + addons/misra.py | 71 +++++++++++++++++++--------- addons/test/misra/misra-ctu-1-test.c | 3 ++ addons/test/misra/misra-ctu-2-test.c | 3 ++ addons/test/misra/misra-ctu-test.h | 9 ++-- lib/tokenize.cpp | 2 + lib/tokenize.h | 1 + 7 files changed, 66 insertions(+), 25 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 4817c52bb..678744b89 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -571,12 +571,14 @@ class TypedefInfo: name = None filename = None lineNumber = None + column = None used = None def __init__(self, element): self.name = element.get('name') self.filename = element.get('file') self.lineNumber = int(element.get('line')) + self.column = int(element.get('column')) self.used = (element.get('used') == '1') class Value: diff --git a/addons/misra.py b/addons/misra.py index 4f2db7729..3158f3975 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -1103,6 +1103,8 @@ class MisraChecker: self.existing_violations = set() + self._ctu_summary_typedefs = False + def __repr__(self): attrs = ["settings", "verify_expected", "verify_actual", "violations", "ruleTexts", "suppressedRules", "filePrefix", @@ -1118,6 +1120,23 @@ class MisraChecker: else: return 63 + def _save_ctu_summary_typedefs(self, dumpfile, typedef_info): + if self._ctu_summary_typedefs: + return + + self._ctu_summary_typedefs = True + + summary = [] + for ti in typedef_info: + summary.append({ 'name': ti.name, 'file': ti.filename, 'line': ti.lineNumber, 'column': ti.column, 'used': ti.used }) + if len(summary) > 0: + cppcheckdata.reportSummary(dumpfile, 'MisraTypedefInfo', summary) + + def misra_2_3(self, data): + dumpfile = data[0] + typedefInfo = data[1] + self._save_ctu_summary_typedefs(dumpfile, typedefInfo) + def misra_2_7(self, data): for func in data.functions: # Skip function with no parameter @@ -1342,11 +1361,8 @@ class MisraChecker: def misra_5_6(self, data): dumpfile = data[0] typedefInfo = data[1] - summary = [] - for ti in typedefInfo: - summary.append({ 'name': ti.name, 'file': ti.filename, 'line': ti.lineNumber }) - if len(summary) > 0: - cppcheckdata.reportSummary(dumpfile, 'misra_5_6', summary) + self._save_ctu_summary_typedefs(dumpfile, typedefInfo) + def misra_6_1(self, data): # Bitfield type must be bool or explicitly signed/unsigned int @@ -3256,6 +3272,7 @@ class MisraChecker: if not self.settings.quiet: self.printStatus('Checking %s, config %s...' % (dumpfile, cfg.name)) + self.executeCheck(203, self.misra_2_3, (dumpfile, cfg.typedefInfo)) self.executeCheck(207, self.misra_2_7, cfg) # data.rawTokens is same for all configurations if cfgNumber == 0: @@ -3362,7 +3379,7 @@ class MisraChecker: # 22.4 is already covered by Cppcheck writeReadOnlyFile def analyse_ctu_info(self, files): - data_misra_5_6 = [] + all_typedef_info = [] Location = namedtuple('Location', 'file linenr column') @@ -3370,23 +3387,33 @@ class MisraChecker: if not filename.endswith('.ctu-info'): continue for line in open(filename, 'rt'): - if line.startswith('{'): - s = json.loads(line) - summary_type = s['summary'] - summary_data = s['data'] + if not line.startswith('{'): + continue - # TODO break out info some function - if summary_type == 'misra_5_6': - for info1 in summary_data: - found = False - for info2 in data_misra_5_6: - if info1['name'] == info2['name']: - found = True - if info1['file'] != info2['file'] or info1['line'] != info2['line']: - self.reportError(Location(info2['file'], info2['line'], 0), 5, 6) - self.reportError(Location(info1['file'], info1['line'], 0), 5, 6) - if not found: - data_misra_5_6.append(info1) + s = json.loads(line) + summary_type = s['summary'] + summary_data = s['data'] + + # TODO break out info some function + if summary_type != 'MisraTypedefInfo': + continue + for new_typedef_info in summary_data: + found = False + for old_typedef_info in all_typedef_info: + if old_typedef_info['name'] == new_typedef_info['name']: + found = True + if old_typedef_info['file'] != new_typedef_info['file'] or old_typedef_info['line'] != new_typedef_info['line']: + self.reportError(Location(old_typedef_info['file'], old_typedef_info['line'], old_typedef_info['column']), 5, 6) + self.reportError(Location(new_typedef_info['file'], new_typedef_info['line'], new_typedef_info['column']), 5, 6) + else: + if new_typedef_info['used']: + old_typedef_info['used'] = True + if not found: + all_typedef_info.append(new_typedef_info) + + for ti in all_typedef_info: + if not ti['used']: + self.reportError(Location(ti['file'], ti['line'], ti['column']), 2, 3) RULE_TEXTS_HELP = '''Path to text file of MISRA rules diff --git a/addons/test/misra/misra-ctu-1-test.c b/addons/test/misra/misra-ctu-1-test.c index 5cbc0ff5b..f0f1021a5 100644 --- a/addons/test/misra/misra-ctu-1-test.c +++ b/addons/test/misra/misra-ctu-1-test.c @@ -3,6 +3,9 @@ #include "misra-ctu-test.h" +MISRA_2_3_A misra_2_3_a; + +// cppcheck-suppress misra-c2012-2.3 // cppcheck-suppress misra-c2012-5.6 typedef int MISRA_5_6_VIOLATION; diff --git a/addons/test/misra/misra-ctu-2-test.c b/addons/test/misra/misra-ctu-2-test.c index 5cbc0ff5b..1756e2cd4 100644 --- a/addons/test/misra/misra-ctu-2-test.c +++ b/addons/test/misra/misra-ctu-2-test.c @@ -3,6 +3,9 @@ #include "misra-ctu-test.h" +MISRA_2_3_B misra_2_3_b; + // cppcheck-suppress misra-c2012-5.6 typedef int MISRA_5_6_VIOLATION; +static MISRA_5_6_VIOLATION misra_5_6_x; diff --git a/addons/test/misra/misra-ctu-test.h b/addons/test/misra/misra-ctu-test.h index 12843044d..7e3c1a91a 100644 --- a/addons/test/misra/misra-ctu-test.h +++ b/addons/test/misra/misra-ctu-test.h @@ -1,5 +1,8 @@ -typedef int t1; -typedef int t2; - + +typedef int MISRA_2_3_A; +typedef int MISRA_2_3_B; +typedef int MISRA_2_3_VIOLATION; // cppcheck-suppress misra-c2012-2.3 + + diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index f779732b4..443bde819 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1048,6 +1048,7 @@ void Tokenizer::simplifyTypedef() typedefInfo.name = typeName->str(); typedefInfo.filename = list.file(typeName); typedefInfo.lineNumber = typeName->linenr(); + typedefInfo.column = typeName->column(); typedefInfo.used = false; mTypedefInfo.push_back(typedefInfo); @@ -5499,6 +5500,7 @@ void Tokenizer::dump(std::ostream &out) const << " name=\"" << typedefInfo.name << "\"" << " file=\"" << typedefInfo.filename << "\"" << " line=\"" << typedefInfo.lineNumber << "\"" + << " column=\"" << typedefInfo.column << "\"" << " used=\"" << (typedefInfo.used?1:0) << "\"" << "/>" << std::endl; } diff --git a/lib/tokenize.h b/lib/tokenize.h index 605c30b20..929b347d2 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -991,6 +991,7 @@ private: std::string name; std::string filename; int lineNumber; + int column; bool used; }; std::vector mTypedefInfo;