Misra: Added 17.2 checker
This commit is contained in:
parent
526a86dc60
commit
f524bf79ad
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
Loading…
Reference in New Issue