Code cleanup
This commit is contained in:
parent
5ba02d2fdd
commit
83066edec0
|
@ -1249,13 +1249,6 @@ void CheckOther::selfAssignmentError(const Token *tok, const std::string &varnam
|
||||||
// Inform that second comparison is always true when first comparison is true.
|
// Inform that second comparison is always true when first comparison is true.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
enum Position { First, Second, NA };
|
|
||||||
enum Relation { Equal, NotEqual, Less, LessEqual, More, MoreEqual };
|
|
||||||
struct Condition {
|
|
||||||
Position position;
|
|
||||||
const char *opTokStr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string invertOperatorForOperandSwap(std::string s)
|
static std::string invertOperatorForOperandSwap(std::string s)
|
||||||
{
|
{
|
||||||
for (std::string::size_type i = 0; i < s.length(); i++) {
|
for (std::string::size_type i = 0; i < s.length(); i++) {
|
||||||
|
@ -2863,111 +2856,6 @@ void CheckOther::doubleCloseDirError(const Token *tok, const std::string &varnam
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ExpressionTokens {
|
|
||||||
const Token *start;
|
|
||||||
const Token *end;
|
|
||||||
int count;
|
|
||||||
bool inconclusiveFunction;
|
|
||||||
ExpressionTokens(const Token *s, const Token *e): start(s), end(e), count(1), inconclusiveFunction(false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FuncFilter {
|
|
||||||
FuncFilter(const Scope *scope, const Token *tok): _scope(scope), _tok(tok) {}
|
|
||||||
|
|
||||||
bool operator()(const Function* func) const {
|
|
||||||
bool matchingFunc = func->type == Function::eFunction &&
|
|
||||||
_tok->str() == func->token->str();
|
|
||||||
// either a class function, or a global function with the same name
|
|
||||||
return (_scope && _scope == func->nestedIn && matchingFunc) ||
|
|
||||||
(!_scope && matchingFunc);
|
|
||||||
}
|
|
||||||
const Scope *_scope;
|
|
||||||
const Token *_tok;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool inconclusiveFunctionCall(const std::list<const Function*> &constFunctions,
|
|
||||||
const ExpressionTokens &tokens)
|
|
||||||
{
|
|
||||||
const Token *start = tokens.start;
|
|
||||||
const Token *end = tokens.end;
|
|
||||||
// look for function calls between start and end...
|
|
||||||
for (const Token *tok = start; tok && tok != end; tok = tok->next()) {
|
|
||||||
if (tok != start && tok->str() == "(") {
|
|
||||||
// go back to find the function call.
|
|
||||||
const Token *prev = tok->previous();
|
|
||||||
if (!prev)
|
|
||||||
continue;
|
|
||||||
if (prev->str() == ">") {
|
|
||||||
// ignore template functions like boo<double>()
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (prev->isName()) {
|
|
||||||
const Variable *v = 0;
|
|
||||||
if (Token::Match(prev->tokAt(-2), "%var% .")) {
|
|
||||||
const Token *scope = prev->tokAt(-2);
|
|
||||||
v = scope->variable();
|
|
||||||
}
|
|
||||||
// hard coded list of safe, no-side-effect functions
|
|
||||||
if (v == 0 && Token::Match(prev, "strcmp|strncmp|strlen|wcscmp|wcsncmp|wcslen|memcmp|strcasecmp|strncasecmp"))
|
|
||||||
return false;
|
|
||||||
std::list<const Function*>::const_iterator it = std::find_if(constFunctions.begin(),
|
|
||||||
constFunctions.end(),
|
|
||||||
FuncFilter(v ? v->typeScope(): 0, prev));
|
|
||||||
if (it == constFunctions.end())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Expressions {
|
|
||||||
public:
|
|
||||||
Expressions(const std::list<const Function*> &constFunctions)
|
|
||||||
: _start(0),
|
|
||||||
_lastTokens(0),
|
|
||||||
_constFunctions(constFunctions) { }
|
|
||||||
|
|
||||||
void endExpr(const Token *end) {
|
|
||||||
const std::string &e = _expression.str();
|
|
||||||
if (!e.empty()) {
|
|
||||||
std::map<std::string, ExpressionTokens>::iterator it = _expressions.find(e);
|
|
||||||
bool lastInconclusive = _lastTokens && _lastTokens->inconclusiveFunction;
|
|
||||||
if (it == _expressions.end()) {
|
|
||||||
ExpressionTokens exprTokens(_start, end);
|
|
||||||
exprTokens.inconclusiveFunction = lastInconclusive || inconclusiveFunctionCall(
|
|
||||||
_constFunctions, exprTokens);
|
|
||||||
_expressions.insert(std::make_pair(e, exprTokens));
|
|
||||||
_lastTokens = &_expressions.find(e)->second;
|
|
||||||
} else {
|
|
||||||
ExpressionTokens &expr = it->second;
|
|
||||||
expr.count += 1;
|
|
||||||
expr.inconclusiveFunction = expr.inconclusiveFunction || lastInconclusive;
|
|
||||||
_lastTokens = &expr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_expression.str("");
|
|
||||||
_start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const Token *tok) {
|
|
||||||
if (!_start)
|
|
||||||
_start = tok;
|
|
||||||
_expression << tok->str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string,ExpressionTokens> &getMap() {
|
|
||||||
return _expressions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<std::string, ExpressionTokens> _expressions;
|
|
||||||
std::ostringstream _expression;
|
|
||||||
const Token *_start;
|
|
||||||
ExpressionTokens *_lastTokens;
|
|
||||||
const std::list<const Function*> &_constFunctions;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool notconst(const Function* func)
|
bool notconst(const Function* func)
|
||||||
{
|
{
|
||||||
return !func->isConst;
|
return !func->isConst;
|
||||||
|
@ -2995,132 +2883,6 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::checkExpressionRange(const std::list<const Function*> &constFunctions,
|
|
||||||
const Token *start,
|
|
||||||
const Token *end,
|
|
||||||
const std::string &toCheck)
|
|
||||||
{
|
|
||||||
if (!start || !end)
|
|
||||||
return;
|
|
||||||
Expressions expressions(constFunctions);
|
|
||||||
std::string opName;
|
|
||||||
int level = 0;
|
|
||||||
for (const Token *tok = start->next(); tok && tok != end; tok = tok->next()) {
|
|
||||||
if (tok->str() == ")")
|
|
||||||
level--;
|
|
||||||
else if (tok->str() == "(")
|
|
||||||
level++;
|
|
||||||
|
|
||||||
if (level == 0 && Token::Match(tok, toCheck.c_str())) {
|
|
||||||
opName = tok->str();
|
|
||||||
expressions.endExpr(tok);
|
|
||||||
} else {
|
|
||||||
expressions.append(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expressions.endExpr(end);
|
|
||||||
std::map<std::string,ExpressionTokens>::const_iterator it = expressions.getMap().begin();
|
|
||||||
for (; it != expressions.getMap().end(); ++it) {
|
|
||||||
// check expression..
|
|
||||||
bool valid = true;
|
|
||||||
unsigned int parentheses = 0; // ()
|
|
||||||
unsigned int brackets = 0; // []
|
|
||||||
|
|
||||||
// taking address?
|
|
||||||
if (Token::Match(it->second.end->previous(), "%op% &")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Token *tok = it->second.start; tok && tok != it->second.end; tok = tok->next()) {
|
|
||||||
if (tok->str() == "(") {
|
|
||||||
++parentheses;
|
|
||||||
} else if (tok->str() == ")") {
|
|
||||||
if (parentheses == 0) {
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--parentheses;
|
|
||||||
} else if (tok->str() == "[") {
|
|
||||||
++brackets;
|
|
||||||
} else if (tok->str() == "]") {
|
|
||||||
if (brackets == 0) {
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--brackets;
|
|
||||||
} else if (tok->type() == Token::eIncDecOp) {
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid || parentheses!=0 || brackets!=0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const ExpressionTokens &expr = it->second;
|
|
||||||
if (expr.count > 1 && !expr.inconclusiveFunction) {
|
|
||||||
duplicateExpressionError(expr.start, expr.start, opName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::complexDuplicateExpressionCheck(const std::list<const Function*> &constFunctions,
|
|
||||||
const Token *classStart,
|
|
||||||
const std::string &toCheck,
|
|
||||||
const std::string &alt)
|
|
||||||
{
|
|
||||||
std::string statementStart(",|=|?|:|return");
|
|
||||||
if (!alt.empty())
|
|
||||||
statementStart += "|" + alt;
|
|
||||||
std::string statementEnd(";|,|?|:");
|
|
||||||
if (!alt.empty())
|
|
||||||
statementEnd += "|" + alt;
|
|
||||||
|
|
||||||
for (const Token *tok = classStart; tok && tok != classStart->link(); tok = tok->next()) {
|
|
||||||
if (!Token::Match(tok, toCheck.c_str()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// look backward for the start of the statement
|
|
||||||
const Token *start = 0;
|
|
||||||
int level = 0;
|
|
||||||
for (const Token *tok1 = tok->previous(); tok1 && tok1 != classStart; tok1 = tok1->previous()) {
|
|
||||||
if (tok1->str() == ")")
|
|
||||||
level++;
|
|
||||||
else if (tok1->str() == "(")
|
|
||||||
level--;
|
|
||||||
|
|
||||||
if (level < 0 || (level == 0 && Token::Match(tok1, statementStart.c_str()))) {
|
|
||||||
start = tok1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok1->isExpandedMacro())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const Token *end = 0;
|
|
||||||
level = 0;
|
|
||||||
// look for the end of the statement
|
|
||||||
for (const Token *tok1 = tok->next(); tok1 && tok1 != classStart->link(); tok1 = tok1->next()) {
|
|
||||||
if (tok1->str() == ")")
|
|
||||||
level--;
|
|
||||||
else if (tok1->str() == "(")
|
|
||||||
level++;
|
|
||||||
|
|
||||||
if (level < 0 || (level == 0 && Token::Match(tok1, statementEnd.c_str()))) {
|
|
||||||
end = tok1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok1->isExpandedMacro())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start && end)
|
|
||||||
checkExpressionRange(constFunctions, start, end, toCheck);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool astIsFloat(const Token *tok)
|
static bool astIsFloat(const Token *tok)
|
||||||
|
|
|
@ -470,16 +470,6 @@ private:
|
||||||
"* NaN (not a number) value used in arithmetic expression.\n"
|
"* NaN (not a number) value used in arithmetic expression.\n"
|
||||||
"* comma in return statement (the comma can easily be misread as a semicolon).\n";
|
"* comma in return statement (the comma can easily be misread as a semicolon).\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkExpressionRange(const std::list<const Function*> &constFunctions,
|
|
||||||
const Token *start,
|
|
||||||
const Token *end,
|
|
||||||
const std::string &toCheck);
|
|
||||||
|
|
||||||
void complexDuplicateExpressionCheck(const std::list<const Function*> &constFunctions,
|
|
||||||
const Token *classStart,
|
|
||||||
const std::string &toCheck,
|
|
||||||
const std::string &alt);
|
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue