Fixed #1477 (false positive: Uninitialized variable when pointer given to struct)

This commit is contained in:
Daniel Marjamäki 2010-03-13 11:52:48 +01:00
parent 846a3a0186
commit 772aa95c8a
3 changed files with 71 additions and 0 deletions

View File

@ -1242,6 +1242,9 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
simplifyConst(); simplifyConst();
// struct initialization (must be used before simplifyVarDecl)
simplifyStructInit();
// Split up variable declarations. // Split up variable declarations.
simplifyVarDecl(); simplifyVarDecl();
@ -1264,6 +1267,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
simplifyFunctionPointers(); simplifyFunctionPointers();
//updateClassList(); //updateClassList();
setVarId(); setVarId();
if (!validate()) if (!validate())
return false; return false;
@ -6535,6 +6539,59 @@ std::string Tokenizer::simplifyString(const std::string &source)
return str; return str;
} }
void Tokenizer::simplifyStructInit()
{
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (Token::Match(tok, "[;{}] struct| %type% %var% = { . %type% ="))
{
// Goto "." and check if the initializations have an expected format
const Token *tok2 = tok;
while (tok2->str() != ".")
tok2 = tok2->next();
while (tok2 && tok2->str() == ".")
{
if (Token::Match(tok2, ". %type% = %num% [,}]"))
tok2 = tok2->tokAt(4);
else if (Token::Match(tok2, ". %type% = %var% [,}]"))
tok2 = tok2->tokAt(4);
else if (Token::Match(tok2, ". %type% = & %var% [,}]"))
tok2 = tok2->tokAt(5);
if (Token::simpleMatch(tok2, ", ."))
tok2 = tok2->next();
}
if (!Token::Match(tok2, "} ;"))
continue;
// Known expression format => Perform simplification
Token *vartok = tok->tokAt(3);
if (vartok->str() == "=")
vartok = vartok->previous();
vartok->next()->str(";");
Token *tok3 = vartok->tokAt(2);
tok3->link(0);
while (Token::Match(tok3, "[{,] . %type% ="))
{
tok3->str(vartok->str());
tok3->varId(vartok->varId());
tok3 = tok3->tokAt(5);
while (!Token::Match(tok3, "[,}]"))
tok3 = tok3->next();
if (tok3->str() == "}")
{
tok3->deleteThis();
break;
}
tok3->previous()->insertToken(";");
}
}
}
}
void Tokenizer::simplifyComparisonOrder() void Tokenizer::simplifyComparisonOrder()
{ {
// Use "<" comparison instead of ">" // Use "<" comparison instead of ">"

View File

@ -290,6 +290,9 @@ private:
*/ */
bool simplifyFunctionReturn(); bool simplifyFunctionReturn();
/** Struct initialization */
void simplifyStructInit();
/** /**
* Remove redundant paranthesis: * Remove redundant paranthesis:
* - "((x))" => "(x)" * - "((x))" => "(x)"

View File

@ -222,6 +222,9 @@ private:
// while(fclose(f)); => r = fclose(f); while(r){r=fclose(f);} // while(fclose(f)); => r = fclose(f); while(r){r=fclose(f);}
TEST_CASE(simplifyFuncInWhile); TEST_CASE(simplifyFuncInWhile);
// struct ABC abc = { .a = 3 }; => struct ABC abc; abc.a = 3;
TEST_CASE(initstruct);
} }
std::string tok(const char code[], bool simplify = true) std::string tok(const char code[], bool simplify = true)
@ -4102,6 +4105,14 @@ private:
"}", "}",
tok("while(fclose(f)); while(fclose(g));")); tok("while(fclose(f)); while(fclose(g));"));
} }
void initstruct()
{
ASSERT_EQUALS("; struct A a ; a . buf = 3 ;", tok("; struct A a = { .buf = 3 };"));
ASSERT_EQUALS("; struct A a ; a . buf = x ;", tok("; struct A a = { .buf = x };"));
ASSERT_EQUALS("; struct A a ; a . buf = & key ;", tok("; struct A a = { .buf = &key };"));
ASSERT_EQUALS("; struct ABC abc ; abc . a = 3 ; abc . b = x ; abc . c = & key ;", tok("; struct ABC abc = { .a = 3, .b = x, .c = &key };"));
}
}; };
REGISTER_TEST(TestSimplifyTokens) REGISTER_TEST(TestSimplifyTokens)