Skip to content

Commit d1eb04c

Browse files
IOBYTEdanmar
authored andcommitted
Fixed danmar#4302 (Member variable not initialized in public delegate constructor)
1 parent 618c26f commit d1eb04c

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

lib/checkclass.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,34 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
469469
}
470470
}
471471
} else if (level == 0 && Token::Match(ftok, "%var% {") && ftok->str() != "const" && Token::Match(ftok->next()->link()->next(), "%type%|,|{")) {
472-
initVar(ftok->str(), scope, usage);
472+
if (ftok->str() != func.name()) {
473+
initVar(ftok->str(), scope, usage);
474+
} else { // c++11 delegate constructor
475+
const Function *member = scope->findFunction(ftok);
476+
// member function found
477+
if (member) {
478+
// recursive call
479+
// assume that all variables are initialized
480+
if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
481+
/** @todo false negative: just bail */
482+
assignAllVar(usage);
483+
return;
484+
}
485+
486+
// member function has implementation
487+
if (member->hasBody) {
488+
// initialize variable use list using member function
489+
callstack.push_back(member);
490+
initializeVarList(*member, callstack, scope, usage);
491+
callstack.pop_back();
492+
}
493+
494+
// there is a called member function, but it has no implementation, so we assume it initializes everything
495+
else {
496+
assignAllVar(usage);
497+
}
498+
}
499+
}
473500
ftok = ftok->linkAt(1);
474501
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
475502
assignVar(ftok->str(), scope, usage);

lib/symboldatabase.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,11 +2500,12 @@ const Function* Scope::findFunction(const Token *tok) const
25002500
for (std::list<Function>::const_iterator i = functionList.begin(); i != functionList.end(); ++i) {
25012501
if (i->tokenDef->str() == tok->str()) {
25022502
const Function *func = &*i;
2503-
if (tok->strAt(1) == "(" && tok->tokAt(2)) {
2503+
if ((tok->strAt(1) == "(" || (func->name() == tok->str() && tok->strAt(1) == "{" && func->type == Function::eConstructor)) && tok->tokAt(2)) {
2504+
std::string end(tok->strAt(1) == "{" ? "}" : ")");
25042505
// check the arguments
25052506
unsigned int args = 0;
25062507
const Token *arg = tok->tokAt(2);
2507-
while (arg && arg->str() != ")") {
2508+
while (arg && arg->str() != end) {
25082509
/** @todo check argument type for match */
25092510

25102511
// mismatch parameter: passing parameter by address to function, argument is reference

test/testconstructors.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,40 @@ class TestConstructors : public TestFixture {
832832
" A() { number = 42; }\n"
833833
"};");
834834
ASSERT_EQUALS("", errout.str());
835+
836+
check("class A {\n"
837+
" int number;\n"
838+
"public:\n"
839+
" A(int n) { }\n"
840+
" A() : A{42} {}\n"
841+
"};");
842+
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'A::number' is not initialized in the constructor.\n"
843+
"[test.cpp:5]: (warning) Member variable 'A::number' is not initialized in the constructor.\n", errout.str());
844+
845+
check("class A {\n"
846+
" int number;\n"
847+
"public:\n"
848+
" A(int n) { number = n; }\n"
849+
" A() : A{42} {}\n"
850+
"};");
851+
ASSERT_EQUALS("", errout.str());
852+
853+
check("class A {\n"
854+
" int number;\n"
855+
"public:\n"
856+
" A(int n) : A{} { }\n"
857+
" A() {}\n"
858+
"};", true);
859+
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'A::number' is not initialized in the constructor.\n"
860+
"[test.cpp:5]: (warning, inconclusive) Member variable 'A::number' is not initialized in the constructor.\n", errout.str());
861+
862+
check("class A {\n"
863+
" int number;\n"
864+
"public:\n"
865+
" A(int n) : A{} { }\n"
866+
" A() { number = 42; }\n"
867+
"};");
868+
ASSERT_EQUALS("", errout.str());
835869
}
836870

837871

0 commit comments

Comments
 (0)