diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index ccfbf895b..ad18608c1 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -67,9 +67,17 @@ void CheckStl::iterators() const Variable* var = symbolDatabase->getVariableFromVarId(iteratorId); // Check that its an iterator - if (!var || !var->isLocal() || !Token::Match(var->nameToken()->previous(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator")) + if (!var || !var->isLocal() || !Token::Match(var->typeEndToken(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator")) continue; + if (var->type()) { // If it is defined, ensure that it is defined like an iterator + // look for operator* and operator++ + const Function* end = var->type()->getFunction("operator*"); + const Function* incOperator = var->type()->getFunction("operator++"); + if (!end || end->argCount() > 0 || !incOperator) + continue; + } + // the validIterator flag says if the iterator has a valid value or not bool validIterator = Token::Match(var->nameToken()->next(), "[(=]"); const Scope* invalidationScope = 0; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 11bc17625..e5a04fc57 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1456,6 +1456,24 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons } } +const Function* Type::getFunction(const std::string& funcName) const +{ + if (classScope) { + for (std::list::const_iterator i = classScope->functionList.begin(); i != classScope->functionList.end(); ++i) + if (i->name() == funcName) + return &*i; + } + + for (std::size_t i = 0; i < derivedFrom.size(); i++) { + if (derivedFrom[i].type) { + const Function* func = derivedFrom[i].type->getFunction(funcName); + if (func) + return func; + } + } + return 0; +} + bool Variable::arrayDimensions(std::vector &dimensions, const Token *tok) { bool isArray = false; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 0ca03b0ac..b710c3329 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -95,6 +95,8 @@ public: } const Token *initBaseInfo(const Token *tok, const Token *tok1); + + const Function* getFunction(const std::string& funcName) const; }; /** @brief Information about a member variable. */ diff --git a/test/teststl.cpp b/test/teststl.cpp index 7237d48f5..f8419aade 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -93,6 +93,7 @@ private: TEST_CASE(stlBoundaries2); TEST_CASE(stlBoundaries3); TEST_CASE(stlBoundaries4); // #4364 + TEST_CASE(stlBoundaries5); // #4352 // if (str.find("ab")) TEST_CASE(if_find); @@ -1329,6 +1330,26 @@ private: ASSERT_EQUALS("[test.cpp:4]: (error) Dangerous iterator comparison using operator< on 'std::forward_list'.\n", errout.str()); } + void stlBoundaries5() { + check("class iterator { int foo(); };\n" + "int foo() {\n" + " iterator i;\n" + " return i.foo();;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("class iterator {\n" + " Class operator*();\n" + " iterator& operator++();\n" + " int foo();\n" + "};\n" + "int foo() {\n" + " iterator i;\n" + " return i.foo();;\n" + "}"); + ASSERT_EQUALS("[test.cpp:8]: (error) Invalid iterator 'i' used.\n", errout.str()); + } + void if_find() { // --------------------------- diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 3b169725f..2e77f801c 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -576,6 +576,8 @@ private: ASSERT(function && function->token == tokenizer.tokens()->tokAt(4)); ASSERT(function && function->hasBody && function->isInline); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); + + ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("func") == function); } } @@ -1434,6 +1436,15 @@ private: ASSERT(Bar_Sub && Bar_Sub->classScope && Bar_Sub->classScope->numConstructors == 2 && Bar_Sub->classScope->className == "Sub"); } + void symboldatabase32() { + GET_SYMBOL_DB("struct Base {\n" + " void foo() {}\n" + "};\n" + "class Deri : Base {\n" + "};"); + ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->definedType->getFunction("foo")); + } + void isImplicitlyVirtual() { { GET_SYMBOL_DB("class Base {\n"