diff --git a/Makefile b/Makefile index daed0997479..baa32b81669 100644 --- a/Makefile +++ b/Makefile @@ -907,7 +907,7 @@ test/testsizeof.o: test/testsizeof.cpp lib/check.h lib/checkers.h lib/checkimpl. test/teststandards.o: test/teststandards.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/refthunk.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststandards.cpp -test/teststl.o: test/teststl.cpp lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/refthunk.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/teststl.o: test/teststl.cpp lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/refthunk.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststl.cpp test/teststring.o: test/teststring.cpp lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstring.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/refthunk.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index a4e8a92c188..e88481c51c1 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -652,14 +652,16 @@ void CheckStlImpl::mismatchingContainerIteratorError(const Token* containerTok, } // Error message for bad iterator usage.. -void CheckStlImpl::mismatchingContainersError(const Token* tok1, const Token* tok2) +void CheckStlImpl::mismatchingContainersError(const Token* tok1, const Token* tok2, ValueFlow::Value::LifetimeKind ltk) { const std::string expr1(tok1 ? tok1->expressionString() : std::string("v1")); const std::string expr2(tok2 ? tok2->expressionString() : std::string("v2")); + const std::string dataStr = (ltk == ValueFlow::Value::LifetimeKind::Iterator) ? "Iterators" : (ltk == ValueFlow::Value::LifetimeKind::Address ? "Addresses" : "Pointers"); + const std::string objectStr = (ltk == ValueFlow::Value::LifetimeKind::Iterator || ltk == ValueFlow::Value::LifetimeKind::Object) ? "containers '" : "objects '"; reportError(tok1, Severity::error, "mismatchingContainers", - "Iterators of different containers '" + expr1 + "' and '" + expr2 + "' are used together.", + dataStr + " of different " + objectStr + expr1 + "' and '" + expr2 + "' are used together.", CWE664, Certainty::normal); } @@ -791,7 +793,7 @@ bool CheckStlImpl::checkIteratorPair(const Token* tok1, const Token* tok2) if (val1.tokvalue->expressionString() == val2.tokvalue->expressionString()) iteratorsError(tok1, val1.tokvalue, val1.tokvalue->expressionString()); else - mismatchingContainersError(val1.tokvalue, val2.tokvalue); + mismatchingContainersError(val1.tokvalue, val2.tokvalue, val1.lifetimeKind); return true; } diff --git a/lib/checkstl.h b/lib/checkstl.h index 0f9a70a7a15..0c2ebae9793 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -27,6 +27,7 @@ #include "config.h" #include "errortypes.h" #include "mathlib.h" +#include "vfvalue.h" #include #include @@ -37,10 +38,6 @@ class Token; class Variable; class ErrorLogger; class Tokenizer; -namespace ValueFlow -{ - class Value; -} /// @addtogroup Checks /// @{ @@ -214,7 +211,7 @@ class CPPCHECKLIB CheckStlImpl : public CheckImpl { void iteratorsError(const Token* tok, const std::string& containerName1, const std::string& containerName2); void iteratorsError(const Token* tok, const Token* containerTok, const std::string& containerName); void mismatchingContainerIteratorError(const Token* containerTok, const Token* iterTok, const Token* containerTok2); - void mismatchingContainersError(const Token* tok1, const Token* tok2); + void mismatchingContainersError(const Token* tok1, const Token* tok2, ValueFlow::Value::LifetimeKind ltk = ValueFlow::Value::LifetimeKind::Iterator); void mismatchingContainerExpressionError(const Token *tok1, const Token *tok2); void sameIteratorExpressionError(const Token *tok); void stlBoundariesError(const Token* tok); diff --git a/test/teststl.cpp b/test/teststl.cpp index bb20d2d8182..bc8d7bb2a43 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -75,6 +75,7 @@ class TestStl : public TestFixture { TEST_CASE(iterator29); TEST_CASE(iterator30); TEST_CASE(iterator31); + TEST_CASE(iterator32); TEST_CASE(iteratorExpression); TEST_CASE(iteratorSameExpression); TEST_CASE(mismatchingContainerIterator); @@ -1914,13 +1915,13 @@ class TestStl : public TestFixture { check("void f(int a, int b) {\n" " if (std::for_each(&a, &b + 1, [](auto) {})) {}\n" "}\n"); - ASSERT_EQUALS("[test.cpp:2:22]: (error) Iterators of different containers 'a' and 'b' are used together. [mismatchingContainers]\n", + ASSERT_EQUALS("[test.cpp:2:22]: (error) Addresses of different objects 'a' and 'b' are used together. [mismatchingContainers]\n", errout_str()); check("void f(int a, int b) {\n" " if (std::for_each(&a, &b, [](auto) {})) {}\n" "}\n"); - ASSERT_EQUALS("[test.cpp:2:22]: (error) Iterators of different containers 'a' and 'b' are used together. [mismatchingContainers]\n", + ASSERT_EQUALS("[test.cpp:2:22]: (error) Addresses of different objects 'a' and 'b' are used together. [mismatchingContainers]\n", errout_str()); check("void f(int a) {\n" @@ -2061,8 +2062,21 @@ class TestStl : public TestFixture { " std::string b;\n" " return t.s.a.c_str() == b.c_str();\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9:13]: (error) Iterators of different containers 's.a' and 'b' are used together. [mismatchingContainers]\n" - "[test.cpp:13:15]: (error) Iterators of different containers 't.s.a' and 'b' are used together. [mismatchingContainers]\n", + ASSERT_EQUALS("[test.cpp:9:13]: (error) Pointers of different containers 's.a' and 'b' are used together. [mismatchingContainers]\n" + "[test.cpp:13:15]: (error) Pointers of different containers 't.s.a' and 'b' are used together. [mismatchingContainers]\n", + errout_str()); + } + + void iterator32() + { + check("bool f(const std::string& a, const std::string& b) {\n" // #15158 + " return a.data() != b.data();\n" + "}\n" + "bool g(const std::unique_ptr& a, const std::unique_ptr& b) {\n" + " return a.get() != b.get();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:12]: (error) Pointers of different containers 'a' and 'b' are used together. [mismatchingContainers]\n" + "[test.cpp:5:12]: (error) Pointers of different objects 'a' and 'b' are used together. [mismatchingContainers]\n", errout_str()); }