@@ -1349,15 +1349,83 @@ def misra_12_2(self, data):
13491349 if maxval >= sz :
13501350 self .reportError (token , 12 , 2 )
13511351
1352- def misra_12_3 (self , data ):
1352+ def misra_12_3 (self , data , rawTokens , filename ):
1353+ # We need an additional check for closing braces using in
1354+ # initialization lists and function calls, e.g.:
1355+ # struct S a = {1, 2, 3}, b, c = foo(1, 2), d;
1356+ # ^ ^
1357+ end_tokens_map = {}
1358+
13531359 for token in data .tokenlist :
1354- if token .str != ',' or token .scope .type == 'Enum' or \
1355- token .scope .type == 'Class' or token .scope .type == 'Global' :
1356- continue
1357- if token .astParent and token .astParent .str in ['(' , ',' , '{' ]:
1360+ if token .scope .type in ('Enum' , 'Class' , 'Struct' , 'Global' ):
13581361 continue
1362+ # Save end tokens from function calls in initialization
1363+ if simpleMatch (token , ') ;' ):
1364+ if (token .isExpandedMacro ):
1365+ end_tokens_map .setdefault (token .next .linenr , set ())
1366+ end_tokens_map [token .linenr ].add (token .next .column )
1367+ else :
1368+ end_tokens_map .setdefault (token .linenr , set ())
1369+ end_tokens_map [token .linenr ].add (token .column )
1370+ if token .str != ',' :
1371+ continue
1372+ if token .astParent :
1373+ if token .astParent .str in ('(' , '{' ):
1374+ end_token = token .astParent .link
1375+ if end_token :
1376+ end_tokens_map .setdefault (end_token .linenr , set ())
1377+ end_tokens_map [end_token .linenr ].add (end_token .column )
1378+ continue
1379+ elif token .astParent .str == ',' :
1380+ continue
13591381 self .reportError (token , 12 , 3 )
13601382
1383+ # Cppcheck performs some simplifications in variables declaration code:
1384+ # int a, b, c;
1385+ # Will be reresented in dump file as:
1386+ # int a; int b; int c;
1387+ name_tokens_map = {}
1388+ for v in data .variables :
1389+ if v .isArgument :
1390+ continue
1391+ nt = v .nameToken
1392+ if nt and nt .scope and nt .scope .type not in ('Enum' , 'Class' , 'Struct' ):
1393+ name_tokens_map .setdefault (nt .linenr , set ())
1394+ name_tokens_map [nt .linenr ].add (nt .column )
1395+ if not name_tokens_map :
1396+ return
1397+
1398+ # Select tokens to check
1399+ maybe_map = {}
1400+ for linenr in set (name_tokens_map .keys ()) | set (end_tokens_map .keys ()):
1401+ maybe_map [linenr ] = name_tokens_map .get (linenr , set ())
1402+ maybe_map [linenr ] |= end_tokens_map .get (linenr , set ())
1403+
1404+ # Check variables declaration code in raw tokens to distinguish ';' and
1405+ # ',' symbols.
1406+ STATE_SKIP = 0
1407+ STATE_CHECK = 1
1408+ state = STATE_SKIP
1409+ cur_line = min (maybe_map )
1410+ for tok in rawTokens :
1411+ if tok .linenr in maybe_map and tok .column in maybe_map [tok .linenr ]:
1412+ if tok .linenr in end_tokens_map and tok .column in end_tokens_map [tok .linenr ]:
1413+ if tok .str == ',' or (tok .next and tok .next .str == ',' ):
1414+ self .reportError (tok , 12 , 3 )
1415+ end_tokens_map [tok .linenr ].remove (tok .column )
1416+ state = STATE_CHECK
1417+ cur_line = tok .linenr
1418+ if tok .str in ('(' , ';' , '{' ):
1419+ state = STATE_SKIP
1420+ if tok .linenr > cur_line :
1421+ maybe_map .pop (cur_line )
1422+ if not maybe_map :
1423+ break
1424+ cur_line = min (maybe_map )
1425+ if state == STATE_CHECK and tok .str == ',' :
1426+ self .reportError (tok , 12 , 3 )
1427+
1428+
13611429 def misra_12_4 (self , data ):
13621430 if typeBits ['INT' ] == 16 :
13631431 max_uint = 0xffff
@@ -2454,18 +2522,18 @@ def printStatus(self, *args, **kwargs):
24542522 if not self .settings .quiet :
24552523 print (* args , ** kwargs )
24562524
2457- def executeCheck (self , rule_num , check_function , arg ):
2525+ def executeCheck (self , rule_num , check_function , * args ):
24582526 """Execute check function for a single MISRA rule.
24592527
24602528 :param rule_num: Number of rule in hundreds format
24612529 :param check_function: Check function to execute
2462- :param arg : Check function argument
2530+ :param args : Check function arguments
24632531 """
24642532 if not self .isRuleGloballySuppressed (rule_num ):
2465- check_function (arg )
2533+ check_function (* args )
24662534
24672535 def parseDump (self , dumpfile ):
2468-
2536+ filename = '.' . join ( dumpfile . split ( '.' )[: - 1 ])
24692537 data = cppcheckdata .parsedump (dumpfile )
24702538
24712539 self .dumpfileSuppressions = data .suppressions
@@ -2530,7 +2598,7 @@ def parseDump(self, dumpfile):
25302598 self .executeCheck (1201 , self .misra_12_1_sizeof , data .rawTokens )
25312599 self .executeCheck (1201 , self .misra_12_1 , cfg )
25322600 self .executeCheck (1202 , self .misra_12_2 , cfg )
2533- self .executeCheck (1203 , self .misra_12_3 , cfg )
2601+ self .executeCheck (1203 , self .misra_12_3 , cfg , data . rawTokens , filename )
25342602 self .executeCheck (1204 , self .misra_12_4 , cfg )
25352603 self .executeCheck (1301 , self .misra_13_1 , cfg )
25362604 self .executeCheck (1303 , self .misra_13_3 , cfg )
0 commit comments