misra_14_2 various fixes (#4324)
This commit is contained in:
parent
9b4973d711
commit
be658e2392
|
@ -711,6 +711,7 @@ def getForLoopCounterVariables(forToken):
|
||||||
if not tn or tn.str != '(':
|
if not tn or tn.str != '(':
|
||||||
return None
|
return None
|
||||||
vars_defined = set()
|
vars_defined = set()
|
||||||
|
vars_initialized = set()
|
||||||
vars_exit = set()
|
vars_exit = set()
|
||||||
vars_modified = set()
|
vars_modified = set()
|
||||||
cur_clause = 1
|
cur_clause = 1
|
||||||
|
@ -722,14 +723,16 @@ def getForLoopCounterVariables(forToken):
|
||||||
elif cur_clause == 2:
|
elif cur_clause == 2:
|
||||||
vars_exit.add(tn.variable)
|
vars_exit.add(tn.variable)
|
||||||
elif cur_clause == 3:
|
elif cur_clause == 3:
|
||||||
if tn.next and hasSideEffectsRecursive(tn.next):
|
if tn.next and countSideEffectsRecursive(tn.next) > 0:
|
||||||
vars_modified.add(tn.variable)
|
vars_modified.add(tn.variable)
|
||||||
elif tn.previous and tn.previous.str in ('++', '--'):
|
elif tn.previous and tn.previous.str in ('++', '--'):
|
||||||
vars_modified.add(tn.variable)
|
vars_modified.add(tn.variable)
|
||||||
|
if cur_clause == 1 and tn.isAssignmentOp and tn.astOperand1.variable:
|
||||||
|
vars_initialized.add(tn.astOperand1.variable)
|
||||||
if tn.str == ';':
|
if tn.str == ';':
|
||||||
cur_clause += 1
|
cur_clause += 1
|
||||||
tn = tn.next
|
tn = tn.next
|
||||||
return vars_defined & vars_exit & vars_modified
|
return vars_defined | vars_initialized, vars_exit & vars_modified
|
||||||
|
|
||||||
|
|
||||||
def findCounterTokens(cond):
|
def findCounterTokens(cond):
|
||||||
|
@ -779,23 +782,23 @@ def isFloatCounterInWhileLoop(whileToken):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def hasSideEffectsRecursive(expr):
|
def countSideEffectsRecursive(expr):
|
||||||
if not expr or expr.str == ';':
|
if not expr or expr.str == ';':
|
||||||
return False
|
return 0
|
||||||
if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '[':
|
if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '[':
|
||||||
prev = expr.astOperand1.previous
|
prev = expr.astOperand1.previous
|
||||||
if prev and (prev.str == '{' or prev.str == '{'):
|
if prev and (prev.str == '{' or prev.str == '{'):
|
||||||
return hasSideEffectsRecursive(expr.astOperand2)
|
return countSideEffectsRecursive(expr.astOperand2)
|
||||||
if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '.':
|
if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '.':
|
||||||
e = expr.astOperand1
|
e = expr.astOperand1
|
||||||
while e and e.str == '.' and e.astOperand2:
|
while e and e.str == '.' and e.astOperand2:
|
||||||
e = e.astOperand1
|
e = e.astOperand1
|
||||||
if e and e.str == '.':
|
if e and e.str == '.':
|
||||||
return False
|
return 0
|
||||||
if expr.isAssignmentOp or expr.str in {'++', '--'}:
|
if expr.isAssignmentOp or expr.str in {'++', '--'}:
|
||||||
return True
|
return 1
|
||||||
# Todo: Check function calls
|
# Todo: Check function calls
|
||||||
return hasSideEffectsRecursive(expr.astOperand1) or hasSideEffectsRecursive(expr.astOperand2)
|
return countSideEffectsRecursive(expr.astOperand1) + countSideEffectsRecursive(expr.astOperand2)
|
||||||
|
|
||||||
|
|
||||||
def isBoolExpression(expr):
|
def isBoolExpression(expr):
|
||||||
|
@ -2694,12 +2697,12 @@ class MisraChecker:
|
||||||
|
|
||||||
def misra_13_5(self, data):
|
def misra_13_5(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if token.isLogicalOp and hasSideEffectsRecursive(token.astOperand2):
|
if token.isLogicalOp and countSideEffectsRecursive(token.astOperand2) > 0:
|
||||||
self.reportError(token, 13, 5)
|
self.reportError(token, 13, 5)
|
||||||
|
|
||||||
def misra_13_6(self, data):
|
def misra_13_6(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if token.str == 'sizeof' and hasSideEffectsRecursive(token.next):
|
if token.str == 'sizeof' and countSideEffectsRecursive(token.next) > 0:
|
||||||
self.reportError(token, 13, 6)
|
self.reportError(token, 13, 6)
|
||||||
|
|
||||||
def misra_14_1(self, data):
|
def misra_14_1(self, data):
|
||||||
|
@ -2717,34 +2720,45 @@ class MisraChecker:
|
||||||
|
|
||||||
def misra_14_2(self, data):
|
def misra_14_2(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
expressions = getForLoopExpressions(token)
|
if token.str == 'for':
|
||||||
if not expressions:
|
expressions = getForLoopExpressions(token)
|
||||||
continue
|
if not expressions:
|
||||||
if expressions[0] and not expressions[0].isAssignmentOp:
|
continue
|
||||||
self.reportError(token, 14, 2)
|
if expressions[0] and not expressions[0].isAssignmentOp:
|
||||||
elif hasSideEffectsRecursive(expressions[1]):
|
self.reportError(token, 14, 2)
|
||||||
self.reportError(token, 14, 2)
|
if countSideEffectsRecursive(expressions[1]) > 0:
|
||||||
|
self.reportError(token, 14, 2)
|
||||||
|
if countSideEffectsRecursive(expressions[2]) > 1:
|
||||||
|
self.reportError(token, 14, 2)
|
||||||
|
|
||||||
# Inspect modification of loop counter in loop body
|
counter_vars_first_clause, counter_vars_exit_modified = getForLoopCounterVariables(token)
|
||||||
counter_vars = getForLoopCounterVariables(token)
|
if len(counter_vars_exit_modified) == 0:
|
||||||
outer_scope = token.scope
|
# if it's not possible to identify a loop counter, all 3 clauses must be empty
|
||||||
body_scope = None
|
for idx in range(len(expressions)):
|
||||||
tn = token.next
|
if expressions[idx]:
|
||||||
while tn and tn.next != outer_scope.bodyEnd:
|
self.reportError(token, 14, 2)
|
||||||
if tn.scope and tn.scope.nestedIn == outer_scope:
|
break
|
||||||
body_scope = tn.scope
|
elif len(counter_vars_exit_modified) > 1:
|
||||||
break
|
# there shall be a single loop counter
|
||||||
tn = tn.next
|
self.reportError(token, 14, 2)
|
||||||
if not body_scope:
|
else: # len(counter_vars_exit_modified) == 1:
|
||||||
continue
|
loop_counter = counter_vars_exit_modified.pop()
|
||||||
tn = body_scope.bodyStart
|
# if the first clause is not empty, then it shall (declare and) initialize the loop counter
|
||||||
while tn and tn != body_scope.bodyEnd:
|
if expressions[0] is not None and loop_counter not in counter_vars_first_clause:
|
||||||
if tn.variable and tn.variable in counter_vars:
|
self.reportError(token, 14, 2)
|
||||||
if tn.next:
|
|
||||||
# TODO: Check modifications in function calls
|
# Inspect modification of loop counter in loop body
|
||||||
if hasSideEffectsRecursive(tn.next):
|
body_scope = token.next.link.next.scope
|
||||||
self.reportError(tn, 14, 2)
|
if not body_scope:
|
||||||
tn = tn.next
|
continue
|
||||||
|
tn = body_scope.bodyStart
|
||||||
|
while tn and tn != body_scope.bodyEnd:
|
||||||
|
if tn.variable == loop_counter:
|
||||||
|
if tn.next:
|
||||||
|
# TODO: Check modifications in function calls
|
||||||
|
if countSideEffectsRecursive(tn.next) > 0:
|
||||||
|
self.reportError(tn, 14, 2)
|
||||||
|
tn = tn.next
|
||||||
|
|
||||||
def misra_14_4(self, data):
|
def misra_14_4(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
|
|
|
@ -894,7 +894,8 @@ void misra_12_3(int a, int b, int c) {
|
||||||
|
|
||||||
f((1,2),3); // TODO
|
f((1,2),3); // TODO
|
||||||
|
|
||||||
for (i=0; i<10; i++, j++){} // 12.3
|
// third clause: 2 persistent side effects instead of 1 (14.2)
|
||||||
|
for (i=0; i<10; i++, j++){} // 12.3 14.2
|
||||||
for (int i = 0, p = &a1; // 12.3 14.2
|
for (int i = 0, p = &a1; // 12.3 14.2
|
||||||
i < 42;
|
i < 42;
|
||||||
++i, ++p ) // 12.3
|
++i, ++p ) // 12.3
|
||||||
|
@ -1157,7 +1158,7 @@ static void misra_14_2_init_value(int32_t *var) {
|
||||||
}
|
}
|
||||||
static void misra_14_2_fn1(bool b) {
|
static void misra_14_2_fn1(bool b) {
|
||||||
for (;i++<10;) {} // 14.2
|
for (;i++<10;) {} // 14.2
|
||||||
for (;i<10;dostuff()) {} // TODO
|
for (;i<10;dostuff()) {} // 14.2
|
||||||
int32_t g = 0;
|
int32_t g = 0;
|
||||||
int g_arr[42];
|
int g_arr[42];
|
||||||
g += 2; // no-warning
|
g += 2; // no-warning
|
||||||
|
@ -1175,7 +1176,12 @@ static void misra_14_2_fn1(bool b) {
|
||||||
for (misra_14_2_init_value(&i); i < 10; ++i) {} // no-warning FIXME: False positive for 14.2 Trac #9491
|
for (misra_14_2_init_value(&i); i < 10; ++i) {} // no-warning FIXME: False positive for 14.2 Trac #9491
|
||||||
|
|
||||||
bool abort = false;
|
bool abort = false;
|
||||||
for (i = 0; (i < 10) && !abort; ++i) { // no-warning
|
for (i = 0; (i < 10) && !abort; ++i) { // 14.2 as 'i' is not a variable
|
||||||
|
if (b) {
|
||||||
|
abort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; (i < 10) && !abort; ++i) { // no warning
|
||||||
if (b) {
|
if (b) {
|
||||||
abort = true;
|
abort = true;
|
||||||
}
|
}
|
||||||
|
@ -1186,6 +1192,18 @@ static void misra_14_2_fn1(bool b) {
|
||||||
for (int i = x; i < 42; i++) {
|
for (int i = x; i < 42; i++) {
|
||||||
x++; // no warning
|
x++; // no warning
|
||||||
}
|
}
|
||||||
|
// 1st clause item 2 + loop counter modification
|
||||||
|
for(x = 0; x < 10; x++) {
|
||||||
|
x++; // 14.2
|
||||||
|
}
|
||||||
|
// third clause: 2 persistent side effects instead of 1 (14.2)
|
||||||
|
for (int i = 0; i < 10; i++, x++) { // 12.3 14.2
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 loop counters, there shall be only 1
|
||||||
|
for(int i=0, j=0; (i<10) && (j<10); i++, j++) { // 12.3 14.2
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = (x - 3); i < 42; i++) {
|
for (int i = (x - 3); i < 42; i++) {
|
||||||
x ^= 3; // no warning
|
x ^= 3; // no warning
|
||||||
}
|
}
|
||||||
|
@ -1218,16 +1236,18 @@ static void misra_14_2_fn2(void)
|
||||||
for (int i = 0, j = 19; y < 10, --j > 10; y++, j--) { // 14.2 12.3
|
for (int i = 0, j = 19; y < 10, --j > 10; y++, j--) { // 14.2 12.3
|
||||||
i++; // no warning
|
i++; // no warning
|
||||||
}
|
}
|
||||||
for (int i = 0; y < 10; y++) { // TODO: 14.2
|
// 1st clause is not empty, but is not used in 2nd and 3rd clause
|
||||||
|
for (int i = 0; y < 10; y++) { // 14.2
|
||||||
i++; // no warning
|
i++; // no warning
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; y++) { // TODO: 14.2
|
for (; y < 10; y++) {} // without 1st clause, no error
|
||||||
|
for (int i = 0; i < 10; y++) { // 14.2
|
||||||
i++; // no warning
|
i++; // no warning
|
||||||
}
|
}
|
||||||
for (int i = 0; y < 10; i++) { // TODO: 14.2
|
for (int i = 0; y < 10; i++) { // 14.2
|
||||||
i++; // no warning
|
i++; // no warning
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; (y+=i)) {
|
for (int i = 0; i < 10; (y+=i)) { // 14.2
|
||||||
i++; // no warning
|
i++; // no warning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1343,7 @@ static void misra_15_4(void) {
|
||||||
if (y==2) {
|
if (y==2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (z = 0; y < 42; ++z) {
|
for (z = 0; y < 42; ++z) { // 14.2
|
||||||
if (z==1) {
|
if (z==1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue