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%|,|{")) {
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue