@@ -150,7 +150,7 @@ void CheckStl::iterators()
150150 }
151151
152152 // invalidate the iterator if it is erased
153- else if (tok2->strAt (2 ) == std::string ( " erase" )) {
153+ else if (tok2->strAt (2 ) == " erase" && (tok2-> strAt ( 4 ) != " * " || (container && tok2-> varId () == container-> declarationId ()) )) {
154154 validIterator = false ;
155155 eraseToken = tok2;
156156 invalidationScope = tok2->scope ();
@@ -593,128 +593,100 @@ void CheckStl::pushback()
593593 }
594594
595595 // Iterator becomes invalid after reserve, resize, insert, push_back or push_front..
596- for (std::size_t i = 0 ; i < functions; ++i) {
597- const Scope * scope = symbolDatabase->functionScopes [i];
598- for (const Token* tok = scope->classStart ->next (); tok && tok != scope->classEnd ; tok = tok->next ()) {
599- if (!Token::simpleMatch (tok, " vector <" ))
600- continue ;
601-
602- // if iterator declaration inside for() loop
603- bool iteratorDeclaredInsideLoop = false ;
604- if ((tok->tokAt (-2 ) && Token::simpleMatch (tok->tokAt (-2 ), " for (" )) ||
605- (tok->tokAt (-4 ) && Token::simpleMatch (tok->tokAt (-4 ), " for ( std ::" ))) {
606- iteratorDeclaredInsideLoop = true ;
607- }
608-
609- while (tok && tok->str () != " >" )
610- tok = tok->next ();
611- if (!tok)
612- break ;
613- if (!Token::Match (tok, " > :: iterator|const_iterator %var% =|;" ))
614- continue ;
615-
616- const unsigned int iteratorid (tok->tokAt (3 )->varId ());
617- if (iteratorid == 0 )
618- continue ;
596+ for (unsigned int iteratorId = 1 ; iteratorId < symbolDatabase->getVariableListSize (); iteratorId++) {
597+ const Variable* var = symbolDatabase->getVariableFromVarId (iteratorId);
619598
620- if (iteratorDeclaredInsideLoop && tok->strAt (4 ) == " =" ) {
621- // skip "> :: iterator|const_iterator"
622- tok = tok->tokAt (3 );
623- }
599+ // Check that its an iterator
600+ if (!var || !var->isLocal () || !Token::Match (var->typeEndToken (), " iterator|const_iterator|reverse_iterator|const_reverse_iterator" ))
601+ continue ;
624602
625- // the variable id for the vector
626- unsigned int vectorid = 0 ;
603+ // ... on std::vector
604+ if (!Token::Match (var->typeStartToken (), " std| ::| vector <" ))
605+ continue ;
627606
628- // count { , } and parentheses for tok2
629- int indent = 0 ;
607+ // the variable id for the vector
608+ unsigned int vectorid = 0 ;
630609
631- const Token* validatingToken = 0 ;
610+ const Token* validatingToken = 0 ;
632611
633- std::string invalidIterator;
634- for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next ()) {
635- if (tok2->str () == " {" || tok2->str () == " (" )
636- ++indent;
637- else if (tok2->str () == " }" || tok2->str () == " )" ) {
638- if (indent == 0 && Token::simpleMatch (tok2, " ) {" ))
639- tok2 = tok2->next ();
640- else
641- --indent;
642- }
612+ std::string invalidIterator;
613+ const Token* end2 = var->scope ()->classEnd ;
614+ for (const Token *tok2 = var->nameToken (); tok2 != end2; tok2 = tok2->next ()) {
643615
644- if (validatingToken == tok2) {
645- invalidIterator.clear ();
646- validatingToken = 0 ;
647- }
616+ if (validatingToken == tok2) {
617+ invalidIterator.clear ();
618+ validatingToken = 0 ;
619+ }
648620
649- // Using push_back or push_front inside a loop..
650- if (Token::simpleMatch (tok2, " for (" )) {
651- tok2 = tok2->tokAt (2 );
652- ++indent;
653- }
621+ // Using push_back or push_front inside a loop..
622+ if (Token::simpleMatch (tok2, " for (" )) {
623+ tok2 = tok2->tokAt (2 );
624+ }
654625
655- if (Token::Match (tok2, " %varid% = %var% . begin|rbegin|cbegin|crbegin ( ) ; %varid% != %var% . end|rend|cend|crend ( ) ; ++| %varid% ++| ) {" , iteratorid )) {
656- // variable id for the loop iterator
657- const unsigned int varId (tok2->tokAt (2 )->varId ());
658- if (varId == 0 )
659- continue ;
626+ if (Token::Match (tok2, " %varid% = %var% . begin|rbegin|cbegin|crbegin ( ) ; %varid% != %var% . end|rend|cend|crend ( ) ; ++| %varid% ++| ) {" , iteratorId )) {
627+ // variable id for the loop iterator
628+ const unsigned int varId (tok2->tokAt (2 )->varId ());
629+ if (varId == 0 )
630+ continue ;
660631
661- const Token *pushbackTok = nullptr ;
632+ const Token *pushbackTok = nullptr ;
662633
663- // Count { and } for tok3
664- const Token *tok3 = tok2->tokAt (20 );
665- for (const Token* const end3 = tok3->linkAt (-1 ); tok3 != end3; tok3 = tok3->next ()) {
666- if (tok3->str () == " break" || tok3->str () == " return" ) {
667- pushbackTok = 0 ;
668- break ;
669- } else if (Token::Match (tok3, " %varid% . push_front|push_back|insert|reserve|resize|clear (" , varId) && !tok3->previous ()->isAssignmentOp ()) {
634+ // Count { and } for tok3
635+ const Token *tok3 = tok2->tokAt (20 );
636+ for (const Token* const end3 = tok3->linkAt (-1 ); tok3 != end3; tok3 = tok3->next ()) {
637+ if (tok3->str () == " break" || tok3->str () == " return" ) {
638+ pushbackTok = 0 ;
639+ break ;
640+ } else if (Token::Match (tok3, " %varid% . push_front|push_back|insert|reserve|resize|clear|erase (" , varId) && !tok3->previous ()->isAssignmentOp ()) {
641+ if (tok3->strAt (2 ) != " erase" || (tok3->tokAt (4 )->varId () != iteratorId && tok3->tokAt (5 )->varId () != iteratorId)) // This case is handled in: CheckStl::iterators()
670642 pushbackTok = tok3->tokAt (2 );
671- }
672643 }
673-
674- if (pushbackTok)
675- invalidIteratorError (pushbackTok, pushbackTok->str (), tok2->str ());
676644 }
677645
678- // Assigning iterator..
679- if (Token::Match (tok2, " %varid% =" , iteratorid)) {
680- if (Token::Match (tok2->tokAt (2 ), " %var% . begin|end|rbegin|rend|cbegin|cend|crbegin|crend|insert (" )) {
681- if (!invalidIterator.empty () && Token::Match (tok2->tokAt (4 ), " insert ( %varid% ," , iteratorid)) {
682- invalidIteratorError (tok2, invalidIterator, tok2->strAt (6 ));
683- break ;
684- }
685- vectorid = tok2->tokAt (2 )->varId ();
686- tok2 = tok2->linkAt (5 );
687- } else {
688- vectorid = 0 ;
689- }
690- invalidIterator = " " ;
691- }
646+ if (pushbackTok)
647+ invalidIteratorError (pushbackTok, pushbackTok->str (), tok2->str ());
648+ }
692649
693- // push_back on vector..
694- if (vectorid > 0 && Token::Match (tok2, " %varid% . push_front|push_back|insert|reserve|resize|clear (" , vectorid)) {
695- if (!invalidIterator.empty () && Token::Match (tok2->tokAt (2 ), " insert ( %varid% ," , iteratorid)) {
696- invalidIteratorError (tok2, invalidIterator, tok2->strAt (4 ));
650+ // Assigning iterator..
651+ if (Token::Match (tok2, " %varid% =" , iteratorId)) {
652+ if (Token::Match (tok2->tokAt (2 ), " %var% . begin|end|rbegin|rend|cbegin|cend|crbegin|crend|insert|erase|find (" )) {
653+ if (!invalidIterator.empty () && Token::Match (tok2->tokAt (4 ), " insert|erase ( *| %varid% )|," , iteratorId)) {
654+ invalidIteratorError (tok2, invalidIterator, var->name ());
697655 break ;
698656 }
657+ vectorid = tok2->tokAt (2 )->varId ();
658+ tok2 = tok2->linkAt (5 );
659+ } else {
660+ vectorid = 0 ;
661+ }
662+ invalidIterator = " " ;
663+ }
699664
700- invalidIterator = tok2->strAt (2 );
701- tok2 = tok2->linkAt (3 );
665+ // push_back on vector..
666+ if (vectorid > 0 && Token::Match (tok2, " %varid% . push_front|push_back|insert|reserve|resize|clear|erase (" , vectorid)) {
667+ if (!invalidIterator.empty () && Token::Match (tok2->tokAt (2 ), " insert|erase ( *| %varid% ,|)" , iteratorId)) {
668+ invalidIteratorError (tok2, invalidIterator, var->name ());
669+ break ;
702670 }
703671
704- else if (tok2->str () == " return" || tok2->str () == " throw" )
705- validatingToken = Token::findsimplematch (tok2->next (), " ;" );
672+ if (tok2->strAt (2 ) != " erase" || (tok2->tokAt (4 )->varId () != iteratorId && tok2->tokAt (5 )->varId () != iteratorId)) // This case is handled in: CheckStl::iterators()
673+ invalidIterator = tok2->strAt (2 );
674+ tok2 = tok2->linkAt (3 );
675+ }
706676
707- // TODO: instead of bail out for 'else' try to check all execution paths.
708- else if (tok2->str () == " break" || tok2->str () == " else" )
709- invalidIterator.clear ();
677+ else if (tok2->str () == " return" || tok2->str () == " throw" )
678+ validatingToken = Token::findsimplematch (tok2->next (), " ;" );
710679
711- // Using invalid iterator..
712- if (!invalidIterator.empty ()) {
713- if (Token::Match (tok2, " ++|--|*|+|-|(|,|=|!= %varid%" , iteratorid))
714- invalidIteratorError (tok2, invalidIterator, tok2->strAt (1 ));
715- if (Token::Match (tok2, " %varid% ++|--|+|-|." , iteratorid))
716- invalidIteratorError (tok2, invalidIterator, tok2->str ());
717- }
680+ // TODO: instead of bail out for 'else' try to check all execution paths.
681+ else if (tok2->str () == " break" || tok2->str () == " else" )
682+ invalidIterator.clear ();
683+
684+ // Using invalid iterator..
685+ if (!invalidIterator.empty ()) {
686+ if (Token::Match (tok2, " ++|--|*|+|-|(|,|=|!= %varid%" , iteratorId))
687+ invalidIteratorError (tok2, invalidIterator, tok2->strAt (1 ));
688+ if (Token::Match (tok2, " %varid% ++|--|+|-|." , iteratorId))
689+ invalidIteratorError (tok2, invalidIterator, tok2->str ());
718690 }
719691 }
720692 }
0 commit comments