Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 53 additions & 12 deletions addons/misra.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,50 @@ def getForLoopExpressions(forToken):
lpar.astOperand2.astOperand2.astOperand2]


def hasFloatComparison(expr):
if not expr:
def findCounterTokens(cond):
if not cond:
return []
if cond.str in ['&&', '||']:
c = findCounterTokens(cond.astOperand1)
c.extend(findCounterTokens(cond.astOperand2))
return c
ret = []
if ((cond.isArithmeticalOp and cond.astOperand1 and cond.astOperand2) or
(cond.isComparisonOp and cond.astOperand1 and cond.astOperand2)):
if cond.astOperand1.isName:
ret.append(cond.astOperand1)
if cond.astOperand2.isName:
ret.append(cond.astOperand2)
if cond.astOperand1.isOp:
ret.extend(findCounterTokens(cond.astOperand1))
if cond.astOperand2.isOp:
ret.extend(findCounterTokens(cond.astOperand2))
return ret


def isFloatCounterInWhileLoop(whileToken):
if not simpleMatch(whileToken, 'while ('):
return False
lpar = whileToken.next
rpar = lpar.link
counterTokens = findCounterTokens(lpar.astOperand2)
whileBodyStart = None
if simpleMatch(rpar, ') {'):
whileBodyStart = rpar.next
elif simpleMatch(whileToken.previous, '} while') and simpleMatch(whileToken.previous.link.previous, 'do {'):
whileBodyStart = whileToken.previous.link
else:
return False
if expr.isLogicalOp:
return hasFloatComparison(expr.astOperand1) or hasFloatComparison(expr.astOperand2)
if expr.isComparisonOp:
# TODO: Use ValueType
return cppcheckdata.astIsFloat(expr.astOperand1) or cppcheckdata.astIsFloat(expr.astOperand2)
token = whileBodyStart
while (token != whileBodyStart.link):
token = token.next
for counterToken in counterTokens:
if not counterToken.valueType or not counterToken.valueType.isFloat():
continue
if token.isAssignmentOp and token.astOperand1.str == counterToken.str:
return True
if token.str == counterToken.str and token.astParent and token.astParent.str in {'++', '--'}:
return True
return False


Expand Down Expand Up @@ -1107,11 +1143,16 @@ def misra_13_6(data):

def misra_14_1(data):
for token in data.tokenlist:
if token.str != 'for':
continue
exprs = getForLoopExpressions(token)
if exprs and hasFloatComparison(exprs[1]):
reportError(token, 14, 1)
if token.str == 'for':
exprs = getForLoopExpressions(token)
if not exprs:
continue
for counter in findCounterTokens(exprs[1]):
if counter.valueType and counter.valueType.isFloat():
reportError(token, 14, 1)
elif token.str == 'while':
if isFloatCounterInWhileLoop(token):
reportError(token, 14, 1)


def misra_14_2(data):
Expand Down
11 changes: 11 additions & 0 deletions addons/test/misra-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,17 @@ void misra_13_6() {

void misra_14_1() {
for (float f=0.1f; f<1.0f; f += 0.1f){} // 14.1
float a = 0.0f;
int b = 10;
while ((a<100.0f) || (b > 100)) //14.1
{
a++;
}
do
{
;
} while ( a < 10.0f ); // no-warning

}

void misra_14_2() {
Expand Down