Uninitialized Member Variables: Fixed problems with different classes with same name (Bug 2208157)
This commit is contained in:
parent
e13dfbafe6
commit
d60d133671
|
@ -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..
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue