Fixed #6279 (False Positive: Member variable 'Fred::i' is not initialized in the constructor)
This commit is contained in:
parent
b7c9187539
commit
d12f14844a
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
// 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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue