Skip to content

Commit dd05839

Browse files
pfultz2danmar
authored andcommitted
Fix false positives in knownConditionTrueFalse when using expressions with const variables (#2469)
1 parent 41caf28 commit dd05839

5 files changed

Lines changed: 36 additions & 9 deletions

File tree

lib/astutils.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,27 +1411,31 @@ bool isCPPCast(const Token* tok)
14111411
return tok && Token::simpleMatch(tok->previous(), "> (") && tok->astOperand2() && tok->astOperand1() && tok->astOperand1()->str().find("_cast") != std::string::npos;
14121412
}
14131413

1414-
bool isConstVarExpression(const Token *tok)
1414+
bool isConstVarExpression(const Token *tok, const char* skipMatch)
14151415
{
14161416
if (!tok)
14171417
return false;
1418+
if (skipMatch && Token::Match(tok, skipMatch))
1419+
return false;
14181420
if (Token::simpleMatch(tok->previous(), "sizeof ("))
14191421
return true;
14201422
if (Token::Match(tok->previous(), "%name% (")) {
1423+
if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipMatch))
1424+
return false;
14211425
std::vector<const Token *> args = getArguments(tok);
1422-
return std::all_of(args.begin(), args.end(), &isConstVarExpression);
1426+
return std::all_of(args.begin(), args.end(), [&](const Token* t) { return isConstVarExpression(t, skipMatch); });
14231427
}
14241428
if (isCPPCast(tok)) {
1425-
return isConstVarExpression(tok->astOperand2());
1429+
return isConstVarExpression(tok->astOperand2(), skipMatch);
14261430
}
14271431
if (Token::Match(tok, "( %type%"))
1428-
return isConstVarExpression(tok->astOperand1());
1432+
return isConstVarExpression(tok->astOperand1(), skipMatch);
14291433
if (tok->str() == "::" && tok->hasKnownValue())
1430-
return isConstVarExpression(tok->astOperand2());
1434+
return isConstVarExpression(tok->astOperand2(), skipMatch);
14311435
if (Token::Match(tok, "%cop%|[|.")) {
1432-
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1()))
1436+
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipMatch))
14331437
return false;
1434-
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2()))
1438+
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipMatch))
14351439
return false;
14361440
return true;
14371441
}
@@ -1440,7 +1444,7 @@ bool isConstVarExpression(const Token *tok)
14401444
if (tok->isEnumerator())
14411445
return true;
14421446
if (tok->variable())
1443-
return tok->variable()->isConst();
1447+
return tok->variable()->isConst() && tok->variable()->nameToken() && tok->variable()->nameToken()->hasKnownValue();
14441448
return false;
14451449
}
14461450

lib/astutils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
205205

206206
bool isCPPCast(const Token* tok);
207207

208-
bool isConstVarExpression(const Token *tok);
208+
bool isConstVarExpression(const Token *tok, const char * skipMatch = nullptr);
209209

210210
const Variable *getLHSVariable(const Token *tok);
211211

lib/checkcondition.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,8 @@ void CheckCondition::alwaysTrueFalse()
13781378
continue;
13791379
if (Token::Match(tok, "%comp%") && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
13801380
continue;
1381+
if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<"))
1382+
continue;
13811383

13821384
const bool constIfWhileExpression =
13831385
tok->astParent() && Token::Match(tok->astTop()->astOperand1(), "if|while") && !tok->astTop()->astOperand1()->isConstexpr() &&

lib/checkother.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,6 +3000,9 @@ static bool isVariableExpression(const Token* tok)
30003000
if (Token::simpleMatch(tok, "."))
30013001
return isVariableExpression(tok->astOperand1()) &&
30023002
isVariableExpression(tok->astOperand2());
3003+
if (Token::simpleMatch(tok, "["))
3004+
return isVariableExpression(tok->astOperand1()) &&
3005+
tok->astOperand2() && tok->astOperand2()->hasKnownIntValue();
30033006
return false;
30043007
}
30053008

test/testcondition.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,24 @@ class TestCondition : public TestFixture {
33293329
" return;\n"
33303330
"}\n");
33313331
ASSERT_EQUALS("", errout.str());
3332+
3333+
check("int f(int a, int b) {\n"
3334+
" static const int x = 10;\n"
3335+
" return x == 1 ? a : b;\n"
3336+
"}\n");
3337+
ASSERT_EQUALS("", errout.str());
3338+
3339+
check("const bool x = false;\n"
3340+
"void f() {\n"
3341+
" if (x) {}\n"
3342+
"}\n");
3343+
ASSERT_EQUALS("", errout.str());
3344+
3345+
check("const bool x = false;\n"
3346+
"void f() {\n"
3347+
" if (!x) {}\n"
3348+
"}\n");
3349+
ASSERT_EQUALS("", errout.str());
33323350
}
33333351

33343352
void alwaysTrueInfer() {

0 commit comments

Comments
 (0)