Skip to content

Commit cff4c24

Browse files
authored
Fix #15031 (False positive: knownConditionTrueFalse reported when calling a function with a known result) (#8853)
1 parent 9b3b160 commit cff4c24

4 files changed

Lines changed: 53 additions & 39 deletions

File tree

.selfcheck_suppressions

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ funcArgNamesDifferent:externals/tinyxml2/tinyxml2.cpp
7676
funcArgNamesDifferentUnnamed:externals/tinyxml2/tinyxml2.cpp
7777
funcArgNamesDifferentUnnamed:externals/tinyxml2/tinyxml2.h
7878
nullPointerRedundantCheck:externals/tinyxml2/tinyxml2.cpp
79-
knownConditionTrueFalse:externals/tinyxml2/tinyxml2.cpp
8079
useStlAlgorithm:externals/simplecpp/simplecpp.cpp
8180
funcArgNamesDifferentUnnamed:externals/simplecpp/simplecpp.h
8281
missingMemberCopy:externals/simplecpp/simplecpp.h

lib/checkcondition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ void CheckConditionImpl::alwaysTrueFalse()
15561556
condition = parent->astParent()->astParent()->previous();
15571557
else if (Token::Match(tok, "%comp%"))
15581558
condition = tok;
1559-
else if ((tok->str() == "(" || (hasComp && Token::Match(tok, "!|%var%"))) && astIsBool(parent) && Token::Match(parent, "%assign%"))
1559+
else if (hasComp && Token::Match(tok, "!|%var%") && astIsBool(parent) && Token::Match(parent, "%assign%"))
15601560
condition = tok;
15611561
else
15621562
continue;

man/checkers/knownConditionTrueFalse.md

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,66 @@
11
# knownConditionTrueFalse
22

33
**Message**: Condition 'x==5' is always true<br/>
4-
**Category**: Correctness<br/>
4+
**Category**: Code cleanup<br/>
55
**Severity**: Style<br/>
66
**Language**: C/C++
77

88
## Description
99

10-
cppcheck can already work out this condition's value from what it knows about the variables involved,
11-
so the condition is always true or always false.
10+
A condition is always true or always false.
1211

13-
## Motivation
12+
Note: a warning is not written for obvious cases like `if (false)`.
13+
14+
If a condition is always true then technically the condition is redundant. It
15+
can be removed so that the conditional code will be unconditionally executed.
16+
This reduces complexity.
17+
18+
If a condition is always false then the conditional code is unreachable and can
19+
be removed.
20+
21+
It is however also possible that the intended check never actually happens and
22+
a real bug (a wrong comparison, a typo'd variable, a value that was supposed to
23+
vary but doesn't) slips through unnoticed.
1424

15-
A condition that's always true or always false isn't testing anything - at best it's confusing,
16-
leftover, or dead code; at worst, it means the intended check never actually happens and a real bug (a
17-
wrong comparison, a typo'd variable, a value that was supposed to vary but doesn't) slips through
18-
unnoticed.
25+
## Motivation
1926

20-
This check may need `--check-level=exhaustive` to see every case.
27+
The condition may be invariant (always true or always false) by mistake,
28+
otherwise it is possible to cleanup redundant code to reduce complexity.
2129

2230
## How to fix
2331

24-
Before:
32+
Before (condition is always true):
2533
```cpp
2634
void f() {
2735
int x = 5;
28-
if (x == 5) {} // <- always true
36+
if (x == 5) { // <- always true
37+
dostuff();
38+
}
39+
}
40+
```
41+
42+
After: The condition is technically redundant, this code is logically the same.
43+
```cpp
44+
void f() {
45+
dostuff();
2946
}
3047
```
3148

32-
After: use the real variable instead of a fixed value, or remove the redundant check.
49+
Before (condition is always false):
3350
```cpp
34-
void f(int x) {
35-
if (x == 5) {}
51+
void f() {
52+
int x = 5;
53+
if (x < 3) { // <- always false
54+
dostuff();
55+
}
3656
}
3757
```
3858

39-
## False positives to be aware of
40-
41-
- **This check does not account for a member value changing through a call that reaches it indirectly**
42-
(for example, through a container of pointers the function iterates over). A member read before such
43-
a call can be wrongly assumed to still hold the same value afterwards:
44-
```cpp
45-
#include <map>
46-
#include <string>
47-
struct S { int i; };
48-
struct T {
49-
std::map<std::string, S*> m;
50-
S* get(const std::string& s) { return m[s]; }
51-
void modify() { for (const auto& e : m) e.second->i = 0; }
52-
};
53-
void f(T& t) {
54-
const S* p = t.get("abc");
55-
const int o = p->i;
56-
t.modify(); // this can change p->i
57-
if (p->i == o) {} // wrongly reported as always true
58-
}
59-
```
59+
After: The conditional code is unreachable, this code is logically the same.
60+
```cpp
61+
void f() {
62+
}
63+
```
6064

6165
## Related checkers
6266

test/testcondition.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,7 +3668,7 @@ class TestCondition : public TestFixture {
36683668
"}\n");
36693669
ASSERT_EQUALS("", errout_str());
36703670

3671-
check("long X::g(bool unknown, int& result) {\n"
3671+
check("long g(bool unknown, int& result) {\n"
36723672
" long ret = 0;\n"
36733673
" bool f = false;\n"
36743674
" f = f || unknown;\n"
@@ -4878,7 +4878,18 @@ class TestCondition : public TestFixture {
48784878
" }\n"
48794879
" return false;\n"
48804880
"}\n");
4881-
ASSERT_EQUALS("[test.cpp:6:12] -> [test.cpp:7:21]: (style) Assigned value 's.g()' is always true [knownConditionTrueFalse]\n", errout_str());
4881+
TODO_ASSERT_EQUALS("[test.cpp:6:12] -> [test.cpp:7:21]: (style) Assigned value 's.g()' is always true [knownConditionTrueFalse]\n", "", errout_str());
4882+
4883+
check("static bool parse(int r) {\n" // #15031
4884+
" bool res = false;\n"
4885+
" return res;\n"
4886+
"}\n"
4887+
"\n"
4888+
"int main (void) {\n"
4889+
" bool res = parse(1101);\n"
4890+
" return res;\n"
4891+
"}\n");
4892+
ASSERT_EQUALS("", errout_str());
48824893

48834894
check("void f(const void* p) {\n" // #11519
48844895
" bool b = false;\n"

0 commit comments

Comments
 (0)