Fixed #4302 (Member variable not initialized in public delegate constructor)
This commit is contained in:
parent
618c26f6bf
commit
d1eb04c539
|
@ -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%|,|{")) {
|
} 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);
|
ftok = ftok->linkAt(1);
|
||||||
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
|
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
|
||||||
assignVar(ftok->str(), scope, usage);
|
assignVar(ftok->str(), scope, usage);
|
||||||
|
|
|
@ -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) {
|
for (std::list<Function>::const_iterator i = functionList.begin(); i != functionList.end(); ++i) {
|
||||||
if (i->tokenDef->str() == tok->str()) {
|
if (i->tokenDef->str() == tok->str()) {
|
||||||
const Function *func = &*i;
|
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
|
// check the arguments
|
||||||
unsigned int args = 0;
|
unsigned int args = 0;
|
||||||
const Token *arg = tok->tokAt(2);
|
const Token *arg = tok->tokAt(2);
|
||||||
while (arg && arg->str() != ")") {
|
while (arg && arg->str() != end) {
|
||||||
/** @todo check argument type for match */
|
/** @todo check argument type for match */
|
||||||
|
|
||||||
// mismatch parameter: passing parameter by address to function, argument is reference
|
// mismatch parameter: passing parameter by address to function, argument is reference
|
||||||
|
|
|
@ -832,6 +832,40 @@ private:
|
||||||
" A() { number = 42; }\n"
|
" A() { number = 42; }\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue