From 6d4eff46beb800264cfd820523a1788fa73b822a Mon Sep 17 00:00:00 2001 From: Georgy Komarov Date: Sun, 9 Feb 2020 12:46:13 +0300 Subject: [PATCH] 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. --- addons/misra.py | 67 +++++++++++++++------------------- addons/test/misra/misra-test.c | 1 + 2 files changed, 31 insertions(+), 37 deletions(-) diff --git a/addons/misra.py b/addons/misra.py index b866547a4..fc058f942 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -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): diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 58bf323a3..67b8c30d3 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -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