Fixed #1643 (Variable usage (pointer is assigned but never used))
This commit is contained in:
parent
eb276346c5
commit
7ce70777a4
|
@ -453,7 +453,8 @@ public:
|
||||||
_type(type),
|
_type(type),
|
||||||
_read(read),
|
_read(read),
|
||||||
_write(write),
|
_write(write),
|
||||||
_modified(modified)
|
_modified(modified),
|
||||||
|
_noAlias(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,6 +476,7 @@ public:
|
||||||
bool _read;
|
bool _read;
|
||||||
bool _write;
|
bool _write;
|
||||||
bool _modified; // read/modify/write
|
bool _modified; // read/modify/write
|
||||||
|
bool _noAlias; // don't alias
|
||||||
std::set<unsigned int> _aliases;
|
std::set<unsigned int> _aliases;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,6 +508,10 @@ public:
|
||||||
void eraseAliases(unsigned int varid);
|
void eraseAliases(unsigned int varid);
|
||||||
void eraseAll(unsigned int varid);
|
void eraseAll(unsigned int varid);
|
||||||
|
|
||||||
|
// don't alias this variable because it's aliased to something undefined or unsupported
|
||||||
|
// or because it's aliased to something in a larger scope
|
||||||
|
void noAlias(unsigned int varid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VariableMap _varUsage;
|
VariableMap _varUsage;
|
||||||
};
|
};
|
||||||
|
@ -517,7 +523,10 @@ void Variables::alias(unsigned int varid1, unsigned int varid2)
|
||||||
{
|
{
|
||||||
VariableUsage *var = find(varid1);
|
VariableUsage *var = find(varid1);
|
||||||
if (var)
|
if (var)
|
||||||
|
{
|
||||||
|
var->_noAlias = false;
|
||||||
var->use();
|
var->use();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,6 +544,7 @@ void Variables::alias(unsigned int varid1, unsigned int varid2)
|
||||||
|
|
||||||
// remove all aliases from var1
|
// remove all aliases from var1
|
||||||
var1->_aliases.clear();
|
var1->_aliases.clear();
|
||||||
|
var1->_noAlias = false;
|
||||||
|
|
||||||
VariableUsage *var2 = find(varid2);
|
VariableUsage *var2 = find(varid2);
|
||||||
|
|
||||||
|
@ -572,6 +582,14 @@ void Variables::eraseAll(unsigned int varid)
|
||||||
erase(varid);
|
erase(varid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Variables::noAlias(unsigned int varid)
|
||||||
|
{
|
||||||
|
VariableUsage *usage = find(varid);
|
||||||
|
|
||||||
|
if (usage)
|
||||||
|
usage->_noAlias = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Variables::addVar(const Token *name,
|
void Variables::addVar(const Token *name,
|
||||||
VariableType type,
|
VariableType type,
|
||||||
bool write_)
|
bool write_)
|
||||||
|
@ -593,14 +611,17 @@ void Variables::readAliases(unsigned int varid)
|
||||||
|
|
||||||
if (usage)
|
if (usage)
|
||||||
{
|
{
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->_read = true;
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->_read = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,19 +634,21 @@ void Variables::readAll(unsigned int varid)
|
||||||
{
|
{
|
||||||
usage->_read = true;
|
usage->_read = true;
|
||||||
|
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->_read = true;
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->_read = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Variables::write(unsigned int varid)
|
void Variables::write(unsigned int varid)
|
||||||
{
|
{
|
||||||
VariableUsage *usage = find(varid);
|
VariableUsage *usage = find(varid);
|
||||||
|
@ -640,14 +663,17 @@ void Variables::writeAliases(unsigned int varid)
|
||||||
|
|
||||||
if (usage)
|
if (usage)
|
||||||
{
|
{
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->_write = true;
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->_write = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,14 +686,17 @@ void Variables::writeAll(unsigned int varid)
|
||||||
{
|
{
|
||||||
usage->_write = true;
|
usage->_write = true;
|
||||||
|
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->_write = true;
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->_write = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -680,14 +709,17 @@ void Variables::use(unsigned int varid)
|
||||||
{
|
{
|
||||||
usage->use();
|
usage->use();
|
||||||
|
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->use();
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->use();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -700,14 +732,17 @@ void Variables::modified(unsigned int varid)
|
||||||
{
|
{
|
||||||
usage->_modified = true;
|
usage->_modified = true;
|
||||||
|
|
||||||
std::set<unsigned int>::iterator aliases;
|
if (!usage->_noAlias)
|
||||||
|
|
||||||
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
|
||||||
{
|
{
|
||||||
VariableUsage *aliased = find(*aliases);
|
std::set<unsigned int>::iterator aliases;
|
||||||
|
|
||||||
if (aliased)
|
for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases)
|
||||||
aliased->_modified = true;
|
{
|
||||||
|
VariableUsage *aliased = find(*aliases);
|
||||||
|
|
||||||
|
if (aliased)
|
||||||
|
aliased->_modified = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,14 +875,15 @@ static int doAssignment(Variables &variables, const Token *tok, bool pointer)
|
||||||
{
|
{
|
||||||
variables.alias(varid1, varid2);
|
variables.alias(varid1, varid2);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
variables.read(varid2);
|
||||||
}
|
}
|
||||||
else // not a local variable
|
else // not a local variable (or an unsupported local variable)
|
||||||
{
|
{
|
||||||
if (var1->_type == Variables::pointer && !pointer)
|
if (var1->_type == Variables::pointer && !pointer)
|
||||||
{
|
{
|
||||||
// aliased variables in a larger scope are not supported yet
|
// aliased variables in a larger scope are not supported
|
||||||
if (varid2)
|
var1->_noAlias = true;
|
||||||
variables.erase(varid1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ private:
|
||||||
TEST_CASE(localvaralias1);
|
TEST_CASE(localvaralias1);
|
||||||
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(localvarasm);
|
TEST_CASE(localvarasm);
|
||||||
|
|
||||||
// Don't give false positives for variables in structs/unions
|
// Don't give false positives for variables in structs/unions
|
||||||
|
@ -1125,22 +1126,22 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
// a is not a local variable and b is aliased to it (not supported yet)
|
// a is not a local variable and b is aliased to it
|
||||||
functionVariableUsage("int a;\n"
|
functionVariableUsage("int a;\n"
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int *b = &a;\n"
|
" int *b = &a;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
// a is not a local variable and b is aliased to it (not supported yet)
|
// a is not a local variable and b is aliased to it
|
||||||
functionVariableUsage("void foo(int a)\n"
|
functionVariableUsage("void foo(int a)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int *b = &a;\n"
|
" int *b = &a;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
// a is not a local variable and b is aliased to it (not supported yet)
|
// a is not a local variable and b is aliased to it
|
||||||
functionVariableUsage("class A\n"
|
functionVariableUsage("class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
|
@ -1149,7 +1150,7 @@ private:
|
||||||
" int *b = &a;\n"
|
" int *b = &a;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS(std::string("[test.cpp:6]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:6]: (style) Variable 'b' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
functionVariableUsage("int a;\n"
|
functionVariableUsage("int a;\n"
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
|
@ -1241,6 +1242,78 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("int a[10];\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int *c = b;\n"
|
||||||
|
" *c = 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int *c = b;\n"
|
||||||
|
" *c = 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int *c = b;\n"
|
||||||
|
" *c = b[0];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int *c;\n"
|
||||||
|
" *c = b[0];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Variable 'c' is not assigned a value\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("int a[10];\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int c = b[0];\n"
|
||||||
|
" c = c;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" int c = b[0];\n"
|
||||||
|
" c = c;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("int a[10];\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = &a[0];\n"
|
||||||
|
" a[0] = b[0];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = &a[0];\n"
|
||||||
|
" a[0] = b[0];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *b = a;\n"
|
||||||
|
" a[0] = b[0];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo(int a[10])\n"
|
functionVariableUsage("void foo(int a[10])\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int *b = a;\n"
|
" int *b = a;\n"
|
||||||
|
@ -1421,6 +1494,41 @@ private:
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void localvaralias4() // ticket 1643
|
||||||
|
{
|
||||||
|
functionVariableUsage("struct AB { int a; int b; } ab;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int * a = &ab.a;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Variable 'a' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("struct AB { int a; int b; } ab;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int * a = &ab.a;\n"
|
||||||
|
" *a = 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("struct AB { int a; int b; };\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" struct AB ab;\n"
|
||||||
|
" int * a = &ab.a;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(std::string("[test.cpp:5]: (style) Variable 'a' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("struct AB { int a; int b; };\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" struct AB ab;\n"
|
||||||
|
" int * a = &ab.a;\n"
|
||||||
|
" *a = 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"
|
||||||
|
|
Loading…
Reference in New Issue