diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2c63e8db6..8256a0312 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1453,13 +1453,19 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func) } else if (Token::Match(tok1, "%var% . %var% (")) { if (!isMemberVar(scope, tok1)) tok1 = tok1->next(); - else if (tok1->varId() && (Token::Match(tok1->tokAt(2), "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(tok1->tokAt(2), "rfind|copy"))) { + else if (tok1->varId()) { const Variable *var = symbolDatabase->getVariableFromVarId(tok1->varId()); - // assume all std::*::size() and std::*::empty() are const - if (var && Token::simpleMatch(var->typeStartToken(), "std ::")) + if (var && Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const + && Token::Match(tok1->tokAt(2), "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(tok1->tokAt(2), "rfind|copy")) tok1 = tok1->next(); - else // TODO: Check if the function is const (#2477) + else if (var) { // Check if the function is const + const Scope* type = var->type(); + if (!type || !isConstMemberFunc(type, tok1->tokAt(2))) + return(false); + else + tok1 = tok1->next(); + } else return(false); } else return(false); diff --git a/test/testclass.cpp b/test/testclass.cpp index e5395453d..8d0425f6d 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -132,7 +132,7 @@ private: TEST_CASE(const54); // ticket #3052 TEST_CASE(const55); TEST_CASE(const56); // ticket #3149 - TEST_CASE(const57); // ticket #2669 + TEST_CASE(const57); // tickets #2669 and #2477 TEST_CASE(const58); // ticket #2698 TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); @@ -4260,8 +4260,7 @@ private: ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str()); } - void const57() { // ticket #2669 - + void const57() { // tickets #2669 and #2477 checkConst("namespace MyGUI\n" "{\n" " namespace types\n" @@ -4283,9 +4282,38 @@ private: "private:\n" " MyGUI::IntCoord mCoordValue;\n" "};\n"); - TODO_ASSERT_EQUALS("[test.cpp:15]: (style, inconclusive) Technically the member function 'MyGUI::SelectorControl::getSize' can be const.\n", - "", errout.str()); + ASSERT_EQUALS("[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str()); + checkConst("struct Foo {\n" + " Bar b;\n" + " void foo(Foo f) {\n" + " b.run();\n" + " }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + + checkConst("struct Bar {\n" + " int i = 0;\n" + " void run() { i++; }\n" + "};\n" + "struct Foo {\n" + " Bar b;\n" + " void foo(Foo f) {\n" + " b.run();\n" + " }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + + checkConst("struct Bar {\n" + " void run() const { }\n" + "};\n" + "struct Foo {\n" + " Bar b;\n" + " void foo(Foo f) {\n" + " b.run();\n" + " }\n" + "};"); + ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str()); } void const58() {