Fixed #5107 (redundantAssignment when pointer changes)
This commit is contained in:
parent
7996d609be
commit
fb04c8ff84
|
@ -594,6 +594,18 @@ static void eraseNotLocalArg(std::map<unsigned int, const Token*>& container, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void eraseMemberAssignments(const unsigned int varId, std::map<unsigned int, std::set<unsigned int> > &membervars, std::map<unsigned int, const Token*> &varAssignments)
|
||||||
|
{
|
||||||
|
const std::map<unsigned int, std::set<unsigned int> >::const_iterator it = membervars.find(varId);
|
||||||
|
if (it != membervars.end()) {
|
||||||
|
const std::set<unsigned int> &v = it->second;
|
||||||
|
for (std::set<unsigned int>::const_iterator vit = v.begin(); vit != v.end(); ++vit) {
|
||||||
|
varAssignments.erase(*vit);
|
||||||
|
eraseMemberAssignments(*vit, membervars, varAssignments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::checkRedundantAssignment()
|
void CheckOther::checkRedundantAssignment()
|
||||||
{
|
{
|
||||||
const bool performance = _settings->isEnabled("performance");
|
const bool performance = _settings->isEnabled("performance");
|
||||||
|
@ -609,6 +621,7 @@ void CheckOther::checkRedundantAssignment()
|
||||||
|
|
||||||
std::map<unsigned int, const Token*> varAssignments;
|
std::map<unsigned int, const Token*> varAssignments;
|
||||||
std::map<unsigned int, const Token*> memAssignments;
|
std::map<unsigned int, const Token*> memAssignments;
|
||||||
|
std::map<unsigned int, std::set<unsigned int> > membervars;
|
||||||
std::set<unsigned int> initialized;
|
std::set<unsigned int> initialized;
|
||||||
const Token* writtenArgumentsEnd = 0;
|
const Token* writtenArgumentsEnd = 0;
|
||||||
|
|
||||||
|
@ -638,8 +651,11 @@ void CheckOther::checkRedundantAssignment()
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token *startToken = tok;
|
const Token *startToken = tok;
|
||||||
while (Token::Match(startToken, "%var%|::|."))
|
while (Token::Match(startToken, "%var%|::|.")) {
|
||||||
startToken = startToken->previous();
|
startToken = startToken->previous();
|
||||||
|
if (Token::Match(startToken, "%var% . %var%"))
|
||||||
|
membervars[startToken->varId()].insert(startToken->tokAt(2)->varId());
|
||||||
|
}
|
||||||
|
|
||||||
std::map<unsigned int, const Token*>::iterator it = varAssignments.find(tok->varId());
|
std::map<unsigned int, const Token*>::iterator it = varAssignments.find(tok->varId());
|
||||||
if (tok->next()->isAssignmentOp() && Token::Match(startToken, "[;{}]")) { // Assignment
|
if (tok->next()->isAssignmentOp() && Token::Match(startToken, "[;{}]")) { // Assignment
|
||||||
|
@ -671,9 +687,11 @@ void CheckOther::checkRedundantAssignment()
|
||||||
if (!Token::simpleMatch(tok->tokAt(2), "0 ;") || (tok->variable() && tok->variable()->nameToken() != tok->tokAt(-2)))
|
if (!Token::simpleMatch(tok->tokAt(2), "0 ;") || (tok->variable() && tok->variable()->nameToken() != tok->tokAt(-2)))
|
||||||
varAssignments[tok->varId()] = tok;
|
varAssignments[tok->varId()] = tok;
|
||||||
memAssignments.erase(tok->varId());
|
memAssignments.erase(tok->varId());
|
||||||
|
eraseMemberAssignments(tok->varId(), membervars, varAssignments);
|
||||||
} else if (tok->next()->type() == Token::eIncDecOp || (tok->previous()->type() == Token::eIncDecOp && tok->strAt(1) == ";")) { // Variable incremented/decremented; Prefix-Increment is only suspicious, if its return value is unused
|
} else if (tok->next()->type() == Token::eIncDecOp || (tok->previous()->type() == Token::eIncDecOp && tok->strAt(1) == ";")) { // Variable incremented/decremented; Prefix-Increment is only suspicious, if its return value is unused
|
||||||
varAssignments[tok->varId()] = tok;
|
varAssignments[tok->varId()] = tok;
|
||||||
memAssignments.erase(tok->varId());
|
memAssignments.erase(tok->varId());
|
||||||
|
eraseMemberAssignments(tok->varId(), membervars, varAssignments);
|
||||||
} else if (!Token::simpleMatch(tok->tokAt(-2), "sizeof (")) { // Other usage of variable
|
} else if (!Token::simpleMatch(tok->tokAt(-2), "sizeof (")) { // Other usage of variable
|
||||||
if (it != varAssignments.end())
|
if (it != varAssignments.end())
|
||||||
varAssignments.erase(it);
|
varAssignments.erase(it);
|
||||||
|
|
|
@ -6347,6 +6347,28 @@ private:
|
||||||
" return ab.a;\n"
|
" return ab.a;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct AB { int a; int b; };\n"
|
||||||
|
"\n"
|
||||||
|
"int f(struct AB *ab) {\n"
|
||||||
|
" ab->a = 1;\n"
|
||||||
|
" ab->b = 2;\n"
|
||||||
|
" ab++;\n"
|
||||||
|
" ab->a = 1;\n"
|
||||||
|
" ab->b = 2;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct AB { int a; int b; };\n"
|
||||||
|
"\n"
|
||||||
|
"int f(struct AB *ab) {\n"
|
||||||
|
" ab->a = 1;\n"
|
||||||
|
" ab->b = 2;\n"
|
||||||
|
" ab = x;\n"
|
||||||
|
" ab->a = 1;\n"
|
||||||
|
" ab->b = 2;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void redundantMemWrite() {
|
void redundantMemWrite() {
|
||||||
|
|
Loading…
Reference in New Issue