Variable usage: Better aliasing support (Ticket #1729)
This commit is contained in:
parent
49626e427e
commit
2d6dfa57e1
|
@ -565,7 +565,7 @@ public:
|
||||||
void use(unsigned int varid);
|
void use(unsigned int varid);
|
||||||
void modified(unsigned int varid);
|
void modified(unsigned int varid);
|
||||||
VariableUsage *find(unsigned int varid);
|
VariableUsage *find(unsigned int varid);
|
||||||
void alias(unsigned int varid1, unsigned int varid2);
|
void alias(unsigned int varid1, unsigned int varid2, bool replace);
|
||||||
void erase(unsigned int varid)
|
void erase(unsigned int varid)
|
||||||
{
|
{
|
||||||
_varUsage.erase(varid);
|
_varUsage.erase(varid);
|
||||||
|
@ -578,21 +578,30 @@ private:
|
||||||
VariableMap _varUsage;
|
VariableMap _varUsage;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Variables::alias(unsigned int varid1, unsigned int varid2)
|
/**
|
||||||
|
* Alias the 2 given variables. Either replace the existing aliases if
|
||||||
|
* they exist or merge them. You would replace an existing alias when this
|
||||||
|
* assignment is in the same scope as the previous assignment. You might
|
||||||
|
* merge the aliases when this assignment is in a different scope from the
|
||||||
|
* previous assignment depending on the relationship of the 2 scopes.
|
||||||
|
*/
|
||||||
|
void Variables::alias(unsigned int varid1, unsigned int varid2, bool replace)
|
||||||
{
|
{
|
||||||
|
VariableUsage *var1 = find(varid1);
|
||||||
|
VariableUsage *var2 = find(varid2);
|
||||||
|
|
||||||
// alias to self
|
// alias to self
|
||||||
if (varid1 == varid2)
|
if (varid1 == varid2)
|
||||||
{
|
{
|
||||||
VariableUsage *var = find(varid1);
|
if (var1)
|
||||||
if (var)
|
var1->use();
|
||||||
var->use();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<unsigned int>::iterator i;
|
std::set<unsigned int>::iterator i;
|
||||||
|
|
||||||
VariableUsage *var1 = find(varid1);
|
if (replace)
|
||||||
|
{
|
||||||
// remove var1 from all aliases
|
// remove var1 from all aliases
|
||||||
for (i = var1->_aliases.begin(); i != var1->_aliases.end(); ++i)
|
for (i = var1->_aliases.begin(); i != var1->_aliases.end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -604,8 +613,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();
|
||||||
|
}
|
||||||
VariableUsage *var2 = find(varid2);
|
|
||||||
|
|
||||||
// var1 gets all var2s aliases
|
// var1 gets all var2s aliases
|
||||||
for (i = var2->_aliases.begin(); i != var2->_aliases.end(); ++i)
|
for (i = var2->_aliases.begin(); i != var2->_aliases.end(); ++i)
|
||||||
|
@ -925,13 +933,15 @@ static int doAssignment(Variables &variables, const Token *tok, bool dereference
|
||||||
var2->_type == Variables::array ||
|
var2->_type == Variables::array ||
|
||||||
var2->_type == Variables::pointer)
|
var2->_type == Variables::pointer)
|
||||||
{
|
{
|
||||||
variables.alias(varid1, varid2);
|
bool replace = true;
|
||||||
|
|
||||||
|
variables.alias(varid1, varid2, replace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (var1->_type == Variables::reference)
|
else if (var1->_type == Variables::reference)
|
||||||
{
|
{
|
||||||
variables.alias(varid1, varid2);
|
variables.alias(varid1, varid2, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1796,6 +1796,56 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" buf[0] = 1;\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" }\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'buf' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" buf[0] = 1;\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'buf' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Unused variable: buf\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char buf[8];\n"
|
" char buf[8];\n"
|
||||||
|
@ -1810,6 +1860,60 @@ private:
|
||||||
" b(srcdata);\n"
|
" b(srcdata);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" char vdata[8];\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" buf[0] = 1;\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" }\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'buf' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" char vdata[8];\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" buf[0] = 1;\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'buf' is assigned a value that is never used\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" char vdata[8];\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Unused variable: buf\n"), errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" char buf[8];\n"
|
||||||
|
" char *srcdata;\n"
|
||||||
|
" char vdata[8];\n"
|
||||||
|
" if (a()) {\n"
|
||||||
|
" srcdata = vdata;\n"
|
||||||
|
" }\n"
|
||||||
|
" srcdata = buf;\n"
|
||||||
|
" b(srcdata);\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS(std::string("[test.cpp:5]: (style) Unused variable: vdata\n"), errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvaralias7() // ticket 1732
|
void localvaralias7() // ticket 1732
|
||||||
|
|
Loading…
Reference in New Issue