CheckStl::stlOutOfBounds() now uses <container> information from Libraries

This commit is contained in:
PKEuS 2015-01-03 22:17:35 +01:00
parent e39729ffcc
commit 7ece58c3a0
2 changed files with 29 additions and 18 deletions

View File

@ -298,10 +298,6 @@ void CheckStl::mismatchingContainers()
void CheckStl::stlOutOfBounds() void CheckStl::stlOutOfBounds()
{ {
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
static const char* const stl_bounded_container [] = {
"array", "basic_string", "deque", "string", "vector", "wstring"
};
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
// Scan through all scopes.. // Scan through all scopes..
@ -317,38 +313,50 @@ void CheckStl::stlOutOfBounds()
tok = tok->linkAt(1)->tokAt(2); tok = tok->linkAt(1)->tokAt(2);
} else } else
tok = tok->next(); tok = tok->next();
tok = tok->next();
// check if the for loop condition is wrong // check if the for loop condition is wrong
if (Token::Match(tok, ";|( %var% <= %var% . size|length ( ) ;|)|%oror%")) { if (Token::Match(tok, "%var% <= %var% . %var% ( ) ;|)|%oror%")) {
// Is it a vector? // Is it a vector?
const Variable *container = tok->tokAt(3)->variable(); const Variable *var = tok->tokAt(2)->variable();
if (!var)
continue;
const Library::Container* container = _settings->library.detectContainer(var->typeStartToken());
if (!container) if (!container)
continue; continue;
if (!container->isStlType(stl_bounded_container))
Library::Container::Yield yield = container->getYield(tok->strAt(4));
if (yield != Library::Container::SIZE)
continue; continue;
// variable id for loop variable. // variable id for loop variable.
const unsigned int numId = tok->next()->varId(); const unsigned int numId = tok->varId();
// variable id for the container variable // variable id for the container variable
const unsigned int declarationId = container->declarationId(); const unsigned int declarationId = var->declarationId();
for (const Token *tok3 = i->classStart; tok3 && tok3 != i->classEnd; tok3 = tok3->next()) { for (const Token *tok3 = i->classStart; tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
if (tok3->varId() == declarationId) { if (tok3->varId() == declarationId) {
if (Token::Match(tok3->next(), ". size|length ( )")) tok3 = tok3->next();
if (Token::Match(tok3, ". %var% ( )")) {
Library::Container::Yield yield = container->getYield(tok3->strAt(1));
if (yield == Library::Container::SIZE)
break; break;
else if (Token::Match(tok3->next(), "[ %varid% ]", numId)) } else if (container->arrayLike_indexOp && Token::Match(tok3, "[ %varid% ]", numId))
stlOutOfBoundsError(tok3, tok3->strAt(2), tok3->str(), false); stlOutOfBoundsError(tok3, tok3->strAt(1), var->name(), false);
else if (Token::Match(tok3->next(), ". at ( %varid% )", numId)) else if (Token::Match(tok3, ". %var% ( %varid% )", numId)) {
stlOutOfBoundsError(tok3, tok3->strAt(4), tok3->str(), true); Library::Container::Yield yield = container->getYield(tok3->strAt(1));
if (yield == Library::Container::AT_INDEX)
stlOutOfBoundsError(tok3, tok3->strAt(3), var->name(), true);
} }
} }
break; }
continue;
} }
} }
} }
// Error message for bad iterator usage..
void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at) void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at)
{ {
if (at) if (at)

View File

@ -31,7 +31,11 @@ public:
} }
private: private:
Settings settings;
void run() { void run() {
LOAD_LIB_2(settings.library, "std.cfg");
TEST_CASE(iterator1); TEST_CASE(iterator1);
TEST_CASE(iterator2); TEST_CASE(iterator2);
TEST_CASE(iterator3); TEST_CASE(iterator3);
@ -134,7 +138,6 @@ private:
// Clear the error buffer.. // Clear the error buffer..
errout.str(""); errout.str("");
Settings settings;
settings.addEnabled("warning"); settings.addEnabled("warning");
settings.addEnabled("style"); settings.addEnabled("style");
settings.addEnabled("performance"); settings.addEnabled("performance");