Uninitialized Member Variables: Fixed problems with different classes with same name (Bug 2208157)

This commit is contained in:
Daniel Marjamäki 2008-11-01 18:01:35 +00:00
parent e13dfbafe6
commit d60d133671
2 changed files with 87 additions and 38 deletions

View File

@ -44,13 +44,8 @@ struct VAR
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static struct VAR *ClassChecking_GetVarList(const char classname[]) static struct VAR *ClassChecking_GetVarList(const TOKEN *tok1)
{ {
// Locate class..
const char *pattern[] = {"class","","{",0};
pattern[1] = classname;
const TOKEN *tok1 = findtoken(tokens, pattern);
// Get variable list.. // Get variable list..
struct VAR *varlist = NULL; struct VAR *varlist = NULL;
unsigned int indentlevel = 0; unsigned int indentlevel = 0;
@ -111,48 +106,76 @@ static struct VAR *ClassChecking_GetVarList(const char classname[])
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static const TOKEN * FindClassFunction( const TOKEN *_tokens, const char classname[], const char funcname[], unsigned int &indentlevel ) static const TOKEN * FindClassFunction( const TOKEN *tok, const char classname[], const char funcname[], int &indentlevel )
{ {
const char *_classname[2] = {0,0}; const char *_classname[2] = {0,0};
const char *_funcname[2] = {0,0}; const char *_funcname[2] = {0,0};
_classname[0] = classname; _classname[0] = classname;
_funcname[0] = funcname; _funcname[0] = funcname;
if ( indentlevel < 0 )
return NULL;
while ( _tokens ) for ( ;tok; tok = tok->next )
{ {
if ( indentlevel == 0 &&
( Match(tok, "class %var1% {", _classname) ||
Match(tok, "class %var1% : %type% {", _classname) ) )
{
if ( Match(tok, "class %var% {") )
tok = gettok(tok, 3);
else
tok = gettok(tok, 5);
indentlevel = 1;
}
if ( tok->str[0] == '{' )
{
// If indentlevel==0 don't go to indentlevel 1. Skip the block.
if ( indentlevel > 0 ) if ( indentlevel > 0 )
++indentlevel;
else
{
for ( ; tok; tok = tok->next )
{
if ( tok->str[0] == '{' )
++indentlevel;
else if ( tok->str[0] == '}' )
{
--indentlevel;
if ( indentlevel <= 0 )
break;
}
}
continue;
}
}
if ( tok->str[0] == '}' )
{ {
if ( _tokens->str[0] == '{' )
indentlevel++;
else if ( _tokens->str[0] == '}' )
indentlevel--; indentlevel--;
else if ( indentlevel == 1 ) if ( indentlevel < 0 )
return NULL;
}
if ( indentlevel == 1 )
{ {
// Member function is implemented in the class declaration.. // Member function implemented in the class declaration?
if ( Match( _tokens, "%var1% (", _funcname ) ) if ( Match( tok, "%var1% (", _funcname ) )
{ {
const TOKEN *tok2 = _tokens; const TOKEN *tok2 = tok;
while ( tok2 && tok2->str[0] != '{' && tok2->str[0] != ';' ) while ( tok2 && tok2->str[0] != '{' && tok2->str[0] != ';' )
tok2 = tok2->next; tok2 = tok2->next;
if ( tok2 && tok2->str[0] == '{' ) if ( tok2 && tok2->str[0] == '{' )
return _tokens; return tok;
}
} }
} }
else if ( Match(_tokens, "class %var1% {", _classname) ) else if ( indentlevel == 0 && Match(tok, "%var1% :: %var2% (", _classname, _funcname) )
{ {
indentlevel = 1; return tok;
_tokens = gettok( _tokens, 2 );
} }
else if ( Match(_tokens, "%var1% :: %var2% (", _classname, _funcname) )
{
return _tokens;
}
_tokens = _tokens->next;
} }
// Not found // Not found
@ -173,7 +196,7 @@ static void InitVar(struct VAR *varlist, const char varname[])
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void ClassChecking_VarList_Initialize(const TOKEN *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack) static void ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack)
{ {
bool Assign = false; bool Assign = false;
unsigned int indentlevel = 0; unsigned int indentlevel = 0;
@ -249,9 +272,9 @@ static void ClassChecking_VarList_Initialize(const TOKEN *ftok, struct VAR *varl
if ( std::find(callstack.begin(),callstack.end(),ftok->str) == callstack.end() ) if ( std::find(callstack.begin(),callstack.end(),ftok->str) == callstack.end() )
{ {
callstack.push_back( ftok->str ); callstack.push_back( ftok->str );
unsigned int i = 0; int i = 0;
const TOKEN *ftok2 = FindClassFunction( tokens, classname, ftok->str, i ); const TOKEN *ftok2 = FindClassFunction( tok1, classname, ftok->str, i );
ClassChecking_VarList_Initialize(ftok2, varlist, classname, callstack); ClassChecking_VarList_Initialize(tok1, ftok2, varlist, classname, callstack);
} }
} }
@ -304,7 +327,7 @@ void CheckConstructors()
if ( CheckCodingStyle ) if ( CheckCodingStyle )
{ {
// Check that all member variables are initialized.. // Check that all member variables are initialized..
struct VAR *varlist = ClassChecking_GetVarList(classname); struct VAR *varlist = ClassChecking_GetVarList(tok1);
if ( varlist ) if ( varlist )
{ {
std::ostringstream ostr; std::ostringstream ostr;
@ -326,12 +349,12 @@ void CheckConstructors()
} }
// Check that all member variables are initialized.. // Check that all member variables are initialized..
struct VAR *varlist = ClassChecking_GetVarList(classname); struct VAR *varlist = ClassChecking_GetVarList(tok1);
unsigned int indentlevel = 0; int indentlevel = 0;
constructor_token = FindClassFunction( tokens, classname, classname, indentlevel ); constructor_token = FindClassFunction( tok1, classname, classname, indentlevel );
std::list<std::string> callstack; std::list<std::string> callstack;
ClassChecking_VarList_Initialize(constructor_token, varlist, classname, callstack); ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, classname, callstack);
while ( constructor_token ) while ( constructor_token )
{ {
// Check if any variables are uninitialized // Check if any variables are uninitialized
@ -357,7 +380,7 @@ void CheckConstructors()
var->init = false; var->init = false;
constructor_token = FindClassFunction( constructor_token->next, classname, classname, indentlevel ); constructor_token = FindClassFunction( constructor_token->next, classname, classname, indentlevel );
ClassChecking_VarList_Initialize(constructor_token, varlist, classname, callstack); ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, classname, callstack);
} }
// Delete the varlist.. // Delete the varlist..

View File

@ -58,6 +58,7 @@ private:
TEST_CASE( initvar_with_this ); // BUG 2190300 TEST_CASE( initvar_with_this ); // BUG 2190300
TEST_CASE( initvar_if ); // BUG 2190290 TEST_CASE( initvar_if ); // BUG 2190290
TEST_CASE( initvar_operator_eq ); // BUG 2190376 TEST_CASE( initvar_operator_eq ); // BUG 2190376
TEST_CASE( initvar_same_classname ); // BUG 2208157
} }
@ -169,7 +170,32 @@ private:
"};\n" ); "};\n" );
std::string err( errout.str() ); std::string err( errout.str() );
ASSERT_EQUALS( std::string(""), err );
}
void initvar_same_classname()
{
// Bug 2208157 - False positive: Uninitialized variable, same class name
check( "void func1()\n"
"{\n"
" class Fred\n"
" {\n"
" int a;\n"
" Fred() { a = 0; }\n"
" };\n"
"}\n"
"\n"
"void func2()\n"
"{\n"
" class Fred\n"
" {\n"
" int b;\n"
" Fred() { b = 0; }\n"
" };\n"
"}\n" );
std::string err( errout.str() );
ASSERT_EQUALS( std::string(""), err ); ASSERT_EQUALS( std::string(""), err );
} }