variable usage: refactoring the checking
This commit is contained in:
parent
99a7755218
commit
2bdcf3b5b2
|
@ -470,39 +470,184 @@ static bool isOp(const Token *tok)
|
||||||
Token::Match(tok, "[+-*/%&!~|^,[])?:]")));
|
Token::Match(tok, "[+-*/%&!~|^,[])?:]")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Store information about variable usage */
|
class VariableScope
|
||||||
class VariableUsage
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VariableUsage()
|
/** Store information about variable usage in this scope */
|
||||||
|
class VariableUsage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VariableUsage(const Token *name = 0,
|
||||||
|
const Token *type = 0,
|
||||||
|
bool read = false,
|
||||||
|
bool write = false,
|
||||||
|
bool modified = false,
|
||||||
|
bool aliased = false) :
|
||||||
|
_name(name),
|
||||||
|
_type(type),
|
||||||
|
_read(read),
|
||||||
|
_write(write),
|
||||||
|
_modified(modified),
|
||||||
|
_aliased(aliased)
|
||||||
{
|
{
|
||||||
declare = false;
|
|
||||||
read = false;
|
|
||||||
write = false;
|
|
||||||
modified = false;
|
|
||||||
aliased = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** variable is used.. set both read+write */
|
/** variable is used.. set both read+write */
|
||||||
void use()
|
void use()
|
||||||
{
|
{
|
||||||
read = true;
|
_read = true;
|
||||||
write = true;
|
_write = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is variable unused? */
|
/** is variable unused? */
|
||||||
bool unused() const
|
bool unused() const
|
||||||
{
|
{
|
||||||
return (read == false && write == false);
|
return (_read == false && _write == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool declare;
|
const Token *_name;
|
||||||
bool read;
|
const Token *_type;
|
||||||
bool write;
|
bool _read;
|
||||||
bool modified; // read/modify/write
|
bool _write;
|
||||||
bool aliased; // pointer or reference
|
bool _modified; // read/modify/write
|
||||||
|
bool _aliased; // pointer or reference
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, VariableUsage> VariableMap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VariableMap _varUsage;
|
||||||
|
std::vector<VariableScope*> _varScope;
|
||||||
|
VariableScope *_varScopeBack;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VariableScope(VariableScope *back = 0) : _varScopeBack(back) { }
|
||||||
|
~VariableScope()
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < _varScope.size(); i++)
|
||||||
|
delete _varScope[i];
|
||||||
|
}
|
||||||
|
VariableScope *addScope()
|
||||||
|
{
|
||||||
|
_varScope.push_back(new VariableScope(this));
|
||||||
|
return _varScope.back();
|
||||||
|
}
|
||||||
|
VariableScope *lastScope()
|
||||||
|
{
|
||||||
|
return _varScopeBack;
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
_varUsage.clear();
|
||||||
|
}
|
||||||
|
void addVar(const Token *name,
|
||||||
|
const Token *type,
|
||||||
|
bool write_ = false,
|
||||||
|
bool aliased = false)
|
||||||
|
{
|
||||||
|
_varUsage.insert(std::make_pair(name->str(), VariableUsage(name, type, false, write_, false, aliased)));
|
||||||
|
}
|
||||||
|
const VariableMap &varUsage() const
|
||||||
|
{
|
||||||
|
return _varUsage;
|
||||||
|
}
|
||||||
|
void read(const Token *tok);
|
||||||
|
void write(const Token *tok);
|
||||||
|
void use(const Token *tok);
|
||||||
|
void modified(const Token *tok);
|
||||||
|
void checkUsage(CheckOther * check);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void VariableScope::read(const Token *tok)
|
||||||
|
{
|
||||||
|
VariableScope * scope = this;
|
||||||
|
|
||||||
|
while (scope)
|
||||||
|
{
|
||||||
|
VariableMap::iterator i = scope->_varUsage.find(tok->str());
|
||||||
|
if (i != scope->varUsage().end())
|
||||||
|
{
|
||||||
|
i->second._read = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope->lastScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VariableScope::write(const Token *tok)
|
||||||
|
{
|
||||||
|
VariableScope * scope = this;
|
||||||
|
|
||||||
|
while (scope)
|
||||||
|
{
|
||||||
|
VariableMap::iterator i = scope->_varUsage.find(tok->str());
|
||||||
|
if (i != scope->varUsage().end())
|
||||||
|
{
|
||||||
|
i->second._write = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope->lastScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VariableScope::use(const Token *tok)
|
||||||
|
{
|
||||||
|
VariableScope * scope = this;
|
||||||
|
|
||||||
|
while (scope)
|
||||||
|
{
|
||||||
|
VariableMap::iterator i = scope->_varUsage.find(tok->str());
|
||||||
|
if (i != scope->varUsage().end())
|
||||||
|
{
|
||||||
|
i->second.use();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope->lastScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VariableScope::modified(const Token *tok)
|
||||||
|
{
|
||||||
|
VariableScope * scope = this;
|
||||||
|
|
||||||
|
while (scope)
|
||||||
|
{
|
||||||
|
VariableMap::iterator i = scope->_varUsage.find(tok->str());
|
||||||
|
if (i != scope->varUsage().end())
|
||||||
|
{
|
||||||
|
i->second._modified = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope->lastScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableScope::checkUsage(CheckOther *checkOther)
|
||||||
|
{
|
||||||
|
VariableMap::const_iterator it;
|
||||||
|
for (it = _varUsage.begin(); it != _varUsage.end(); ++it)
|
||||||
|
{
|
||||||
|
const std::string &varname = it->first;
|
||||||
|
const VariableUsage &usage = it->second;
|
||||||
|
|
||||||
|
if (usage.unused() && !usage._modified)
|
||||||
|
checkOther->unusedVariableError(usage._name, varname);
|
||||||
|
|
||||||
|
else if (usage._modified & !usage._write)
|
||||||
|
checkOther->unassignedVariableError(usage._name, varname);
|
||||||
|
|
||||||
|
else if (!usage._read && !usage._modified && !usage._aliased)
|
||||||
|
checkOther->unreadVariableError(usage._name, varname);
|
||||||
|
|
||||||
|
else if (!usage._write)
|
||||||
|
checkOther->unassignedVariableError(usage._name, varname);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0 ; i < _varScope.size(); i++)
|
||||||
|
_varScope[i]->checkUsage(checkOther);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::functionVariableUsage()
|
void CheckOther::functionVariableUsage()
|
||||||
{
|
{
|
||||||
if (!_settings->_checkCodingStyle)
|
if (!_settings->_checkCodingStyle)
|
||||||
|
@ -521,19 +666,25 @@ void CheckOther::functionVariableUsage()
|
||||||
// Find next scope that will be checked next time..
|
// Find next scope that will be checked next time..
|
||||||
token = Token::findmatch(token->link(), ") const| {");
|
token = Token::findmatch(token->link(), ") const| {");
|
||||||
|
|
||||||
// Varname, usage {declare, read, write}
|
// Varname, usage {read, write, modified, ...}
|
||||||
std::map<std::string, VariableUsage> varUsage;
|
// there can be multiple variables with the same name but in different scopes
|
||||||
|
VariableScope rootScope;
|
||||||
|
VariableScope * varScope = &rootScope;
|
||||||
|
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 1;
|
||||||
for (const Token *tok = tok1; tok; tok = tok->next())
|
for (const Token *tok = tok1; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (tok->str() == "{")
|
if (tok->str() == "{" && tok != tok1)
|
||||||
|
{
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
|
varScope = varScope->addScope();
|
||||||
|
}
|
||||||
else if (tok->str() == "}")
|
else if (tok->str() == "}")
|
||||||
{
|
{
|
||||||
if (indentlevel <= 1)
|
|
||||||
break;
|
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
|
if (indentlevel == 0)
|
||||||
|
break;
|
||||||
|
varScope = varScope->lastScope();
|
||||||
}
|
}
|
||||||
else if (Token::Match(tok, "struct|union|class {") ||
|
else if (Token::Match(tok, "struct|union|class {") ||
|
||||||
Token::Match(tok, "struct|union|class %type% {"))
|
Token::Match(tok, "struct|union|class %type% {"))
|
||||||
|
@ -547,188 +698,136 @@ void CheckOther::functionVariableUsage()
|
||||||
|
|
||||||
if (Token::Match(tok, "[;{}] asm ( ) ;"))
|
if (Token::Match(tok, "[;{}] asm ( ) ;"))
|
||||||
{
|
{
|
||||||
varUsage.clear();
|
varScope->clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standard type declaration: int i;
|
||||||
if (Token::Match(tok, "[;{}] %type% %var% ;|=") && tok->next()->isStandardType())
|
if (Token::Match(tok, "[;{}] %type% %var% ;|=") && tok->next()->isStandardType())
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(2)].declare = true;
|
varScope->addVar(tok->tokAt(2), tok->next(), tok->tokAt(3)->str() == "=");
|
||||||
if (tok->tokAt(3)->str() == "=")
|
|
||||||
varUsage[tok->strAt(2)].write = true;
|
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standard type declaration and initialization using constructor: int i(0);
|
||||||
else if (Token::Match(tok, "[;{}] %type% %var% ( %any% ) ;") && tok->next()->isStandardType())
|
else if (Token::Match(tok, "[;{}] %type% %var% ( %any% ) ;") && tok->next()->isStandardType())
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(2)].declare = true;
|
varScope->addVar(tok->tokAt(2), tok->next(), true);
|
||||||
varUsage[tok->strAt(2)].write = true;
|
|
||||||
|
// check if a local variable is used to initialize this variable
|
||||||
if (tok->tokAt(4)->varId() > 0)
|
if (tok->tokAt(4)->varId() > 0)
|
||||||
{
|
varScope->read(tok->tokAt(4));
|
||||||
if (varUsage.find(tok->tokAt(4)->str()) != varUsage.end())
|
|
||||||
{
|
|
||||||
varUsage.find(tok->tokAt(4)->str())->second.read = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tok = tok->tokAt(5);
|
tok = tok->tokAt(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standard type decelaration of array of with optional initialization: int i[10]; int j[2] = { 0, 1 };
|
||||||
else if (Token::Match(tok, "[;{}] %type% %var% [ %num% ] ;|=") && tok->next()->isStandardType())
|
else if (Token::Match(tok, "[;{}] %type% %var% [ %num% ] ;|=") && tok->next()->isStandardType())
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(2)].declare = true;
|
varScope->addVar(tok->tokAt(2), tok->next(), tok->tokAt(6)->str() == "=", false);
|
||||||
if (tok->tokAt(6)->str() == "=")
|
|
||||||
varUsage[tok->strAt(2)].write = true;
|
|
||||||
tok = tok->tokAt(5);
|
tok = tok->tokAt(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointer or reference declaration with optional initialization: int * i; int * j = 0;
|
||||||
else if (Token::Match(tok, "[;{}] %type% *|& %var% ;|="))
|
else if (Token::Match(tok, "[;{}] %type% *|& %var% ;|="))
|
||||||
{
|
{
|
||||||
if (tok->next()->str() != "return")
|
if (tok->next()->str() != "return")
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(3)].declare = true;
|
varScope->addVar(tok->tokAt(3), tok->next(), tok->tokAt(4)->str() == "=", true);
|
||||||
varUsage[tok->strAt(3)].aliased = true;
|
|
||||||
if (tok->tokAt(4)->str() == "=")
|
|
||||||
varUsage[tok->strAt(3)].write = true;
|
|
||||||
tok = tok->tokAt(3);
|
tok = tok->tokAt(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const pointer or reference declaration with optional initialization: const int * i; const int * j = 0;
|
||||||
else if (Token::Match(tok, "[;{}] const %type% *|& %var% ;|="))
|
else if (Token::Match(tok, "[;{}] const %type% *|& %var% ;|="))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(4)].declare = true;
|
varScope->addVar(tok->tokAt(4), tok->tokAt(2), tok->tokAt(5)->str() == "=", true);
|
||||||
varUsage[tok->strAt(4)].aliased = true;
|
|
||||||
if (tok->tokAt(5)->str() == "=")
|
|
||||||
varUsage[tok->strAt(4)].write = true;
|
|
||||||
tok = tok->tokAt(4);
|
tok = tok->tokAt(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointer or reference of struct or union declaration with optional initialization: struct s * i; struct s * j = 0;
|
||||||
else if (Token::Match(tok, "[;{}] struct|union %type% *|& %var% ;|="))
|
else if (Token::Match(tok, "[;{}] struct|union %type% *|& %var% ;|="))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(4)].declare = true;
|
varScope->addVar(tok->tokAt(4), tok->tokAt(2), tok->tokAt(5)->str() == "=", true);
|
||||||
varUsage[tok->strAt(4)].aliased = true;
|
|
||||||
if (tok->tokAt(5)->str() == "=")
|
|
||||||
varUsage[tok->strAt(4)].write = true;
|
|
||||||
tok = tok->tokAt(4);
|
tok = tok->tokAt(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const pointer or reference of struct or union declaration with optional initialization: const struct s * i; const struct s * j = 0;
|
||||||
else if (Token::Match(tok, "[;{}] const struct|union %type% *|& %var% ;|="))
|
else if (Token::Match(tok, "[;{}] const struct|union %type% *|& %var% ;|="))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(5)].declare = true;
|
varScope->addVar(tok->tokAt(5), tok->tokAt(3), tok->tokAt(6)->str() == "=", true);
|
||||||
varUsage[tok->strAt(5)].aliased = true;
|
|
||||||
if (tok->tokAt(6)->str() == "=")
|
|
||||||
varUsage[tok->strAt(5)].write = true;
|
|
||||||
tok = tok->tokAt(5);
|
tok = tok->tokAt(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "[;{}] %type% &|* %var% ( %any% ) ;") && (tok->next()->isStandardType() || tok->next()->str() == "void"))
|
else if (Token::Match(tok, "[;{}] %type% &|* %var% ( %any% ) ;") && (tok->next()->isStandardType() || tok->next()->str() == "void"))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(3)].declare = true;
|
varScope->addVar(tok->tokAt(3), tok->next(), true, true);
|
||||||
varUsage[tok->strAt(3)].write = true;
|
|
||||||
varUsage[tok->strAt(3)].aliased = true;
|
// check if a local variable is used to initialize this variable
|
||||||
if (tok->tokAt(5)->varId() > 0)
|
if (tok->tokAt(5)->varId() > 0)
|
||||||
{
|
|
||||||
if (varUsage.find(tok->tokAt(5)->str()) != varUsage.end())
|
|
||||||
{
|
{
|
||||||
if (tok->tokAt(2)->str() == "&")
|
if (tok->tokAt(2)->str() == "&")
|
||||||
varUsage.find(tok->tokAt(5)->str())->second.read = true;
|
varScope->read(tok->tokAt(5));
|
||||||
else
|
else
|
||||||
varUsage.find(tok->tokAt(5)->str())->second.use();
|
varScope->use(tok->tokAt(5));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tok = tok->tokAt(6);
|
tok = tok->tokAt(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "[;{}] %type% *|& %var% [ %num% ] ;|=") && (tok->next()->isStandardType() || tok->next()->str() == "void"))
|
else if (Token::Match(tok, "[;{}] %type% *|& %var% [ %num% ] ;|=") && (tok->next()->isStandardType() || tok->next()->str() == "void"))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(3)].declare = true;
|
varScope->addVar(tok->tokAt(3), tok->next(), tok->tokAt(7)->str() == "=", true);
|
||||||
varUsage[tok->strAt(3)].aliased = true;
|
|
||||||
if (tok->tokAt(7)->str() == "=")
|
|
||||||
varUsage[tok->strAt(3)].write = true;
|
|
||||||
tok = tok->tokAt(6);
|
tok = tok->tokAt(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "[;{}] const %type% *|& %var% [ %num% ] ;|=") && (tok->tokAt(2)->isStandardType() || tok->tokAt(2)->str() == "void"))
|
else if (Token::Match(tok, "[;{}] const %type% *|& %var% [ %num% ] ;|=") && (tok->tokAt(2)->isStandardType() || tok->tokAt(2)->str() == "void"))
|
||||||
{
|
{
|
||||||
varUsage[tok->strAt(4)].declare = true;
|
varScope->addVar(tok->tokAt(4), tok->next(), tok->tokAt(8)->str() == "=", true);
|
||||||
varUsage[tok->strAt(4)].aliased = true;
|
|
||||||
if (tok->tokAt(8)->str() == "=")
|
|
||||||
varUsage[tok->strAt(4)].write = true;
|
|
||||||
tok = tok->tokAt(7);
|
tok = tok->tokAt(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "delete|return %var%"))
|
else if (Token::Match(tok, "delete|return %var%"))
|
||||||
varUsage[tok->strAt(1)].read = true;
|
varScope->read(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var% ="))
|
else if (Token::Match(tok, "%var% ="))
|
||||||
varUsage[tok->str()].write = true;
|
varScope->write(tok);
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var% [") && Token::Match(tok->next()->link(), "] ="))
|
else if (Token::Match(tok, "%var% [") && Token::Match(tok->next()->link(), "] ="))
|
||||||
varUsage[tok->str()].write = true;
|
varScope->write(tok);
|
||||||
|
|
||||||
else if (Token::Match(tok, "else %var% ="))
|
else if (Token::Match(tok, "else %var% ="))
|
||||||
varUsage[ tok->strAt(1)].write = true;
|
varScope->write(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, ">>|& %var%"))
|
else if (Token::Match(tok, ">>|& %var%"))
|
||||||
varUsage[ tok->strAt(1)].use(); // use = read + write
|
varScope->use(tok->next()); // use = read + write
|
||||||
|
|
||||||
else if (Token::Match(tok, "[(,] %var% [,)]"))
|
else if (Token::Match(tok, "[(,] %var% [,)]"))
|
||||||
varUsage[ tok->strAt(1)].use(); // use = read + write
|
varScope->use(tok->next()); // use = read + write
|
||||||
|
|
||||||
else if (Token::Match(tok, " %var% ."))
|
else if (Token::Match(tok, " %var% ."))
|
||||||
varUsage[ tok->str()].use(); // use = read + write
|
varScope->use(tok); // use = read + write
|
||||||
|
|
||||||
else if ((Token::Match(tok, "[(=&!]") || isOp(tok)) &&
|
else if ((Token::Match(tok, "[(=&!]") || isOp(tok)) &&
|
||||||
(Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false")))
|
(Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false")))
|
||||||
varUsage[ tok->strAt(1)].read = true;
|
varScope->read(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, "-=|+=|*=|/=|&=|^= %var%") || Token::Match(tok, "|= %var%"))
|
else if (Token::Match(tok, "-=|+=|*=|/=|&=|^= %var%") || Token::Match(tok, "|= %var%"))
|
||||||
varUsage[ tok->strAt(1)].modified = true;
|
varScope->modified(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || isOp(tok->next())))
|
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || isOp(tok->next())))
|
||||||
varUsage[ tok->str()].read = true;
|
varScope->read(tok);
|
||||||
|
|
||||||
else if (Token::Match(tok, "; %var% ;"))
|
else if (Token::Match(tok, "; %var% ;"))
|
||||||
varUsage[ tok->strAt(1)].read = true;
|
varScope->read(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, "++|-- %var%"))
|
else if (Token::Match(tok, "++|-- %var%"))
|
||||||
varUsage[tok->strAt(1)].modified = true;
|
varScope->modified(tok->next());
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var% ++|--"))
|
else if (Token::Match(tok, "%var% ++|--"))
|
||||||
varUsage[tok->str()].modified = true;
|
varScope->modified(tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check usage of all variables in the current scope..
|
// Check usage of all variables in the current scope..
|
||||||
for (std::map<std::string, VariableUsage>::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it)
|
rootScope.checkUsage(this);
|
||||||
{
|
|
||||||
const std::string &varname = it->first;
|
|
||||||
const VariableUsage &usage = it->second;
|
|
||||||
|
|
||||||
if (!std::isalpha(varname[0]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!usage.declare)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (usage.unused() && !usage.modified)
|
|
||||||
{
|
|
||||||
unusedVariableError(tok1, varname);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (usage.modified & !usage.write)
|
|
||||||
{
|
|
||||||
unassignedVariableError(tok1, varname);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!usage.read && !usage.modified && !usage.aliased)
|
|
||||||
{
|
|
||||||
unreadVariableError(tok1, varname);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!usage.write)
|
|
||||||
{
|
|
||||||
unassignedVariableError(tok1, varname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ private:
|
||||||
TEST_CASE(localvar7);
|
TEST_CASE(localvar7);
|
||||||
TEST_CASE(localvar8);
|
TEST_CASE(localvar8);
|
||||||
TEST_CASE(localvar9); // ticket #1605
|
TEST_CASE(localvar9); // ticket #1605
|
||||||
|
TEST_CASE(localvar10);
|
||||||
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
|
||||||
|
@ -322,25 +323,25 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i = 0;\n"
|
" int i = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" bool i = false;\n"
|
" bool i = false;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int * i = 0;\n"
|
" int * i = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" void * i = 0;\n"
|
" void * i = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar2()
|
void localvar2()
|
||||||
|
@ -350,14 +351,14 @@ private:
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
" return i;\n"
|
" return i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
|
|
||||||
functionVariableUsage("bool foo()\n"
|
functionVariableUsage("bool foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" bool i;\n"
|
" bool i;\n"
|
||||||
" return i;\n"
|
" return i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar3()
|
void localvar3()
|
||||||
|
@ -369,7 +370,7 @@ private:
|
||||||
" ;\n"
|
" ;\n"
|
||||||
" else i = 0;\n"
|
" else i = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n"), errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar4()
|
void localvar4()
|
||||||
|
@ -401,7 +402,7 @@ private:
|
||||||
" for (int i=0;i<10;++i)\n"
|
" for (int i=0;i<10;++i)\n"
|
||||||
" b[i] = ++a;\n"
|
" b[i] = ++a;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar7()// ticket 1253
|
void localvar7()// ticket 1253
|
||||||
|
@ -411,7 +412,7 @@ private:
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
" i--;\n"
|
" i--;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -419,7 +420,7 @@ private:
|
||||||
" int &ii(i);\n"
|
" int &ii(i);\n"
|
||||||
" ii--;\n"
|
" ii--;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -427,7 +428,7 @@ private:
|
||||||
" int &ii=i;\n"
|
" int &ii=i;\n"
|
||||||
" ii--;\n"
|
" ii--;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar8()
|
void localvar8()
|
||||||
|
@ -436,61 +437,61 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i[2];\n"
|
" int i[2];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" void * i;\n"
|
" void * i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" const void * i;\n"
|
" const void * i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" A * i;\n"
|
" A * i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct A * i;\n"
|
" struct A * i;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int * i[2];\n"
|
" int * i[2];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" const int * i[2];\n"
|
" const int * i[2];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" void * i[2];\n"
|
" void * i[2];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" const void * i[2];\n"
|
" const void * i[2];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: i\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -524,20 +525,20 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i = 0;\n"
|
" int i = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i(0);\n"
|
" int i(0);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *i;\n"
|
" char *i;\n"
|
||||||
" i = fgets();\n"
|
" i = fgets();\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
ASSERT_EQUALS("", errout.str()); // current value - catch changes
|
ASSERT_EQUALS("", errout.str()); // current value - catch changes
|
||||||
|
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
|
@ -581,7 +582,62 @@ private:
|
||||||
" for (int i = 0; i < 10; )\n"
|
" for (int i = 0; i < 10; )\n"
|
||||||
" a[i++] = 0;\n"
|
" a[i++] = 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'a' is assigned a value that is never used\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void localvar10()
|
||||||
|
{
|
||||||
|
functionVariableUsage("void foo(int x)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i;\n"
|
||||||
|
" if (x) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:5]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:7]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo(int x)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i;\n"
|
||||||
|
" if (x)\n"
|
||||||
|
" int i;\n"
|
||||||
|
" else\n"
|
||||||
|
" int i;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:5]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:7]: (style) Unused variable: i\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo(int x)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i;\n"
|
||||||
|
" if (x) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:5]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:7]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo(int x)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i;\n"
|
||||||
|
" if (x) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" }\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n"
|
||||||
|
"[test.cpp:5]: (style) Unused variable: i\n"
|
||||||
|
"[test.cpp:7]: (style) Unused variable: i\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarasm()
|
void localvarasm()
|
||||||
|
@ -627,7 +683,7 @@ private:
|
||||||
" func();\n"
|
" func();\n"
|
||||||
" } while(a--);\n"
|
" } while(a--);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (style) Unused variable: z\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Unused variable: z\n"), errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarStruct4()
|
void localvarStruct4()
|
||||||
|
@ -698,7 +754,7 @@ private:
|
||||||
" int b = 2;\n"
|
" int b = 2;\n"
|
||||||
" a |= b;\n"
|
" a |= b;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:2]: (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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarFor()
|
void localvarFor()
|
||||||
|
|
Loading…
Reference in New Issue