Esempio n. 1
0
void CheckStl::pushback()
{
    // Pointer can become invalid after push_back or push_front..
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
    {
        if (Token::Match(tok, "%var% = & %var% ["))
        {
            const unsigned int pointerId(tok->varId());
            const unsigned int containerId(tok->tokAt(3)->varId());
            if (pointerId == 0 || containerId == 0)
                continue;

            int indent = 0;
            bool invalidPointer = false;
            for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next())
            {
                if (tok2->str() == "{" || tok2->str() == "(")
                    ++indent;
                else if (tok2->str() == "}" || tok2->str() == ")")
                {
                    if (indent == 0 && Token::simpleMatch(tok2, ") {"))
                        tok2 = tok2->next();
                    else
                        --indent;
                }

                // push_back on vector..
                if (Token::Match(tok2, "%varid% . push_front|push_back", containerId))
                    invalidPointer = true;

                // Using invalid pointer..
                if (invalidPointer && tok2->varId() == pointerId)
                {
                    if (tok2->previous()->str() == "*")
                        invalidPointerError(tok2, tok2->str());
                    else if (tok2->next()->str() == ".")
                        invalidPointerError(tok2, tok2->str());
                    break;
                }
            }
        }
    }

    // Iterator becomes invalid after push_back or push_front..
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
    {
        if (!Token::simpleMatch(tok, "vector <"))
            continue;

        // if iterator declaration inside for() loop
        bool iteratorDeclaredInsideLoop = false;
        if ((tok->tokAt(-2) && Token::simpleMatch(tok->tokAt(-2), "for (")) ||
            (tok->tokAt(-4) && Token::simpleMatch(tok->tokAt(-4), "for ( std ::")))
        {
            iteratorDeclaredInsideLoop = true;
        }

        while (tok && tok->str() != ">")
            tok = tok->next();
        if (!tok)
            break;
        if (!Token::Match(tok, "> :: iterator|const_iterator %var% =|;"))
            continue;

        const unsigned int iteratorid(tok->tokAt(3)->varId());
        if (iteratorid == 0)
            continue;

        if (iteratorDeclaredInsideLoop && tok->tokAt(4)->str() == "=")
        {
            // skip "> :: iterator|const_iterator"
            tok = tok->tokAt(3);
        }

        unsigned int vectorid = 0;
        int indent = 0;
        std::string invalidIterator;
        for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next())
        {
            if (tok2->str() == "{" || tok2->str() == "(")
                ++indent;
            else if (tok2->str() == "}" || tok2->str() == ")")
            {
                if (indent == 0 && Token::simpleMatch(tok2, ") {"))
                    tok2 = tok2->next();
                else
                    --indent;
            }

            // Using push_back or push_front inside a loop..
            if (Token::Match(tok2, "for ("))
            {
                tok2 = tok2->tokAt(2);
            }

            if (Token::Match(tok2, "%varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++| %varid% ++| ) {", iteratorid))
            {
                const unsigned int vectorid(tok2->tokAt(2)->varId());
                if (vectorid == 0)
                    continue;

                const Token *pushback = 0;
                unsigned int indent3 = 0;
                for (const Token *tok3 = tok2->tokAt(20); tok3; tok3 = tok3->next())
                {
                    if (tok3->str() == "{")
                        ++indent3;
                    else if (tok3->str() == "}")
                    {
                        if (indent3 <= 1)
                            break;
                        --indent3;
                    }
                    else if (tok3->str() == "break")
                    {
                        pushback = 0;
                        break;
                    }
                    else if (Token::Match(tok3, "%varid% . push_front|push_back|insert (", vectorid))
                    {
                        pushback = tok3->tokAt(2);
                    }
                }

                if (pushback)
                    invalidIteratorError(pushback, pushback->str(), tok2->strAt(0));
            }

            // Assigning iterator..
            if (Token::Match(tok2, "%varid% =", iteratorid))
            {
                if (Token::Match(tok2->tokAt(2), "%var% . begin|end|rbegin|rend ( )"))
                {
                    vectorid = tok2->tokAt(2)->varId();
                    tok2 = tok2->tokAt(6);
                }
                else
                {
                    vectorid = 0;
                }
                invalidIterator = "";
            }

            // push_back on vector..
            if (vectorid > 0 && Token::Match(tok2, "%varid% . push_front|push_back|insert (", vectorid))
            {
                if (!invalidIterator.empty() && Token::Match(tok2->tokAt(2), "insert ( %varid% ,", iteratorid))
                {
                    invalidIteratorError(tok2, invalidIterator, tok2->strAt(4));
                    break;
                }

                invalidIterator = tok2->strAt(2);
                if (!iteratorDeclaredInsideLoop)
                {
                    tok2 = tok2->tokAt(3)->link();
                    if (!tok2)
                        break;
                }
            }

            // Using invalid iterator..
            if (!invalidIterator.empty())
            {
                if (Token::Match(tok2, "++|--|*|+|-|(|,|=|!= %varid%", iteratorid))
                    invalidIteratorError(tok2, invalidIterator, tok2->strAt(1));
                if (Token::Match(tok2, "%varid% ++|--|+|-", iteratorid))
                    invalidIteratorError(tok2, invalidIterator, tok2->str());
            }
        }
    }
}
Esempio n. 2
0
void CheckStl::iterators()
{
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
    {
        if (!Token::Match(tok, "%var% = %var% . begin ( ) ;|+"))
            continue;

        const unsigned int iteratorId(tok->varId());
        const unsigned int containerId(tok->tokAt(2)->varId());
        if (iteratorId == 0 || containerId == 0)
            continue;

        bool validIterator = true;
        unsigned int indent = 0;
        for (const Token *tok2 = tok->tokAt(7); tok2; tok2 = tok2->next())
        {
            if (tok2->str() == "{" && ++indent)
                continue;
            if (tok2->str() == "}" && --indent == 0)
                break;

            if (Token::Match(tok2, "%varid% != %var% . end ( )", iteratorId) && tok2->tokAt(2)->varId() != containerId)
            {
                iteratorsError(tok2, tok->strAt(2), tok2->strAt(2));
                tok2 = tok2->tokAt(6);
            }
            else if (Token::Match(tok2, "%var% . insert|erase ( %varid% )|,", iteratorId))
            {
                if (!validIterator)
                    invalidIteratorError(tok2, tok2->strAt(4));

                if (tok2->varId() != containerId && tok2->tokAt(5)->str() != ".")
                {
                    // skip error message if container is a set..
                    if (tok2->varId() > 0)
                    {
                        const Token *decltok = Token::findmatch(_tokenizer->tokens(), "%varid%", tok2->varId());
                        while (decltok && !Token::Match(decltok, "[;{},(]"))
                            decltok = decltok->previous();
                        if (Token::Match(decltok, "%any% const| std :: set"))
                            continue;	// No warning
                    }

                    // Show error message, mismatching iterator is used.
                    iteratorsError(tok2, tok->strAt(2), tok2->str());
                }
                else if (tok2->strAt(2) == std::string("erase"))
                    validIterator = false;

                tok2 = tok2->tokAt(4);
            }
            else if (Token::Match(tok2, "%varid% = %var% . erase (", iteratorId))
            {
                validIterator = true;
                tok2 = tok2->tokAt(5)->link();
                if (!tok2)
                    break;
            }
            else if (Token::Match(tok2, "%varid% = %var% ;", iteratorId))
            {
                validIterator = true;
                tok2 = tok2->tokAt(2);
            }
            else if (!validIterator && Token::Match(tok2, "* %varid%", iteratorId))
            {
                dereferenceErasedError(tok2, tok2->strAt(1));
                tok2 = tok2->next();
            }
            else if (!validIterator && Token::Match(tok2, "%varid% . %var%", iteratorId))
            {
                dereferenceErasedError(tok2, tok2->strAt(0));
                tok2 = tok2->tokAt(2);
            }
            else if (Token::Match(tok2, "%var% . erase ( * %varid%", iteratorId) && tok2->varId() == containerId)
            {
                eraseByValueError(tok2, tok2->strAt(0), tok2->strAt(5));
            }
            else if (Token::Match(tok2, "return|break ;"))
            {
                validIterator = true;
            }
        }
    }
}