Skip to content

Commit d12f148

Browse files
IOBYTEdanmar
authored andcommitted
Fixed danmar#6279 (False Positive: Member variable 'Fred::i' is not initialized in the constructor)
1 parent b7c9187 commit d12f148

File tree

4 files changed

+59
-72
lines changed

4 files changed

+59
-72
lines changed

lib/checkclass.cpp

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,53 +1682,10 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
16821682
return false;
16831683
}
16841684

1685-
static unsigned int countParameters(const Token *tok)
1686-
{
1687-
tok = tok->tokAt(2);
1688-
if (tok->str() == ")")
1689-
return 0;
1690-
1691-
unsigned int numpar = 1;
1692-
while (nullptr != (tok = tok->nextArgument()))
1693-
numpar++;
1694-
1695-
return numpar;
1696-
}
1697-
1698-
static unsigned int countMinArgs(const Token* argList)
1699-
{
1700-
if (!argList)
1701-
return 0;
1702-
1703-
argList = argList->next();
1704-
if (argList->str() == ")")
1705-
return 0;
1706-
1707-
unsigned int count = 1;
1708-
for (; argList; argList = argList->next()) {
1709-
if (argList->link() && Token::Match(argList, "(|[|{|<"))
1710-
argList = argList->link();
1711-
else if (argList->str() == ",")
1712-
count++;
1713-
else if (argList->str() == "=")
1714-
return count-1;
1715-
else if (argList->str() == ")")
1716-
break;
1717-
}
1718-
return count;
1719-
}
1720-
17211685
bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
17221686
{
1723-
unsigned int args = countParameters(tok);
1724-
1725-
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
1726-
/** @todo we need to look at the argument types when there are overloaded functions
1727-
* with the same number of arguments */
1728-
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
1729-
return !func->isStatic;
1730-
}
1731-
}
1687+
if (tok->function() && tok->function()->nestedIn == scope)
1688+
return !tok->function()->isStatic;
17321689

17331690
// not found in this class
17341691
if (!scope->definedType->derivedFrom.empty()) {
@@ -1750,25 +1707,8 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
17501707

17511708
bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const
17521709
{
1753-
unsigned int args = countParameters(tok);
1754-
1755-
std::list<Function>::const_iterator func;
1756-
unsigned int matches = 0;
1757-
unsigned int consts = 0;
1758-
1759-
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
1760-
/** @todo we need to look at the argument types when there are overloaded functions
1761-
* with the same number of arguments */
1762-
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
1763-
matches++;
1764-
if (func->isConst)
1765-
consts++;
1766-
}
1767-
}
1768-
1769-
// if there are multiple matches that are all const, return const
1770-
if (matches > 0 && matches == consts)
1771-
return true;
1710+
if (tok->function() && tok->function()->nestedIn == scope)
1711+
return tok->function()->isConst;
17721712

17731713
// not found in this class
17741714
if (!scope->definedType->derivedFrom.empty()) {

lib/symboldatabase.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,9 +2961,9 @@ void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const
29612961

29622962
//---------------------------------------------------------------------------
29632963

2964-
/** @todo This function only counts the number of arguments in the function call.
2965-
It does not take into account function constantness.
2966-
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.
2964+
/** @todo This function does not take into account argument types when they don't match.
2965+
This can be difficult because of promotion and conversion operators and casts
2966+
and because the argument can also be a function call.
29672967
*/
29682968
const Function* Scope::findFunction(const Token *tok) const
29692969
{
@@ -2998,7 +2998,8 @@ const Function* Scope::findFunction(const Token *tok) const
29982998
findFunctionInBase(tok, args, matches);
29992999

30003000
// check each function against the arguments in the function call for a match
3001-
for (size_t i = 0; i < matches.size(); ++i) {
3001+
for (std::size_t i = 0; i < matches.size();) {
3002+
bool erased = false;
30023003
const Function * func = matches[i];
30033004
size_t same = 0;
30043005
for (std::size_t j = 0; j < args; ++j) {
@@ -3089,16 +3090,28 @@ const Function* Scope::findFunction(const Token *tok) const
30893090
// check that function argument type is not mismatching
30903091
else if (arguments[j]->str() == "&" && funcarg && funcarg->isReference()) {
30913092
// can't match so remove this function from possible matches
3092-
matches.erase(matches.begin() + i--);
3093+
matches.erase(matches.begin() + i);
3094+
erased = true;
30933095
break;
30943096
}
30953097
}
30963098

30973099
// check if all arguments matched
30983100
if (same == args) {
3099-
// found a match
3100-
return func;
3101+
// get the function this call is in
3102+
const Scope * scope = tok->scope();
3103+
3104+
// check if this function is a member function
3105+
if (scope && scope->functionOf && scope->functionOf->isClassOrStruct()) {
3106+
// check if isConst match
3107+
if (scope->function && scope->function->isConst == func->isConst)
3108+
return func;
3109+
} else
3110+
return func;
31013111
}
3112+
3113+
if (!erased)
3114+
++i;
31023115
}
31033116

31043117
// no exact match so just return first function found

test/testclass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4825,7 +4825,7 @@ class TestClass : public TestFixture {
48254825
" void set(const Key& key) {\n"
48264826
" inherited::set(inherited::Key(key));\n"
48274827
" }\n"
4828-
"};\n");
4828+
"};\n", 0, false);
48294829
ASSERT_EQUALS("", errout.str());
48304830
}
48314831

test/testconstructors.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class TestConstructors : public TestFixture {
136136
TEST_CASE(uninitVar26);
137137
TEST_CASE(uninitVar27); // ticket #5170 - rtl::math::setNan(&d)
138138
TEST_CASE(uninitVar28); // ticket #6258
139+
TEST_CASE(uninitVar29);
139140
TEST_CASE(uninitVarEnum);
140141
TEST_CASE(uninitVarStream);
141142
TEST_CASE(uninitVarTypedef);
@@ -2126,6 +2127,39 @@ class TestConstructors : public TestFixture {
21262127
ASSERT_EQUALS("", errout.str());
21272128
}
21282129

2130+
void uninitVar29() {
2131+
check("class A {\n"
2132+
" int i;\n"
2133+
"public:\n"
2134+
" A() { foo(); }\n"
2135+
" void foo() const { };\n"
2136+
" void foo() { i = 0; }\n"
2137+
"};\n"
2138+
"class B {\n"
2139+
" int i;\n"
2140+
"public:\n"
2141+
" B() { foo(); }\n"
2142+
" void foo() { i = 0; }\n"
2143+
" void foo() const { }\n"
2144+
"};\n"
2145+
"class C {\n"
2146+
" int i;\n"
2147+
"public:\n"
2148+
" C() { foo(); }\n"
2149+
" void foo() const { i = 0; }\n"
2150+
" void foo() { }\n"
2151+
"};\n"
2152+
"class D {\n"
2153+
" int i;\n"
2154+
"public:\n"
2155+
" D() { foo(); }\n"
2156+
" void foo() { }\n"
2157+
" void foo() const { i = 0; }\n"
2158+
"};");
2159+
ASSERT_EQUALS("[test.cpp:18]: (warning) Member variable 'C::i' is not initialized in the constructor.\n"
2160+
"[test.cpp:25]: (warning) Member variable 'D::i' is not initialized in the constructor.\n", errout.str());
2161+
}
2162+
21292163
void uninitVarArray1() {
21302164
check("class John\n"
21312165
"{\n"

0 commit comments

Comments
 (0)