Fixed #1622 (False positive: buf is not assigned a value (pointer aliasing))

This commit is contained in:
Robert Reif 2010-04-30 18:11:51 +02:00 committed by Daniel Marjamäki
parent 344b6bf434
commit 5738f34872
2 changed files with 125 additions and 26 deletions

View File

@ -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

View File

@ -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()