Skip to content

Commit 042c2ed

Browse files
committed
Fix #14717 (FP: same exprId for different expressions leads to wrong redundantAssignment)
1 parent 6278f6b commit 042c2ed

2 files changed

Lines changed: 41 additions & 15 deletions

File tree

lib/symboldatabase.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,10 +1643,30 @@ namespace {
16431643
continue;
16441644
}
16451645

1646+
const auto getExprIdForOperand = [](const Token* tok) -> int {
1647+
if (!tok)
1648+
return 0;
1649+
1650+
int otherExprId = 0;
1651+
1652+
// Look through all referenced tokens.
1653+
// If two exprIds are found and one matches tok->exprId(), return the other.
1654+
// Otherwise, default to returning tok->exprId().
1655+
for (const auto& ref: followAllReferences(tok)) {
1656+
const int refExprId = ref.token->exprId();
1657+
if (refExprId != 0 && refExprId != tok->exprId()) {
1658+
if (otherExprId != 0 && otherExprId != refExprId)
1659+
return tok->exprId();
1660+
otherExprId = refExprId;
1661+
}
1662+
}
1663+
return otherExprId != 0 ? otherExprId : tok->exprId();
1664+
};
1665+
16461666
ExprIdKey key;
16471667
key.parentOp = tok->astParent()->str();
1648-
key.operand1 = op1 ? op1->exprId() : 0;
1649-
key.operand2 = op2 ? op2->exprId() : 0;
1668+
key.operand1 = getExprIdForOperand(op1);
1669+
key.operand2 = getExprIdForOperand(op2);
16501670

16511671
if (tok->astParent()->isCast() && tok->astParent()->str() == "(") {
16521672
const Token* typeStartToken;
@@ -1665,19 +1685,6 @@ namespace {
16651685
key.parentOp += type;
16661686
}
16671687

1668-
for (const auto& ref: followAllReferences(op1)) {
1669-
if (ref.token->exprId() != 0) { // cppcheck-suppress useStlAlgorithm
1670-
key.operand1 = ref.token->exprId();
1671-
break;
1672-
}
1673-
}
1674-
for (const auto& ref: followAllReferences(op2)) {
1675-
if (ref.token->exprId() != 0) { // cppcheck-suppress useStlAlgorithm
1676-
key.operand2 = ref.token->exprId();
1677-
break;
1678-
}
1679-
}
1680-
16811688
if (key.operand1 > key.operand2 && key.operand2 &&
16821689
Token::Match(tok->astParent(), "%or%|%oror%|+|*|&|&&|^|==|!=")) {
16831690
// In C++ the order of operands of + might matter

test/testvarid.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ class TestVarID : public TestFixture {
262262
TEST_CASE(exprid12);
263263
TEST_CASE(exprid13);
264264
TEST_CASE(exprid14);
265+
TEST_CASE(exprid15);
265266

266267
TEST_CASE(structuredBindings);
267268
}
@@ -4518,6 +4519,24 @@ class TestVarID : public TestFixture {
45184519
ASSERT_EQUALS(exp, tokenize(code, s)); // don't crash
45194520
}
45204521

4522+
void exprid15()
4523+
{
4524+
// #14717
4525+
const char code[] = "#define MAX(a, b) (((a) > (b)) ? (a) : (b))\n"
4526+
"\n"
4527+
"void f(char *d) {\n"
4528+
" const char *p = &d[0];\n"
4529+
" int a = 1 / MAX(1, p[0]);\n"
4530+
" a = 1 / MAX(1, p[1]);\n"
4531+
"}\n";
4532+
const char exp[] = "3: void f ( char * d ) {\n"
4533+
"4: const char * p@2 ; p@2 =@UNIQUE &@UNIQUE d@1 [@UNIQUE 0 ] ;\n"
4534+
"5: int a@3 ; a@3 =@UNIQUE 1 /@UNIQUE $( $( 1 $>@UNIQUE $( p@2 [@9 0 ] $) $) $?@UNIQUE $( 1 $) $:@UNIQUE $( p@2 [@9 0 ] $) $) ;\n"
4535+
"6: a@3 =@UNIQUE 1 /@UNIQUE $( $( 1 $>@UNIQUE $( p@2 [@15 1 ] $) $) $?@UNIQUE $( 1 $) $:@UNIQUE $( p@2 [@15 1 ] $) $) ;\n"
4536+
"7: }\n";
4537+
ASSERT_EQUALS(exp, tokenizeExpr(code));
4538+
}
4539+
45214540
void structuredBindings() {
45224541
const char code[] = "int foo() { auto [x,y] = xy(); return x+y; }";
45234542
ASSERT_EQUALS("1: int foo ( ) { auto [ x@1 , y@2 ] = xy ( ) ; return x@1 + y@2 ; }\n",

0 commit comments

Comments
 (0)