From 59de7934b73162685392c2eea1ae9ca86d21febd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 22 Jan 2010 18:51:25 +0100 Subject: [PATCH] Fixed #643 (Member variable not initialized not detected if any unknown function called) --- lib/checkclass.cpp | 54 ++++++++++++++++++++++++++++++++++++++++------ test/testclass.cpp | 23 +++++++++++++++++++- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 304048066..8e95d7f03 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -292,13 +292,55 @@ void CheckClass::initializeVarList(const Token *tok1, const Token *ftok, Var *va } else // there is a called member function, but it is not defined where we can find it, so we assume it initializes everything { - for (Var *var = varlist; var; var = var->next) - var->init = true; - break; + // check if the function is part of this class.. + const Token *tok = Token::findmatch(_tokenizer->tokens(), (std::string("class ") + classname + " {").c_str()); + for (tok = tok ? tok->tokAt(3) : 0; tok; tok = tok->next()) + { + if (tok->str() == "{") + { + tok = tok->link(); + if (!tok) + break; + } + else if (tok->str() == "}") + { + break; + } + else if (tok->str() == ftok->str() || tok->str() == "friend") + { + tok = 0; + break; + } + } - // we don't report this, as somewhere along the line we hope that the class and member function - // are checked together. It is possible that this will not be the case (where there are enough - // nested functions defined in different files), but that isn't really likely. + // bail out.. + if (!tok) + { + for (Var *var = varlist; var; var = var->next) + var->init = true; + break; + } + + // the function is external and it's neither friend nor inherited virtual function. + // assume all variables that are passed to it are initialized.. + unsigned int indentlevel = 0; + for (tok = ftok->tokAt(2); tok; tok = tok->next()) + { + if (tok->str() == "(") + ++indentlevel; + else if (tok->str() == ")") + { + if (indentlevel == 0) + break; + --indentlevel; + } + if (tok->isName()) + { + for (Var *var = varlist; var; var = var->next) + var->init |= bool(tok->str() == var->name); + } + } + continue; } } } diff --git a/test/testclass.cpp b/test/testclass.cpp index 07b7c1de1..239192aa0 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -1142,6 +1142,27 @@ private: "};\n"); ASSERT_EQUALS("", errout.str()); + // Unknown non-member function (friend class) + checkUninitVar("class Fred\n" + "{\n" + "public:\n" + " Fred() { Init(); }\n" + "private:\n" + " friend ABC;\n" + " int i;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + // Unknown non-member function (is Init a virtual function?) + checkUninitVar("class Fred : private ABC\n" + "{\n" + "public:\n" + " Fred() { Init(); }\n" + "private:\n" + " int i;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + // Unknown non-member function checkUninitVar("class Fred\n" "{\n" @@ -1150,7 +1171,7 @@ private: "private:\n" " int i;\n" "};\n"); - TODO_ASSERT_EQUALS("[test.cpp:4]: (style) Member variable not initialized in the constructor 'Fred::i'\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Member variable not initialized in the constructor 'Fred::i'\n", errout.str()); } void uninitVarEnum()