Fixed #4302 (Member variable not initialized in public delegate constructor)

This commit is contained in:
Robert Reif 2014-03-12 05:48:13 +01:00 committed by Daniel Marjamäki
parent 618c26f6bf
commit d1eb04c539
3 changed files with 65 additions and 3 deletions

View File

@ -469,7 +469,34 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
}
}
} else if (level == 0 && Token::Match(ftok, "%var% {") && ftok->str() != "const" && Token::Match(ftok->next()->link()->next(), "%type%|,|{")) {
initVar(ftok->str(), scope, usage);
if (ftok->str() != func.name()) {
initVar(ftok->str(), scope, usage);
} else { // c++11 delegate constructor
const Function *member = scope->findFunction(ftok);
// member function found
if (member) {
// recursive call
// assume that all variables are initialized
if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
/** @todo false negative: just bail */
assignAllVar(usage);
return;
}
// member function has implementation
if (member->hasBody) {
// initialize variable use list using member function
callstack.push_back(member);
initializeVarList(*member, callstack, scope, usage);
callstack.pop_back();
}
// there is a called member function, but it has no implementation, so we assume it initializes everything
else {
assignAllVar(usage);
}
}
}
ftok = ftok->linkAt(1);
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
assignVar(ftok->str(), scope, usage);

View File

@ -2500,11 +2500,12 @@ const Function* Scope::findFunction(const Token *tok) const
for (std::list<Function>::const_iterator i = functionList.begin(); i != functionList.end(); ++i) {
if (i->tokenDef->str() == tok->str()) {
const Function *func = &*i;
if (tok->strAt(1) == "(" && tok->tokAt(2)) {
if ((tok->strAt(1) == "(" || (func->name() == tok->str() && tok->strAt(1) == "{" && func->type == Function::eConstructor)) && tok->tokAt(2)) {
std::string end(tok->strAt(1) == "{" ? "}" : ")");
// check the arguments
unsigned int args = 0;
const Token *arg = tok->tokAt(2);
while (arg && arg->str() != ")") {
while (arg && arg->str() != end) {
/** @todo check argument type for match */
// mismatch parameter: passing parameter by address to function, argument is reference

View File

@ -832,6 +832,40 @@ private:
" A() { number = 42; }\n"
"};");
ASSERT_EQUALS("", errout.str());
check("class A {\n"
" int number;\n"
"public:\n"
" A(int n) { }\n"
" A() : A{42} {}\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'A::number' is not initialized in the constructor.\n"
"[test.cpp:5]: (warning) Member variable 'A::number' is not initialized in the constructor.\n", errout.str());
check("class A {\n"
" int number;\n"
"public:\n"
" A(int n) { number = n; }\n"
" A() : A{42} {}\n"
"};");
ASSERT_EQUALS("", errout.str());
check("class A {\n"
" int number;\n"
"public:\n"
" A(int n) : A{} { }\n"
" A() {}\n"
"};", true);
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'A::number' is not initialized in the constructor.\n"
"[test.cpp:5]: (warning, inconclusive) Member variable 'A::number' is not initialized in the constructor.\n", errout.str());
check("class A {\n"
" int number;\n"
"public:\n"
" A(int n) : A{} { }\n"
" A() { number = 42; }\n"
"};");
ASSERT_EQUALS("", errout.str());
}