Fixed #1622 (False positive: buf is not assigned a value (pointer aliasing))
This commit is contained in:
parent
344b6bf434
commit
5738f34872
|
@ -702,44 +702,58 @@ static int doAssignment(Variables &variables, const Token *tok, bool pointer)
|
||||||
Variables::VariableUsage *var2 = 0;
|
Variables::VariableUsage *var2 = 0;
|
||||||
|
|
||||||
if (Token::Match(tok->tokAt(2), "&| %var%") ||
|
if (Token::Match(tok->tokAt(2), "&| %var%") ||
|
||||||
Token::Match(tok->tokAt(2), "( %type% * ) &| %var%") ||
|
Token::Match(tok->tokAt(2), "( const| struct|union| %type% * ) &| %var%") ||
|
||||||
Token::Match(tok->tokAt(2), "( %type% * ) ( &| %var%") ||
|
Token::Match(tok->tokAt(2), "( const| struct|union| %type% * ) ( &| %var%") ||
|
||||||
Token::Match(tok->tokAt(2), "%any% < %type% * > ( &| %var%"))
|
Token::Match(tok->tokAt(2), "%any% < const| struct|union| %type% * > ( &| %var%"))
|
||||||
{
|
{
|
||||||
|
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(2)->str() == "(")
|
||||||
{
|
{
|
||||||
if (tok->tokAt(6)->str() == "&")
|
if (tok->tokAt(3)->str() == "const")
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (Token::Match(tok->tokAt(3 + offset), "struct|union"))
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (tok->tokAt(6 + offset)->str() == "&")
|
||||||
{
|
{
|
||||||
addressOf = true;
|
addressOf = true;
|
||||||
next = 7;
|
next = 7 + offset;
|
||||||
}
|
}
|
||||||
else if (tok->tokAt(6)->str() == "(")
|
else if (tok->tokAt(6 + offset)->str() == "(")
|
||||||
{
|
{
|
||||||
if (tok->tokAt(7)->str() == "&")
|
if (tok->tokAt(7 + offset)->str() == "&")
|
||||||
{
|
{
|
||||||
addressOf = true;
|
addressOf = true;
|
||||||
next = 8;
|
next = 8 + offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
next = 7;
|
next = 7 + offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
next = 6;
|
next = 6 + 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(2)->str().find("cast") != std::string::npos)
|
||||||
{
|
{
|
||||||
if (tok->tokAt(8)->str() == "&")
|
if (tok->tokAt(3)->str() == "const")
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (Token::Match(tok->tokAt(3 + offset), "struct|union"))
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (tok->tokAt(8 + offset)->str() == "&")
|
||||||
{
|
{
|
||||||
addressOf = true;
|
addressOf = true;
|
||||||
next = 9;
|
next = 9 + offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
next = 8;
|
next = 8 + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no cast
|
// no cast
|
||||||
|
@ -876,9 +890,9 @@ void CheckOther::functionVariableUsage()
|
||||||
tok = tok->tokAt(5);
|
tok = tok->tokAt(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard type decelaration of array of with possible initialization
|
// standard type declaration of array of with possible initialization
|
||||||
// int i[10]; int j[2] = { 0, 1 };
|
// int i[10]; int j[2] = { 0, 1 };
|
||||||
else if (Token::Match(tok, "[;{}] %type% %var% [ %num% ] ;|=") &&
|
else if (Token::Match(tok, "[;{}] %type% %var% [ %any% ] ;|=") &&
|
||||||
tok->next()->isStandardType())
|
tok->next()->isStandardType())
|
||||||
{
|
{
|
||||||
variables.addVar(tok->tokAt(2), Variables::array,
|
variables.addVar(tok->tokAt(2), Variables::array,
|
||||||
|
@ -932,7 +946,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(4), false);
|
||||||
|
|
||||||
tok = tok->tokAt(4 + offset);
|
tok = tok->tokAt(4 + offset);
|
||||||
}
|
}
|
||||||
|
@ -956,7 +970,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(4), false);
|
||||||
|
|
||||||
tok = tok->tokAt(4 + offset);
|
tok = tok->tokAt(4 + offset);
|
||||||
}
|
}
|
||||||
|
@ -980,7 +994,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(5), false);
|
||||||
|
|
||||||
tok = tok->tokAt(5 + offset);
|
tok = tok->tokAt(5 + offset);
|
||||||
}
|
}
|
||||||
|
@ -1030,7 +1044,7 @@ void CheckOther::functionVariableUsage()
|
||||||
|
|
||||||
// array of pointer or reference declaration with possible initialization
|
// array of pointer or reference declaration with possible initialization
|
||||||
// int * p[10]; int * q[10] = { 0 };
|
// int * p[10]; int * q[10] = { 0 };
|
||||||
else if (Token::Match(tok, "[;{}] %type% *|& %var% [ %num% ] ;|="))
|
else if (Token::Match(tok, "[;{}] %type% *|& %var% [ %any% ] ;|="))
|
||||||
{
|
{
|
||||||
if (tok->next()->str() != "return")
|
if (tok->next()->str() != "return")
|
||||||
{
|
{
|
||||||
|
@ -1043,7 +1057,7 @@ void CheckOther::functionVariableUsage()
|
||||||
|
|
||||||
// const array of pointer or reference declaration with possible initialization
|
// const array of pointer or reference declaration with possible initialization
|
||||||
// const int * p[10]; const int * q[10] = { 0 };
|
// const int * p[10]; const int * q[10] = { 0 };
|
||||||
else if (Token::Match(tok, "[;{}] const %type% *|& %var% [ %num% ] ;|="))
|
else if (Token::Match(tok, "[;{}] const %type% *|& %var% [ %any% ] ;|="))
|
||||||
{
|
{
|
||||||
variables.addVar(tok->tokAt(4),
|
variables.addVar(tok->tokAt(4),
|
||||||
tok->tokAt(3)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
tok->tokAt(3)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
||||||
|
@ -1053,7 +1067,7 @@ void CheckOther::functionVariableUsage()
|
||||||
|
|
||||||
// array of pointer or reference of struct or union declaration with possible initialization
|
// array of pointer or reference of struct or union declaration with possible initialization
|
||||||
// struct S * p[10]; struct T * q[10] = { 0 };
|
// struct S * p[10]; struct T * q[10] = { 0 };
|
||||||
else if (Token::Match(tok, "[;{}] struct|union %type% *|& %var% [ %num% ] ;|="))
|
else if (Token::Match(tok, "[;{}] struct|union %type% *|& %var% [ %any% ] ;|="))
|
||||||
{
|
{
|
||||||
variables.addVar(tok->tokAt(4),
|
variables.addVar(tok->tokAt(4),
|
||||||
tok->tokAt(3)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
tok->tokAt(3)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
||||||
|
@ -1063,7 +1077,7 @@ void CheckOther::functionVariableUsage()
|
||||||
|
|
||||||
// const array of pointer or reference of struct or union declaration with possible initialization
|
// const array of pointer or reference of struct or union declaration with possible initialization
|
||||||
// const struct S * p[10]; const struct T * q[10] = { 0 };
|
// const struct S * p[10]; const struct T * q[10] = { 0 };
|
||||||
else if (Token::Match(tok, "[;{}] const struct|union %type% *|& %var% [ %num% ] ;|="))
|
else if (Token::Match(tok, "[;{}] const struct|union %type% *|& %var% [ %any% ] ;|="))
|
||||||
{
|
{
|
||||||
variables.addVar(tok->tokAt(5),
|
variables.addVar(tok->tokAt(5),
|
||||||
tok->tokAt(4)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
tok->tokAt(4)->str() == "*" ? Variables::pointerArray : Variables::referenceArray,
|
||||||
|
@ -1120,6 +1134,7 @@ void CheckOther::functionVariableUsage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assignment
|
||||||
else if (Token::Match(tok, "%var% [") && Token::Match(tok->next()->link(), "] ="))
|
else if (Token::Match(tok, "%var% [") && Token::Match(tok->next()->link(), "] ="))
|
||||||
{
|
{
|
||||||
unsigned int varid = tok->varId();
|
unsigned int varid = tok->varId();
|
||||||
|
@ -1140,6 +1155,11 @@ void CheckOther::functionVariableUsage()
|
||||||
else if (Token::Match(tok, ">>|& %var%"))
|
else if (Token::Match(tok, ">>|& %var%"))
|
||||||
variables.use(tok->next()->varId()); // use = read + write
|
variables.use(tok->next()->varId()); // use = read + write
|
||||||
|
|
||||||
|
// function parameter
|
||||||
|
else if (Token::Match(tok, "[(,] %var% ["))
|
||||||
|
variables.use(tok->next()->varId()); // use = read + write
|
||||||
|
|
||||||
|
// function parameter
|
||||||
else if (Token::Match(tok, "[(,] %var% [,)]"))
|
else if (Token::Match(tok, "[(,] %var% [,)]"))
|
||||||
variables.use(tok->next()->varId()); // use = read + write
|
variables.use(tok->next()->varId()); // use = read + write
|
||||||
|
|
||||||
|
|
|
@ -407,6 +407,30 @@ private:
|
||||||
" int j = i;\n"
|
" int j = i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int i[10] = { 0 };\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo(int n)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i[n] = { 0 };\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char i[10] = \"123456789\";\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char *i = \"123456789\";\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar2()
|
void localvar2()
|
||||||
|
@ -468,33 +492,64 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'i' is not assigned a value\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'i' is not assigned a value\n"), errout.str());
|
||||||
|
|
||||||
|
// assume f() can write a
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a[10];\n"
|
" int a[10];\n"
|
||||||
" f(a[0]);\n"
|
" f(a[0]);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assume f() can write a
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a[10];\n"
|
" int a[10];\n"
|
||||||
" f(a[0], 0);\n"
|
" f(a[0], 0);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assume f() can write a
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a[10];\n"
|
" int a[10];\n"
|
||||||
" f(0, a[0]);\n"
|
" f(0, a[0]);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assume f() can write a
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a[10];\n"
|
" int a[10];\n"
|
||||||
" f(0, a[0], 0);\n"
|
" f(0, a[0], 0);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// f() can not write a (not supported yet)
|
||||||
|
functionVariableUsage("void f(int i) { }\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" f(a[0]);\n"
|
||||||
|
"}\n");
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
||||||
|
|
||||||
|
// f() can not write a (not supported yet)
|
||||||
|
functionVariableUsage("void f(const int & i) { }\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" f(a[0]);\n"
|
||||||
|
"}\n");
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
||||||
|
|
||||||
|
// f() writes a
|
||||||
|
functionVariableUsage("void f(int & i) { }\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" f(a[0]);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar3()
|
void localvar3()
|
||||||
|
@ -662,6 +717,12 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo(int n)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i[n];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i = 0;\n"
|
" int i = 0;\n"
|
||||||
|
@ -1102,6 +1163,24 @@ private:
|
||||||
" f(d);\n"
|
" f(d);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is not assigned a value\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("struct S { char c[100]; };\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char a[100];\n"
|
||||||
|
" struct S * s = (struct S *)a;\n"
|
||||||
|
" s->c[0] = 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("struct S { char c[100]; };\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char a[100];\n"
|
||||||
|
" struct S * s = (struct S *)a;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (style) Unused variable: a\n"
|
||||||
|
"[test.cpp:5]: (style) Variable 's' is assigned a value that is never used\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarasm()
|
void localvarasm()
|
||||||
|
|
Loading…
Reference in New Issue