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:
Georgy Komarov 2020-02-09 12:46:13 +03:00 committed by GitHub
parent e9b7e7811b
commit 6d4eff46be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 37 deletions

View File

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

View File

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