CheckStl: Added comments
This commit is contained in:
parent
d005245188
commit
c7f2ddf63c
|
@ -47,35 +47,54 @@ void CheckStl::dereferenceErasedError(const Token *tok, const std::string &itern
|
||||||
|
|
||||||
void CheckStl::iterators()
|
void CheckStl::iterators()
|
||||||
{
|
{
|
||||||
|
// Using same iterator against different containers.
|
||||||
|
// for (it = foo.begin(); it != bar.end(); ++it)
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
|
// Locate an iterator..
|
||||||
if (!Token::Match(tok, "%var% = %var% . begin ( ) ;|+"))
|
if (!Token::Match(tok, "%var% = %var% . begin ( ) ;|+"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Get variable ids for both the iterator and container
|
||||||
const unsigned int iteratorId(tok->varId());
|
const unsigned int iteratorId(tok->varId());
|
||||||
const unsigned int containerId(tok->tokAt(2)->varId());
|
const unsigned int containerId(tok->tokAt(2)->varId());
|
||||||
if (iteratorId == 0 || containerId == 0)
|
if (iteratorId == 0 || containerId == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// the validIterator flag says if the iterator has a valid value or not
|
||||||
bool validIterator = true;
|
bool validIterator = true;
|
||||||
|
|
||||||
|
// counter for { and }
|
||||||
unsigned int indent = 0;
|
unsigned int indent = 0;
|
||||||
|
|
||||||
|
// Scan through the rest of the code and see if the iterator is
|
||||||
|
// used against other containers.
|
||||||
for (const Token *tok2 = tok->tokAt(7); tok2; tok2 = tok2->next())
|
for (const Token *tok2 = tok->tokAt(7); tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
|
// If a { is found then count it and continue
|
||||||
if (tok2->str() == "{" && ++indent)
|
if (tok2->str() == "{" && ++indent)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// If a } is found then count it. break if indentlevel becomes 0.
|
||||||
if (tok2->str() == "}" && --indent == 0)
|
if (tok2->str() == "}" && --indent == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Is iterator compared against different container?
|
||||||
if (Token::Match(tok2, "%varid% != %var% . end ( )", iteratorId) && tok2->tokAt(2)->varId() != containerId)
|
if (Token::Match(tok2, "%varid% != %var% . end ( )", iteratorId) && tok2->tokAt(2)->varId() != containerId)
|
||||||
{
|
{
|
||||||
iteratorsError(tok2, tok->strAt(2), tok2->strAt(2));
|
iteratorsError(tok2, tok->strAt(2), tok2->strAt(2));
|
||||||
tok2 = tok2->tokAt(6);
|
tok2 = tok2->tokAt(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is the iterator used in a insert/erase operation?
|
||||||
else if (Token::Match(tok2, "%var% . insert|erase ( %varid% )|,", iteratorId))
|
else if (Token::Match(tok2, "%var% . insert|erase ( %varid% )|,", iteratorId))
|
||||||
{
|
{
|
||||||
|
// It is bad to insert/erase an invalid iterator
|
||||||
if (!validIterator)
|
if (!validIterator)
|
||||||
invalidIteratorError(tok2, tok2->strAt(4));
|
invalidIteratorError(tok2, tok2->strAt(4));
|
||||||
|
|
||||||
|
// If insert/erase is used on different container then
|
||||||
|
// report an error
|
||||||
if (tok2->varId() != containerId && tok2->tokAt(5)->str() != ".")
|
if (tok2->varId() != containerId && tok2->tokAt(5)->str() != ".")
|
||||||
{
|
{
|
||||||
// skip error message if container is a set..
|
// skip error message if container is a set..
|
||||||
|
@ -91,23 +110,40 @@ void CheckStl::iterators()
|
||||||
// Show error message, mismatching iterator is used.
|
// Show error message, mismatching iterator is used.
|
||||||
iteratorsError(tok2, tok->strAt(2), tok2->str());
|
iteratorsError(tok2, tok->strAt(2), tok2->str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// invalidate the iterator if it is erased
|
||||||
else if (tok2->strAt(2) == std::string("erase"))
|
else if (tok2->strAt(2) == std::string("erase"))
|
||||||
validIterator = false;
|
validIterator = false;
|
||||||
|
|
||||||
|
// skip the operation
|
||||||
tok2 = tok2->tokAt(4);
|
tok2 = tok2->tokAt(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// it = foo.erase(..
|
||||||
|
// taking the result of an erase is ok
|
||||||
else if (Token::Match(tok2, "%varid% = %var% . erase (", iteratorId))
|
else if (Token::Match(tok2, "%varid% = %var% . erase (", iteratorId))
|
||||||
{
|
{
|
||||||
|
// the returned iterator is valid
|
||||||
validIterator = true;
|
validIterator = true;
|
||||||
|
|
||||||
|
// skip the operation
|
||||||
tok2 = tok2->tokAt(5)->link();
|
tok2 = tok2->tokAt(5)->link();
|
||||||
if (!tok2)
|
if (!tok2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reassign the iterator
|
||||||
else if (Token::Match(tok2, "%varid% = %var% ;", iteratorId))
|
else if (Token::Match(tok2, "%varid% = %var% ;", iteratorId))
|
||||||
{
|
{
|
||||||
|
// Assume that the iterator becomes valid.
|
||||||
|
// TODO: is it valid?
|
||||||
validIterator = true;
|
validIterator = true;
|
||||||
|
|
||||||
|
// skip ahead
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dereferencing invalid iterator?
|
||||||
else if (!validIterator && Token::Match(tok2, "* %varid%", iteratorId))
|
else if (!validIterator && Token::Match(tok2, "* %varid%", iteratorId))
|
||||||
{
|
{
|
||||||
dereferenceErasedError(tok2, tok2->strAt(1));
|
dereferenceErasedError(tok2, tok2->strAt(1));
|
||||||
|
@ -122,10 +158,16 @@ void CheckStl::iterators()
|
||||||
{
|
{
|
||||||
// eraseByValueError(tok2, tok2->strAt(0), tok2->strAt(5));
|
// eraseByValueError(tok2, tok2->strAt(0), tok2->strAt(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bailout handling. Assume that the iterator becomes valid if we see return/break.
|
||||||
|
// TODO: better handling
|
||||||
else if (Token::Match(tok2, "return|break ;"))
|
else if (Token::Match(tok2, "return|break ;"))
|
||||||
{
|
{
|
||||||
validIterator = true;
|
validIterator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bailout handling. Assume that the iterator becomes valid if we see else.
|
||||||
|
// TODO: better handling
|
||||||
else if (tok2->str() == "else")
|
else if (tok2->str() == "else")
|
||||||
{
|
{
|
||||||
validIterator = true;
|
validIterator = true;
|
||||||
|
@ -143,6 +185,7 @@ void CheckStl::mismatchingContainersError(const Token *tok)
|
||||||
|
|
||||||
void CheckStl::mismatchingContainers()
|
void CheckStl::mismatchingContainers()
|
||||||
{
|
{
|
||||||
|
// Check if different containers are used in various calls of standard functions
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (tok->str() != "std")
|
if (tok->str() != "std")
|
||||||
|
|
Loading…
Reference in New Issue