Skip to content

Commit 9172f2a

Browse files
committed
addons; add CTU infrastructure
1 parent 5825a35 commit 9172f2a

11 files changed

Lines changed: 238 additions & 47 deletions

File tree

.github/workflows/CI-unixish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ jobs:
125125
run: |
126126
./cppcheck --addon=threadsafety addons/test/threadsafety
127127
./cppcheck --addon=threadsafety --std=c++03 addons/test/threadsafety
128+
./cppcheck --addon=misra --inline-suppr --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c
128129
129130
- name: Build GUI on ubuntu
130131
if: contains(matrix.os, 'ubuntu')

.github/workflows/CI-windows.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,8 @@ jobs:
127127
python -m pytest test-more-projects.py || exit /b !errorlevel!
128128
python -m pytest test-proj2.py || exit /b !errorlevel!
129129
python -m pytest test-suppress-syntaxError.py || exit /b !errorlevel!
130+
131+
- name: Test addons
132+
run: |
133+
.\cppcheck.exe --addon=misra --inline-suppr --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c
134+

addons/cppcheckdata.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,21 @@ def setId(self, IdMap):
559559
self.scope = IdMap[self.scopeId]
560560

561561

562+
class TypedefInfo:
563+
"""
564+
TypedefInfo class -- information about typedefs
565+
"""
566+
name = None
567+
filename = None
568+
lineNumber = None
569+
used = None
570+
571+
def __init__(self, element):
572+
self.name = element.get('name')
573+
self.filename = element.get('file')
574+
self.lineNumber = int(element.get('line'))
575+
self.used = (element.get('used') == '1')
576+
562577
class Value:
563578
"""
564579
Value class
@@ -707,6 +722,7 @@ class Configuration:
707722
scopes = []
708723
functions = []
709724
variables = []
725+
typedefInfo = []
710726
valueflow = []
711727
standards = None
712728

@@ -717,6 +733,7 @@ def __init__(self, name):
717733
self.scopes = []
718734
self.functions = []
719735
self.variables = []
736+
self.typedefInfo = []
720737
self.valueflow = []
721738
self.standards = Standards()
722739

@@ -939,6 +956,9 @@ def iterconfigurations(self):
939956
# Iterating <varlist> in a <scope>.
940957
iter_scope_varlist = False
941958

959+
# Iterating <typedef-info>
960+
iter_typedef_info = False
961+
942962
# Use iterable objects to traverse XML tree for dump files incrementally.
943963
# Iterative approach is required to avoid large memory consumption.
944964
# Calling .clear() is necessary to let the element be garbage collected.
@@ -1013,6 +1033,12 @@ def iterconfigurations(self):
10131033
else:
10141034
cfg_arguments.append(var)
10151035

1036+
# Parse typedef info
1037+
elif node.tag == 'typedef-info':
1038+
iter_typedef_info = (event == 'start')
1039+
elif iter_typedef_info and node.tag == 'info' and event == 'start':
1040+
cfg.typedefInfo.append(TypedefInfo(node))
1041+
10161042
# Parse valueflows (list of values)
10171043
elif node.tag == 'valueflow' and event == 'start':
10181044
continue
@@ -1163,3 +1189,10 @@ def reportError(location, severity, message, addon, errorId, extra=''):
11631189
sys.stderr.write('%s (%s) %s [%s-%s]\n' % (loc, severity, message, addon, errorId))
11641190
global EXIT_CODE
11651191
EXIT_CODE = 1
1192+
1193+
def reportSummary(dumpfile, summary_type, summary_data):
1194+
# dumpfile ends with ".dump"
1195+
ctu_info_file = dumpfile[:-4] + "ctu-info"
1196+
with open(ctu_info_file, 'at') as f:
1197+
msg = {'summary': summary_type, 'data': summary_data}
1198+
f.write(json.dumps(msg) + '\n')

addons/misra.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717

1818
import cppcheckdata
1919
import itertools
20+
import json
2021
import sys
2122
import re
2223
import os
2324
import argparse
2425
import codecs
2526
import string
2627

28+
from collections import namedtuple
29+
2730
try:
2831
from itertools import izip as zip
2932
except ImportError:
@@ -1336,6 +1339,15 @@ def misra_5_5(self, data):
13361339
self.reportError(scope.bodyStart, 5, 5)
13371340

13381341

1342+
def misra_5_6(self, data):
1343+
dumpfile = data[0]
1344+
typedefInfo = data[1]
1345+
summary = []
1346+
for ti in typedefInfo:
1347+
summary.append({ 'name': ti.name, 'file': ti.filename, 'line': ti.lineNumber })
1348+
if len(summary) > 0:
1349+
cppcheckdata.reportSummary(dumpfile, 'misra_5_6', summary)
1350+
13391351
def misra_6_1(self, data):
13401352
# Bitfield type must be bool or explicitly signed/unsigned int
13411353
for token in data.tokenlist:
@@ -3250,6 +3262,7 @@ def fillVerifyExpected(verify_expected, tok):
32503262
self.executeCheck(502, self.misra_5_2, cfg)
32513263
self.executeCheck(504, self.misra_5_4, cfg)
32523264
self.executeCheck(505, self.misra_5_5, cfg)
3265+
self.executeCheck(506, self.misra_5_6, (dumpfile, cfg.typedefInfo))
32533266
self.executeCheck(601, self.misra_6_1, cfg)
32543267
self.executeCheck(602, self.misra_6_2, cfg)
32553268
if cfgNumber == 0:
@@ -3342,6 +3355,32 @@ def fillVerifyExpected(verify_expected, tok):
33423355
self.executeCheck(2112, self.misra_21_12, cfg)
33433356
# 22.4 is already covered by Cppcheck writeReadOnlyFile
33443357

3358+
def analyse_ctu_info(self, files):
3359+
data_misra_5_6 = []
3360+
3361+
Location = namedtuple('Location', 'file linenr column')
3362+
3363+
for filename in files:
3364+
if not filename.endswith('.ctu-info'):
3365+
continue
3366+
for line in open(filename, 'rt'):
3367+
if line.startswith('{'):
3368+
s = json.loads(line)
3369+
summary_type = s['summary']
3370+
summary_data = s['data']
3371+
3372+
# TODO break out info some function
3373+
if summary_type == 'misra_5_6':
3374+
for info1 in summary_data:
3375+
found = False
3376+
for info2 in data_misra_5_6:
3377+
if info1['name'] == info2['name']:
3378+
found = True
3379+
if info1['file'] != info2['file'] or info1['line'] != info2['line']:
3380+
self.reportError(Location(info2['file'], info2['line'], 0), 5, 6)
3381+
self.reportError(Location(info1['file'], info1['line'], 0), 5, 6)
3382+
if not found:
3383+
data_misra_5_6.append(info1)
33453384

33463385
RULE_TEXTS_HELP = '''Path to text file of MISRA rules
33473386
@@ -3434,6 +3473,9 @@ def main():
34343473
checker.setSeverity(args.severity)
34353474

34363475
for item in args.dumpfile:
3476+
if item.endswith('.ctu-info'):
3477+
continue
3478+
34373479
checker.parseDump(item)
34383480

34393481
if settings.verify:
@@ -3457,6 +3499,8 @@ def main():
34573499
if exitCode != 0:
34583500
sys.exit(exitCode)
34593501

3502+
checker.analyse_ctu_info(args.dumpfile)
3503+
34603504
if settings.verify:
34613505
sys.exit(exitCode)
34623506

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Test with command:
2+
// ./cppcheck --addon=misra --inline-suppr addons/test/misra/misra-ctu-*-test.c
3+
4+
#include "misra-ctu-test.h"
5+
6+
// cppcheck-suppress misra-c2012-5.6
7+
typedef int MISRA_5_6_VIOLATION;
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Test with command:
2+
// ./cppcheck --addon=misra --inline-suppr addons/test/misra/misra-ctu-*-test.c
3+
4+
#include "misra-ctu-test.h"
5+
6+
// cppcheck-suppress misra-c2012-5.6
7+
typedef int MISRA_5_6_VIOLATION;
8+

addons/test/misra/misra-ctu-test.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
typedef int t1;
3+
typedef int t2;
4+
5+

0 commit comments

Comments
 (0)