cfg/qt.cfg marks QFile::exists as <pure/>. When the argument is a local const QString, cppcheck reuses the first call's result after a call to an unknown function, and then reports a later identical call as always true. But QFile::exists reads filesystem state, which any unknown call (or another
process) can change, so the second result is not known.
Either QFile::exists (and probably QFileInfo::exists/QDir::exists) should not be <pure/>, or value flow should drop a pure call's known result after a call to an unknown function.
pure-exists.cpp:11:knownConditionTrueFalse:Condition 'QFile::exists(path)' is always true
Expected:
No warning. RemoveFile is unknown and may delete the file, so the second QFile::exists(path) can return false.
Note:
With path as a const QString& function parameter instead of a local, no warning is emitted.
In googletest code the first call is usually ASSERT_TRUE(QFile::exists(p)). googletest.cfg expands it to {if (!(cond)) throw false;}, which produces the same pattern. A following retry loop such asfor(...; retries < 10 && !deleted; ...) { QTest::qWait(10); deleted = !QFile::exists(p); } is then reported as Condition '!deleted' is always true.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
cfg/qt.cfgmarksQFile::existsas<pure/>. When the argument is a localconst QString, cppcheck reuses the first call's result after a call to an unknown function, and then reports a later identical call as always true. ButQFile::existsreads filesystem state, which any unknown call (or anotherprocess) can change, so the second result is not known.
Either
QFile::exists(and probablyQFileInfo::exists/QDir::exists) should not be<pure/>, or value flow should drop a pure call's known result after a call to an unknown function.Reproduction
Save as
pure-exists.cpp:Actual:
Expected:
No warning.
RemoveFileis unknown and may delete the file, so the secondQFile::exists(path)can return false.Note:
pathas aconst QString&function parameter instead of a local, no warning is emitted.ASSERT_TRUE(QFile::exists(p)). googletest.cfg expands it to{if (!(cond)) throw false;}, which produces the same pattern. A following retry loop such asfor(...; retries < 10 && !deleted; ...) { QTest::qWait(10); deleted = !QFile::exists(p); }is then reported asCondition '!deleted' is always true.Thanks for reporting, ticket is here: https://trac.cppcheck.net/ticket/15173