Skip to content

Commit 9786f1c

Browse files
authored
Suggested implementation for rule 8.2 (#3169)
1 parent e6e0cb7 commit 9786f1c

10 files changed

Lines changed: 169 additions & 88 deletions

File tree

addons/misra.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,79 @@ def reportErrorIfVariableIsNotConst(variable, stringLiteral):
14611461
if usedParameter.isString and parameterDefinition.nameToken:
14621462
reportErrorIfVariableIsNotConst(parameterDefinition.nameToken, usedParameter)
14631463

1464+
def misra_8_2(self, data, rawTokens):
1465+
def getFollowingRawTokens(rawTokens, token, count):
1466+
following =[]
1467+
for rawToken in rawTokens:
1468+
if (rawToken.file == token.file and
1469+
rawToken.linenr == token.linenr and
1470+
rawToken.column == token.column):
1471+
for _ in range(count):
1472+
rawToken = rawToken.next
1473+
# Skip comments
1474+
while rawTokens and (rawToken.str.startswith('/*') or rawToken.str.startswith('//')):
1475+
rawToken = rawToken.next
1476+
if rawToken is None:
1477+
break
1478+
following.append(rawToken)
1479+
1480+
return following
1481+
1482+
# Check arguments in function declaration
1483+
for func in data.functions:
1484+
1485+
startCall = func.tokenDef.next
1486+
if startCall is None or startCall.str != '(':
1487+
continue
1488+
1489+
endCall = startCall.link
1490+
if endCall is None or endCall.str != ')':
1491+
continue
1492+
1493+
# Zero arguments should be in form ( void )
1494+
if (len(func.argument) == 0):
1495+
voidArg = startCall.next
1496+
while voidArg is not endCall:
1497+
if voidArg.str == 'void':
1498+
break
1499+
voidArg = voidArg.next
1500+
if not voidArg.str == 'void':
1501+
self.reportError(func.tokenDef, 8, 2)
1502+
1503+
for arg in func.argument:
1504+
argument = func.argument[arg]
1505+
typeStartToken = argument.typeStartToken
1506+
if typeStartToken is None:
1507+
continue
1508+
1509+
nameToken = argument.nameToken
1510+
# Arguments should have a name unless variable length arg
1511+
if nameToken is None and typeStartToken.str != '...':
1512+
self.reportError(typeStartToken, 8, 2)
1513+
1514+
# Type declaration on next line (old style declaration list) is not allowed
1515+
if (typeStartToken.linenr > endCall.linenr) or (typeStartToken.column > endCall.column):
1516+
self.reportError(typeStartToken, 8, 2)
1517+
1518+
# Check arguments in pointer declarations
1519+
for var in data.variables:
1520+
if not var.isPointer:
1521+
continue
1522+
1523+
if var.nameToken is None:
1524+
continue
1525+
1526+
rawTokensFollowingPtr = getFollowingRawTokens(rawTokens, var.nameToken, 3)
1527+
if len(rawTokensFollowingPtr) != 3:
1528+
continue
1529+
1530+
# Compliant: returnType (*ptrName) ( ArgType )
1531+
# Non-compliant: returnType (*ptrName) ( )
1532+
if (rawTokensFollowingPtr[0].str == ')' and
1533+
rawTokensFollowingPtr[1].str == '(' and
1534+
rawTokensFollowingPtr[2].str == ')'):
1535+
self.reportError(var.nameToken, 8, 2)
1536+
14641537
def misra_8_11(self, data):
14651538
for var in data.variables:
14661539
if var.isExtern and simpleMatch(var.nameToken.next, '[ ]') and var.nameToken.scope.type == 'Global':
@@ -3095,6 +3168,8 @@ def parseDump(self, dumpfile):
30953168
if cfgNumber == 0:
30963169
self.executeCheck(703, self.misra_7_3, data.rawTokens)
30973170
self.executeCheck(704, self.misra_7_4, cfg)
3171+
if cfgNumber == 0:
3172+
self.executeCheck(802, self.misra_8_2, cfg, data.rawTokens)
30983173
self.executeCheck(811, self.misra_8_11, cfg)
30993174
self.executeCheck(812, self.misra_8_12, cfg)
31003175
if cfgNumber == 0:

0 commit comments

Comments
 (0)