uninitialized class members: better handling of nested classes

This commit is contained in:
Robert Reif 2010-07-18 20:43:51 +02:00 committed by Daniel Marjamäki
parent 9063983e2b
commit 689de10abf
3 changed files with 100 additions and 5 deletions

View File

@ -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<std::string> &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;
}

View File

@ -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;
}

View File

@ -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()