cppcheck/addons/misra.py

229 lines
4.5 KiB
Python
Raw Normal View History

2017-04-08 16:08:54 +02:00
#/usr/bin/python
#
2017-04-11 14:45:38 +02:00
# MISRA C 2012 checkers
2017-04-08 16:08:54 +02:00
#
# Example usage of this addon (scan a sourcefile main.cpp)
# cppcheck --dump main.cpp
# python misra.py main.cpp.dump
#
# Limitations: This addon is released as open source. Rule texts can't be freely
# distributed. https://www.misra.org.uk/forum/viewtopic.php?f=56&t=1189
#
#
2017-04-08 16:08:54 +02:00
import cppcheckdata
import sys
import re
def reportError(token, num):
2017-04-08 16:08:54 +02:00
sys.stderr.write(
'[' + token.file + ':' + str(token.linenr) + '] misra ' + str(num) + ' violation\n')
2017-04-08 16:08:54 +02:00
def hasSideEffects(expr):
if not expr:
return False
2017-04-08 19:00:50 +02:00
if expr.str in ['++', '--', '=']:
2017-04-08 16:08:54 +02:00
return True
# Todo: Check function calls
return hasSideEffects(expr.astOperand1) or hasSideEffects(expr.astOperand2)
2017-04-11 14:45:38 +02:00
def isBoolExpression(expr):
return expr and expr.str in ['!', '==', '!=', '<', '<=', '>', '>=', '&&', '||']
# 1.1 Done. Use compiler.
# 1.2 Done. gcc
# 1.3 Done. Use Cppcheck, compiler, ..
# 2.1 Done. Use Cppcheck, clang, etc.
# 2.2 Done. Use Cppcheck
# 2.3 TODO
# 2.4 TODO
# 2.5 Done. clang
# 2.6 Done. Cppcheck
# 2.7 Done. clang, gcc
# 3.1 TODO
# 3.2 TODO
# 4.1 TODO
# 4.2 Done. clang, gcc
# 5.1 Done.
# 5.2 Done.
# 5.3 Done. -Wshadow
# 5.4 Done. clang -Weverything
# 5.5 TODO
# 5.6 TODO
# 5.7 TODO
# 5.8 Done.
# 5.9 Done. -Wshadow
# 6.1 TODO
# 6.2 TODO
# 7.1 Done.
# 7.2 TODO
# 7.3 TODO
# 7.4 Done. Cppcheck, gcc, clang
# 8.1 Done. gcc, clang
# 8.2 TODO
# 8.3 Done. Cppcheck
# 8.4 Done. Clang
# 8.5 TODO
# 8.6 TODO
# 8.7 TODO
# 8.8 TODO
# 8.9 TODO
# 8.10 TODO
# 8.11 TODO
# 8.12 TODO
# 8.13 TODO
# 8.14 TODO
# 9.1 Done. Cppcheck.
# 9.2 TODO
# 9.3 TODO
# 9.4 TODO
# 9.5 TODO
# 10.1 TODO
# 10.2 TODO
# 10.3 Done. Cppcheck.
# 10.4 TODO
# 10.5 TODO
# 10.6 TODO
# 10.7 TODO
# 10.8 TODO
# 11.1 TODO
# 11.2 TODO
# 11.3 TODO
# 11.4 TODO
# 11.5 TODO
# 11.6 TODO
# 11.7 TODO
# 11.8 TODO
# 11.9 TODO
# 12.1 TODO
# 12.2 Done. Cppcheck.
# 12.3 TODO
# 12.4 TODO
# 13.1 TODO
# 13.2 TODO
# 13.3 TODO
# 13.4 TODO
# 13.5 Done
# 13.6 Done. Cppcheck.
# 14.1 TODO
# 14.2 TODO
# 14.3 TODO
# 14.4 Done.
# 15.1 Done.
# 15.2 TODO
# 15.3 TODO
# 15.4 TODO
# 15.5 TODO
# 15.6 TODO
# 15.7 TODO
# 16.1 TODO
# 16.2 TODO
# 16.3 TODO
# 16.4 TODO
# 16.5 TODO
# 16.6 TODO
# 16.7 TODO
# 17.1 TODO
# 17.2 TODO
# 17.3 Done. Compiler.
# 17.4 Done. Compiler.
# 17.5 Done. Cppcheck.
# 17.6 TODO
# 17.7 TODO
# 17.8 TODO
# 18.1 TODO
# 18.2 TODO. Cppcheck.
# 18.3 TODO. Cppcheck.
# 18.4 TODO
# 18.5 TODO
# 18.6 TODO
# 18.7 TODO
# 18.8 TODO
# 19.1 TODO
# 19.2 TODO
# 20.1 TODO
# 20.2 TODO
# 20.3 TODO
# 20.4 TODO
# 20.5 TODO
# 20.6 TODO
# 20.7 TODO
# 20.8 TODO
# 20.9 TODO
# 20.10 TODO
# 20.11 TODO
# 20.12 TODO
# 20.13 TODO
# 20.14 TODO
# 21.1 TODO
# 21.2 TODO
# 21.3 TODO
# 21.4 TODO
# 21.5 TODO
# 21.6 TODO
# 21.7 TODO
# 21.8 TODO
# 21.9 TODO
# 21.10 TODO
# 21.11 TODO
# 21.12 TODO
# 22.1 TODO
# 22.2 TODO
# 22.3 TODO
# 22.4 TODO
# 22.5 TODO
# 22.6 TODO
def misra_5_1(data):
2017-04-08 16:08:54 +02:00
for token in data.tokenlist:
if token.isName and len(token.str) > 31:
2017-04-11 14:45:38 +02:00
reportError(token, 51)
2017-04-08 16:08:54 +02:00
2017-04-11 14:45:38 +02:00
def misra_7_1(rawTokens):
2017-04-09 10:11:54 +02:00
for tok in rawTokens:
2017-04-11 14:45:38 +02:00
if re.match(r'^0[0-7]+$', tok.str):
reportError(tok, 71)
2017-04-08 16:08:54 +02:00
2017-04-11 14:45:38 +02:00
def misra_13_5(data):
2017-04-08 16:08:54 +02:00
for token in data.tokenlist:
if token.isLogicalOp and hasSideEffects(token.astOperand2):
2017-04-11 14:45:38 +02:00
reportError(token, 135)
2017-04-08 16:08:54 +02:00
2017-04-11 14:45:38 +02:00
def misra_14_4(data):
2017-04-08 16:08:54 +02:00
for token in data.tokenlist:
2017-04-11 14:45:38 +02:00
if token.str != '(':
2017-04-08 19:00:50 +02:00
continue
2017-04-11 14:45:38 +02:00
if not token.astOperand1 or not (token.astOperand1.str in ['if', 'while']):
continue
if not isBoolExpression(token.astOperand2):
reportError(token, 144)
2017-04-08 16:08:54 +02:00
2017-04-11 14:45:38 +02:00
def misra_15_1(data):
2017-04-08 16:08:54 +02:00
for token in data.tokenlist:
2017-04-08 19:00:50 +02:00
if token.str == "goto":
2017-04-11 14:45:38 +02:00
reportError(token, 151)
2017-04-08 16:08:54 +02:00
for arg in sys.argv[1:]:
print('Checking ' + arg + '...')
data = cppcheckdata.parsedump(arg)
2017-04-09 10:11:54 +02:00
cfgNumber = 0
2017-04-08 16:08:54 +02:00
for cfg in data.configurations:
2017-04-09 10:11:54 +02:00
cfgNumber = cfgNumber + 1
2017-04-08 16:08:54 +02:00
if len(data.configurations) > 1:
print('Checking ' + arg + ', config "' + cfg.name + '"...')
2017-04-11 14:45:38 +02:00
misra_5_1(cfg)
if cfgNumber == 1:
misra_7_1(data.rawTokens)
misra_13_5(cfg)
misra_14_4(cfg)
misra_15_1(cfg)