Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4405,7 +4405,8 @@ void CheckOtherImpl::checkKnownArgument()
if (Token::Match(child, "%var%|.|[")) {
if (child->hasKnownIntValue())
return ChildrenToVisit::none;
if (astIsIntegral(child, false) && !astIsPointer(child) && child->values().empty()) {
if (astIsIntegral(child, false) && !astIsPointer(child) &&
(child->values().empty() || (child->values().front().isIntValue() && child->values().front().isImpossible()))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

Accepting a variable whose first value is impossible also lets through comparisons whose result follows from those impossible values, and those warnings are wrong. With this PR:

  • void f(int x) { if (x != 0) g(x == 0); } gives Argument 'x==0' to function g is always 0. It does not matter what value 'x' has. [knownArgument]
  • if (x < 0) return; g(x >= 0); gives the same kind of warning.
  • void f(unsigned x) { g(x >= 0); } and g(x < 0) give the same kind of warning, on top of the existing unsignedPositive / unsignedLessThanZero.

The value of x is what decides each of these results, so "It does not matter what value 'x' has" is misleading. Base reports none of them. Consider accepting impossible values only when a constant literal (0*x, x&0, ...) hides the variable, or skipping comparison operators here, and add a negative test such as if (x != 0) g(x == 0);.

vartok = child;
return ChildrenToVisit::done;
}
Expand Down
7 changes: 7 additions & 0 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13822,6 +13822,13 @@ class TestOther : public TestFixture {
"[test.cpp:5:18]: (style) Argument 'true||x' to function dostuff is always 1. Constant literal calculation disable/hide variable expression 'x'. [knownArgumentHiddenVariableExpression]\n"
"[test.cpp:6:15]: (style) Argument 'x*0' to function dostuff is always 0. Constant literal calculation disable/hide variable expression 'x'. [knownArgumentHiddenVariableExpression]\n"
"[test.cpp:7:15]: (style) Argument '0*x' to function dostuff is always 0. Constant literal calculation disable/hide variable expression 'x'. [knownArgumentHiddenVariableExpression]\n", errout_str());

check("void f(int x) {\n" // #15145
" if (x != 0)\n"
" g(0 * x);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:13]: (style) Argument '0*x' to function g is always 0. Constant literal calculation disable/hide variable expression 'x'. [knownArgumentHiddenVariableExpression]\n",
errout_str());
}

void knownArgumentTernaryOperator() { // #10374
Expand Down
Loading