Fix issue 9916: False positive: duplicateAssignExpression when it's checked if variables have initial value later (#2825)
This commit is contained in:
parent
acb4ed5eb8
commit
887b40e08b
|
@ -2050,19 +2050,40 @@ void CheckOther::checkDuplicateExpression()
|
||||||
isSameExpression(mTokenizer->isCPP(), true, tok->next(), nextAssign->next(), mSettings->library, true, false) &&
|
isSameExpression(mTokenizer->isCPP(), true, tok->next(), nextAssign->next(), mSettings->library, true, false) &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), nextAssign->astOperand2(), mSettings->library, true, false) &&
|
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), nextAssign->astOperand2(), mSettings->library, true, false) &&
|
||||||
tok->astOperand2()->expressionString() == nextAssign->astOperand2()->expressionString()) {
|
tok->astOperand2()->expressionString() == nextAssign->astOperand2()->expressionString()) {
|
||||||
bool assigned = false;
|
bool differentDomain = false;
|
||||||
const Scope * varScope = var1->scope() ? var1->scope() : scope;
|
const Scope * varScope = var1->scope() ? var1->scope() : scope;
|
||||||
for (const Token *assignTok = Token::findsimplematch(var2, ";"); assignTok && assignTok != varScope->bodyEnd; assignTok = assignTok->next()) {
|
for (const Token *assignTok = Token::findsimplematch(var2, ";"); assignTok && assignTok != varScope->bodyEnd; assignTok = assignTok->next()) {
|
||||||
if (Token::Match(assignTok, "%varid% = %var%", var1->varId()) && Token::Match(assignTok, "%var% = %varid%", var2->varId())) {
|
if (!Token::Match(assignTok, "%assign%|%comp%"))
|
||||||
assigned = true;
|
continue;
|
||||||
break;
|
if (!assignTok->astOperand1())
|
||||||
}
|
continue;
|
||||||
if (Token::Match(assignTok, "%varid% = %var%", var2->varId()) && Token::Match(assignTok, "%var% = %varid%", var1->varId())) {
|
if (!assignTok->astOperand2())
|
||||||
assigned = true;
|
continue;
|
||||||
break;
|
|
||||||
}
|
if (assignTok->astOperand1()->varId() != var1->varId() &&
|
||||||
|
assignTok->astOperand1()->varId() != var2->varId() &&
|
||||||
|
!isSameExpression(mTokenizer->isCPP(),
|
||||||
|
true,
|
||||||
|
tok->astOperand2(),
|
||||||
|
assignTok->astOperand1(),
|
||||||
|
mSettings->library,
|
||||||
|
true,
|
||||||
|
true))
|
||||||
|
continue;
|
||||||
|
if (assignTok->astOperand2()->varId() != var1->varId() &&
|
||||||
|
assignTok->astOperand2()->varId() != var2->varId() &&
|
||||||
|
!isSameExpression(mTokenizer->isCPP(),
|
||||||
|
true,
|
||||||
|
tok->astOperand2(),
|
||||||
|
assignTok->astOperand2(),
|
||||||
|
mSettings->library,
|
||||||
|
true,
|
||||||
|
true))
|
||||||
|
continue;
|
||||||
|
differentDomain = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!assigned && !isUniqueExpression(tok->astOperand2()))
|
if (!differentDomain && !isUniqueExpression(tok->astOperand2()))
|
||||||
duplicateAssignExpressionError(var1, var2, false);
|
duplicateAssignExpressionError(var1, var2, false);
|
||||||
else if (mSettings->inconclusive)
|
else if (mSettings->inconclusive)
|
||||||
duplicateAssignExpressionError(var1, var2, true);
|
duplicateAssignExpressionError(var1, var2, true);
|
||||||
|
|
|
@ -5694,6 +5694,42 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct A { int x; int y; };"
|
||||||
|
"void use(int);\n"
|
||||||
|
"void test(A a) {\n"
|
||||||
|
" int i = a.x;\n"
|
||||||
|
" int j = a.x;\n"
|
||||||
|
" use(j);\n"
|
||||||
|
" if (i == j) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS(
|
||||||
|
"[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("struct A { int x; int y; };"
|
||||||
|
"void use(int);\n"
|
||||||
|
"void test(A a) {\n"
|
||||||
|
" int i = a.x;\n"
|
||||||
|
" int j = a.x;\n"
|
||||||
|
" use(j);\n"
|
||||||
|
" if (i == a.x) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS(
|
||||||
|
"[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("struct A { int x; int y; };"
|
||||||
|
"void use(int);\n"
|
||||||
|
"void test(A a) {\n"
|
||||||
|
" int i = a.x;\n"
|
||||||
|
" int j = a.x;\n"
|
||||||
|
" use(i);\n"
|
||||||
|
" if (j == a.x) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS(
|
||||||
|
"[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
// Issue #8612
|
// Issue #8612
|
||||||
check("struct P\n"
|
check("struct P\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue