Misra: Added 17.2 checker

This commit is contained in:
Daniel Marjamäki 2019-07-13 15:09:50 +02:00
parent 526a86dc60
commit f524bf79ad
3 changed files with 91 additions and 2 deletions

View File

@ -88,7 +88,6 @@ class ValueType:
return self.typeScope and self.typeScope.type == "Enum" return self.typeScope and self.typeScope.type == "Enum"
class Token: class Token:
""" """
Token class. Contains information about each token in the source code. Token class. Contains information about each token in the source code.
@ -288,6 +287,8 @@ class Scope:
className Name of this scope. className Name of this scope.
For a function scope, this is the function name; For a function scope, this is the function name;
For a class scope, this is the class 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 type Type of scope: Global, Function, Class, If, While
""" """
@ -297,6 +298,8 @@ class Scope:
bodyEndId = None bodyEndId = None
bodyEnd = None bodyEnd = None
className = None className = None
functionId = None
function = None
nestedInId = None nestedInId = None
nestedIn = None nestedIn = None
type = None type = None
@ -305,6 +308,8 @@ class Scope:
def __init__(self, element): def __init__(self, element):
self.Id = element.get('id') self.Id = element.get('id')
self.className = element.get('className') self.className = element.get('className')
self.functionId = element.get('function')
self.function = None
self.bodyStartId = element.get('bodyStart') self.bodyStartId = element.get('bodyStart')
self.bodyStart = None self.bodyStart = None
self.bodyEndId = element.get('bodyEnd') self.bodyEndId = element.get('bodyEnd')
@ -318,6 +323,7 @@ class Scope:
self.bodyStart = IdMap[self.bodyStartId] self.bodyStart = IdMap[self.bodyStartId]
self.bodyEnd = IdMap[self.bodyEndId] self.bodyEnd = IdMap[self.bodyEndId]
self.nestedIn = IdMap[self.nestedInId] self.nestedIn = IdMap[self.nestedInId]
self.function = IdMap[self.functionId]
class Function: class Function:
@ -325,6 +331,12 @@ class Function:
Information about a function Information about a function
C++ class: C++ class:
http://cppcheck.net/devinfo/doxyoutput/classFunction.html 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 Id = None

View File

@ -1580,6 +1580,54 @@ class MisraChecker:
elif token.str == 'va_list': elif token.str == 'va_list':
self.reportError(token, 17, 1) 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): def misra_17_6(self, rawTokens):
for token in rawTokens: for token in rawTokens:
@ -2313,6 +2361,7 @@ class MisraChecker:
self.misra_16_6(cfg) self.misra_16_6(cfg)
self.misra_16_7(cfg) self.misra_16_7(cfg)
self.misra_17_1(cfg) self.misra_17_1(cfg)
self.misra_17_2(cfg)
if cfgNumber == 1: if cfgNumber == 1:
self.misra_17_6(data.rawTokens) self.misra_17_6(data.rawTokens)
self.misra_17_7(cfg) self.misra_17_7(cfg)

View File

@ -224,8 +224,9 @@ void misra_11_7(int *p, float f) {
y = ( int * ) f; //11.7 y = ( int * ) f; //11.7
} }
char * misra_11_8_const(const char *str) { }
char * misra_11_8(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 return (char *)str; // 11.8
} }
@ -495,6 +496,33 @@ void misra_17_1() {
va_copy(); // 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 void misra_17_6(int x[static 20]) {} // 17.6
int calculation(int x) { return x + 1; } int calculation(int x) { return x + 1; }