Fixed #6279 (False Positive: Member variable 'Fred::i' is not initialized in the constructor)

This commit is contained in:
Robert Reif 2014-11-20 06:18:29 +01:00 committed by Daniel Marjamäki
parent b7c9187539
commit d12f14844a
4 changed files with 59 additions and 72 deletions

View File

@ -1682,53 +1682,10 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
return false;
}
static unsigned int countParameters(const Token *tok)
{
tok = tok->tokAt(2);
if (tok->str() == ")")
return 0;
unsigned int numpar = 1;
while (nullptr != (tok = tok->nextArgument()))
numpar++;
return numpar;
}
static unsigned int countMinArgs(const Token* argList)
{
if (!argList)
return 0;
argList = argList->next();
if (argList->str() == ")")
return 0;
unsigned int count = 1;
for (; argList; argList = argList->next()) {
if (argList->link() && Token::Match(argList, "(|[|{|<"))
argList = argList->link();
else if (argList->str() == ",")
count++;
else if (argList->str() == "=")
return count-1;
else if (argList->str() == ")")
break;
}
return count;
}
bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
{
unsigned int args = countParameters(tok);
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
/** @todo we need to look at the argument types when there are overloaded functions
* with the same number of arguments */
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
return !func->isStatic;
}
}
if (tok->function() && tok->function()->nestedIn == scope)
return !tok->function()->isStatic;
// not found in this class
if (!scope->definedType->derivedFrom.empty()) {
@ -1750,25 +1707,8 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const
{
unsigned int args = countParameters(tok);
std::list<Function>::const_iterator func;
unsigned int matches = 0;
unsigned int consts = 0;
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
/** @todo we need to look at the argument types when there are overloaded functions
* with the same number of arguments */
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
matches++;
if (func->isConst)
consts++;
}
}
// if there are multiple matches that are all const, return const
if (matches > 0 && matches == consts)
return true;
if (tok->function() && tok->function()->nestedIn == scope)
return tok->function()->isConst;
// not found in this class
if (!scope->definedType->derivedFrom.empty()) {

View File

@ -2961,9 +2961,9 @@ void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const
//---------------------------------------------------------------------------
/** @todo This function only counts the number of arguments in the function call.
It does not take into account function constantness.
It does not take into account argument types. This can be difficult because of promotion and conversion operators and casts and because the argument can also be a function call.
/** @todo This function does not take into account argument types when they don't match.
This can be difficult because of promotion and conversion operators and casts
and because the argument can also be a function call.
*/
const Function* Scope::findFunction(const Token *tok) const
{
@ -2998,7 +2998,8 @@ const Function* Scope::findFunction(const Token *tok) const
findFunctionInBase(tok, args, matches);
// check each function against the arguments in the function call for a match
for (size_t i = 0; i < matches.size(); ++i) {
for (std::size_t i = 0; i < matches.size();) {
bool erased = false;
const Function * func = matches[i];
size_t same = 0;
for (std::size_t j = 0; j < args; ++j) {
@ -3089,16 +3090,28 @@ const Function* Scope::findFunction(const Token *tok) const
// check that function argument type is not mismatching
else if (arguments[j]->str() == "&" && funcarg && funcarg->isReference()) {
// can't match so remove this function from possible matches
matches.erase(matches.begin() + i--);
matches.erase(matches.begin() + i);
erased = true;
break;
}
}
// check if all arguments matched
if (same == args) {
// found a match
return func;
// get the function this call is in
const Scope * scope = tok->scope();
// check if this function is a member function
if (scope && scope->functionOf && scope->functionOf->isClassOrStruct()) {
// check if isConst match
if (scope->function && scope->function->isConst == func->isConst)
return func;
} else
return func;
}
if (!erased)
++i;
}
// no exact match so just return first function found

View File

@ -4825,7 +4825,7 @@ private:
" void set(const Key& key) {\n"
" inherited::set(inherited::Key(key));\n"
" }\n"
"};\n");
"};\n", 0, false);
ASSERT_EQUALS("", errout.str());
}

View File

@ -136,6 +136,7 @@ private:
TEST_CASE(uninitVar26);
TEST_CASE(uninitVar27); // ticket #5170 - rtl::math::setNan(&d)
TEST_CASE(uninitVar28); // ticket #6258
TEST_CASE(uninitVar29);
TEST_CASE(uninitVarEnum);
TEST_CASE(uninitVarStream);
TEST_CASE(uninitVarTypedef);
@ -2126,6 +2127,39 @@ private:
ASSERT_EQUALS("", errout.str());
}
void uninitVar29() {
check("class A {\n"
" int i;\n"
"public:\n"
" A() { foo(); }\n"
" void foo() const { };\n"
" void foo() { i = 0; }\n"
"};\n"
"class B {\n"
" int i;\n"
"public:\n"
" B() { foo(); }\n"
" void foo() { i = 0; }\n"
" void foo() const { }\n"
"};\n"
"class C {\n"
" int i;\n"
"public:\n"
" C() { foo(); }\n"
" void foo() const { i = 0; }\n"
" void foo() { }\n"
"};\n"
"class D {\n"
" int i;\n"
"public:\n"
" D() { foo(); }\n"
" void foo() { }\n"
" void foo() const { i = 0; }\n"
"};");
ASSERT_EQUALS("[test.cpp:18]: (warning) Member variable 'C::i' is not initialized in the constructor.\n"
"[test.cpp:25]: (warning) Member variable 'D::i' is not initialized in the constructor.\n", errout.str());
}
void uninitVarArray1() {
check("class John\n"
"{\n"