Skip to content

Fix #6552: false constant value warnings after overloaded extraction - #8835

Open
tzi4 wants to merge 3 commits into
cppcheck-opensource:mainfrom
tzi4:fix/trac-6552-overloaded-extraction
Open

tzi4 wants to merge 3 commits into
cppcheck-opensource:mainfrom
tzi4:fix/trac-6552-overloaded-extraction

Conversation

@tzi4

@tzi4 tzi4 commented Sep 8, 2026

Copy link
Copy Markdown

This fixes the false knownConditionTrueFalse warning reported in Trac #6552.

In the example, x starts at 0.5 and can be changed by value >>= x. Cppcheck keeps using 0.5 afterwards and reports that x < 0 is always false.

The patch checks the argument of a member operator>>= to see whether it can change x. I added regression tests for this and checked that operators taking their argument by value or const reference still produce the expected warning.

I also compiled and ran a small example that reaches the branch Cppcheck reports as impossible. The full C++ suite passes with 5,324 tests and 355 existing TODOs.

Comment thread lib/astutils.cpp Fixed
Comment thread lib/astutils.cpp Fixed
Comment thread lib/astutils.cpp Fixed
Comment thread lib/astutils.cpp Fixed
Comment thread lib/astutils.cpp
return (function->isConst() ? 1U : 0U) | (function->isVolatile() ? 2U : 0U);
};
const unsigned int lhsCV = (lhsType->isConst() ? 1U : 0U) | (lhsType->isVolatile() ? 2U : 0U);
const auto operators = lhsType->typeScope->functionMap.equal_range("operator>>=");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is an AI review take it with a grain of salt. Please feel free to reject it by clicking on Resolve button

Only member operators of the lhs class itself are looked at. When none is found, the loop does nothing and we fall through, so x is still treated as unchanged. I built this branch and the false positive remains for:

// non-member operator, as in CORBA::Any (the classic `any >>= x` use case)
namespace CORBA { typedef int Long; struct Any {}; }
bool operator>>=(const CORBA::Any&, CORBA::Long&);
bool f1(const CORBA::Any& a) {
    CORBA::Long x = 1;
    a >>= x;
    if (x < 0) return true;   // knownConditionTrueFalse
    return false;
}

// operator inherited from a base class
struct Base { void operator>>=(int&) const; };
struct Derived : Base {};
bool f2(const Derived& d) {
    int x = 1;
    d >>= x;
    if (x < 0) return true;   // knownConditionTrueFalse
    return false;
}

Since an FN is better than an FP here, a simpler and more robust rule might be: for a class-type lhs, assume the rhs is changed unless a member operator>>= is found and all the candidates take the argument by value or by const reference. That would also make most of the overload-ranking logic below unnecessary. It's quite a lot of code to keep warnings in rare cases, and it is hard to be sure it matches C++ overload resolution.

Comment thread test/testcondition.cpp
ASSERT_EQUALS("", errout_str());
}

void knownConditionShiftAssignment() { // #6552

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is an AI review take it with a grain of salt. Please feel free to reject it by clicking on Resolve button

FYI: since f99ea4b on main (#15056, "remove warnings for return result"), knownConditionTrueFalse is no longer reported for return x < 0;. I checked with current main: even int x = 1; return x < 0; gives no warning. After rebasing, the tests here that expect Return value 'x<0' is always false will fail. Worse, the tests that expect "" will pass whether or not the fix works. Using if (x < 0) {} instead of return x < 0; in these tests should keep them meaningful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants