Fixed #1647 (False positive: buffer is not assigned value (assigned through alias))

This commit is contained in:
Robert Reif 2010-05-05 17:31:07 +02:00 committed by Daniel Marjamäki
parent 612be2557b
commit 4c95264d29
2 changed files with 90 additions and 30 deletions

View File

@ -758,7 +758,7 @@ Variables::VariableUsage *Variables::find(unsigned int varid)
return 0; return 0;
} }
static int doAssignment(Variables &variables, const Token *tok, bool pointer) static int doAssignment(Variables &variables, const Token *tok, bool pointer, bool post)
{ {
int next = 0; int next = 0;
@ -769,72 +769,76 @@ static int doAssignment(Variables &variables, const Token *tok, bool pointer)
if (var1) if (var1)
{ {
Variables::VariableUsage *var2 = 0; Variables::VariableUsage *var2 = 0;
int start = 2;
if (Token::Match(tok->tokAt(2), "&| %var%") || if (post)
Token::Match(tok->tokAt(2), "( const| struct|union| %type% * ) &| %var%") || start++;
Token::Match(tok->tokAt(2), "( const| struct|union| %type% * ) ( &| %var%") ||
Token::Match(tok->tokAt(2), "%any% < const| struct|union| %type% * > ( &| %var%")) if (Token::Match(tok->tokAt(start), "&| %var%") ||
Token::Match(tok->tokAt(start), "( const| struct|union| %type% * ) &| %var%") ||
Token::Match(tok->tokAt(start), "( const| struct|union| %type% * ) ( &| %var%") ||
Token::Match(tok->tokAt(start), "%any% < const| struct|union| %type% * > ( &| %var%"))
{ {
unsigned int offset = 0; unsigned int offset = 0;
unsigned int varid2; unsigned int varid2;
bool addressOf = false; bool addressOf = false;
// check for C style cast // check for C style cast
if (tok->tokAt(2)->str() == "(") if (tok->tokAt(start)->str() == "(")
{ {
if (tok->tokAt(3)->str() == "const") if (tok->tokAt(start + 1)->str() == "const")
offset++; offset++;
if (Token::Match(tok->tokAt(3 + offset), "struct|union")) if (Token::Match(tok->tokAt(start + 1 + offset), "struct|union"))
offset++; offset++;
if (tok->tokAt(6 + offset)->str() == "&") if (tok->tokAt(start + 4 + offset)->str() == "&")
{ {
addressOf = true; addressOf = true;
next = 7 + offset; next = start + 5 + offset;
} }
else if (tok->tokAt(6 + offset)->str() == "(") else if (tok->tokAt(start + 4 + offset)->str() == "(")
{ {
if (tok->tokAt(7 + offset)->str() == "&") if (tok->tokAt(start + 5 + offset)->str() == "&")
{ {
addressOf = true; addressOf = true;
next = 8 + offset; next = start + 6 + offset;
} }
else else
next = 7 + offset; next = start + 5 + offset;
} }
else else
next = 6 + offset; next = start + 4 + offset;
} }
// check for C++ style cast // check for C++ style cast
else if (tok->tokAt(2)->str().find("cast") != std::string::npos) else if (tok->tokAt(start)->str().find("cast") != std::string::npos)
{ {
if (tok->tokAt(4)->str() == "const") if (tok->tokAt(start + 2)->str() == "const")
offset++; offset++;
if (Token::Match(tok->tokAt(4 + offset), "struct|union")) if (Token::Match(tok->tokAt(start + 2 + offset), "struct|union"))
offset++; offset++;
if (tok->tokAt(8 + offset)->str() == "&") if (tok->tokAt(start + 6 + offset)->str() == "&")
{ {
addressOf = true; addressOf = true;
next = 9 + offset; next = start + 7 + offset;
} }
else else
next = 8 + offset; next = start + 6 + offset;
} }
// no cast // no cast
else else
{ {
if (tok->tokAt(2)->str() == "&") if (tok->tokAt(start)->str() == "&")
{ {
addressOf = true; addressOf = true;
next = 3; next = start + 1;
} }
else else
next = 2; next = start;
} }
// check if variable is local // check if variable is local
@ -1014,7 +1018,7 @@ void CheckOther::functionVariableUsage()
// check for assignment // check for assignment
if (written) if (written)
offset = doAssignment(variables, tok->tokAt(3), false); offset = doAssignment(variables, tok->tokAt(3), false, false);
tok = tok->tokAt(3 + offset); tok = tok->tokAt(3 + offset);
} }
@ -1039,7 +1043,7 @@ void CheckOther::functionVariableUsage()
// check for assignment // check for assignment
if (written) if (written)
offset = doAssignment(variables, tok->tokAt(4), false); offset = doAssignment(variables, tok->tokAt(4), false, false);
tok = tok->tokAt(4 + offset); tok = tok->tokAt(4 + offset);
} }
@ -1063,7 +1067,7 @@ void CheckOther::functionVariableUsage()
// check for assignment // check for assignment
if (written) if (written)
offset = doAssignment(variables, tok->tokAt(4), false); offset = doAssignment(variables, tok->tokAt(4), false, false);
tok = tok->tokAt(4 + offset); tok = tok->tokAt(4 + offset);
} }
@ -1087,7 +1091,7 @@ void CheckOther::functionVariableUsage()
// check for assignment // check for assignment
if (written) if (written)
offset = doAssignment(variables, tok->tokAt(5), false); offset = doAssignment(variables, tok->tokAt(5), false, false);
tok = tok->tokAt(5 + offset); tok = tok->tokAt(5 + offset);
} }
@ -1225,9 +1229,11 @@ void CheckOther::functionVariableUsage()
variables.readAll(tok->next()->varId()); variables.readAll(tok->next()->varId());
// assignment // assignment
else if (Token::Match(tok, "*| %var% =")) else if (Token::Match(tok, "*| ++|--| %var% ++|--| ="))
{ {
bool pointer = false; bool pointer = false;
bool pre = false;
bool post = false;
if (tok->str() == "*") if (tok->str() == "*")
{ {
@ -1235,10 +1241,24 @@ void CheckOther::functionVariableUsage()
tok = tok->next(); tok = tok->next();
} }
if (Token::Match(tok, "++|--"))
{
pre = true;
tok = tok->next();
}
if (Token::Match(tok->next(), "++|--"))
{
post = true;
}
unsigned int varid1 = tok->varId(); unsigned int varid1 = tok->varId();
const Token *start = tok; const Token *start = tok;
tok = tok->tokAt(doAssignment(variables, tok, pointer)); tok = tok->tokAt(doAssignment(variables, tok, pointer, post));
if (pre || post)
variables.use(varid1);
if (pointer) if (pointer)
{ {

View File

@ -80,6 +80,7 @@ private:
TEST_CASE(localvaralias2); // ticket #1637 TEST_CASE(localvaralias2); // ticket #1637
TEST_CASE(localvaralias3); // ticket #1639 TEST_CASE(localvaralias3); // ticket #1639
TEST_CASE(localvaralias4); // ticket #1643 TEST_CASE(localvaralias4); // ticket #1643
TEST_CASE(localvaralias5); // ticket #1647
TEST_CASE(localvarasm); TEST_CASE(localvarasm);
// Don't give false positives for variables in structs/unions // Don't give false positives for variables in structs/unions
@ -1529,6 +1530,45 @@ private:
ASSERT_EQUALS(std::string(""), errout.str()); ASSERT_EQUALS(std::string(""), errout.str());
} }
void localvaralias5() // ticket 1647
{
functionVariableUsage("char foo()\n"
"{\n"
" char buf[8];\n"
" char *p = &buf[0];\n"
" *p++ = 0;\n"
" return buf[0];\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
functionVariableUsage("char foo()\n"
"{\n"
" char buf[8];\n"
" char *p = &buf[1];\n"
" *p-- = 0;\n"
" return buf[0];\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
functionVariableUsage("char foo()\n"
"{\n"
" char buf[8];\n"
" char *p = &buf[0];\n"
" *++p = 0;\n"
" return buf[0];\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
functionVariableUsage("char foo()\n"
"{\n"
" char buf[8];\n"
" char *p = &buf[1];\n"
" *--p = 0;\n"
" return buf[0];\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
void localvarasm() void localvarasm()
{ {
functionVariableUsage("void foo(int &b)\n" functionVariableUsage("void foo(int &b)\n"