misra; implement rule 2.3

This commit is contained in:
Daniel Marjamäki 2021-07-07 15:16:53 +02:00
parent 00a9671f46
commit 13d55c7060
7 changed files with 66 additions and 25 deletions

View File

@ -571,12 +571,14 @@ class TypedefInfo:
name = None name = None
filename = None filename = None
lineNumber = None lineNumber = None
column = None
used = None used = None
def __init__(self, element): def __init__(self, element):
self.name = element.get('name') self.name = element.get('name')
self.filename = element.get('file') self.filename = element.get('file')
self.lineNumber = int(element.get('line')) self.lineNumber = int(element.get('line'))
self.column = int(element.get('column'))
self.used = (element.get('used') == '1') self.used = (element.get('used') == '1')
class Value: class Value:

View File

@ -1103,6 +1103,8 @@ class MisraChecker:
self.existing_violations = set() self.existing_violations = set()
self._ctu_summary_typedefs = False
def __repr__(self): def __repr__(self):
attrs = ["settings", "verify_expected", "verify_actual", "violations", attrs = ["settings", "verify_expected", "verify_actual", "violations",
"ruleTexts", "suppressedRules", "filePrefix", "ruleTexts", "suppressedRules", "filePrefix",
@ -1118,6 +1120,23 @@ class MisraChecker:
else: else:
return 63 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): def misra_2_7(self, data):
for func in data.functions: for func in data.functions:
# Skip function with no parameter # Skip function with no parameter
@ -1342,11 +1361,8 @@ class MisraChecker:
def misra_5_6(self, data): def misra_5_6(self, data):
dumpfile = data[0] dumpfile = data[0]
typedefInfo = data[1] typedefInfo = data[1]
summary = [] self._save_ctu_summary_typedefs(dumpfile, typedefInfo)
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)
def misra_6_1(self, data): def misra_6_1(self, data):
# Bitfield type must be bool or explicitly signed/unsigned int # Bitfield type must be bool or explicitly signed/unsigned int
@ -3256,6 +3272,7 @@ class MisraChecker:
if not self.settings.quiet: if not self.settings.quiet:
self.printStatus('Checking %s, config %s...' % (dumpfile, cfg.name)) 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) self.executeCheck(207, self.misra_2_7, cfg)
# data.rawTokens is same for all configurations # data.rawTokens is same for all configurations
if cfgNumber == 0: if cfgNumber == 0:
@ -3362,7 +3379,7 @@ class MisraChecker:
# 22.4 is already covered by Cppcheck writeReadOnlyFile # 22.4 is already covered by Cppcheck writeReadOnlyFile
def analyse_ctu_info(self, files): def analyse_ctu_info(self, files):
data_misra_5_6 = [] all_typedef_info = []
Location = namedtuple('Location', 'file linenr column') Location = namedtuple('Location', 'file linenr column')
@ -3370,23 +3387,33 @@ class MisraChecker:
if not filename.endswith('.ctu-info'): if not filename.endswith('.ctu-info'):
continue continue
for line in open(filename, 'rt'): for line in open(filename, 'rt'):
if line.startswith('{'): if not line.startswith('{'):
s = json.loads(line) continue
summary_type = s['summary']
summary_data = s['data']
# TODO break out info some function s = json.loads(line)
if summary_type == 'misra_5_6': summary_type = s['summary']
for info1 in summary_data: summary_data = s['data']
found = False
for info2 in data_misra_5_6: # TODO break out info some function
if info1['name'] == info2['name']: if summary_type != 'MisraTypedefInfo':
found = True continue
if info1['file'] != info2['file'] or info1['line'] != info2['line']: for new_typedef_info in summary_data:
self.reportError(Location(info2['file'], info2['line'], 0), 5, 6) found = False
self.reportError(Location(info1['file'], info1['line'], 0), 5, 6) for old_typedef_info in all_typedef_info:
if not found: if old_typedef_info['name'] == new_typedef_info['name']:
data_misra_5_6.append(info1) 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 RULE_TEXTS_HELP = '''Path to text file of MISRA rules

View File

@ -3,6 +3,9 @@
#include "misra-ctu-test.h" #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 // cppcheck-suppress misra-c2012-5.6
typedef int MISRA_5_6_VIOLATION; typedef int MISRA_5_6_VIOLATION;

View File

@ -3,6 +3,9 @@
#include "misra-ctu-test.h" #include "misra-ctu-test.h"
MISRA_2_3_B misra_2_3_b;
// cppcheck-suppress misra-c2012-5.6 // cppcheck-suppress misra-c2012-5.6
typedef int MISRA_5_6_VIOLATION; typedef int MISRA_5_6_VIOLATION;
static MISRA_5_6_VIOLATION misra_5_6_x;

View File

@ -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

View File

@ -1048,6 +1048,7 @@ void Tokenizer::simplifyTypedef()
typedefInfo.name = typeName->str(); typedefInfo.name = typeName->str();
typedefInfo.filename = list.file(typeName); typedefInfo.filename = list.file(typeName);
typedefInfo.lineNumber = typeName->linenr(); typedefInfo.lineNumber = typeName->linenr();
typedefInfo.column = typeName->column();
typedefInfo.used = false; typedefInfo.used = false;
mTypedefInfo.push_back(typedefInfo); mTypedefInfo.push_back(typedefInfo);
@ -5499,6 +5500,7 @@ void Tokenizer::dump(std::ostream &out) const
<< " name=\"" << typedefInfo.name << "\"" << " name=\"" << typedefInfo.name << "\""
<< " file=\"" << typedefInfo.filename << "\"" << " file=\"" << typedefInfo.filename << "\""
<< " line=\"" << typedefInfo.lineNumber << "\"" << " line=\"" << typedefInfo.lineNumber << "\""
<< " column=\"" << typedefInfo.column << "\""
<< " used=\"" << (typedefInfo.used?1:0) << "\"" << " used=\"" << (typedefInfo.used?1:0) << "\""
<< "/>" << std::endl; << "/>" << std::endl;
} }

View File

@ -991,6 +991,7 @@ private:
std::string name; std::string name;
std::string filename; std::string filename;
int lineNumber; int lineNumber;
int column;
bool used; bool used;
}; };
std::vector<TypedefInfo> mTypedefInfo; std::vector<TypedefInfo> mTypedefInfo;