uninitialized class members: better handling of nested classes
This commit is contained in:
parent
9063983e2b
commit
689de10abf
|
@ -485,7 +485,7 @@ struct Constructor
|
||||||
bool isCopyConstructor;
|
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;
|
bool match = false;
|
||||||
while (first->str() == second->str())
|
while (first->str() == second->str())
|
||||||
|
@ -528,6 +528,35 @@ static bool argsMatch(const Token *first, const Token *second)
|
||||||
first = first->tokAt(2);
|
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();
|
first = first->next();
|
||||||
second = second->next();
|
second = second->next();
|
||||||
}
|
}
|
||||||
|
@ -630,6 +659,8 @@ void CheckClass::constructors()
|
||||||
int stack_index = spaceInfo.size() - 1;
|
int stack_index = spaceInfo.size() - 1;
|
||||||
|
|
||||||
std::string classPattern;
|
std::string classPattern;
|
||||||
|
std::string classPath;
|
||||||
|
std::string searchPattern;
|
||||||
int offset1, offset2;
|
int offset1, offset2;
|
||||||
if (operatorEqual)
|
if (operatorEqual)
|
||||||
{
|
{
|
||||||
|
@ -643,20 +674,23 @@ void CheckClass::constructors()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasBody = false;
|
bool hasBody = false;
|
||||||
|
unsigned int depth = 0;
|
||||||
while (!hasBody && stack_index >= 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;
|
offset2 += 2;
|
||||||
|
depth++;
|
||||||
|
|
||||||
// start looking at end of class
|
// start looking at end of class
|
||||||
const Token *constructor_token = spaceInfo[stack_index].classEnd;
|
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
|
// skip destructor and other classes
|
||||||
if (!Token::Match(constructor_token->previous(), "~|::"))
|
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));
|
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
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,11 @@ void Tokenizer::createTokens(std::istream &code)
|
||||||
{
|
{
|
||||||
if (lineNumbers.empty() || fileIndexes.empty())
|
if (lineNumbers.empty() || fileIndexes.empty())
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
cppcheckError(0);
|
cppcheckError(0);
|
||||||
|
=======
|
||||||
|
std::cerr << "####### Preprocessor bug! #######\n";
|
||||||
|
>>>>>>> asd
|
||||||
deallocateTokens();
|
deallocateTokens();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -733,6 +733,63 @@ private:
|
||||||
"[test.cpp:21]: (style) Member variable not initialized in the constructor 'B::b'\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: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());
|
"[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()
|
void initvar_destructor()
|
||||||
|
|
Loading…
Reference in New Issue