misra.py: Fix false negative for rule 20.4 (#2528)
Define different sets of reserved keywords for C90 and C99. This will fix false negative for compliant example, defined in MISRA document, and close trac 9506.
This commit is contained in:
parent
e9b7e7811b
commit
6d4eff46be
|
@ -70,42 +70,35 @@ def rawlink(rawtoken):
|
|||
return rawtoken
|
||||
|
||||
|
||||
KEYWORDS = {
|
||||
'auto',
|
||||
'break',
|
||||
'case',
|
||||
'char',
|
||||
'const',
|
||||
'continue',
|
||||
'default',
|
||||
'do',
|
||||
'double',
|
||||
'else',
|
||||
'enum',
|
||||
'extern',
|
||||
'float',
|
||||
'for',
|
||||
'goto',
|
||||
'if',
|
||||
'int',
|
||||
'long',
|
||||
'register',
|
||||
'return',
|
||||
'short',
|
||||
'signed',
|
||||
'sizeof',
|
||||
'static',
|
||||
'struct',
|
||||
'switch',
|
||||
'typedef',
|
||||
'union',
|
||||
'unsigned',
|
||||
'void',
|
||||
'volatile',
|
||||
'while'
|
||||
# Reserved keywords defined in ISO/IEC9899:1990 -- ch 6.1.1
|
||||
C90_KEYWORDS = {
|
||||
'auto', 'break', 'double', 'else', 'enum', 'extern', 'float', 'for',
|
||||
'goto', 'if', 'case', 'char', 'const', 'continue', 'default', 'do', 'int',
|
||||
'long', 'struct', 'switch', 'register', 'typedef', 'union', 'unsigned',
|
||||
'void', 'volatile', 'while', 'return', 'short', 'signed', 'sizeof',
|
||||
'static'
|
||||
}
|
||||
|
||||
|
||||
# Reserved keywords defined in ISO/IEC 9899 WF14/N1256 -- ch. 6.4.1
|
||||
C99_KEYWORDS = {
|
||||
'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do',
|
||||
'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline',
|
||||
'int', 'long', 'register', 'restrict', 'return', 'short', 'signed',
|
||||
'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned',
|
||||
'void', 'volatile', 'while', '_Bool', '_Complex', '_Imaginary'
|
||||
}
|
||||
|
||||
|
||||
def isKeyword(keyword, standard='c99'):
|
||||
kw_set = {}
|
||||
if standard == 'c89':
|
||||
kw_set = C90_KEYWORDS
|
||||
elif standard == 'c99':
|
||||
kw_set = C99_KEYWORDS
|
||||
return keyword in kw_set
|
||||
|
||||
|
||||
def getEssentialTypeCategory(expr):
|
||||
if not expr:
|
||||
return None
|
||||
|
@ -218,14 +211,14 @@ def isCast(expr):
|
|||
return True
|
||||
|
||||
|
||||
def isFunctionCall(expr):
|
||||
def isFunctionCall(expr, std='c99'):
|
||||
if not expr:
|
||||
return False
|
||||
if expr.str != '(' or not expr.astOperand1:
|
||||
return False
|
||||
if expr.astOperand1 != expr.previous:
|
||||
return False
|
||||
if expr.astOperand1.str in KEYWORDS:
|
||||
if isKeyword(expr.astOperand1.str, std):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -1838,7 +1831,7 @@ class MisraChecker:
|
|||
tok = scope.bodyStart
|
||||
while tok != scope.bodyEnd:
|
||||
tok = tok.next
|
||||
if not isFunctionCall(tok):
|
||||
if not isFunctionCall(tok, data.standards.c):
|
||||
continue
|
||||
f = tok.astOperand1.function
|
||||
if f is not None and f not in calls:
|
||||
|
@ -1998,7 +1991,7 @@ class MisraChecker:
|
|||
def misra_20_4(self, data):
|
||||
for directive in data.directives:
|
||||
res = re.search(r'#define ([a-z][a-z0-9_]+)', directive.str)
|
||||
if res and (res.group(1) in KEYWORDS):
|
||||
if res and isKeyword(res.group(1), data.standards.c):
|
||||
self.reportError(directive, 20, 4)
|
||||
|
||||
def misra_20_5(self, data):
|
||||
|
|
|
@ -955,6 +955,7 @@ union misra_19_2 { }; // 19.2
|
|||
#include "notfound.h" // 20.1
|
||||
|
||||
#define int short // 20.4
|
||||
#define inline "foo" // no warning in C90 standard
|
||||
#undef X // 20.5
|
||||
|
||||
#define M_20_7_1(A) (A+1) // 20.7
|
||||
|
|
Loading…
Reference in New Issue