From f524bf79ad1ece0f1acc9d3c0395f4d2578405af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 13 Jul 2019 15:09:50 +0200 Subject: [PATCH] Misra: Added 17.2 checker --- addons/cppcheckdata.py | 14 +++++++++++- addons/misra.py | 49 ++++++++++++++++++++++++++++++++++++++++ addons/test/misra-test.c | 30 +++++++++++++++++++++++- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index f64f92a51..2e86d3449 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -88,7 +88,6 @@ class ValueType: return self.typeScope and self.typeScope.type == "Enum" - class Token: """ Token class. Contains information about each token in the source code. @@ -288,6 +287,8 @@ class Scope: className Name of this scope. For a function scope, this is the function name; For a class scope, this is the class name. + function If this scope belongs at a function call, this attribute + has the Function information. See the Function class. type Type of scope: Global, Function, Class, If, While """ @@ -297,6 +298,8 @@ class Scope: bodyEndId = None bodyEnd = None className = None + functionId = None + function = None nestedInId = None nestedIn = None type = None @@ -305,6 +308,8 @@ class Scope: def __init__(self, element): self.Id = element.get('id') self.className = element.get('className') + self.functionId = element.get('function') + self.function = None self.bodyStartId = element.get('bodyStart') self.bodyStart = None self.bodyEndId = element.get('bodyEnd') @@ -318,6 +323,7 @@ class Scope: self.bodyStart = IdMap[self.bodyStartId] self.bodyEnd = IdMap[self.bodyEndId] self.nestedIn = IdMap[self.nestedInId] + self.function = IdMap[self.functionId] class Function: @@ -325,6 +331,12 @@ class Function: Information about a function C++ class: http://cppcheck.net/devinfo/doxyoutput/classFunction.html + + Attributes + argument Argument list + tokenDef Token in function definition + isVirtual Is this function is virtual + isImplicitlyVirtual Is this function is virtual this in the base classes """ Id = None diff --git a/addons/misra.py b/addons/misra.py index b4869fd17..4a3d58ecf 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -1580,6 +1580,54 @@ class MisraChecker: elif token.str == 'va_list': self.reportError(token, 17, 1) + def misra_17_2(self, data): + # find recursions.. + def find_recursive_call(search_for_function, direct_call, calls_map, visited=set()): + if direct_call == search_for_function: + return True + for indirect_call in calls_map[direct_call]: + if indirect_call == search_for_function: + return True + if indirect_call in visited: + # This has already been handled + continue + visited.add(indirect_call) + if find_recursive_call(search_for_function, indirect_call, calls_map, visited): + return True + return False + + # List functions called in each function + function_calls = {} + for scope in data.scopes: + if scope.type != 'Function': + continue + calls = [] + tok = scope.bodyStart + while tok != scope.bodyEnd: + tok = tok.next + if not isFunctionCall(tok): + continue + f = tok.astOperand1.function + if f is not None and f not in calls: + calls.append(f) + function_calls[scope.function] = calls + + # Report warnings for all recursions.. + for func in function_calls: + for call in function_calls[func]: + if not find_recursive_call(func, call, function_calls): + # Function call is not recursive + continue + # Warn about all functions calls.. + for scope in data.scopes: + if scope.type != 'Function' or scope.function != func: + continue + tok = scope.bodyStart + while tok != scope.bodyEnd: + if tok.function and tok.function == call: + self.reportError(tok, 17, 2) + tok = tok.next + def misra_17_6(self, rawTokens): for token in rawTokens: @@ -2313,6 +2361,7 @@ class MisraChecker: self.misra_16_6(cfg) self.misra_16_7(cfg) self.misra_17_1(cfg) + self.misra_17_2(cfg) if cfgNumber == 1: self.misra_17_6(data.rawTokens) self.misra_17_7(cfg) diff --git a/addons/test/misra-test.c b/addons/test/misra-test.c index 1f90e9c50..42333f6cd 100644 --- a/addons/test/misra-test.c +++ b/addons/test/misra-test.c @@ -224,8 +224,9 @@ void misra_11_7(int *p, float f) { y = ( int * ) f; //11.7 } +char * misra_11_8_const(const char *str) { } char * misra_11_8(const char *str) { - (void)misra_11_8(str); // no-warning + (void)misra_11_8_const(str); // no-warning return (char *)str; // 11.8 } @@ -495,6 +496,33 @@ void misra_17_1() { va_copy(); // 17.1 } +void misra_17_2_ok_1(void) { ; } +void misra_17_2_ok_2(void) { + misra_17_2_ok_1(); // no-warning +} +void misra_17_2_1(void) { + misra_17_2_ok_1(); // no-warning + misra_17_2_1(); // 17.2 + misra_17_2_ok_2(); // no-warning + misra_17_2_1(); // 17.2 +} +void misra_17_2_2(void) { + misra_17_2_3(); // 17.2 +} +void misra_17_2_3(void) { + misra_17_2_4(); // 17.2 +} +void misra_17_2_4(void) { + misra_17_2_2(); // 17.2 + misra_17_2_3(); // 17.2 +} + +void misra_17_2_5(void) { + misra_17_2_ok_1(); // no-warning + misra_17_2_5(); // 17.2 + misra_17_2_1(); // no-warning +} + void misra_17_6(int x[static 20]) {} // 17.6 int calculation(int x) { return x + 1; }