diff --git a/Makefile b/Makefile index 5ec799fc8..3e720f776 100644 --- a/Makefile +++ b/Makefile @@ -465,7 +465,7 @@ $(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/astutils.h lib/check $(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/astutils.h lib/check.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checknullpointer.o $(libcppdir)/checknullpointer.cpp -$(libcppdir)/checkother.o: lib/checkother.cpp lib/astutils.h lib/check.h lib/checkother.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h +$(libcppdir)/checkother.o: lib/checkother.cpp lib/astutils.h lib/check.h lib/checkclass.h lib/checkother.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkother.o $(libcppdir)/checkother.cpp $(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/check.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index bf7e8525c..eb77a3aac 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2131,9 +2131,7 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const return false; } - -// The container contains the STL types whose operator[] is not a const. -static const std::set stl_containers_not_const = { "map", "unordered_map" }; +const std::set CheckClass::stl_containers_not_const = { "map", "unordered_map" }; bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed) const { diff --git a/lib/checkclass.h b/lib/checkclass.h index 6309f2566..419707020 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -188,6 +188,9 @@ public: /** @brief Analyse all file infos for all TU */ bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; + /** @brief Set of the STL types whose operator[] is not const */ + static const std::set stl_containers_not_const; + private: const SymbolDatabase *mSymbolDatabase; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index a15f4e543..1134105f3 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -32,6 +32,7 @@ #include "valueflow.h" #include "checkuninitvar.h" // CheckUninitVar::isVariableUsage +#include "checkclass.h" // CheckClass::stl_containers_not_const #include // find_if() #include @@ -1502,11 +1503,21 @@ void CheckOther::checkConstVariable() if (var->isReference()) { bool callNonConstMethod = false; for (const Token* tok = var->nameToken(); tok != scope->bodyEnd && tok != nullptr; tok = tok->next()) { - if (tok->variable() == var && Token::Match(tok, "%var% . * ( & %name% ::")) { - const Token *ftok = tok->linkAt(3)->previous(); - if (!ftok->function() || !ftok->function()->isConst()) - callNonConstMethod = true; - break; + if (tok->variable() == var) { + if (Token::Match(tok, "%var% . * ( & %name% ::")) { + const Token* ftok = tok->linkAt(3)->previous(); + if (!ftok->function() || !ftok->function()->isConst()) + callNonConstMethod = true; + break; + } + if (var->isStlType() && Token::Match(tok, "%var% [")) { // containers whose operator[] is non-const + const Token* typeTok = var->typeStartToken() ? var->typeStartToken()->tokAt(2) : nullptr; + const auto& notConst = CheckClass::stl_containers_not_const; + if (typeTok && notConst.find(typeTok->str()) != notConst.end()) { + callNonConstMethod = true; + break; + } + } } } if (callNonConstMethod) diff --git a/test/testother.cpp b/test/testother.cpp index ee5e2fc7b..239676d58 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2746,6 +2746,11 @@ private: " T& g(C& c, T C::*f) { return c.*f; }\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + check("void f(std::map& m) {\n" + " std::cout << m[0] << std::endl;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void constParameterCallback() {