diff --git a/src/checkstl.cpp b/src/checkstl.cpp index a490e8e5e..a569c60a9 100644 --- a/src/checkstl.cpp +++ b/src/checkstl.cpp @@ -88,6 +88,30 @@ void CheckStl::iterators() } +// Error message for bad iterator usage.. +void CheckStl::mismatchingContainersError(const Token *tok) +{ + reportError(tok, Severity::error, "mismatchingContainers", "mismatching containers"); +} + +void CheckStl::mismatchingContainers() +{ + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + if (tok->str() != "std") + continue; + + if (Token::Match(tok, "std :: find|find_if|count|transform|replace|replace_if|sort ( %var% . begin|rbegin ( ) , %var% . end|rend ( ) ,")) + { + if (tok->tokAt(4)->str() != tok->tokAt(10)->str()) + { + mismatchingContainersError(tok); + } + } + } +} + + void CheckStl::stlOutOfBounds() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) diff --git a/src/checkstl.h b/src/checkstl.h index 9a44ec042..2bb59d40c 100644 --- a/src/checkstl.h +++ b/src/checkstl.h @@ -49,6 +49,7 @@ public: checkStl.stlOutOfBounds(); checkStl.iterators(); + checkStl.mismatchingContainers(); checkStl.erase(); checkStl.pushback(); checkStl.stlBoundries(); @@ -67,6 +68,12 @@ public: */ void iterators(); + /** + * Mismatching containers: + * std::find(foo.begin(), bar.end(), x) + */ + void mismatchingContainers(); + /** Dereferencing an erased iterator */ void dereferenceErasedError(const Token *tok, const std::string &itername); @@ -96,6 +103,7 @@ private: void stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var); void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2); + void mismatchingContainersError(const Token *tok); void eraseError(const Token *tok); void pushbackError(const Token *tok, const std::string &func, const std::string &iterator_name); void invalidPointerError(const Token *tok, const std::string &pointer_name); @@ -104,6 +112,7 @@ private: void getErrorMessages() { iteratorsError(0, "container1", "container2"); + mismatchingContainersError(0); dereferenceErasedError(0, "iter"); stlOutOfBoundsError(0, "i", "foo"); eraseError(0); @@ -122,6 +131,7 @@ private: return "Check for invalid usage of STL:\n" " * out of bounds errors\n" " * misuse of iterators when iterating through a container\n" + " * mismatching containers in calls\n" " * dereferencing an erased iterator\n" " * for vectors: using iterator/pointer after push_back has been used\n"; } diff --git a/test/teststl.cpp b/test/teststl.cpp index e33b8a29b..61f42a77f 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -38,6 +38,7 @@ private: TEST_CASE(iterator2); TEST_CASE(iterator3); TEST_CASE(iterator4); + TEST_CASE(iterator5); TEST_CASE(dereference); TEST_CASE(dereference_member); @@ -140,6 +141,17 @@ private: ASSERT_EQUALS("", errout.str()); } + void iterator5() + { + check("void foo()\n" + "{\n" + " std::vector ints1;\n" + " std::vector ints2;\n" + " std::vector::iterator it = std::find(ints1.begin(), ints2.end(), 22);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) mismatching containers\n", errout.str()); + } + // Dereferencing invalid pointer void dereference() {