diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d1b7dc0d2..beb65595d 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -485,7 +485,7 @@ struct Constructor bool isCopyConstructor; }; -static bool argsMatch(const Token *first, const Token *second) +static bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) { bool match = false; while (first->str() == second->str()) @@ -528,6 +528,35 @@ static bool argsMatch(const Token *first, const Token *second) first = first->tokAt(2); } + // variable with class path + else if (depth && Token::Match(first->next(), "%var%")) + { + std::string param = path + first->next()->str(); + + if (Token::Match(second->next(), param.c_str())) + { + second = second->tokAt(depth * 2); + } + else if (depth > 1) + { + std::string short_path = path; + + // remove last " :: " + short_path.resize(short_path.size() - 4); + + // remove last name + while (!short_path.empty() && short_path[short_path.size() - 1] != ' ') + short_path.resize(short_path.size() - 1); + + param = short_path + first->next()->str(); + + if (Token::Match(second->next(), param.c_str())) + { + second = second->tokAt((depth - 1) * 2); + } + } + } + first = first->next(); second = second->next(); } @@ -630,6 +659,8 @@ void CheckClass::constructors() int stack_index = spaceInfo.size() - 1; std::string classPattern; + std::string classPath; + std::string searchPattern; int offset1, offset2; if (operatorEqual) { @@ -643,20 +674,23 @@ void CheckClass::constructors() } bool hasBody = false; + unsigned int depth = 0; while (!hasBody && stack_index >= 0) { - classPattern = spaceInfo[stack_index].className + std::string(" :: ") + classPattern; + classPath = spaceInfo[stack_index].className + std::string(" :: ") + classPath; + searchPattern = classPath + classPattern; offset2 += 2; + depth++; // start looking at end of class const Token *constructor_token = spaceInfo[stack_index].classEnd; - while ((constructor_token = Token::findmatch(constructor_token, classPattern.c_str())) != NULL) + while ((constructor_token = Token::findmatch(constructor_token, searchPattern.c_str())) != NULL) { // skip destructor and other classes if (!Token::Match(constructor_token->previous(), "~|::")) { - if (argsMatch(tok->tokAt(offset1), constructor_token->tokAt(offset2))) + if (argsMatch(tok->tokAt(offset1), constructor_token->tokAt(offset2), classPath, depth)) { constructorList.push_back(Constructor(constructor_token, access, true, operatorEqual, copyConstructor)); @@ -1774,7 +1808,7 @@ bool CheckClass::isVirtual(const std::vector &derivedFrom, const To } // check for matching function parameters - if (returnMatch && argsMatch(tok->tokAt(2), functionToken->tokAt(2))) + if (returnMatch && argsMatch(tok->tokAt(2), functionToken->tokAt(2), std::string(""), 0)) { return true; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 21f01524b..56befec09 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -359,7 +359,11 @@ void Tokenizer::createTokens(std::istream &code) { if (lineNumbers.empty() || fileIndexes.empty()) { +<<<<<<< HEAD cppcheckError(0); +======= + std::cerr << "####### Preprocessor bug! #######\n"; +>>>>>>> asd deallocateTokens(); return; } diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 88d6a3613..ed51eb141 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -733,6 +733,63 @@ private: "[test.cpp:21]: (style) Member variable not initialized in the constructor 'B::b'\n" "[test.cpp:22]: (style) Member variable not initialized in the constructor 'C::c'\n" "[test.cpp:23]: (style) Member variable not initialized in the constructor 'D::d'\n", errout.str()); + + check("class A {\n" + "public:\n" + " A();\n" + " struct B {\n" + " B();\n" + " struct C {\n" + " C();\n" + " struct D {\n" + " D(const D &);\n" + " int d;\n" + " };\n" + " int c;\n" + " };\n" + " int b;\n" + " };\n" + "private:\n" + " int a;\n" + " B b;\n" + "};\n" + "A::A(){}\n" + "A::B::B(){}\n" + "A::B::C::C(){}\n" + "A::B::C::D::D(const A::B::C::D & d){}\n"); + ASSERT_EQUALS("[test.cpp:20]: (style) Member variable not initialized in the constructor 'A::a'\n" + "[test.cpp:21]: (style) Member variable not initialized in the constructor 'B::b'\n" + "[test.cpp:22]: (style) Member variable not initialized in the constructor 'C::c'\n" + "[test.cpp:23]: (style) Member variable not initialized in the constructor 'D::d'\n", errout.str()); + + check("class A {\n" + "public:\n" + " A();\n" + " struct B {\n" + " B();\n" + " struct C {\n" + " C();\n" + " struct D {\n" + " struct E { };\n" + " E d;\n" + " D(const E &);\n" + " };\n" + " int c;\n" + " };\n" + " int b;\n" + " };\n" + "private:\n" + " int a;\n" + " B b;\n" + "};\n" + "A::A(){}\n" + "A::B::B(){}\n" + "A::B::C::C(){}\n" + "A::B::C::D::D(const A::B::C::D::E & e){}\n"); + ASSERT_EQUALS("[test.cpp:21]: (style) Member variable not initialized in the constructor 'A::a'\n" + "[test.cpp:22]: (style) Member variable not initialized in the constructor 'B::b'\n" + "[test.cpp:23]: (style) Member variable not initialized in the constructor 'C::c'\n" + "[test.cpp:24]: (style) Member variable not initialized in the constructor 'D::d'\n", errout.str()); } void initvar_destructor()