Line data Source code
1 : /*
2 : * Cppcheck - A tool for static C/C++ code analysis
3 : * Copyright (C) 2007-2024 Cppcheck team.
4 : *
5 : * This program is free software: you can redistribute it and/or modify
6 : * it under the terms of the GNU General Public License as published by
7 : * the Free Software Foundation, either version 3 of the License, or
8 : * (at your option) any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #include "checkcondition.h"
20 : #include "errortypes.h"
21 : #include "fixture.h"
22 : #include "helpers.h"
23 : #include "platform.h"
24 : #include "settings.h"
25 : #include "tokenize.h"
26 :
27 : #include <limits>
28 : #include <string>
29 : #include <vector>
30 :
31 : class TestCondition : public TestFixture {
32 : public:
33 2 : TestCondition() : TestFixture("TestCondition") {}
34 :
35 : private:
36 1 : const Settings settings0 = settingsBuilder().library("qt.cfg").library("std.cfg").severity(Severity::style).severity(Severity::warning).build();
37 1 : /*const*/ Settings settings1 = settingsBuilder().severity(Severity::style).severity(Severity::warning).build();
38 :
39 1 : void run() override {
40 1 : const char cfg[] = "<?xml version=\"1.0\"?>\n"
41 : "<def>\n"
42 : " <function name=\"bar\"> <pure/> </function>\n"
43 : "</def>";
44 1 : settings1 = settingsBuilder(settings1).libraryxml(cfg, sizeof(cfg)).build();
45 :
46 1 : TEST_CASE(assignAndCompare); // assignment and comparison don't match
47 1 : TEST_CASE(mismatchingBitAnd); // overlapping bitmasks
48 1 : TEST_CASE(comparison); // CheckCondition::comparison test cases
49 1 : TEST_CASE(multicompare); // mismatching comparisons
50 1 : TEST_CASE(overlappingElseIfCondition); // overlapping conditions in if and else-if
51 1 : TEST_CASE(oppositeElseIfCondition); // opposite conditions in if and else-if
52 :
53 1 : TEST_CASE(checkBadBitmaskCheck);
54 :
55 1 : TEST_CASE(incorrectLogicOperator1);
56 1 : TEST_CASE(incorrectLogicOperator2);
57 1 : TEST_CASE(incorrectLogicOperator3);
58 1 : TEST_CASE(incorrectLogicOperator4);
59 1 : TEST_CASE(incorrectLogicOperator5); // complex expressions
60 1 : TEST_CASE(incorrectLogicOperator6); // char literals
61 1 : TEST_CASE(incorrectLogicOperator7); // opposite expressions: (expr || !expr)
62 1 : TEST_CASE(incorrectLogicOperator8); // !
63 1 : TEST_CASE(incorrectLogicOperator9);
64 1 : TEST_CASE(incorrectLogicOperator10); // enum
65 1 : TEST_CASE(incorrectLogicOperator11);
66 1 : TEST_CASE(incorrectLogicOperator12);
67 1 : TEST_CASE(incorrectLogicOperator13);
68 1 : TEST_CASE(incorrectLogicOperator14);
69 1 : TEST_CASE(incorrectLogicOperator15);
70 1 : TEST_CASE(incorrectLogicOperator16); // #10070
71 1 : TEST_CASE(incorrectLogicOperator17);
72 1 : TEST_CASE(secondAlwaysTrueFalseWhenFirstTrueError);
73 1 : TEST_CASE(incorrectLogicOp_condSwapping);
74 1 : TEST_CASE(testBug5895);
75 1 : TEST_CASE(testBug5309);
76 :
77 1 : TEST_CASE(modulo);
78 :
79 1 : TEST_CASE(oppositeInnerCondition);
80 1 : TEST_CASE(oppositeInnerConditionPointers);
81 1 : TEST_CASE(oppositeInnerConditionClass);
82 1 : TEST_CASE(oppositeInnerConditionUndeclaredVariable);
83 1 : TEST_CASE(oppositeInnerConditionAlias);
84 1 : TEST_CASE(oppositeInnerCondition2);
85 1 : TEST_CASE(oppositeInnerCondition3);
86 1 : TEST_CASE(oppositeInnerConditionAnd);
87 1 : TEST_CASE(oppositeInnerConditionOr);
88 1 : TEST_CASE(oppositeInnerConditionEmpty);
89 1 : TEST_CASE(oppositeInnerConditionFollowVar);
90 :
91 1 : TEST_CASE(identicalInnerCondition);
92 :
93 1 : TEST_CASE(identicalConditionAfterEarlyExit);
94 1 : TEST_CASE(innerConditionModified);
95 :
96 1 : TEST_CASE(clarifyCondition1); // if (a = b() < 0)
97 1 : TEST_CASE(clarifyCondition2); // if (a & b == c)
98 1 : TEST_CASE(clarifyCondition3); // if (! a & b)
99 1 : TEST_CASE(clarifyCondition4); // ticket #3110
100 1 : TEST_CASE(clarifyCondition5); // #3609 CWinTraits<WS_CHILD|WS_VISIBLE>..
101 1 : TEST_CASE(clarifyCondition6); // #3818
102 1 : TEST_CASE(clarifyCondition7);
103 1 : TEST_CASE(clarifyCondition8);
104 :
105 1 : TEST_CASE(alwaysTrue);
106 1 : TEST_CASE(alwaysTrueSymbolic);
107 1 : TEST_CASE(alwaysTrueInfer);
108 1 : TEST_CASE(alwaysTrueContainer);
109 1 : TEST_CASE(alwaysTrueLoop);
110 1 : TEST_CASE(alwaysTrueTryCatch);
111 1 : TEST_CASE(multiConditionAlwaysTrue);
112 1 : TEST_CASE(duplicateCondition);
113 :
114 1 : TEST_CASE(checkInvalidTestForOverflow);
115 1 : TEST_CASE(checkConditionIsAlwaysTrueOrFalseInsideIfWhile);
116 1 : TEST_CASE(alwaysTrueFalseInLogicalOperators);
117 1 : TEST_CASE(pointerAdditionResultNotNull);
118 1 : TEST_CASE(duplicateConditionalAssign);
119 :
120 1 : TEST_CASE(checkAssignmentInCondition);
121 1 : TEST_CASE(compareOutOfTypeRange);
122 1 : TEST_CASE(knownConditionCast); // #9976
123 1 : TEST_CASE(knownConditionIncrementLoop); // #9808
124 1 : TEST_CASE(knownConditionAfterBailout); // #12526
125 1 : }
126 :
127 : #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
128 722 : void check_(const char* file, int line, const char code[], const Settings &settings, const char* filename = "test.cpp") {
129 2166 : std::vector<std::string> files(1, filename);
130 1444 : Tokenizer tokenizer(settings, *this);
131 722 : PreprocessorHelper::preprocess(code, files, tokenizer, *this);
132 :
133 : // Tokenizer..
134 723 : ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line);
135 :
136 : // Run checks..
137 721 : runChecks<CheckCondition>(tokenizer, this);
138 721 : }
139 :
140 708 : void check_(const char* file, int line, const char code[], const char* filename = "test.cpp", bool inconclusive = false) {
141 2124 : const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).build();
142 708 : check_(file, line, code, settings, filename);
143 707 : }
144 :
145 1 : void assignAndCompare() {
146 : // &
147 1 : check("void foo(int x)\n"
148 : "{\n"
149 : " int y = x & 4;\n"
150 : " if (y == 3);\n"
151 : "}");
152 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false.\n", errout_str());
153 :
154 1 : check("void foo(int x)\n"
155 : "{\n"
156 : " int y = x & 4;\n"
157 : " if (y != 3);\n"
158 : "}");
159 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y!=3' is always true.\n", errout_str());
160 :
161 : // |
162 1 : check("void foo(int x) {\n"
163 : " int y = x | 0x14;\n"
164 : " if (y == 0x710);\n"
165 : "}");
166 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==0x710' is always false.\n", errout_str());
167 :
168 1 : check("void foo(int x) {\n"
169 : " int y = x | 0x14;\n"
170 : " if (y == 0x71f);\n"
171 : "}");
172 1 : ASSERT_EQUALS("", errout_str());
173 :
174 : // various simple assignments
175 1 : check("void foo(int x) {\n"
176 : " int y = (x+1) | 1;\n"
177 : " if (y == 2);\n"
178 : "}");
179 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==2' is always false.\n", errout_str());
180 :
181 1 : check("void foo() {\n"
182 : " int y = 1 | x();\n"
183 : " if (y == 2);\n"
184 : "}");
185 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==2' is always false.\n", errout_str());
186 :
187 : // multiple conditions
188 1 : check("void foo(int x) {\n"
189 : " int y = x & 4;\n"
190 : " if ((y == 3) && (z == 1));\n"
191 : "}");
192 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false.\n", errout_str());
193 :
194 1 : check("void foo(int x) {\n"
195 : " int y = x & 4;\n"
196 : " if ((x==123) || ((y == 3) && (z == 1)));\n"
197 : "}");
198 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false.\n", errout_str());
199 :
200 1 : check("void f(int x) {\n"
201 : " int y = x & 7;\n"
202 : " if (setvalue(&y) && y != 8);\n"
203 : "}");
204 1 : ASSERT_EQUALS("", errout_str());
205 :
206 : // recursive checking into scopes
207 1 : check("void f(int x) {\n"
208 : " int y = x & 7;\n"
209 : " if (z) y=0;\n"
210 : " else { if (y==8); }\n" // always false
211 : "}");
212 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false.\n", errout_str());
213 :
214 : // while
215 1 : check("void f(int x) {\n"
216 : " int y = x & 7;\n"
217 : " while (y==8);\n" // local variable => always false
218 : "}");
219 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false.\n", errout_str());
220 :
221 1 : check("void f(int x) {\n"
222 : " extern int y; y = x & 7;\n"
223 : " while (y==8);\n" // non-local variable => no error
224 : "}");
225 1 : ASSERT_EQUALS("", errout_str());
226 :
227 1 : check("void f(int x) {\n"
228 : " int a = 100;\n"
229 : " while (x) {\n"
230 : " int y = 16 | a;\n"
231 : " while (y != 0) y--;\n"
232 : " }\n"
233 : "}");
234 1 : ASSERT_EQUALS("", errout_str());
235 :
236 1 : check("void g(int x);\n"
237 : "void f(int x) {\n"
238 : " int a = 100;\n"
239 : " while (x) {\n"
240 : " int y = 16 | a;\n"
241 : " while (y != 0) g(y);\n"
242 : " }\n"
243 : "}");
244 1 : ASSERT_EQUALS(
245 : "[test.cpp:5] -> [test.cpp:6]: (style) Mismatching assignment and comparison, comparison 'y!=0' is always true.\n",
246 : errout_str());
247 :
248 1 : check("void g(int &x);\n"
249 : "void f(int x) {\n"
250 : " int a = 100;\n"
251 : " while (x) {\n"
252 : " int y = 16 | a;\n"
253 : " while (y != 0) g(y);\n"
254 : " }\n"
255 : "}");
256 1 : ASSERT_EQUALS("", errout_str());
257 :
258 : // calling function
259 1 : check("void f(int x) {\n"
260 : " int y = x & 7;\n"
261 : " do_something();\n"
262 : " if (y==8);\n" // local variable => always false
263 : "}");
264 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false.\n", errout_str());
265 :
266 1 : check("void f(int x) {\n"
267 : " int y = x & 7;\n"
268 : " do_something(&y);\n" // passing variable => no error
269 : " if (y==8);\n"
270 : "}");
271 1 : ASSERT_EQUALS("", errout_str());
272 :
273 1 : check("void do_something(int);\n"
274 : "void f(int x) {\n"
275 : " int y = x & 7;\n"
276 : " do_something(y);\n"
277 : " if (y==8);\n"
278 : "}");
279 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false.\n", errout_str());
280 :
281 1 : check("void f(int x) {\n"
282 : " extern int y; y = x & 7;\n"
283 : " do_something();\n"
284 : " if (y==8);\n" // non-local variable => no error
285 : "}");
286 1 : ASSERT_EQUALS("", errout_str());
287 :
288 : // #4434 : false positive: ?:
289 1 : check("void f(int x) {\n"
290 : " x = x & 1;\n"
291 : " x = x & 1 ? 1 : -1;\n"
292 : " if(x != -1) { }\n"
293 : "}");
294 1 : ASSERT_EQUALS("", errout_str());
295 :
296 : // #4735
297 1 : check("void f() {\n"
298 : " int x = *(char*)&0x12345678;\n"
299 : " if (x==18) { }\n"
300 : "}");
301 1 : ASSERT_EQUALS("", errout_str());
302 :
303 : // bailout: no variable info
304 1 : check("void foo(int x) {\n"
305 : " y = 2 | x;\n" // y not declared => no error
306 : " if(y == 1) {}\n"
307 : "}");
308 1 : ASSERT_EQUALS("", errout_str());
309 :
310 : // bailout: negative number
311 1 : check("void foo(int x) {\n"
312 : " int y = -2 | x;\n" // negative number => no error
313 : " if (y==1) {}\n"
314 : "}");
315 1 : ASSERT_EQUALS("", errout_str());
316 :
317 : // bailout: pass variable to function
318 1 : check("void foo(int x) {\n"
319 : " int y = 2 | x;\n"
320 : " bar(&y);\n" // pass variable to function => no error
321 : " if (y==1) {}\n"
322 : "}");
323 1 : ASSERT_EQUALS("", errout_str());
324 :
325 : // no crash on unary operator& (#5643)
326 : // #11610
327 1 : check("SdrObject* ApplyGraphicToObject() {\n"
328 : " if (&rHitObject) {}\n"
329 : " else if (rHitObject.IsClosedObj() && !&rHitObject) { }\n"
330 : "}");
331 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition '&rHitObject' is always true\n"
332 : "[test.cpp:3]: (style) Condition '!&rHitObject' is always false\n",
333 : errout_str());
334 :
335 : // #5695: increment
336 1 : check("void f(int a0, int n) {\n"
337 : " int c = a0 & 3;\n"
338 : " for (int a = 0; a < n; a++) {\n"
339 : " c++;\n"
340 : " if (c == 4)\n"
341 : " c = 0;\n"
342 : " }\n"
343 : "}");
344 1 : ASSERT_EQUALS("", errout_str());
345 :
346 1 : check("void f(int a) {\n" // #6662
347 : " int x = a & 1;\n"
348 : " while (x <= 4) {\n"
349 : " if (x != 5) {}\n"
350 : " }\n"
351 : "}");
352 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'x!=5' is always true.\n", errout_str());
353 :
354 1 : check("void f(int a) {\n" // #6662
355 : " int x = a & 1;\n"
356 : " while ((x += 4) < 10) {\n"
357 : " if (x != 5) {}\n"
358 : " }\n"
359 : "}");
360 1 : ASSERT_EQUALS("", errout_str());
361 :
362 1 : check("void f() {\n"
363 : " int x = 100;\n"
364 : " while (x) {\n"
365 : " g(x);\n"
366 : " }\n"
367 : "}");
368 1 : ASSERT_EQUALS("", errout_str());
369 :
370 1 : check("void g(int x);\n"
371 : "void f() {\n"
372 : " int x = 100;\n"
373 : " while (x) {\n"
374 : " g(x);\n"
375 : " }\n"
376 : "}");
377 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'x' is always true\n", errout_str());
378 :
379 1 : check("void g(int & x);\n"
380 : "void f() {\n"
381 : " int x = 100;\n"
382 : " while (x) {\n"
383 : " g(x);\n"
384 : " }\n"
385 : "}");
386 1 : ASSERT_EQUALS("", errout_str());
387 :
388 : }
389 :
390 1 : void mismatchingBitAnd() {
391 1 : check("void f(int a) {\n"
392 : " int b = a & 0xf0;\n"
393 : " b &= 1;\n"
394 : "}");
395 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0).\n", errout_str());
396 :
397 1 : check("void f(int a) {\n"
398 : " int b = a & 0xf0;\n"
399 : " int c = b & 1;\n"
400 : "}");
401 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0).\n", errout_str());
402 :
403 1 : check("void f(int a) {\n"
404 : " int b = a;"
405 : " switch (x) {\n"
406 : " case 1: b &= 1; break;\n"
407 : " case 2: b &= 2; break;\n"
408 : " };\n"
409 : "}");
410 1 : ASSERT_EQUALS("", errout_str());
411 : }
412 :
413 1 : void comparison() {
414 : // CheckCondition::comparison test cases
415 : // '=='
416 1 : check("void f(int a) {\n assert( (a & 0x07) == 8U );\n}");
417 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) == 0x8' is always false.\n",errout_str());
418 1 : check("void f(int a) {\n assert( (a & b & 4 & c ) == 3 );\n}");
419 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x4) == 0x3' is always false.\n", errout_str());
420 1 : check("void f(int a) {\n assert( (a | 0x07) == 8U );\n}");
421 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) == 0x8' is always false.\n",errout_str());
422 1 : check("void f(int a) {\n assert( (a & 0x07) == 7U );\n}");
423 1 : ASSERT_EQUALS("", errout_str());
424 1 : check("void f(int a) {\n assert( (a | 0x01) == -15 );\n}");
425 1 : ASSERT_EQUALS("", errout_str());
426 : // '!='
427 1 : check("void f(int a) {\n assert( (a & 0x07) != 8U );\n}");
428 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) != 0x8' is always true.\n",errout_str());
429 1 : check("void f(int a) {\n assert( (a | 0x07) != 8U );\n}");
430 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) != 0x8' is always true.\n",errout_str());
431 1 : check("void f(int a) {\n assert( (a & 0x07) != 7U );\n}");
432 1 : ASSERT_EQUALS("", errout_str());
433 1 : check("void f(int a) {\n assert( (a | 0x07) != 7U );\n}");
434 1 : ASSERT_EQUALS("", errout_str());
435 : // '>='
436 1 : check("void f(int a) {\n assert( (a & 0x07) >= 8U );\n}");
437 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) >= 0x8' is always false.\n",errout_str());
438 1 : check("void f(unsigned int a) {\n assert( (a | 0x7) >= 7U );\n}");
439 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) >= 0x7' is always true.\n",errout_str());
440 1 : check("void f(int a) {\n assert( (a & 0x07) >= 7U );\n}");
441 1 : ASSERT_EQUALS("",errout_str());
442 1 : check("void f(int a) {\n assert( (a | 0x07) >= 8U );\n}");
443 1 : ASSERT_EQUALS("",errout_str()); //correct for negative 'a'
444 : // '>'
445 1 : check("void f(int a) {\n assert( (a & 0x07) > 7U );\n}");
446 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) > 0x7' is always false.\n",errout_str());
447 1 : check("void f(unsigned int a) {\n assert( (a | 0x7) > 6U );\n}");
448 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) > 0x6' is always true.\n",errout_str());
449 1 : check("void f(int a) {\n assert( (a & 0x07) > 6U );\n}");
450 1 : ASSERT_EQUALS("",errout_str());
451 1 : check("void f(int a) {\n assert( (a | 0x07) > 7U );\n}");
452 1 : ASSERT_EQUALS("",errout_str()); //correct for negative 'a'
453 : // '<='
454 1 : check("void f(int a) {\n assert( (a & 0x07) <= 7U );\n}");
455 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) <= 0x7' is always true.\n",errout_str());
456 1 : check("void f(unsigned int a) {\n assert( (a | 0x08) <= 7U );\n}");
457 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x8) <= 0x7' is always false.\n",errout_str());
458 1 : check("void f(int a) {\n assert( (a & 0x07) <= 6U );\n}");
459 1 : ASSERT_EQUALS("",errout_str());
460 1 : check("void f(int a) {\n assert( (a | 0x08) <= 7U );\n}");
461 1 : ASSERT_EQUALS("",errout_str()); //correct for negative 'a'
462 : // '<'
463 1 : check("void f(int a) {\n assert( (a & 0x07) < 8U );\n}");
464 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) < 0x8' is always true.\n",errout_str());
465 1 : check("void f(unsigned int a) {\n assert( (a | 0x07) < 7U );\n}");
466 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) < 0x7' is always false.\n",errout_str());
467 1 : check("void f(int a) {\n assert( (a & 0x07) < 3U );\n}");
468 1 : ASSERT_EQUALS("",errout_str());
469 1 : check("void f(int a) {\n assert( (a | 0x07) < 7U );\n}");
470 1 : ASSERT_EQUALS("",errout_str()); //correct for negative 'a'
471 :
472 1 : check("void f(int i) {\n" // #11998
473 : " if ((i & 0x100) == 0x200) {}\n"
474 : " if (0x200 == (i & 0x100)) {}\n"
475 : "}\n");
476 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition\n"
477 : "[test.cpp:2]: (style) Expression '(X & 0x100) == 0x200' is always false.\n"
478 : "[test.cpp:3]: (style) Expression '(X & 0x100) == 0x200' is always false.\n",
479 : errout_str());
480 : }
481 :
482 : #define checkPureFunction(code) checkPureFunction_(code, __FILE__, __LINE__)
483 1 : void multicompare() {
484 1 : check("void foo(int x)\n"
485 : "{\n"
486 : " if (x & 7);\n"
487 : " else { if (x == 1); }\n"
488 : "}");
489 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3.\n", errout_str());
490 :
491 1 : check("void foo(int x)\n"
492 : "{\n"
493 : " if (x & 7);\n"
494 : " else { if (x & 1); }\n"
495 : "}");
496 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3.\n", errout_str());
497 :
498 1 : check("extern int bar() __attribute__((pure));\n"
499 : "void foo(int x)\n"
500 : "{\n"
501 : " if ( bar() >1 && b) {}\n"
502 : " else if (bar() >1 && b) {}\n"
503 : "}");
504 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4.\n", errout_str());
505 :
506 1 : checkPureFunction("extern int bar();\n"
507 : "void foo(int x)\n"
508 : "{\n"
509 : " if ( bar() >1 && b) {}\n"
510 : " else if (bar() >1 && b) {}\n"
511 : "}");
512 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4.\n", errout_str());
513 :
514 : // 7284
515 1 : check("void foo() {\n"
516 : " if (a) {}\n"
517 : " else if (!!a) {}\n"
518 : "}");
519 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
520 :
521 : // #11059
522 1 : check("int f();\n"
523 : "void g() {\n"
524 : " int i = f();\n"
525 : " if (i == 3) {}\n"
526 : " else if ((i = f()) == 5) {}\n"
527 : " else if (i == 3) {}\n"
528 : "}\n");
529 1 : ASSERT_EQUALS("", errout_str());
530 :
531 1 : check("int f();\n"
532 : "void g() {\n"
533 : " int i = f();\n"
534 : " if (i == 3) {}\n"
535 : " else if ((i = f()) == 5) {}\n"
536 : " else if (i != 3) {}\n"
537 : "}\n");
538 1 : ASSERT_EQUALS("", errout_str());
539 : }
540 :
541 1 : void checkPureFunction_(const char code[], const char* file, int line) {
542 : // Tokenize..
543 2 : SimpleTokenizer tokenizer(settings1, *this);
544 1 : ASSERT_LOC(tokenizer.tokenize(code), file, line);
545 :
546 1 : runChecks<CheckCondition>(tokenizer, this);
547 1 : }
548 :
549 1 : void overlappingElseIfCondition() {
550 1 : check("void f(int a, int &b) {\n"
551 : " if (a) { b = 1; }\n"
552 : " else { if (a) { b = 2; } }\n"
553 : "}");
554 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
555 :
556 1 : check("void f(int a, int &b) {\n"
557 : " if (a) { b = 1; }\n"
558 : " else { if (a) { b = 2; } }\n"
559 : "}");
560 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
561 :
562 1 : check("void f(int a, int &b) {\n"
563 : " if (a == 1) { b = 1; }\n"
564 : " else { if (a == 2) { b = 2; }\n"
565 : " else { if (a == 1) { b = 3; } } }\n"
566 : "}");
567 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
568 :
569 1 : check("void f(int a, int &b) {\n"
570 : " if (a == 1) { b = 1; }\n"
571 : " else { if (a == 2) { b = 2; }\n"
572 : " else { if (a == 2) { b = 3; } } }\n"
573 : "}");
574 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3.\n", errout_str());
575 :
576 1 : check("void f(int a, int &b) {\n"
577 : " if (a++) { b = 1; }\n"
578 : " else { if (a++) { b = 2; }\n"
579 : " else { if (a++) { b = 3; } } }\n"
580 : "}");
581 1 : ASSERT_EQUALS("", errout_str());
582 :
583 1 : check("void f(int a, int &b) {\n"
584 : " if (!strtok(NULL, \" \")) { b = 1; }\n"
585 : " else { if (!strtok(NULL, \" \")) { b = 2; } }\n"
586 : "}");
587 1 : ASSERT_EQUALS("", errout_str());
588 :
589 : {
590 1 : check("void f(Class &c) {\n"
591 : " if (c.dostuff() == 3) {}\n"
592 : " else { if (c.dostuff() == 3) {} }\n"
593 : "}");
594 1 : ASSERT_EQUALS("", errout_str());
595 :
596 1 : check("void f(const Class &c) {\n"
597 : " if (c.dostuff() == 3) {}\n"
598 : " else { if (c.dostuff() == 3) {} }\n"
599 : "}");
600 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
601 : }
602 :
603 1 : check("void f(int a, int &b) {\n"
604 : " x = x / 2;\n"
605 : " if (x < 100) { b = 1; }\n"
606 : " else { x = x / 2; if (x < 100) { b = 2; } }\n"
607 : "}");
608 1 : ASSERT_EQUALS("", errout_str());
609 :
610 1 : check("void f(int i) {\n"
611 : " if(i == 0x02e2000000 || i == 0xa0c6000000)\n"
612 : " foo(i);\n"
613 : "}");
614 1 : ASSERT_EQUALS("", errout_str());
615 :
616 : // ticket 3689 ( avoid false positive )
617 1 : check("int fitInt(long long int nValue){\n"
618 : " if( nValue < 0x7fffffffLL )\n"
619 : " {\n"
620 : " return 32;\n"
621 : " }\n"
622 : " if( nValue < 0x7fffffffffffLL )\n"
623 : " {\n"
624 : " return 48;\n"
625 : " }\n"
626 : " else {\n"
627 : " if( nValue < 0x7fffffffffffffffLL )\n"
628 : " {\n"
629 : " return 64;\n"
630 : " } else\n"
631 : " {\n"
632 : " return -1;\n"
633 : " }\n"
634 : " }\n"
635 : "}");
636 1 : ASSERT_EQUALS("", errout_str());
637 :
638 1 : check("void f(WIDGET *widget) {\n"
639 : " if (dynamic_cast<BUTTON*>(widget)){}\n"
640 : " else if (dynamic_cast<LABEL*>(widget)){}\n"
641 : "}");
642 1 : ASSERT_EQUALS("", errout_str());
643 :
644 1 : check("class B { virtual void v() {} };\n" // #11037
645 : "class D1 : public B {};\n"
646 : "class D2 : public B {};\n"
647 : "void f(const std::shared_ptr<B>&p) {\n"
648 : " const auto d1 = dynamic_cast<D1*>(p.get());\n"
649 : " const auto d2 = dynamic_cast<D2*>(p.get());\n"
650 : " if (d1) {}\n"
651 : " else if (d2) {}\n"
652 : "}\n");
653 1 : ASSERT_EQUALS("", errout_str());
654 :
655 1 : check("void f(int x) {\n" // #6482
656 : " if (x & 1) {}\n"
657 : " else if (x == 0) {}\n"
658 : "}");
659 1 : ASSERT_EQUALS("", errout_str());
660 :
661 1 : check("void f(int x) {\n"
662 : " if (x & 15) {}\n"
663 : " else if (x == 40) {}\n"
664 : "}");
665 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
666 :
667 1 : check("void f(int x) {\n"
668 : " if (x == sizeof(double)) {}\n"
669 : " else { if (x == sizeof(long double)) {} }"
670 : "}");
671 1 : ASSERT_EQUALS("", errout_str());
672 :
673 1 : check("void f(int x) {\n"
674 : " if (x & 0x08) {}\n"
675 : " else if (x & 0xF8) {}\n"
676 : "}");
677 1 : ASSERT_EQUALS("", errout_str());
678 :
679 1 : check("void f(int x) {\n"
680 : " if (x & 0xF8) {}\n"
681 : " else if (x & 0x08) {}\n"
682 : "}");
683 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
684 :
685 1 : check("void f(bool a, bool b) {\n"
686 : " if(a && b){}\n"
687 : " else if( !!b && !!a){}\n"
688 : "}");
689 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
690 :
691 1 : check("void f(bool a, bool b) {\n"
692 : " if(a && b){}\n"
693 : " else if( !!b && a){}\n"
694 : "}");
695 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
696 :
697 1 : check("void f(bool a, bool b) {\n"
698 : " if(a && b){}\n"
699 : " else if( b && !!a){}\n"
700 : "}");
701 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
702 :
703 1 : check("void f(bool a, bool b) {\n"
704 : " if(a && b){}\n"
705 : " else if( b && !(!a)){}\n"
706 : "}");
707 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
708 :
709 1 : check("void f(bool a, bool b) {\n"
710 : " if(a && b){}\n"
711 : " else if( !!b && !(!a)){}\n"
712 : "}");
713 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2.\n", errout_str());
714 :
715 1 : check("void f(bool a, bool b) {\n"
716 : " if(a && b){}\n"
717 : " else if( !!(b) && !!(a+b)){}\n"
718 : "}");
719 1 : ASSERT_EQUALS("", errout_str());
720 :
721 : // #8168
722 1 : check("enum MaskValues\n"
723 : "{\n"
724 : " Value1 = 0x00000001,\n"
725 : " Value2 = 0x00000002\n"
726 : "};\n"
727 : "void TestFunction(int value) {\n"
728 : " if ( value & (int)Value1 ) {}\n"
729 : " else if ( value & (int)Value2 ) {}\n"
730 : "}");
731 1 : ASSERT_EQUALS("", errout_str());
732 :
733 1 : check("void f(size_t x) {\n"
734 : " if (x == sizeof(int)) {}\n"
735 : " else { if (x == sizeof(long))} {}\n"
736 : "}\n");
737 1 : ASSERT_EQUALS("", errout_str());
738 :
739 1 : check("void f(size_t x) {\n"
740 : " if (x == sizeof(long)) {}\n"
741 : " else { if (x == sizeof(long long))} {}\n"
742 : "}\n");
743 1 : ASSERT_EQUALS("", errout_str());
744 : }
745 :
746 1 : void oppositeElseIfCondition() {
747 1 : setMultiline();
748 :
749 1 : check("void f(int x) {\n"
750 : " if (x) {}\n"
751 : " else if (!x) {}\n"
752 : "}");
753 1 : ASSERT_EQUALS("test.cpp:3:style:Expression is always true because 'else if' condition is opposite to previous condition at line 2.\n"
754 : "test.cpp:2:note:first condition\n"
755 : "test.cpp:3:note:else if condition is opposite to first condition\n", errout_str());
756 :
757 1 : check("void f(int x) {\n"
758 : " int y = x;\n"
759 : " if (x) {}\n"
760 : " else if (!y) {}\n"
761 : "}");
762 1 : ASSERT_EQUALS("test.cpp:4:style:Expression is always true because 'else if' condition is opposite to previous condition at line 3.\n"
763 : "test.cpp:2:note:'y' is assigned value 'x' here.\n"
764 : "test.cpp:3:note:first condition\n"
765 : "test.cpp:4:note:else if condition is opposite to first condition\n", errout_str());
766 : }
767 :
768 1 : void checkBadBitmaskCheck() {
769 1 : check("bool f(int x) {\n"
770 : " bool b = x | 0x02;\n"
771 : " return b;\n"
772 : "}");
773 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
774 :
775 1 : check("bool f(int x) {\n"
776 : " bool b = 0x02 | x;\n"
777 : " return b;\n"
778 : "}");
779 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
780 :
781 1 : check("int f(int x) {\n"
782 : " int b = x | 0x02;\n"
783 : " return b;\n"
784 : "}");
785 1 : ASSERT_EQUALS("", errout_str());
786 :
787 1 : check("bool f(int x) {\n"
788 : " bool b = x & 0x02;\n"
789 : " return b;\n"
790 : "}");
791 1 : ASSERT_EQUALS("", errout_str());
792 :
793 1 : check("bool f(int x) {\n"
794 : " if(x | 0x02)\n"
795 : " return b;\n"
796 : "}");
797 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
798 :
799 1 : check("bool f(int x) {\n"
800 : " int y = 0x1;\n"
801 : " if(b) y = 0;\n"
802 : " if(x | y)\n"
803 : " return b;\n"
804 : "}");
805 1 : ASSERT_EQUALS("", errout_str());
806 :
807 1 : check("bool f(int x) {\n"
808 : " foo(a && (x | 0x02));\n"
809 : "}");
810 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
811 :
812 1 : check("int f(int x) {\n"
813 : " return (x | 0x02) ? 0 : 5;\n"
814 : "}");
815 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
816 :
817 1 : check("int f(int x) {\n"
818 : " return x ? (x | 0x02) : 5;\n"
819 : "}");
820 1 : ASSERT_EQUALS("", errout_str());
821 :
822 1 : check("bool f(int x) {\n"
823 : " return x | 0x02;\n"
824 : "}");
825 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
826 :
827 1 : check("bool f(int x) {\n"
828 : " if (x) {\n"
829 : " return x | 0x02;\n"
830 : " }\n"
831 : " return 0;\n"
832 : "}");
833 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
834 :
835 1 : check("const bool f(int x) {\n"
836 : " return x | 0x02;\n"
837 : "}");
838 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
839 :
840 1 : check("struct F {\n"
841 : " static const bool f(int x) {\n"
842 : " return x | 0x02;\n"
843 : " }\n"
844 : "};");
845 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
846 :
847 1 : check("struct F {\n"
848 : " typedef bool b_t;\n"
849 : "};\n"
850 : "F::b_t f(int x) {\n"
851 : " return x | 0x02;\n"
852 : "}");
853 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout_str());
854 :
855 1 : check("int f(int x) {\n"
856 : " return x | 0x02;\n"
857 : "}");
858 1 : ASSERT_EQUALS("", errout_str());
859 :
860 1 : check("void create_rop_masks_4( rop_mask_bits *bits) {\n"
861 : "DWORD mask_offset;\n"
862 : "BYTE *and_bits = bits->and;\n"
863 : "rop_mask *rop_mask;\n"
864 : "and_bits[mask_offset] |= (rop_mask->and & 0x0f);\n"
865 : "}");
866 1 : ASSERT_EQUALS("", errout_str());
867 :
868 1 : check("void f(unsigned a, unsigned b) {\n"
869 : " unsigned cmd1 = b & 0x0F;\n"
870 : " if (cmd1 | a) {\n"
871 : " if (b == 0x0C) {}\n"
872 : " }\n"
873 : "}");
874 1 : ASSERT_EQUALS("", errout_str());
875 :
876 1 : check("void f(int i) {\n" // #11082
877 : " int j = 0;\n"
878 : " if (i | j) {}\n"
879 : "}\n");
880 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Operator '|' with one operand equal to zero is redundant.\n", errout_str());
881 :
882 1 : check("#define EIGHTTOIS(x) (((x) << 8) | (x))\n"
883 : "int f() {\n"
884 : " return EIGHTTOIS(0);\n"
885 : "}\n");
886 1 : ASSERT_EQUALS("", errout_str());
887 :
888 1 : check("#define O_RDONLY 0\n"
889 : "void f(const char* s, int* pFd) {\n"
890 : " *pFd = open(s, O_RDONLY | O_BINARY, 0);\n"
891 : "}\n");
892 1 : ASSERT_EQUALS("", errout_str());
893 :
894 1 : check("const int FEATURE_BITS = x |\n"
895 : "#if FOO_ENABLED\n"
896 : " FEATURE_FOO |\n"
897 : "#endif\n"
898 : "#if BAR_ENABLED\n"
899 : " FEATURE_BAR |\n"
900 : "#endif\n"
901 : " 0;");
902 1 : ASSERT_EQUALS("", errout_str());
903 :
904 1 : check("enum precedence { PC0, UNARY };\n"
905 : "int x = PC0 | UNARY;\n"
906 : "int y = UNARY | PC0;\n");
907 1 : ASSERT_EQUALS("", errout_str());
908 :
909 1 : check("#define MASK 0\n"
910 : "#define SHIFT 1\n"
911 : "int x = 1 | (MASK << SHIFT);\n");
912 1 : ASSERT_EQUALS("", errout_str());
913 : }
914 :
915 :
916 1 : void incorrectLogicOperator1() {
917 1 : check("void f(int x) {\n"
918 : " if ((x != 1) || (x != 3))\n"
919 : " a++;\n"
920 : "}");
921 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 1 || x != 3.\n", errout_str());
922 :
923 1 : check("void f(int x) {\n"
924 : " if (1 != x || 3 != x)\n"
925 : " a++;\n"
926 : "}");
927 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 1 || x != 3.\n", errout_str());
928 :
929 1 : check("void f(int x) {\n"
930 : " if (x<0 && !x) {}\n"
931 : "}");
932 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 0 && !x.\n", errout_str());
933 :
934 1 : check("void f(int x) {\n"
935 : " if (x==0 && x) {}\n"
936 : "}");
937 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 0 && x.\n", errout_str());
938 :
939 1 : check("void f(int x) {\n" // ast..
940 : " if (y == 1 && x == 1 && x == 7) { }\n"
941 : "}");
942 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1 && x == 7.\n", errout_str());
943 :
944 1 : check("void f(int x, int y) {\n"
945 : " if (x != 1 || y != 1)\n"
946 : " a++;\n"
947 : "}");
948 1 : ASSERT_EQUALS("", errout_str());
949 :
950 1 : check("void f(int x, int y) {\n"
951 : " if ((y == 1) && (x != 1) || (x != 3))\n"
952 : " a++;\n"
953 : "}");
954 1 : ASSERT_EQUALS("", errout_str());
955 :
956 1 : check("void f(int x, int y) {\n"
957 : " if ((x != 1) || (x != 3) && (y == 1))\n"
958 : " a++;\n"
959 : "}"
960 : );
961 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'x!=3' is always true\n", errout_str());
962 :
963 1 : check("void f(int x) {\n"
964 : " if ((x != 1) && (x != 3))\n"
965 : " a++;\n"
966 : "}");
967 1 : ASSERT_EQUALS("", errout_str());
968 :
969 1 : check("void f(int x) {\n"
970 : " if ((x == 1) || (x == 3))\n"
971 : " a++;\n"
972 : "}");
973 1 : ASSERT_EQUALS("", errout_str());
974 :
975 1 : check("void f(int x, int y) {\n"
976 : " if ((x != 1) || (y != 3))\n"
977 : " a++;\n"
978 : "}");
979 1 : ASSERT_EQUALS("", errout_str());
980 :
981 1 : check("void f(int x, int y) {\n"
982 : " if ((x != hotdog) || (y != hotdog))\n"
983 : " a++;\n"
984 : "}");
985 1 : ASSERT_EQUALS("", errout_str());
986 :
987 1 : check("void f(int x, int y) {\n"
988 : " if ((x != 5) || (y != 5))\n"
989 : " a++;\n"
990 : "}");
991 1 : ASSERT_EQUALS("", errout_str());
992 :
993 :
994 1 : check("void f(int x) {\n"
995 : " if ((x != 5) || (x != 6))\n"
996 : " a++;\n"
997 : "}");
998 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 5 || x != 6.\n", errout_str());
999 :
1000 1 : check("void f(unsigned int a, unsigned int b, unsigned int c) {\n"
1001 : " if((a != b) || (c != b) || (c != a))\n"
1002 : " {\n"
1003 : " return true;\n"
1004 : " }\n"
1005 : " return false;\n"
1006 : "}");
1007 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'c!=a' is always false\n", errout_str());
1008 : }
1009 :
1010 1 : void incorrectLogicOperator2() {
1011 1 : check("void f(float x) {\n"
1012 : " if ((x == 1) && (x == 1.0))\n"
1013 : " a++;\n"
1014 : "}");
1015 1 : ASSERT_EQUALS("", errout_str());
1016 :
1017 1 : check("void f(int x) {\n"
1018 : " if ((x == 1) && (x == 0x00000001))\n"
1019 : " a++;\n"
1020 : "}");
1021 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'x==0x00000001' is always true\n", errout_str());
1022 :
1023 1 : check("void f(int x) {\n"
1024 : " if (x == 1 && x == 3)\n"
1025 : " a++;\n"
1026 : "}");
1027 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1 && x == 3.\n", errout_str());
1028 :
1029 1 : check("void f(int x) {\n"
1030 : " if (x == 1.0 && x == 3.0)\n"
1031 : " a++;\n"
1032 : "}");
1033 1 : ASSERT_EQUALS("", errout_str()); // float comparisons with == and != are not checked right now - such comparison is a bad idea
1034 :
1035 1 : check("void f(float x) {\n"
1036 : " if (x == 1 && x == 1.0)\n"
1037 : " a++;\n"
1038 : "}");
1039 1 : ASSERT_EQUALS("", errout_str());
1040 :
1041 1 : check("void bar(float f) {\n" // #5246
1042 : " if ((f > 0) && (f < 1)) {}\n"
1043 : "}");
1044 1 : ASSERT_EQUALS("", errout_str());
1045 :
1046 1 : check("void f(int x) {\n"
1047 : " if (x < 1 && x > 1)\n"
1048 : " a++;\n"
1049 : "}");
1050 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 1.\n", errout_str());
1051 :
1052 1 : check("void f(int x) {\n"
1053 : " if (x < 1.0 && x > 1.0)\n"
1054 : " a++;\n"
1055 : "}");
1056 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1.0 && x > 1.0.\n", errout_str());
1057 :
1058 1 : check("void f(int x) {\n"
1059 : " if (x < 1 && x > 1.0)\n"
1060 : " a++;\n"
1061 : "}");
1062 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 1.0.\n", errout_str());
1063 :
1064 1 : check("void f(int x) {\n"
1065 : " if (x >= 1.0 && x <= 1.001)\n"
1066 : " a++;\n"
1067 : "}");
1068 1 : ASSERT_EQUALS("", errout_str());
1069 :
1070 1 : check("void f(int x) {\n"
1071 : " if (x < 1 && x > 3)\n"
1072 : " a++;\n"
1073 : "}");
1074 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1075 :
1076 1 : check("void f(float x) {\n"
1077 : " if (x < 1.0 && x > 3.0)\n"
1078 : " a++;\n"
1079 : "}");
1080 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1.0 && x > 3.0.\n", errout_str());
1081 :
1082 1 : check("void f(int x) {\n"
1083 : " if (1 > x && 3 < x)\n"
1084 : " a++;\n"
1085 : "}");
1086 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1087 :
1088 1 : check("void f(int x) {\n"
1089 : " if (x < 3 && x > 1)\n"
1090 : " a++;\n"
1091 : "}");
1092 1 : ASSERT_EQUALS("", errout_str());
1093 :
1094 1 : check("void f(int x) {\n"
1095 : " if (x > 3 || x < 10)\n"
1096 : " a++;\n"
1097 : "}");
1098 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x < 10.\n", errout_str());
1099 :
1100 1 : check("void f(int x) {\n"
1101 : " if (x >= 3 || x <= 10)\n"
1102 : " a++;\n"
1103 : "}");
1104 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x <= 10.\n", errout_str());
1105 :
1106 1 : check("void f(int x) {\n"
1107 : " if (x >= 3 || x < 10)\n"
1108 : " a++;\n"
1109 : "}");
1110 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x < 10.\n", errout_str());
1111 :
1112 1 : check("void f(int x) {\n"
1113 : " if (x > 3 || x <= 10)\n"
1114 : " a++;\n"
1115 : "}");
1116 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x <= 10.\n", errout_str());
1117 :
1118 1 : check("void f(int x) {\n"
1119 : " if (x > 3 || x < 3)\n"
1120 : " a++;\n"
1121 : "}");
1122 1 : ASSERT_EQUALS("", errout_str());
1123 :
1124 1 : check("void f(int x) {\n"
1125 : " if (x >= 3 || x <= 3)\n"
1126 : " a++;\n"
1127 : "}"
1128 : );
1129 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x <= 3.\n", errout_str());
1130 :
1131 1 : check("void f(int x) {\n"
1132 : " if (x >= 3 || x < 3)\n"
1133 : " a++;\n"
1134 : "}"
1135 : );
1136 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x < 3.\n", errout_str());
1137 :
1138 1 : check("void f(int x) {\n"
1139 : " if (x > 3 || x <= 3)\n"
1140 : " a++;\n"
1141 : "}"
1142 : );
1143 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x <= 3.\n", errout_str());
1144 :
1145 1 : check("void f(int x) {\n"
1146 : " if((x==3) && (x!=4))\n"
1147 : " a++;\n"
1148 : "}");
1149 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x != 4' is redundant since 'x == 3' is sufficient.\n", errout_str());
1150 :
1151 1 : check("void f(const std::string &s) {\n" // #8860
1152 : " const std::size_t p = s.find(\"42\");\n"
1153 : " const std::size_t * const ptr = &p;\n"
1154 : " if(p != std::string::npos && p == 0 && *ptr != 1){;}\n"
1155 : "}");
1156 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:4]: (style) Condition '*ptr!=1' is always true\n", errout_str());
1157 :
1158 1 : check("void f(int x) {\n"
1159 : " if ((x!=4) && (x==3))\n"
1160 : " a++;\n"
1161 : "}");
1162 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x != 4' is redundant since 'x == 3' is sufficient.\n", errout_str());
1163 :
1164 1 : check("void f(int x) {\n"
1165 : " if ((x==3) || (x!=4))\n"
1166 : " a++;\n"
1167 : "}");
1168 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x == 3' is redundant since 'x != 4' is sufficient.\n", errout_str());
1169 :
1170 1 : check("void f(int x) {\n"
1171 : " if ((x!=4) || (x==3))\n"
1172 : " a++;\n"
1173 : "}");
1174 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x == 3' is redundant since 'x != 4' is sufficient.\n", errout_str());
1175 :
1176 1 : check("void f(int x) {\n"
1177 : " if ((x==3) && (x!=3))\n"
1178 : " a++;\n"
1179 : "}");
1180 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 3 && x != 3.\n", errout_str());
1181 :
1182 1 : check("void f(int x) {\n"
1183 : " if ((x==6) || (x!=6))\n"
1184 : " a++;\n"
1185 : "}");
1186 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x == 6 || x != 6.\n", errout_str());
1187 :
1188 1 : check("void f(int x) {\n"
1189 : " if (x > 10 || x < 3)\n"
1190 : " a++;\n"
1191 : "}");
1192 1 : ASSERT_EQUALS("", errout_str());
1193 :
1194 1 : check("void f(int x) {\n"
1195 : " if (x > 5 && x == 1)\n"
1196 : " a++;\n"
1197 : "}");
1198 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 5 && x == 1.\n", errout_str());
1199 :
1200 1 : check("void f(int x) {\n"
1201 : " if (x > 5 && x == 6)\n"
1202 : " a++;\n"
1203 : "}");
1204 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x == 6' is sufficient.\n", errout_str());
1205 :
1206 : // #3419
1207 1 : check("void f() {\n"
1208 : " if ( &q != &a && &q != &b ) { }\n"
1209 : "}");
1210 1 : ASSERT_EQUALS("", errout_str());
1211 :
1212 : // #3676
1213 1 : check("void f(int m_x2, int w, int x) {\n"
1214 : " if (x + w - 1 > m_x2 || m_x2 < 0 )\n"
1215 : " m_x2 = x + w - 1;\n"
1216 : "}");
1217 1 : ASSERT_EQUALS("", errout_str());
1218 :
1219 1 : check("void f(float x) {\n" // x+1 => x
1220 : " if (x <= 1.0e20 && x >= -1.0e20) {}\n"
1221 : "}");
1222 1 : ASSERT_EQUALS("", errout_str());
1223 :
1224 1 : check("void f(float x) {\n" // x+1 => x
1225 : " if (x >= 1.0e20 && x <= 1.0e21) {}\n"
1226 : "}");
1227 1 : ASSERT_EQUALS("", errout_str());
1228 :
1229 1 : check("void f(float x) {\n" // x+1 => x
1230 : " if (x <= -1.0e20 && x >= -1.0e21) {}\n"
1231 : "}");
1232 1 : ASSERT_EQUALS("", errout_str());
1233 : }
1234 :
1235 1 : void incorrectLogicOperator3() {
1236 1 : check("void f(int x, bool& b) {\n"
1237 : " b = x > 5 && x == 1;\n"
1238 : " c = x < 1 && x == 3;\n"
1239 : " d = x >= 5 && x == 1;\n"
1240 : " e = x <= 1 && x == 3;\n"
1241 : "}");
1242 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 5 && x == 1.\n"
1243 : "[test.cpp:3]: (warning) Logical conjunction always evaluates to false: x < 1 && x == 3.\n"
1244 : "[test.cpp:4]: (warning) Logical conjunction always evaluates to false: x >= 5 && x == 1.\n"
1245 : "[test.cpp:5]: (warning) Logical conjunction always evaluates to false: x <= 1 && x == 3.\n", errout_str());
1246 : }
1247 :
1248 1 : void incorrectLogicOperator4() {
1249 1 : check("#define ZERO 0\n"
1250 : "void f(int x) {\n"
1251 : " if (x && x != ZERO) {}\n"
1252 : "}");
1253 1 : ASSERT_EQUALS("", errout_str());
1254 :
1255 1 : check("void f(int N) {\n" // #9789
1256 : " T a[20] = { 0 };\n"
1257 : " for (int i = 0; i < N; ++i) {\n"
1258 : " if (0 < a[i] && a[i] < 1) {}\n"
1259 : " }\n"
1260 : "}\n");
1261 1 : ASSERT_EQUALS("", errout_str());
1262 : }
1263 :
1264 1 : void incorrectLogicOperator5() { // complex expressions
1265 1 : check("void f(int x) {\n"
1266 : " if (x+3 > 2 || x+3 < 10) {}\n"
1267 : "}");
1268 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x+3 > 2 || x+3 < 10.\n", errout_str());
1269 : }
1270 :
1271 1 : void incorrectLogicOperator6() { // char literals
1272 1 : check("void f(char x) {\n"
1273 : " if (x == '1' || x == '2') {}\n"
1274 : "}", "test.cpp", true);
1275 1 : ASSERT_EQUALS("", errout_str());
1276 :
1277 1 : check("void f(char x) {\n"
1278 : " if (x == '1' && x == '2') {}\n"
1279 : "}", "test.cpp", true);
1280 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == '1' && x == '2'.\n", errout_str());
1281 :
1282 1 : check("int f(char c) {\n"
1283 : " return (c >= 'a' && c <= 'z');\n"
1284 : "}", "test.cpp", true);
1285 1 : ASSERT_EQUALS("", errout_str());
1286 :
1287 1 : check("int f(char c) {\n"
1288 : " return (c <= 'a' && c >= 'z');\n"
1289 : "}", "test.cpp", true);
1290 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Logical conjunction always evaluates to false: c <= 'a' && c >= 'z'.\n", errout_str());
1291 :
1292 1 : check("int f(char c) {\n"
1293 : " return (c <= 'a' && c >= 'z');\n"
1294 : "}", "test.cpp", false);
1295 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Return value 'c>='z'' is always false\n", errout_str());
1296 : }
1297 :
1298 1 : void incorrectLogicOperator7() { // opposite expressions
1299 1 : check("void f(int i) {\n"
1300 : " if (i || !i) {}\n"
1301 : "}");
1302 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: i || !(i).\n", errout_str());
1303 :
1304 1 : check("void f(int a, int b) {\n"
1305 : " if (a>b || a<=b) {}\n"
1306 : "}");
1307 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: a > b || a <= b.\n", errout_str());
1308 :
1309 1 : check("void f(int a, int b) {\n"
1310 : " if (a>b || a<b) {}\n"
1311 : "}");
1312 1 : ASSERT_EQUALS("", errout_str());
1313 :
1314 : // #6064 False positive incorrectLogicOperator - invalid assumption about template type?
1315 1 : check("template<typename T> T icdf( const T uniform ) {\n"
1316 : " if ((0<uniform) && (uniform<1))\n"
1317 : " {}\n"
1318 : "}");
1319 1 : ASSERT_EQUALS("", errout_str());
1320 :
1321 : // #6081 False positive: incorrectLogicOperator, with close negative comparisons
1322 1 : check("double neg = -1.0 - 1.0e-13;\n"
1323 : "void foo() {\n"
1324 : " if ((neg < -1.0) && (neg > -1.0 - 1.0e-12))\n"
1325 : " return;\n"
1326 : " else\n"
1327 : " return;\n"
1328 : "}");
1329 1 : ASSERT_EQUALS("", errout_str());
1330 : }
1331 :
1332 1 : void incorrectLogicOperator8() { // opposite expressions
1333 1 : check("void f(int i) {\n"
1334 : " if (!(i!=10) && !(i!=20)) {}\n"
1335 : "}");
1336 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: !(i != 10) && !(i != 20).\n", errout_str());
1337 : }
1338 :
1339 1 : void incorrectLogicOperator9() { // #6069 "False positive incorrectLogicOperator due to dynamic_cast"
1340 1 : check("class MyType;\n"
1341 : "class OtherType;\n"
1342 : "void foo (OtherType* obj) {\n"
1343 : " assert((!obj) || dynamic_cast<MyType*>(obj));\n"
1344 : "}");
1345 1 : ASSERT_EQUALS("", errout_str());
1346 : }
1347 :
1348 1 : void incorrectLogicOperator10() { // #7794 - enum
1349 1 : check("typedef enum { A, B } Type_t;\n"
1350 : "void f(Type_t t) {\n"
1351 : " if ((t == A) && (t == B))\n"
1352 : " {}\n"
1353 : "}");
1354 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Logical conjunction always evaluates to false: t == 0 && t == 1.\n", errout_str());
1355 : }
1356 :
1357 1 : void incorrectLogicOperator11() {
1358 1 : check("void foo(int i, const int n) { if ( i < n && i == n ) {} }");
1359 1 : ASSERT_EQUALS("[test.cpp:1]: (warning) Logical conjunction always evaluates to false: i < n && i == n.\n", errout_str());
1360 :
1361 1 : check("void foo(int i, const int n) { if ( i > n && i == n ) {} }");
1362 1 : ASSERT_EQUALS("[test.cpp:1]: (warning) Logical conjunction always evaluates to false: i > n && i == n.\n", errout_str());
1363 :
1364 1 : check("void foo(int i, const int n) { if ( i == n && i > n ) {} }");
1365 1 : ASSERT_EQUALS("[test.cpp:1]: (warning) Logical conjunction always evaluates to false: i == n && i > n.\n", errout_str());
1366 :
1367 1 : check("void foo(int i, const int n) { if ( i == n && i < n ) {} }");
1368 1 : ASSERT_EQUALS("[test.cpp:1]: (warning) Logical conjunction always evaluates to false: i == n && i < n.\n", errout_str());
1369 : }
1370 :
1371 1 : void incorrectLogicOperator12() { // #8696
1372 1 : check("struct A {\n"
1373 : " void f() const;\n"
1374 : "};\n"
1375 : "void foo(A a, A b) {\n"
1376 : " A x = b;\n"
1377 : " A y = b;\n"
1378 : " y.f();\n"
1379 : " if (a > x && a < y)\n"
1380 : " return;\n"
1381 : "}");
1382 1 : ASSERT_EQUALS(
1383 : "[test.cpp:5] -> [test.cpp:6] -> [test.cpp:8]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n",
1384 : errout_str());
1385 :
1386 1 : check("struct A {\n"
1387 : " void f();\n"
1388 : "};\n"
1389 : "void foo(A a, A b) {\n"
1390 : " A x = b;\n"
1391 : " A y = b;\n"
1392 : " y.f();\n"
1393 : " if (a > x && a < y)\n"
1394 : " return;\n"
1395 : "}");
1396 1 : ASSERT_EQUALS("", errout_str());
1397 :
1398 1 : check("void foo(A a, A b) {\n"
1399 : " A x = b;\n"
1400 : " A y = b;\n"
1401 : " y.f();\n"
1402 : " if (a > x && a < y)\n"
1403 : " return;\n"
1404 : "}");
1405 1 : ASSERT_EQUALS("", errout_str());
1406 :
1407 1 : check("void foo(A a, A b) {\n"
1408 : " const A x = b;\n"
1409 : " const A y = b;\n"
1410 : " y.f();\n"
1411 : " if (a > x && a < y)\n"
1412 : " return;\n"
1413 : "}");
1414 1 : ASSERT_EQUALS(
1415 : "[test.cpp:2] -> [test.cpp:3] -> [test.cpp:5]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n",
1416 : errout_str());
1417 :
1418 1 : check("struct A {\n"
1419 : " void f() const;\n"
1420 : "};\n"
1421 : "void foo(A a) {\n"
1422 : " A x = a;\n"
1423 : " A y = a;\n"
1424 : " y.f();\n"
1425 : " if (a > x && a < y)\n"
1426 : " return;\n"
1427 : "}");
1428 1 : ASSERT_EQUALS("[test.cpp:8]: (style) Condition 'a>x' is always false\n"
1429 : "[test.cpp:8]: (style) Condition 'a<y' is always false\n",
1430 : errout_str());
1431 :
1432 1 : check("struct A {\n"
1433 : " void f();\n"
1434 : "};\n"
1435 : "void foo(A a) {\n"
1436 : " A x = a;\n"
1437 : " A y = a;\n"
1438 : " y.f();\n"
1439 : " if (a > x && a < y)\n"
1440 : " return;\n"
1441 : "}");
1442 1 : ASSERT_EQUALS("[test.cpp:8]: (style) Condition 'a>x' is always false\n", errout_str());
1443 :
1444 1 : check("void foo(A a) {\n"
1445 : " A x = a;\n"
1446 : " A y = a;\n"
1447 : " y.f();\n"
1448 : " if (a > x && a < y)\n"
1449 : " return;\n"
1450 : "}");
1451 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'a>x' is always false\n", errout_str());
1452 :
1453 1 : check("void foo(A a) {\n"
1454 : " const A x = a;\n"
1455 : " const A y = a;\n"
1456 : " y.f();\n"
1457 : " if (a > x && a < y)\n"
1458 : " return;\n"
1459 : "}");
1460 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'a>x' is always false\n"
1461 : "[test.cpp:5]: (style) Condition 'a<y' is always false\n",
1462 : errout_str());
1463 : }
1464 :
1465 1 : void incorrectLogicOperator13() {
1466 : // 8780
1467 1 : check("void f(const int &v) {\n"
1468 : " const int x=v;\n"
1469 : " if ((v == 1) && (x == 2)) {;}\n"
1470 : "}");
1471 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Logical conjunction always evaluates to false: v == 1 && x == 2.\n", errout_str());
1472 :
1473 1 : check("void f2(const int *v) {\n"
1474 : " const int *x=v;\n"
1475 : " if ((*v == 1) && (*x == 2)) {;}\n"
1476 : "}");
1477 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Logical conjunction always evaluates to false: *(v) == 1 && *(x) == 2.\n", errout_str());
1478 : }
1479 :
1480 1 : void incorrectLogicOperator14() {
1481 1 : check("static const std ::string h;\n"
1482 : "class i {\n"
1483 : "public:\n"
1484 : " struct j {\n"
1485 : " std ::string k;\n"
1486 : " std ::string l;\n"
1487 : " };\n"
1488 : " struct a {\n"
1489 : " enum { m = 1 };\n"
1490 : " };\n"
1491 : "} b;\n"
1492 : "namespace n {\n"
1493 : "class c;\n"
1494 : "}\n"
1495 : "struct o {\n"
1496 : " enum { p, d, q, r };\n"
1497 : " enum { e, f };\n"
1498 : "\n"
1499 : "public:\n"
1500 : " class j {\n"
1501 : " public:\n"
1502 : " class s {\n"
1503 : " std ::string a;\n"
1504 : " };\n"
1505 : " };\n"
1506 : "};\n"
1507 : "namespace n {\n"
1508 : "class b;\n"
1509 : "}\n"
1510 : "namespace aa {\n"
1511 : "class d {\n"
1512 : "public:\n"
1513 : " char t;\n"
1514 : " enum {} u;\n"
1515 : "};\n"
1516 : "} // namespace aa\n"
1517 : "namespace aa {\n"
1518 : "struct e {};\n"
1519 : "} // namespace aa\n"
1520 : "class a;\n"
1521 : "class w {\n"
1522 : "public:\n"
1523 : " enum { x };\n"
1524 : " struct {\n"
1525 : " } y;\n"
1526 : " std ::string z;\n"
1527 : "};\n"
1528 : "class ab {\n"
1529 : " friend class c;\n"
1530 : "\n"
1531 : "public:\n"
1532 : " class ac {\n"
1533 : " void e(const ac &v) const;\n"
1534 : " };\n"
1535 : "};\n"
1536 : "class f;\n"
1537 : "class ad {\n"
1538 : " friend class e;\n"
1539 : " enum { e, ae, ag, ah, ai, aj, ak, a, b };\n"
1540 : " class c {};\n"
1541 : " class d {\n"
1542 : " enum am { f, an, ao, ap, aq, ar, b, as, at, c, au };\n"
1543 : " enum av { aw, ax, ay, az, e, ba, bb, bc, bd, a };\n"
1544 : " struct b {\n"
1545 : " am action;\n"
1546 : " av c;\n"
1547 : " };\n"
1548 : " };\n"
1549 : " class e {\n"
1550 : " public:\n"
1551 : " std ::string e;\n"
1552 : " class f {\n"
1553 : " } f;\n"
1554 : " class be {\n"
1555 : " public:\n"
1556 : " };\n"
1557 : " std ::vector<be> bf;\n"
1558 : " enum { bg, b } c;\n"
1559 : " };\n"
1560 : " struct bh {\n"
1561 : " std ::map<int, d> b;\n"
1562 : " };\n"
1563 : " std ::map<std ::string, bh> bi;\n"
1564 : " struct {\n"
1565 : " int b;\n"
1566 : " char bj;\n"
1567 : " } bk;\n"
1568 : " class a {\n"
1569 : " public:\n"
1570 : " std ::set<std ::string> b;\n"
1571 : " };\n"
1572 : "};\n"
1573 : "class bl;\n"
1574 : "class al;\n"
1575 : "class bm;\n"
1576 : "class f;\n"
1577 : "class b;\n"
1578 : "class bn;\n"
1579 : "namespace bo {\n"
1580 : "class bp {\n"
1581 : "public:\n"
1582 : " typedef std ::pair<const f *, std ::string> bq;\n"
1583 : " typedef std ::list<bq> br;\n"
1584 : "};\n"
1585 : "const bo ::bp *dg(const f *a, const al *b);\n"
1586 : "} // namespace bo\n"
1587 : "const bn *dh(const f *d, bo ::bp ::br &bs);\n"
1588 : "class f {\n"
1589 : "public:\n"
1590 : " struct bt {};\n"
1591 : " std ::vector<a> f;\n"
1592 : "};\n"
1593 : "class bu;\n"
1594 : "class a;\n"
1595 : "class c;\n"
1596 : "struct bv {};\n"
1597 : "class af {\n"
1598 : "private:\n"
1599 : "public:\n"
1600 : " enum { b, d, e, f, c, bw };\n"
1601 : " void a(int c);\n"
1602 : " af *bx() const;\n"
1603 : "};\n"
1604 : "namespace by {\n"
1605 : "class b;\n"
1606 : "}\n"
1607 : "class b {\n"
1608 : "public:\n"
1609 : " bool d, c;\n"
1610 : "};\n"
1611 : "class bz;\n"
1612 : "class f;\n"
1613 : "class ca {\n"
1614 : " friend class b;\n"
1615 : "\n"
1616 : "public:\n"
1617 : " const bm *cb() const { return cc; }\n"
1618 : " f *d(f *e, bool f) const;\n"
1619 : " int e() { return ++cd; }\n"
1620 : " bl *const c;\n"
1621 : " bm *cc;\n"
1622 : " std ::map<std ::string, int> ce;\n"
1623 : " int cd;\n"
1624 : " bz *a;\n"
1625 : "};\n"
1626 : "namespace n {\n"
1627 : "class c;\n"
1628 : "class d;\n"
1629 : "} // namespace n\n"
1630 : "class cf {\n"
1631 : "public:\n"
1632 : " explicit cf(const std ::string &aname);\n"
1633 : " cf(const std ::string &aname, const ca *cg, const al *ch, bl *ci)\n"
1634 : " : cj(cg), ck(ch), cl(ci), cn(aname) {}\n"
1635 : "\n"
1636 : "protected:\n"
1637 : " const ca *const cj;\n"
1638 : " const al *const ck;\n"
1639 : " bl *const cl;\n"
1640 : " const std ::string cn;\n"
1641 : "};\n"
1642 : "class cm : public cf {\n"
1643 : "public:\n"
1644 : " void cp();\n"
1645 : " std ::string d() const;\n"
1646 : "};\n"
1647 : "struct co {\n"
1648 : " co();\n"
1649 : " const bu *a;\n"
1650 : " enum f {};\n"
1651 : " enum {\n"
1652 : " b = (1 << 0),\n"
1653 : " c = (1 << 1),\n"
1654 : " };\n"
1655 : " void d(bool e);\n"
1656 : "};\n"
1657 : "class bu {\n"
1658 : " friend class e;\n"
1659 : "\n"
1660 : "public:\n"
1661 : " struct f {};\n"
1662 : " enum { d, cr, cq, ct, cs, e, a, b, c, dd, cu, cv, cw, cx, cy, cz, da };\n"
1663 : " const f *db;\n"
1664 : " const af *dc;\n"
1665 : "} f{};\n"
1666 : "class bm {\n"
1667 : "public:\n"
1668 : " std ::list<bu> df;\n"
1669 : " std ::vector<const bu *> de;\n"
1670 : " mutable std ::set<std ::string> f;\n"
1671 : "};\n"
1672 : "void cm ::cp() {\n"
1673 : " const bm *a = cj->cb();\n"
1674 : " for (const bu *b : a->de)\n"
1675 : " for (af *c = b->dc->bx();;) {\n"
1676 : " af *d = c;\n"
1677 : " af *e = c;\n"
1678 : " bool f(d);\n"
1679 : " bool g(e);\n"
1680 : " if (f && g)\n"
1681 : " ;\n"
1682 : " }\n"
1683 : "}");
1684 1 : ASSERT_EQUALS("[test.cpp:200] -> [test.cpp:200]: (style) Condition 'g' is always true\n", errout_str());
1685 : }
1686 :
1687 1 : void incorrectLogicOperator15() {
1688 : // 10022
1689 1 : check("struct PipeRoute {\n"
1690 : " std::deque<int> points;\n"
1691 : " std::deque<int> estimates;\n"
1692 : "};\n"
1693 : "void CleanPipeRoutes(std::map<int, PipeRoute*>& pipeRoutes) {\n"
1694 : " for (auto it = pipeRoutes.begin(); it != pipeRoutes.end(); ) {\n"
1695 : " PipeRoute* curRoute = it->second;\n"
1696 : " if (curRoute->points.empty() && curRoute->estimates.size() != 2)\n"
1697 : " {\n"
1698 : " delete curRoute;\n"
1699 : " it = pipeRoutes.erase(it);\n"
1700 : " }\n"
1701 : " else\n"
1702 : " {\n"
1703 : " ++it;\n"
1704 : " }\n"
1705 : " }\n"
1706 : "}\n");
1707 1 : ASSERT_EQUALS("", errout_str());
1708 : }
1709 :
1710 1 : void incorrectLogicOperator16() { // #10070
1711 1 : check("void foo(void* p) {\n"
1712 : " if (!p || p == -1) { }\n"
1713 : "}\n");
1714 1 : ASSERT_EQUALS("", errout_str());
1715 : }
1716 :
1717 1 : void incorrectLogicOperator17() { // #12471
1718 1 : check("struct R {\n"
1719 : " void set() { i = 1; }\n"
1720 : " int get() const { return i; }\n"
1721 : " int i;\n"
1722 : "};\n"
1723 : "struct P {\n"
1724 : " void f();\n"
1725 : " R* r;\n"
1726 : "};\n"
1727 : "void P::f() {\n"
1728 : " int a = r->get();\n"
1729 : " r->set();\n"
1730 : " if (a == 0 && r->get()) {}\n"
1731 : "}\n");
1732 1 : ASSERT_EQUALS("", errout_str());
1733 : }
1734 :
1735 1 : void secondAlwaysTrueFalseWhenFirstTrueError() {
1736 1 : check("void f(void) {\n" // #8892
1737 : " const char c[1] = { \'x\' }; \n"
1738 : " if(c[0] == \'x\'){;}\n"
1739 : "}");
1740 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'c[0]=='x'' is always true\n", errout_str());
1741 :
1742 1 : check("void f(int x) {\n"
1743 : " if (x > 5 && x != 1)\n"
1744 : " a++;\n"
1745 : "}");
1746 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x != 1' is redundant since 'x > 5' is sufficient.\n", errout_str());
1747 :
1748 1 : check("void f(int x) {\n"
1749 : " if (x > 5 && x != 6)\n"
1750 : " a++;\n"
1751 : "}");
1752 1 : ASSERT_EQUALS("", errout_str());
1753 :
1754 1 : check("void f(int x) {\n"
1755 : " if ((x > 5) && (x != 1))\n"
1756 : " a++;\n"
1757 : "}");
1758 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x != 1' is redundant since 'x > 5' is sufficient.\n", errout_str());
1759 :
1760 1 : check("void f(int x) {\n"
1761 : " if ((x > 5) && (x != 6))\n"
1762 : " a++;\n"
1763 : "}");
1764 1 : ASSERT_EQUALS("", errout_str());
1765 :
1766 1 : check("void f(int x, bool& b) {\n"
1767 : " b = x > 3 || x == 4;\n"
1768 : " c = x < 5 || x == 4;\n"
1769 : " d = x >= 3 || x == 4;\n"
1770 : " e = x <= 5 || x == 4;\n"
1771 : "}");
1772 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x > 3' is sufficient.\n"
1773 : "[test.cpp:3]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x < 5' is sufficient.\n"
1774 : "[test.cpp:4]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x >= 3' is sufficient.\n"
1775 : "[test.cpp:5]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x <= 5' is sufficient.\n",
1776 : errout_str());
1777 :
1778 1 : check("void f(int x, bool& b) {\n"
1779 : " b = x > 5 || x != 1;\n"
1780 : " c = x < 1 || x != 3;\n"
1781 : " d = x >= 5 || x != 1;\n"
1782 : " e = x <= 1 || x != 3;\n"
1783 : "}");
1784 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x != 1' is sufficient.\n"
1785 : "[test.cpp:3]: (style) Redundant condition: The condition 'x < 1' is redundant since 'x != 3' is sufficient.\n"
1786 : "[test.cpp:4]: (style) Redundant condition: The condition 'x >= 5' is redundant since 'x != 1' is sufficient.\n"
1787 : "[test.cpp:5]: (style) Redundant condition: The condition 'x <= 1' is redundant since 'x != 3' is sufficient.\n",
1788 : errout_str());
1789 :
1790 1 : check("void f(int x, bool& b) {\n"
1791 : " b = x > 6 && x > 5;\n"
1792 : " c = x > 5 || x > 6;\n"
1793 : " d = x < 6 && x < 5;\n"
1794 : " e = x < 5 || x < 6;\n"
1795 : "}");
1796 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x > 6' is sufficient.\n"
1797 : "[test.cpp:3]: (style) Redundant condition: The condition 'x > 6' is redundant since 'x > 5' is sufficient.\n"
1798 : "[test.cpp:4]: (style) Redundant condition: The condition 'x < 6' is redundant since 'x < 5' is sufficient.\n"
1799 : "[test.cpp:5]: (style) Redundant condition: The condition 'x < 5' is redundant since 'x < 6' is sufficient.\n",
1800 : errout_str());
1801 :
1802 1 : check("void f(double x, bool& b) {\n"
1803 : " b = x > 6.5 && x > 5.5;\n"
1804 : " c = x > 5.5 || x > 6.5;\n"
1805 : " d = x < 6.5 && x < 5.5;\n"
1806 : " e = x < 5.5 || x < 6.5;\n"
1807 : "}");
1808 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition 'x > 5.5' is redundant since 'x > 6.5' is sufficient.\n"
1809 : "[test.cpp:3]: (style) Redundant condition: The condition 'x > 6.5' is redundant since 'x > 5.5' is sufficient.\n"
1810 : "[test.cpp:4]: (style) Redundant condition: The condition 'x < 6.5' is redundant since 'x < 5.5' is sufficient.\n"
1811 : "[test.cpp:5]: (style) Redundant condition: The condition 'x < 5.5' is redundant since 'x < 6.5' is sufficient.\n",
1812 : errout_str());
1813 :
1814 1 : check("void f(const char *p) {\n" // #10320
1815 : " if (!p || !*p || *p != 'x') {}\n"
1816 : "}\n");
1817 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: The condition '!*p' is redundant since '*p != 'x'' is sufficient.\n",
1818 : errout_str());
1819 : }
1820 :
1821 1 : void incorrectLogicOp_condSwapping() {
1822 1 : check("void f(int x) {\n"
1823 : " if (x < 1 && x > 3)\n"
1824 : " a++;\n"
1825 : "}");
1826 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1827 :
1828 1 : check("void f(int x) {\n"
1829 : " if (1 > x && x > 3)\n"
1830 : " a++;\n"
1831 : "}");
1832 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1833 :
1834 1 : check("void f(int x) {\n"
1835 : " if (x < 1 && 3 < x)\n"
1836 : " a++;\n"
1837 : "}");
1838 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1839 :
1840 1 : check("void f(int x) {\n"
1841 : " if (1 > x && 3 < x)\n"
1842 : " a++;\n"
1843 : "}");
1844 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout_str());
1845 :
1846 1 : check("void f(int x) {\n"
1847 : " if (x > 3 && x < 1)\n"
1848 : " a++;\n"
1849 : "}");
1850 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1.\n", errout_str());
1851 :
1852 1 : check("void f(int x) {\n"
1853 : " if (3 < x && x < 1)\n"
1854 : " a++;\n"
1855 : "}");
1856 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1.\n", errout_str());
1857 :
1858 1 : check("void f(int x) {\n"
1859 : " if (x > 3 && 1 > x)\n"
1860 : " a++;\n"
1861 : "}");
1862 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1.\n", errout_str());
1863 :
1864 1 : check("void f(int x) {\n"
1865 : " if (3 < x && 1 > x)\n"
1866 : " a++;\n"
1867 : "}");
1868 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1.\n", errout_str());
1869 : }
1870 :
1871 1 : void modulo() {
1872 1 : check("bool f(bool& b1, bool& b2, bool& b3) {\n"
1873 : " b1 = a % 5 == 4;\n"
1874 : " b2 = a % c == 100000;\n"
1875 : " b3 = a % 5 == c;\n"
1876 : " return a % 5 == 5-p;\n"
1877 : "}");
1878 1 : ASSERT_EQUALS("", errout_str());
1879 :
1880 1 : check("bool f(bool& b1, bool& b2, bool& b3, bool& b4, bool& b5) {\n"
1881 : " b1 = a % 5 < 5;\n"
1882 : " b2 = a % 5 <= 5;\n"
1883 : " b3 = a % 5 == 5;\n"
1884 : " b4 = a % 5 != 5;\n"
1885 : " b5 = a % 5 >= 5;\n"
1886 : " return a % 5 > 5;\n"
1887 : "}");
1888 1 : ASSERT_EQUALS(
1889 : "[test.cpp:2]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1890 : "[test.cpp:3]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1891 : "[test.cpp:4]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1892 : "[test.cpp:5]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1893 : "[test.cpp:6]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1894 : "[test.cpp:7]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n",
1895 : errout_str());
1896 :
1897 1 : check("void f(bool& b1, bool& b2) {\n"
1898 : " b1 = bar() % 5 < 889;\n"
1899 : " if(x[593] % 5 <= 5)\n"
1900 : " b2 = x.a % 5 == 5;\n"
1901 : "}");
1902 1 : ASSERT_EQUALS(
1903 : "[test.cpp:2]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1904 : "[test.cpp:3]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n"
1905 : "[test.cpp:4]: (warning) Comparison of modulo result is predetermined, because it is always less than 5.\n",
1906 : errout_str());
1907 :
1908 1 : check("void f() {\n"
1909 : " if (a % 2 + b % 2 == 2)\n"
1910 : " foo();\n"
1911 : "}");
1912 1 : ASSERT_EQUALS("", errout_str());
1913 : }
1914 :
1915 1 : void oppositeInnerCondition() {
1916 1 : check("void foo(int a, int b) {\n"
1917 : " if(a==b)\n"
1918 : " if(a!=b)\n"
1919 : " cout << a;\n"
1920 : "}");
1921 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
1922 :
1923 1 : check("bool foo(int a, int b) {\n"
1924 : " if(a==b)\n"
1925 : " return a!=b;\n"
1926 : " return false;\n"
1927 : "}");
1928 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'return' condition leads to a dead code block.\n", errout_str());
1929 :
1930 1 : check("void foo(int a, int b) {\n"
1931 : " if(a==b)\n"
1932 : " if(b!=a)\n"
1933 : " cout << a;\n"
1934 : "}");
1935 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
1936 :
1937 1 : check("void foo(int a) {\n"
1938 : " if(a >= 50) {\n"
1939 : " if(a < 50)\n"
1940 : " cout << a;\n"
1941 : " else\n"
1942 : " cout << 100;\n"
1943 : " }\n"
1944 : "}");
1945 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
1946 :
1947 : // #4186
1948 1 : check("void foo(int a) {\n"
1949 : " if(a >= 50) {\n"
1950 : " if(a > 50)\n"
1951 : " cout << a;\n"
1952 : " else\n"
1953 : " cout << 100;\n"
1954 : " }\n"
1955 : "}");
1956 1 : ASSERT_EQUALS("", errout_str());
1957 :
1958 : // 4170
1959 1 : check("class foo {\n"
1960 : " void bar() {\n"
1961 : " if (tok == '(') {\n"
1962 : " next();\n"
1963 : " if (tok == ',') {\n"
1964 : " next();\n"
1965 : " if (tok != ',') {\n"
1966 : " op->reg2 = asm_parse_reg();\n"
1967 : " }\n"
1968 : " skip(',');\n"
1969 : " }\n"
1970 : " }\n"
1971 : " }\n"
1972 : " void next();\n"
1973 : " const char *tok;\n"
1974 : "};");
1975 1 : ASSERT_EQUALS("", errout_str());
1976 :
1977 1 : check("void foo(int i)\n"
1978 : "{\n"
1979 : " if(i > 5) {\n"
1980 : " i = bar();\n"
1981 : " if(i < 5) {\n"
1982 : " cout << a;\n"
1983 : " }\n"
1984 : " }\n"
1985 : "}");
1986 1 : ASSERT_EQUALS("", errout_str());
1987 :
1988 1 : check("void foo(int& i) {\n"
1989 : " i=6;\n"
1990 : "}\n"
1991 : "void bar(int i) {\n"
1992 : " if(i>5) {\n"
1993 : " foo(i);\n"
1994 : " if(i<5) {\n"
1995 : " }\n"
1996 : " }\n"
1997 : "}");
1998 1 : ASSERT_EQUALS("", errout_str());
1999 :
2000 1 : check("void foo(int& i);\n"
2001 : "void bar() {\n"
2002 : " int i; i = func();\n"
2003 : " if(i>5) {\n"
2004 : " foo(i);\n"
2005 : " if(i<5) {\n"
2006 : " }\n"
2007 : " }\n"
2008 : "}");
2009 1 : ASSERT_EQUALS("", errout_str());
2010 :
2011 1 : check("void foo(int i);\n"
2012 : "void bar(int i) {\n"
2013 : " if(i>5) {\n"
2014 : " foo(i);\n"
2015 : " if(i<5) {\n"
2016 : " }\n"
2017 : " }\n"
2018 : "}");
2019 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2020 :
2021 1 : check("void foo(const int &i);\n"
2022 : "void bar(int i) {\n"
2023 : " if(i>5) {\n"
2024 : " foo(i);\n"
2025 : " if(i<5) {\n"
2026 : " }\n"
2027 : " }\n"
2028 : "}");
2029 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2030 :
2031 1 : check("void foo(int i);\n"
2032 : "void bar() {\n"
2033 : " int i; i = func();\n"
2034 : " if(i>5) {\n"
2035 : " foo(i);\n"
2036 : " if(i<5) {\n"
2037 : " }\n"
2038 : " }\n"
2039 : "}");
2040 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2041 :
2042 1 : check("class C { void f(int &i) const; };\n" // #7028 - variable is changed by const method
2043 : "void foo(C c, int i) {\n"
2044 : " if (i==5) {\n"
2045 : " c.f(i);\n"
2046 : " if (i != 5) {}\n"
2047 : " }\n"
2048 : "}");
2049 1 : ASSERT_EQUALS("", errout_str());
2050 :
2051 : // see linux revision 1f80c0cc
2052 1 : check("int generic_write_sync(int,int,int);\n"
2053 : "\n"
2054 : "void cifs_writev(int i) {\n"
2055 : " int rc = __generic_file_aio_write();\n"
2056 : " if (rc > 0){\n"
2057 : " err = generic_write_sync(file, iocb->ki_pos - rc, rc);\n"
2058 : " if(rc < 0) {\n" // <- condition is always false
2059 : " err = rc;\n"
2060 : " }\n"
2061 : " }\n"
2062 : "}");
2063 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:7]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2064 :
2065 :
2066 : // #5874 - array
2067 1 : check("void testOppositeConditions2() {\n"
2068 : " int array[2] = { 0, 0 };\n"
2069 : " if (array[0] < 2) {\n"
2070 : " array[0] += 5;\n"
2071 : " if (array[0] > 2) {}\n"
2072 : " }\n"
2073 : "}");
2074 1 : ASSERT_EQUALS("", errout_str());
2075 :
2076 : // #6227 - FP caused by simplifications of casts and known variables
2077 1 : check("void foo(A *a) {\n"
2078 : " if(a) {\n"
2079 : " B *b = dynamic_cast<B*>(a);\n"
2080 : " if(!b) {}\n"
2081 : " }\n"
2082 : "}");
2083 1 : ASSERT_EQUALS("", errout_str());
2084 :
2085 1 : check("void foo(int a) {\n"
2086 : " if(a) {\n"
2087 : " int b = a;\n"
2088 : " if(!b) {}\n"
2089 : " }\n"
2090 : "}");
2091 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2092 :
2093 1 : check("void foo(unsigned u) {\n"
2094 : " if (u != 0) {\n"
2095 : " for (int i=0; i<32; i++) {\n"
2096 : " if (u == 0) {}\n" // <- don't warn
2097 : " u = x;\n"
2098 : " }\n"
2099 : " }\n"
2100 : "}");
2101 1 : ASSERT_EQUALS("", errout_str());
2102 :
2103 : // #8186
2104 1 : check("void f() {\n"
2105 : " for (int i=0;i<4;i++) {\n"
2106 : " if (i==5) {}\n"
2107 : " }\n"
2108 : "}");
2109 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2110 :
2111 : // #8938
2112 1 : check("void Delete(SS_CELLCOORD upperleft) {\n"
2113 : " if ((upperleft.Col == -1) && (upperleft.Row == -1)) {\n"
2114 : " GetActiveCell(&(upperleft.Col), &(upperleft.Row));\n"
2115 : " if (upperleft.Row == -1) {}\n"
2116 : " }\n"
2117 : "}");
2118 1 : ASSERT_EQUALS("", errout_str());
2119 :
2120 : // #9702
2121 1 : check("struct A {\n"
2122 : " void DoTest() {\n"
2123 : " if (!IsSet()) {\n"
2124 : " m_value = true;\n"
2125 : " if (IsSet());\n"
2126 : " }\n"
2127 : " }\n"
2128 : " bool IsSet() const { return m_value; }\n"
2129 : " bool m_value = false;\n"
2130 : "};");
2131 1 : ASSERT_EQUALS("", errout_str());
2132 : }
2133 :
2134 1 : void oppositeInnerConditionPointers() {
2135 1 : check("void f(struct ABC *abc) {\n"
2136 : " struct AB *ab = abc->ab;\n"
2137 : " if (ab->a == 123){\n"
2138 : " do_something(abc);\n" // might change ab->a
2139 : " if (ab->a != 123) {\n"
2140 : " err = rc;\n"
2141 : " }\n"
2142 : " }\n"
2143 : "}");
2144 1 : ASSERT_EQUALS("", errout_str());
2145 :
2146 1 : check("void Fred::f() {\n" // daca: ace
2147 : " if (this->next_ == map_man_->table_) {\n"
2148 : " this->next_ = n;\n"
2149 : " if (this->next_ != map_man_->table_) {}\n"
2150 : " }\n"
2151 : "}");
2152 1 : ASSERT_EQUALS("", errout_str());
2153 :
2154 1 : check("void test(float *f) {\n" // #7405
2155 : " if(*f>10) {\n"
2156 : " (*f) += 0.1f;\n"
2157 : " if(*f<10) {}\n"
2158 : " }\n"
2159 : "}");
2160 1 : ASSERT_EQUALS("", errout_str());
2161 :
2162 1 : check("int * f(int * x, int * y) {\n"
2163 : " if(!x) return x;\n"
2164 : " return y;\n"
2165 : "}");
2166 1 : ASSERT_EQUALS("", errout_str());
2167 : }
2168 :
2169 1 : void oppositeInnerConditionClass() {
2170 : // #6095 - calling member function that might change the state
2171 1 : check("void f() {\n"
2172 : " const Fred fred;\n" // <- fred is const, warn
2173 : " if (fred.isValid()) {\n"
2174 : " fred.dostuff();\n"
2175 : " if (!fred.isValid()) {}\n"
2176 : " }\n"
2177 : "}");
2178 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2179 :
2180 1 : check("class Fred { public: bool isValid() const; void dostuff() const; };\n"
2181 : "void f() {\n"
2182 : " Fred fred;\n"
2183 : " if (fred.isValid()) {\n"
2184 : " fred.dostuff();\n" // <- dostuff() is const, warn
2185 : " if (!fred.isValid()) {}\n"
2186 : " }\n"
2187 : "}");
2188 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2189 :
2190 1 : check("void f() {\n"
2191 : " Fred fred;\n"
2192 : " if (fred.isValid()) {\n"
2193 : " fred.dostuff();\n"
2194 : " if (!fred.isValid()) {}\n"
2195 : " }\n"
2196 : "}");
2197 1 : ASSERT_EQUALS("", errout_str());
2198 :
2199 : // #6385 "crash in Variable::getFlag()"
2200 1 : check("class TranslationHandler {\n"
2201 : "QTranslator *mTranslator;\n"
2202 : "void SetLanguage() {\n"
2203 : " if (mTranslator) {\n"
2204 : " qApp->removeTranslator(mTranslator);\n"
2205 : " }\n"
2206 : " }\n"
2207 : "};");
2208 1 : ASSERT_EQUALS("", errout_str()); // just don't crash...
2209 :
2210 1 : check("bool f(std::ofstream &CFileStream) {\n" // #8198
2211 : " if(!CFileStream.good()) { return; }\n"
2212 : " CFileStream << \"abc\";\n"
2213 : " if (!CFileStream.good()) {}\n"
2214 : "}");
2215 1 : ASSERT_EQUALS("", errout_str());
2216 : }
2217 :
2218 1 : void oppositeInnerConditionUndeclaredVariable() {
2219 : // #5731 - fp when undeclared variable is used
2220 1 : check("void f() {\n"
2221 : " if (x == -1){\n"
2222 : " x = do_something();\n"
2223 : " if (x != -1) {}\n"
2224 : " }\n"
2225 : "}");
2226 1 : ASSERT_EQUALS("", errout_str());
2227 :
2228 : // #5750 - another fp when undeclared variable is used
2229 1 : check("void f() {\n"
2230 : " if (r < w){\n"
2231 : " r += 3;\n"
2232 : " if (r > w) {}\n"
2233 : " }\n"
2234 : "}");
2235 1 : ASSERT_EQUALS("", errout_str());
2236 :
2237 : // #6574 - another fp when undeclared variable is used
2238 1 : check("void foo() {\n"
2239 : " if(i) {\n"
2240 : " i++;\n"
2241 : " if(!i) {}\n"
2242 : " }\n"
2243 : "}");
2244 1 : ASSERT_EQUALS("", errout_str());
2245 :
2246 : // undeclared array
2247 1 : check("void f(int x) {\n"
2248 : " if (a[x] > 0) {\n"
2249 : " a[x] -= dt;\n"
2250 : " if (a[x] < 0) {}\n"
2251 : " }\n"
2252 : "}");
2253 1 : ASSERT_EQUALS("", errout_str());
2254 :
2255 : // #6313 - false positive: opposite conditions in nested if blocks when condition changed
2256 1 : check("void Foo::Bar() {\n"
2257 : " if(var){\n"
2258 : " --var;\n"
2259 : " if(!var){}\n"
2260 : " else {}\n"
2261 : " }\n"
2262 : "}");
2263 1 : ASSERT_EQUALS("", errout_str());
2264 :
2265 : // daca hyphy
2266 1 : check("bool f() {\n"
2267 : " if (rec.lLength==0) {\n"
2268 : " rec.Delete(i);\n"
2269 : " if (rec.lLength!=0) {}\n"
2270 : " }\n"
2271 : "}");
2272 1 : ASSERT_EQUALS("", errout_str());
2273 : }
2274 :
2275 1 : void oppositeInnerConditionAlias() {
2276 1 : check("void f() {\n"
2277 : " struct S s;\n"
2278 : " bool hasFailed = false;\n"
2279 : " s.status = &hasFailed;\n"
2280 : "\n"
2281 : " if (! hasFailed) {\n"
2282 : " doStuff(&s);\n"
2283 : " if (hasFailed) {}\n"
2284 : " }\n"
2285 : "}");
2286 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Condition '!hasFailed' is always true\n", errout_str());
2287 : }
2288 :
2289 1 : void oppositeInnerCondition2() {
2290 : // first comparison: <
2291 1 : check("void f(int x) {\n"
2292 : "\n"
2293 : " if (x<4) {\n"
2294 : " if (x==5) {}\n" // <- Warning
2295 : " }\n"
2296 : "}");
2297 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2298 : errout_str());
2299 1 : check("void f(int x) {\n"
2300 : "\n"
2301 : " if (x<4) {\n"
2302 : " if (x!=5) {}\n"
2303 : " }\n"
2304 : "}");
2305 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x!=5' is always true\n", errout_str());
2306 1 : check("void f(int x) {\n"
2307 : "\n"
2308 : " if (x<4) {\n"
2309 : " if (x>5) {}\n" // <- Warning
2310 : " }\n"
2311 : "}");
2312 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2313 : errout_str());
2314 1 : check("void f(int x) {\n"
2315 : "\n"
2316 : " if (x<4) {\n"
2317 : " if (x>=5) {}\n" // <- Warning
2318 : " }\n"
2319 : "}");
2320 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2321 : errout_str());
2322 1 : check("void f(int x) {\n"
2323 : "\n"
2324 : " if (x<4) {\n"
2325 : " if (x<5) {}\n"
2326 : " }\n"
2327 : "}");
2328 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<5' is always true\n", errout_str());
2329 1 : check("void f(int x) {\n"
2330 : "\n"
2331 : " if (x<4) {\n"
2332 : " if (x<=5) {}\n"
2333 : " }\n"
2334 : "}");
2335 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<=5' is always true\n", errout_str());
2336 :
2337 1 : check("void f(int x) {\n"
2338 : "\n"
2339 : " if (x<5) {\n"
2340 : " if (x==4) {}\n"
2341 : " }\n"
2342 : "}");
2343 1 : ASSERT_EQUALS("", errout_str());
2344 1 : check("void f(int x) {\n"
2345 : "\n"
2346 : " if (x<5) {\n"
2347 : " if (x!=4) {}\n"
2348 : " }\n"
2349 : "}");
2350 1 : ASSERT_EQUALS("", errout_str());
2351 1 : check("void f(int x) {\n"
2352 : "\n"
2353 : " if (x<5) {\n"
2354 : " if (x!=6) {}\n"
2355 : " }\n"
2356 : "}");
2357 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x!=6' is always true\n", errout_str());
2358 1 : check("void f(int x) {\n"
2359 : "\n"
2360 : " if (x<5) {\n"
2361 : " if (x>4) {}\n" // <- Warning
2362 : " }\n"
2363 : "}");
2364 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>4' is always false\n", errout_str());
2365 1 : check("void f(int x) {\n"
2366 : "\n"
2367 : " if (x<5) {\n"
2368 : " if (x>=4) {}\n"
2369 : " }\n"
2370 : "}");
2371 1 : ASSERT_EQUALS("", errout_str());
2372 1 : check("void f(int x) {\n"
2373 : "\n"
2374 : " if (x<5) {\n"
2375 : " if (x<4) {}\n"
2376 : " }\n"
2377 : "}");
2378 1 : ASSERT_EQUALS("", errout_str());
2379 1 : check("void f(int x) {\n"
2380 : "\n"
2381 : " if (x<5) {\n"
2382 : " if (x<=4) {}\n"
2383 : " }\n"
2384 : "}");
2385 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<=4' is always true\n", errout_str());
2386 :
2387 : // first comparison: >
2388 1 : check("void f(int x) {\n"
2389 : "\n"
2390 : " if (x>4) {\n"
2391 : " if (x==5) {}\n"
2392 : " }\n"
2393 : "}");
2394 1 : ASSERT_EQUALS("", errout_str());
2395 1 : check("void f(int x) {\n"
2396 : "\n"
2397 : " if (x>4) {\n"
2398 : " if (x>5) {}\n"
2399 : " }\n"
2400 : "}");
2401 1 : ASSERT_EQUALS("", errout_str());
2402 1 : check("void f(int x) {\n"
2403 : "\n"
2404 : " if (x>4) {\n"
2405 : " if (x>=5) {}\n" // <- Warning
2406 : " }\n"
2407 : "}");
2408 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>=5' is always true\n", errout_str());
2409 1 : check("void f(int x) {\n"
2410 : "\n"
2411 : " if (x>4) {\n"
2412 : " if (x<5) {}\n" // <- Warning
2413 : " }\n"
2414 : "}");
2415 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<5' is always false\n", errout_str());
2416 1 : check("void f(int x) {\n"
2417 : "\n"
2418 : " if (x>4) {\n"
2419 : " if (x<=5) {}\n"
2420 : " }\n"
2421 : "}");
2422 1 : ASSERT_EQUALS("", errout_str());
2423 :
2424 1 : check("void f(int x) {\n"
2425 : "\n"
2426 : " if (x>5) {\n"
2427 : " if (x==4) {}\n" // <- Warning
2428 : " }\n"
2429 : "}");
2430 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2431 : errout_str());
2432 1 : check("void f(int x) {\n"
2433 : "\n"
2434 : " if (x>5) {\n"
2435 : " if (x>4) {}\n" // <- Warning
2436 : " }\n"
2437 : "}");
2438 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>4' is always true\n", errout_str());
2439 1 : check("void f(int x) {\n"
2440 : "\n"
2441 : " if (x>5) {\n"
2442 : " if (x>=4) {}\n" // <- Warning
2443 : " }\n"
2444 : "}");
2445 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>=4' is always true\n", errout_str());
2446 1 : check("void f(int x) {\n"
2447 : "\n"
2448 : " if (x>5) {\n"
2449 : " if (x<4) {}\n" // <- Warning
2450 : " }\n"
2451 : "}");
2452 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2453 : errout_str());
2454 1 : check("void f(int x) {\n"
2455 : "\n"
2456 : " if (x>5) {\n"
2457 : " if (x<=4) {}\n" // <- Warning
2458 : " }\n"
2459 : "}");
2460 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2461 : errout_str());
2462 :
2463 1 : check("void f(int x) {\n"
2464 : " if (x < 4) {\n"
2465 : " if (10 < x) {}\n"
2466 : " }\n"
2467 : "}");
2468 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2469 : }
2470 :
2471 1 : void oppositeInnerCondition3() {
2472 1 : check("void f3(char c) { if(c=='x') if(c=='y') {}}");
2473 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2474 :
2475 1 : check("void f4(char *p) { if(*p=='x') if(*p=='y') {}}");
2476 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2477 :
2478 1 : check("void f5(const char * const p) { if(*p=='x') if(*p=='y') {}}");
2479 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2480 :
2481 1 : check("void f5(const char * const p) { if('x'==*p) if('y'==*p) {}}");
2482 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2483 :
2484 1 : check("void f6(char * const p) { if(*p=='x') if(*p=='y') {}}");
2485 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2486 :
2487 1 : check("void f7(const char * p) { if(*p=='x') if(*p=='y') {}}");
2488 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2489 :
2490 1 : check("void f8(int i) { if(i==4) if(i==2) {}}");
2491 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2492 :
2493 1 : check("void f9(int *p) { if (*p==4) if(*p==2) {}}");
2494 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2495 :
2496 1 : check("void f10(int * const p) { if (*p==4) if(*p==2) {}}");
2497 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2498 :
2499 1 : check("void f11(const int *p) { if (*p==4) if(*p==2) {}}");
2500 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2501 :
2502 1 : check("void f12(const int * const p) { if (*p==4) if(*p==2) {}}");
2503 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2504 :
2505 1 : check("struct foo {\n"
2506 : " int a;\n"
2507 : " int b;\n"
2508 : "};\n"
2509 : "void f(foo x) { if(x.a==4) if(x.b==2) {}}");
2510 1 : ASSERT_EQUALS("", errout_str());
2511 :
2512 1 : check("struct foo {\n"
2513 : " int a;\n"
2514 : " int b;\n"
2515 : "};\n"
2516 : "void f(foo x) { if(x.a==4) if(x.b==4) {}}");
2517 1 : ASSERT_EQUALS("", errout_str());
2518 :
2519 1 : check("void f3(char a, char b) { if(a==b) if(a==0) {}}");
2520 1 : ASSERT_EQUALS("", errout_str());
2521 :
2522 1 : check("void f(int x) { if (x == 1) if (x != 1) {} }");
2523 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2524 : }
2525 :
2526 1 : void oppositeInnerConditionAnd() {
2527 1 : check("void f(int x) {\n"
2528 : " if (a>3 && x > 100) {\n"
2529 : " if (x < 10) {}\n"
2530 : " }"
2531 : "}");
2532 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2533 :
2534 1 : check("void f(bool x, const int a, const int b) {\n"
2535 : " if(x && a < b)\n"
2536 : " if( x && a > b){}\n"
2537 : "}\n");
2538 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2539 : }
2540 :
2541 1 : void oppositeInnerConditionOr()
2542 : {
2543 1 : check("void f(int x) {\n"
2544 : " if (x == 1 || x == 2) {\n"
2545 : " if (x == 3) {}\n"
2546 : " }\n"
2547 : "}\n");
2548 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2549 : errout_str());
2550 :
2551 1 : check("void f(int x) {\n"
2552 : " if (x == 1 || x == 2) {\n"
2553 : " if (x == 1) {}\n"
2554 : " }\n"
2555 : "}\n");
2556 1 : ASSERT_EQUALS("", errout_str());
2557 :
2558 1 : check("void f(int x) {\n"
2559 : " if (x == 1 || x == 2) {\n"
2560 : " if (x == 2) {}\n"
2561 : " }\n"
2562 : "}\n");
2563 1 : ASSERT_EQUALS("", errout_str());
2564 :
2565 1 : check("void f(std::string x) {\n"
2566 : " if (x == \"1\" || x == \"2\") {\n"
2567 : " if (x == \"1\") {}\n"
2568 : " }\n"
2569 : "}\n");
2570 1 : ASSERT_EQUALS("", errout_str());
2571 :
2572 1 : check("void f(int x) {\n"
2573 : " if (x < 1 || x > 3) {\n"
2574 : " if (x == 3) {}\n"
2575 : " }\n"
2576 : "}\n");
2577 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block.\n",
2578 : errout_str());
2579 : }
2580 :
2581 1 : void oppositeInnerConditionEmpty() {
2582 1 : check("void f1(const std::string &s) { if(s.size() > 42) if(s.empty()) {}}");
2583 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2584 :
2585 1 : check("void f1(const std::string &s) { if(s.size() > 0) if(s.empty()) {}}");
2586 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2587 :
2588 1 : check("void f1(const std::string &s) { if(s.size() < 0) if(s.empty()) {}} "); // <- CheckOther reports: checking if unsigned expression is less than zero
2589 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Condition 's.empty()' is always false\n", errout_str());
2590 :
2591 1 : check("void f1(const std::string &s) { if(s.empty()) if(s.size() > 42) {}}");
2592 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2593 :
2594 1 : check("template<class T> void f1(const T &s) { if(s.size() > 42) if(s.empty()) {}}");
2595 1 : ASSERT_EQUALS("", errout_str()); //We don't know the type of T so we don't know the relationship between size() and empty(). e.g. s might be a 50 tonne truck with nothing in it.
2596 :
2597 1 : check("void f2(const std::wstring &s) { if(s.empty()) if(s.size() > 42) {}}");
2598 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2599 :
2600 1 : check("void f1(QString s) { if(s.isEmpty()) if(s.length() > 42) {}}");
2601 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout_str());
2602 :
2603 1 : check("void f1(const std::string &s, bool b) { if(s.empty() || ((s.size() == 1) && b)) {}}");
2604 1 : ASSERT_EQUALS("", errout_str());
2605 :
2606 1 : check("void f1(const std::string &x, const std::string &y) { if(x.size() > 42) if(y.empty()) {}}");
2607 1 : ASSERT_EQUALS("", errout_str());
2608 :
2609 1 : check("void f1(const std::string &x, const std::string &y) { if(y.empty()) if(x.size() > 42) {}}");
2610 1 : ASSERT_EQUALS("", errout_str());
2611 :
2612 1 : check("void f1(const std::string v[10]) { if(v[0].size() > 42) if(v[1].empty()) {}}");
2613 1 : ASSERT_EQUALS("", errout_str());
2614 :
2615 1 : check("void f1(const std::string &s) { if(s.size() <= 1) if(s.empty()) {}}");
2616 1 : ASSERT_EQUALS("", errout_str());
2617 :
2618 1 : check("void f1(const std::string &s) { if(s.size() <= 2) if(s.empty()) {}}");
2619 1 : ASSERT_EQUALS("", errout_str());
2620 :
2621 1 : check("void f1(const std::string &s) { if(s.size() < 2) if(s.empty()) {}}");
2622 1 : ASSERT_EQUALS("", errout_str());
2623 :
2624 1 : check("void f1(const std::string &s) { if(s.size() >= 0) if(s.empty()) {}} "); // CheckOther says: Unsigned expression 's.size()' can't be negative so it is unnecessary to test it. [unsignedPositive]
2625 1 : ASSERT_EQUALS("", errout_str());
2626 :
2627 : // TODO: These are identical condition since size cannot be negative
2628 1 : check("void f1(const std::string &s) { if(s.size() <= 0) if(s.empty()) {}}");
2629 1 : ASSERT_EQUALS("", errout_str());
2630 :
2631 : // TODO: These are identical condition since size cannot be negative
2632 1 : check("void f1(const std::string &s) { if(s.size() < 1) if(s.empty()) {}}");
2633 1 : ASSERT_EQUALS("", errout_str());
2634 : }
2635 :
2636 1 : void oppositeInnerConditionFollowVar() {
2637 1 : check("struct X {\n"
2638 : " void f() {\n"
2639 : " const int flag = get();\n"
2640 : " if (flag) {\n"
2641 : " bar();\n"
2642 : " if (!get()) {}\n"
2643 : " }\n"
2644 : " }\n"
2645 : " void bar();\n"
2646 : " int get() const;\n"
2647 : "};");
2648 1 : ASSERT_EQUALS("", errout_str());
2649 :
2650 1 : check("struct CD {\n"
2651 : " bool state;\n"
2652 : " void foo() {\n"
2653 : " const bool flag = this->get();\n"
2654 : " if (flag) {\n"
2655 : " this->bar();\n"
2656 : " if (!this->get()) return;\n"
2657 : " }\n"
2658 : " }\n"
2659 : " bool get() const;\n"
2660 : " void bar();\n"
2661 : "};\n");
2662 1 : ASSERT_EQUALS("", errout_str());
2663 :
2664 1 : check("class C {\n"
2665 : "public:\n"
2666 : " bool f() const { return x > 0; }\n"
2667 : " void g();\n"
2668 : " int x = 0;\n"
2669 : "};\n"
2670 : "\n"
2671 : "void C::g() {\n"
2672 : " bool b = f();\n"
2673 : " x += 1;\n"
2674 : " if (!b && f()) {}\n"
2675 : "}");
2676 1 : ASSERT_EQUALS("", errout_str());
2677 :
2678 1 : check("void f(double d) {\n"
2679 : " if (d != 0) {\n"
2680 : " int i = d;\n"
2681 : " if (i == 0) {}\n"
2682 : " }\n"
2683 : "}\n");
2684 1 : ASSERT_EQUALS("", errout_str());
2685 : }
2686 :
2687 1 : void identicalInnerCondition() {
2688 1 : check("void f1(int a, int b) { if(a==b) if(a==b) {}}");
2689 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true.\n", errout_str());
2690 :
2691 1 : check("void f2(int a, int b) { if(a!=b) if(a!=b) {}}");
2692 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true.\n", errout_str());
2693 :
2694 : // #6645 false negative: condition is always false
2695 1 : check("void f(bool a, bool b) {\n"
2696 : " if(a && b) {\n"
2697 : " if(a) {}\n"
2698 : " else {}\n"
2699 : " }\n"
2700 : "}");
2701 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical inner 'if' condition is always true.\n", errout_str());
2702 :
2703 1 : check("bool f(int a, int b) {\n"
2704 : " if(a == b) { return a == b; }\n"
2705 : " return false;\n"
2706 : "}");
2707 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (warning) Identical inner 'return' condition is always true.\n", errout_str());
2708 :
2709 1 : check("bool f(bool a) {\n"
2710 : " if(a) { return a; }\n"
2711 : " return false;\n"
2712 : "}");
2713 1 : ASSERT_EQUALS("", errout_str());
2714 :
2715 1 : check("int* f(int* a, int * b) {\n"
2716 : " if(a) { return a; }\n"
2717 : " return b;\n"
2718 : "}");
2719 1 : ASSERT_EQUALS("", errout_str());
2720 :
2721 1 : check("int* f(std::shared_ptr<int> a, std::shared_ptr<int> b) {\n"
2722 : " if(a.get()) { return a.get(); }\n"
2723 : " return b.get();\n"
2724 : "}");
2725 1 : ASSERT_EQUALS("", errout_str());
2726 :
2727 1 : check("struct A { int * x; };\n"
2728 : "int* f(A a, int * b) {\n"
2729 : " if(a.x) { return a.x; }\n"
2730 : " return b;\n"
2731 : "}");
2732 1 : ASSERT_EQUALS("", errout_str());
2733 :
2734 1 : check("void f() {\n"
2735 : " uint32_t value;\n"
2736 : " get_value(&value);\n"
2737 : " int opt_function_capable = (value >> 28) & 1;\n"
2738 : " if (opt_function_capable) {\n"
2739 : " value = 0;\n"
2740 : " get_value (&value);\n"
2741 : " if ((value >> 28) & 1) {}\n"
2742 : " }\n"
2743 : "}");
2744 1 : ASSERT_EQUALS("", errout_str());
2745 : }
2746 :
2747 1 : void identicalConditionAfterEarlyExit() {
2748 1 : check("void f(int x) {\n" // #8137
2749 : " if (x > 100) { return; }\n"
2750 : " if (x > 100) {}\n"
2751 : "}");
2752 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false\n", errout_str());
2753 :
2754 1 : check("bool f(int x) {\n"
2755 : " if (x > 100) { return false; }\n"
2756 : " return x > 100;\n"
2757 : "}");
2758 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition and return expression 'x>100', return value is always false\n", errout_str());
2759 :
2760 1 : check("void f(int x) {\n"
2761 : " if (x > 100) { return; }\n"
2762 : " if (x > 100 || y > 100) {}\n"
2763 : "}");
2764 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false\n", errout_str());
2765 :
2766 1 : check("void f(int x) {\n"
2767 : " if (x > 100) { return; }\n"
2768 : " if (x > 100 && y > 100) {}\n"
2769 : "}");
2770 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false\n", errout_str());
2771 :
2772 1 : check("void f(int x) {\n"
2773 : " if (x > 100) { return; }\n"
2774 : " if (abc) {}\n"
2775 : " if (x > 100) {}\n"
2776 : "}");
2777 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Identical condition 'x>100', second condition is always false\n", errout_str());
2778 :
2779 1 : check("void f(int x) {\n"
2780 : " if (x > 100) { return; }\n"
2781 : " while (abc) { y = x; }\n"
2782 : " if (x > 100) {}\n"
2783 : "}");
2784 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Identical condition 'x>100', second condition is always false\n", errout_str());
2785 :
2786 1 : ASSERT_THROW_INTERNAL(check("void f(int x) {\n" // #8217 - crash for incomplete code
2787 : " if (x > 100) { return; }\n"
2788 : " X(do);\n"
2789 : " if (x > 100) {}\n"
2790 : "}"),
2791 : SYNTAX);
2792 :
2793 1 : check("void f(const int *i) {\n"
2794 : " if (!i) return;\n"
2795 : " if (!num1tok) { *num1 = *num2; }\n"
2796 : " if (!i) {}\n"
2797 : "}");
2798 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Identical condition '!i', second condition is always false\n", errout_str());
2799 :
2800 1 : check("void C::f(Tree &coreTree) {\n" // daca
2801 : " if(!coreTree.build())\n"
2802 : " return;\n"
2803 : " coreTree.dostuff();\n"
2804 : " if(!coreTree.build()) {}\n"
2805 : "}");
2806 1 : ASSERT_EQUALS("", errout_str());
2807 :
2808 1 : check("struct C { void f(const Tree &coreTree); };\n"
2809 : "void C::f(const Tree &coreTree) {\n"
2810 : " if(!coreTree.build())\n"
2811 : " return;\n"
2812 : " coreTree.dostuff();\n"
2813 : " if(!coreTree.build()) {}\n"
2814 : "}");
2815 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (warning) Identical condition '!coreTree.build()', second condition is always false\n", errout_str());
2816 :
2817 1 : check("void f(int x) {\n" // daca: labplot
2818 : " switch(type) {\n"
2819 : " case 1:\n"
2820 : " if (x == 0) return 1;\n"
2821 : " else return 2;\n"
2822 : " case 2:\n"
2823 : " if (x == 0) return 3;\n"
2824 : " else return 4;\n"
2825 : " }\n"
2826 : " return 0;\n"
2827 : "}");
2828 1 : ASSERT_EQUALS("", errout_str());
2829 :
2830 1 : check("static int failed = 0;\n"
2831 : "void f() {\n"
2832 : " if (failed) return;\n"
2833 : " checkBuffer();\n"
2834 : " if (failed) {}\n"
2835 : "}");
2836 1 : ASSERT_EQUALS("", errout_str());
2837 :
2838 : // daca icu
2839 1 : check("void f(const uint32_t *section, int32_t start) {\n"
2840 : " if(10<=section[start]) { return; }\n"
2841 : " if(++start<100 && 10<=section[start]) { }\n"
2842 : "}");
2843 1 : ASSERT_EQUALS("", errout_str());
2844 :
2845 : // daca iqtree
2846 1 : check("void readNCBITree(std::istream &in) {\n"
2847 : " char ch;\n"
2848 : " in >> ch;\n"
2849 : " if (ch != '|') return;\n"
2850 : " in >> ch;\n"
2851 : " if (ch != '|') {}\n"
2852 : "}");
2853 1 : ASSERT_EQUALS("", errout_str());
2854 :
2855 : // #8924
2856 1 : check("struct A {\n"
2857 : " void f() {\n"
2858 : " if (this->FileIndex >= 0) return;\n"
2859 : " this->FileIndex = 1 ;\n"
2860 : " if (this->FileIndex < 0) return;\n"
2861 : " }\n"
2862 : " int FileIndex;\n"
2863 : "};");
2864 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'this->FileIndex<0' is always false\n", errout_str());
2865 :
2866 : // #8858 - #if
2867 1 : check("short Do() {\n"
2868 : " short ret = bar1();\n"
2869 : " if ( ret )\n"
2870 : " return ret;\n"
2871 : "#ifdef FEATURE\n"
2872 : " ret = bar2();\n"
2873 : "#endif\n"
2874 : " return ret;\n"
2875 : "}");
2876 1 : ASSERT_EQUALS("", errout_str());
2877 :
2878 : // #10456
2879 1 : check("int f() {\n"
2880 : " int i = 0;\n"
2881 : " auto f = [&](bool b) { if (b) ++i; };\n"
2882 : " if (i) return i;\n"
2883 : " f(true);\n"
2884 : " if (i) return i;\n"
2885 : " return 0;\n"
2886 : "}\n");
2887 1 : ASSERT_EQUALS("", errout_str());
2888 :
2889 : // #11478
2890 1 : check("struct S {\n"
2891 : " void run();\n"
2892 : " bool b = false;\n"
2893 : " const std::function<void(S&)> f;\n"
2894 : "};\n"
2895 : "void S::run() {\n"
2896 : " while (true) {\n"
2897 : " if (b)\n"
2898 : " return;\n"
2899 : " f(*this);\n"
2900 : " if (b)\n"
2901 : " return;\n"
2902 : " }\n"
2903 : "}\n");
2904 1 : ASSERT_EQUALS("", errout_str());
2905 : }
2906 :
2907 1 : void innerConditionModified() {
2908 1 : check("void f(int x, int y) {\n"
2909 : " if (x == 0) {\n"
2910 : " x += y;\n"
2911 : " if (x == 0) {}\n"
2912 : " }\n"
2913 : "}");
2914 1 : ASSERT_EQUALS("", errout_str());
2915 :
2916 1 : check("void f(int x) {\n"
2917 : " if (x == 0) {\n"
2918 : " x += y;\n"
2919 : " if (x == 1) {}\n"
2920 : " }\n"
2921 : "}");
2922 1 : ASSERT_EQUALS("", errout_str());
2923 :
2924 1 : check("void f(int * x, int * y) {\n"
2925 : " if (x[*y] == 0) {\n"
2926 : " (*y)++;\n"
2927 : " if (x[*y] == 0) {}\n"
2928 : " }\n"
2929 : "}");
2930 1 : ASSERT_EQUALS("", errout_str());
2931 : }
2932 :
2933 : // clarify conditions with = and comparison
2934 1 : void clarifyCondition1() {
2935 1 : check("void f() {\n"
2936 : " if (x = b() < 0) {}\n" // don't simplify and verify this code
2937 : "}");
2938 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Suspicious condition (assignment + comparison); Clarify expression with parentheses.\n", errout_str());
2939 :
2940 1 : check("void f(int i) {\n"
2941 : " for (i = 0; i < 10; i++) {}\n"
2942 : "}");
2943 1 : ASSERT_EQUALS("", errout_str());
2944 :
2945 1 : check("void f() {\n"
2946 : " x = a<int>(); if (x) {}\n"
2947 : "}");
2948 1 : ASSERT_EQUALS("", errout_str());
2949 :
2950 1 : check("void f() {\n"
2951 : " if (x = b < 0 ? 1 : 2) {}\n" // don't simplify and verify this code
2952 : "}");
2953 1 : ASSERT_EQUALS("", errout_str());
2954 :
2955 1 : check("void f() {\n"
2956 : " int y = rand(), z = rand();\n"
2957 : " if (y || (!y && z));\n"
2958 : "}");
2959 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: !y. 'y || (!y && z)' is equivalent to 'y || z'\n", errout_str());
2960 :
2961 1 : check("void f() {\n"
2962 : " int y = rand(), z = rand();\n"
2963 : " if (y || !y && z);\n"
2964 : "}");
2965 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: !y. 'y || (!y && z)' is equivalent to 'y || z'\n", errout_str());
2966 :
2967 1 : check("void f() {\n"
2968 : " if (!a || a && b) {}\n"
2969 : "}");
2970 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: a. '!a || (a && b)' is equivalent to '!a || b'\n", errout_str());
2971 :
2972 :
2973 1 : check("void f(const Token *tok) {\n"
2974 : " if (!tok->next()->function() ||\n"
2975 : " (tok->next()->function() && tok->next()->function()->isConstructor()));\n"
2976 : "}");
2977 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: tok->next()->function(). '!A || (A && B)' is equivalent to '!A || B'\n", errout_str());
2978 :
2979 1 : check("void f() {\n"
2980 : " if (!tok->next()->function() ||\n"
2981 : " (!tok->next()->function() && tok->next()->function()->isConstructor()));\n"
2982 : "}");
2983 1 : ASSERT_EQUALS("", errout_str());
2984 :
2985 1 : check("void f() {\n"
2986 : " if (!tok->next()->function() ||\n"
2987 : " (!tok2->next()->function() && tok->next()->function()->isConstructor()));\n"
2988 : "}");
2989 1 : ASSERT_EQUALS("", errout_str());
2990 :
2991 1 : check("void f(const Token *tok) {\n"
2992 : " if (!tok->next(1)->function(1) ||\n"
2993 : " (tok->next(1)->function(1) && tok->next(1)->function(1)->isConstructor()));\n"
2994 : "}");
2995 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: tok->next(1)->function(1). '!A || (A && B)' is equivalent to '!A || B'\n", errout_str());
2996 :
2997 1 : check("void f() {\n"
2998 : " if (!tok->next()->function(1) ||\n"
2999 : " (tok->next()->function(2) && tok->next()->function()->isConstructor()));\n"
3000 : "}");
3001 1 : ASSERT_EQUALS("", errout_str());
3002 :
3003 1 : check("void f() {\n"
3004 : " int y = rand(), z = rand();\n"
3005 : " if (y==0 || y!=0 && z);\n"
3006 : "}");
3007 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: y!=0. 'y==0 || (y!=0 && z)' is equivalent to 'y==0 || z'\n", errout_str());
3008 :
3009 1 : check("void f() {\n"
3010 : " if (x>0 || (x<0 && y)) {}\n"
3011 : "}");
3012 1 : ASSERT_EQUALS("", errout_str());
3013 :
3014 : // Test Token::expressionString, TODO move this test
3015 1 : check("void f() {\n"
3016 : " if (!dead || (dead && (*it).ticks > 0)) {}\n"
3017 : "}");
3018 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: dead. '!dead || (dead && (*it).ticks>0)' is equivalent to '!dead || (*it).ticks>0'\n", errout_str());
3019 :
3020 1 : check("void f() {\n"
3021 : " if (!x || (x && (2>(y-1)))) {}\n"
3022 : "}");
3023 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: x. '!x || (x && 2>(y-1))' is equivalent to '!x || 2>(y-1)'\n", errout_str());
3024 :
3025 1 : check("void f(bool a, bool b) {\n"
3026 : " if (a || (a && b)) {}\n"
3027 : "}");
3028 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: a. 'a || (a && b)' is equivalent to 'a'\n", errout_str());
3029 :
3030 1 : check("void f(bool a, bool b) {\n"
3031 : " if (a && (a || b)) {}\n"
3032 : "}");
3033 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: a. 'a && (a || b)' is equivalent to 'a'\n", errout_str());
3034 : }
3035 :
3036 : // clarify conditions with bitwise operator and comparison
3037 1 : void clarifyCondition2() {
3038 1 : check("void f() {\n"
3039 : " if (x & 3 == 2) {}\n"
3040 : "}");
3041 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Suspicious condition (bitwise operator + comparison); Clarify expression with parentheses.\n"
3042 : "[test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n"
3043 : "[test.cpp:2]: (style) Condition 'x&3==2' is always false\n", errout_str());
3044 :
3045 1 : check("void f() {\n"
3046 : " if (a & fred1.x == fred2.y) {}\n"
3047 : "}");
3048 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Suspicious condition (bitwise operator + comparison); Clarify expression with parentheses.\n"
3049 : "[test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n"
3050 : , errout_str());
3051 : }
3052 :
3053 : // clarify condition that uses ! operator and then bitwise operator
3054 1 : void clarifyCondition3() {
3055 1 : check("void f(int w) {\n"
3056 : " if(!w & 0x8000) {}\n"
3057 : "}");
3058 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n", errout_str());
3059 :
3060 1 : check("void f(int w) {\n"
3061 : " if((!w) & 0x8000) {}\n"
3062 : "}");
3063 1 : ASSERT_EQUALS("", errout_str());
3064 :
3065 1 : check("void f() {\n"
3066 : " if (x == foo() & 2) {}\n"
3067 : "}");
3068 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n", errout_str());
3069 :
3070 1 : check("void f() {\n"
3071 : " if (2 & x == foo()) {}\n"
3072 : "}");
3073 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n", errout_str());
3074 :
3075 1 : check("void f() {\n"
3076 : " if (2 & (x == foo())) {}\n"
3077 : "}");
3078 1 : ASSERT_EQUALS("", errout_str());
3079 :
3080 1 : check("void f(std::list<int> &ints) { }");
3081 1 : ASSERT_EQUALS("", errout_str());
3082 :
3083 1 : check("void f() { A<x &> a; }");
3084 1 : ASSERT_EQUALS("", errout_str());
3085 :
3086 1 : check("void f() { a(x<y|z,0); }", "test.c"); // filename is c => there are never templates
3087 1 : ASSERT_EQUALS("[test.c:1]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses.\n", errout_str());
3088 :
3089 1 : check("class A<B&,C>;", "test.cpp");
3090 1 : ASSERT_EQUALS("", errout_str());
3091 :
3092 1 : check("void f() {\n"
3093 : " if (result != (char *)&inline_result) { }\n" // don't simplify and verify cast
3094 : "}");
3095 1 : ASSERT_EQUALS("", errout_str());
3096 :
3097 : // #8495
3098 1 : check("void f(bool a, bool b) {\n"
3099 : " C & a & b;\n"
3100 : "}");
3101 1 : ASSERT_EQUALS("", errout_str());
3102 : }
3103 :
3104 1 : void clarifyCondition4() { // ticket #3110
3105 1 : check("typedef double SomeType;\n"
3106 : "typedef std::pair<std::string,SomeType> PairType;\n"
3107 : "struct S\n"
3108 : "{\n"
3109 : " bool operator()\n"
3110 : " ( PairType const & left\n"
3111 : " , PairType const & right) const\n"
3112 : " {\n"
3113 : " return left.first < right.first;\n"
3114 : " }\n"
3115 : "}");
3116 1 : ASSERT_EQUALS("", errout_str());
3117 : }
3118 :
3119 1 : void clarifyCondition5() { // ticket #3609 (using | in template instantiation)
3120 1 : check("template<bool B> struct CWinTraits;\n"
3121 : "CWinTraits<WS_CHILD|WS_VISIBLE>::GetWndStyle(0);");
3122 1 : ASSERT_EQUALS("", errout_str());
3123 : }
3124 :
3125 1 : void clarifyCondition6() {
3126 1 : check("template<class Y>\n"
3127 : "SharedPtr& operator=( SharedPtr<Y> const & r ) {\n"
3128 : " px = r.px;\n"
3129 : " return *this;\n"
3130 : "}");
3131 1 : ASSERT_EQUALS("", errout_str());
3132 : }
3133 :
3134 1 : void clarifyCondition7() {
3135 : // Ensure that binary and unary &, and & in declarations are distinguished properly
3136 1 : check("void f(bool error) {\n"
3137 : " bool & withoutSideEffects=found.first->second;\n" // Declaring a reference to a boolean; & is no operator at all
3138 : " execute(secondExpression, &programMemory, &result, &error);\n" // Unary &
3139 : "}");
3140 1 : ASSERT_EQUALS("", errout_str());
3141 : }
3142 :
3143 1 : void clarifyCondition8() {
3144 : // don't warn when boolean result comes from function call, array index, etc
3145 : // the operator precedence is not unknown then
3146 1 : check("bool a();\n"
3147 : "bool f(bool b) {\n"
3148 : " return (a() & b);\n"
3149 : "}");
3150 1 : ASSERT_EQUALS("", errout_str());
3151 :
3152 1 : check("bool f(bool *a, bool b) {\n"
3153 : " return (a[10] & b);\n"
3154 : "}");
3155 1 : ASSERT_EQUALS("", errout_str());
3156 :
3157 1 : check("struct A { bool a; };\n"
3158 : "bool f(struct A a, bool b) {\n"
3159 : " return (a.a & b);\n"
3160 : "}");
3161 1 : ASSERT_EQUALS("", errout_str());
3162 :
3163 1 : check("struct A { bool a; };\n"
3164 : "bool f(struct A a, bool b) {\n"
3165 : " return (A::a & b);\n"
3166 : "}");
3167 1 : ASSERT_EQUALS("", errout_str());
3168 : }
3169 :
3170 1 : void testBug5895() {
3171 1 : check("void png_parse(uint64_t init, int buf_size) {\n"
3172 : " if (init == 0x89504e470d0a1a0a || init == 0x8a4d4e470d0a1a0a)\n"
3173 : " ;\n"
3174 : "}");
3175 1 : ASSERT_EQUALS("", errout_str());
3176 : }
3177 :
3178 1 : void testBug5309() {
3179 1 : check("extern uint64_t value;\n"
3180 : "void foo() {\n"
3181 : " if( ( value >= 0x7ff0000000000001ULL )\n"
3182 : " && ( value <= 0x7fffffffffffffffULL ) );\n"
3183 : "}");
3184 1 : ASSERT_EQUALS("", errout_str());
3185 : }
3186 :
3187 1 : void alwaysTrue() {
3188 :
3189 1 : check("void f(const struct S *s) {\n" //#8196
3190 : " int x1 = s->x;\n"
3191 : " int x2 = s->x;\n"
3192 : " if (x1 == 10 && x2 == 10) {}\n" // <<
3193 : "}");
3194 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:4]: (style) Condition 'x2==10' is always true\n", errout_str());
3195 :
3196 1 : check("void f ()\n"// #8220
3197 : "{\n"
3198 : " int a;\n"
3199 : " int b = 0;\n"
3200 : " int ret;\n"
3201 : " \n"
3202 : " a = rand();\n"
3203 : " while (((0 < a) && (a < 2)) && ((8 < a) && (a < 10))) \n"
3204 : " {\n"
3205 : " b += a;\n"
3206 : " a ++;\n"
3207 : " }\n"
3208 : " ret = b;\n"
3209 : "}");
3210 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:8]: (style) Condition '8<a' is always false\n", errout_str());
3211 :
3212 1 : check("void f() {\n" // #4842
3213 : " int x = 0;\n"
3214 : " if (a) { return; }\n" // <- this is just here to fool simplifyKnownVariabels
3215 : " if (!x) {}\n"
3216 : "}");
3217 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition '!x' is always true\n", errout_str());
3218 :
3219 1 : check("bool f(int x) {\n"
3220 : " if(x == 0) { x++; return x == 0; }\n"
3221 : " return false;\n"
3222 : "}");
3223 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Return value 'x==0' is always false\n", errout_str());
3224 :
3225 1 : check("void f() {\n" // #6898 (Token::expressionString)
3226 : " int x = 0;\n"
3227 : " A(x++ == 1);\n"
3228 : " A(x++ == 2);\n"
3229 : "}");
3230 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'x++==1' is always false\n"
3231 : "[test.cpp:4]: (style) Condition 'x++==2' is always false\n",
3232 : errout_str());
3233 :
3234 1 : check("bool foo(int bar) {\n"
3235 : " bool ret = false;\n"
3236 : " if (bar == 1)\n"
3237 : " return ret;\n" // <- #9326 - FP condition is always false
3238 : " if (bar == 2)\n"
3239 : " ret = true;\n"
3240 : " return ret;\n"
3241 : "}");
3242 1 : ASSERT_EQUALS("", errout_str());
3243 :
3244 1 : check("void f1(const std::string &s) { if(s.empty()) if(s.size() == 0) {}}");
3245 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Condition 's.size()==0' is always true\n", errout_str());
3246 :
3247 1 : check("void f() {\n"
3248 : " int buf[42];\n"
3249 : " if( buf != 0) {}\n"
3250 : "}");
3251 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'buf!=0' is always true\n", errout_str()); // #8924
3252 :
3253 1 : check("void f() {\n"
3254 : " int buf[42];\n"
3255 : " if( !buf ) {}\n"
3256 : "}");
3257 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!buf' is always false\n", errout_str());
3258 :
3259 1 : check("void f() {\n"
3260 : " int buf[42];\n"
3261 : " bool b = buf;\n"
3262 : " if( b ) {}\n"
3263 : "}");
3264 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'b' is always true\n", errout_str());
3265 :
3266 1 : check("void f() {\n"
3267 : " int buf[42];\n"
3268 : " bool b = buf;\n"
3269 : " if( !b ) {}\n"
3270 : "}");
3271 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition '!b' is always false\n", errout_str());
3272 :
3273 1 : check("void f() {\n"
3274 : " int buf[42];\n"
3275 : " int * p = nullptr;\n"
3276 : " if( buf == p ) {}\n"
3277 : "}");
3278 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'buf==p' is always false\n", errout_str());
3279 :
3280 1 : check("void f(bool x) {\n"
3281 : " int buf[42];\n"
3282 : " if( buf || x ) {}\n"
3283 : "}");
3284 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'buf' is always true\n", errout_str());
3285 :
3286 1 : check("void f(int * p) {\n"
3287 : " int buf[42];\n"
3288 : " if( buf == p ) {}\n"
3289 : "}");
3290 1 : ASSERT_EQUALS("", errout_str());
3291 :
3292 1 : check("void f() {\n"
3293 : " int buf[42];\n"
3294 : " int p[42];\n"
3295 : " if( buf == p ) {}\n"
3296 : "}");
3297 1 : ASSERT_EQUALS("", errout_str());
3298 :
3299 1 : check("void f() {\n"
3300 : " int buf[42];\n"
3301 : " if( buf == 1) {}\n"
3302 : "}");
3303 1 : ASSERT_EQUALS("", errout_str());
3304 :
3305 : // Avoid FP when condition comes from macro
3306 1 : check("#define NOT !\n"
3307 : "void f() {\n"
3308 : " int x = 0;\n"
3309 : " if (a) { return; }\n" // <- this is just here to fool simplifyKnownVariabels
3310 : " if (NOT x) {}\n"
3311 : "}");
3312 1 : ASSERT_EQUALS("", errout_str());
3313 :
3314 1 : check("#define M x != 0\n"
3315 : "void f() {\n"
3316 : " int x = 0;\n"
3317 : " if (a) { return; }\n" // <- this is just here to fool simplifyKnownVariabels
3318 : " if (M) {}\n"
3319 : "}");
3320 1 : ASSERT_EQUALS("", errout_str());
3321 :
3322 1 : check("#define IF(X) if (X && x())\n"
3323 : "void f() {\n"
3324 : " IF(1) {}\n"
3325 : "}");
3326 1 : ASSERT_EQUALS("", errout_str());
3327 :
3328 : // Avoid FP for sizeof condition
3329 1 : check("void f() {\n"
3330 : " if (sizeof(char) != 123) {}\n"
3331 : " if (123 != sizeof(char)) {}\n"
3332 : "}");
3333 1 : ASSERT_EQUALS("", errout_str());
3334 :
3335 1 : check("void f() {\n"
3336 : " int x = 123;\n"
3337 : " if (sizeof(char) != x) {}\n"
3338 : " if (x != sizeof(char)) {}\n"
3339 : "}");
3340 1 : TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'sizeof(char)!=x' is always true\n"
3341 : "[test.cpp:4]: (style) Condition 'x!=sizeof(char)' is always true\n", "", errout_str());
3342 :
3343 : // Don't warn in assertions. Condition is often 'always true' by intention.
3344 : // If platform,defines,etc cause an 'always false' assertion then that is not very dangerous neither
3345 1 : check("void f() {\n"
3346 : " int x = 0;\n"
3347 : " assert(x == 0);\n"
3348 : "}");
3349 1 : ASSERT_EQUALS("", errout_str());
3350 :
3351 : // #9363 - do not warn about value passed to function
3352 1 : check("void f(bool b) {\n"
3353 : " if (b) {\n"
3354 : " if (bar(!b)) {}\n"
3355 : " }\n"
3356 : "}");
3357 1 : ASSERT_EQUALS("", errout_str());
3358 :
3359 :
3360 : // #7783 FP knownConditionTrueFalse on assert(0 && "message")
3361 1 : check("void foo(int x) {\n"
3362 : " if (x<0)\n"
3363 : " {\n"
3364 : " assert(0 && \"bla\");\n"
3365 : " ASSERT(0 && \"bla\");\n"
3366 : " assert_foo(0 && \"bla\");\n"
3367 : " ASSERT_FOO(0 && \"bla\");\n"
3368 : " assert((int)(0==0));\n"
3369 : " assert((int)(0==0) && \"bla\");\n"
3370 : " }\n"
3371 : "}");
3372 1 : ASSERT_EQUALS("", errout_str());
3373 :
3374 : // #7750 char literals in boolean expressions
3375 1 : check("void f() {\n"
3376 : " if('a'){}\n"
3377 : " if(L'b'){}\n"
3378 : " if(1 && 'c'){}\n"
3379 : " int x = 'd' ? 1 : 2;\n"
3380 : "}");
3381 1 : ASSERT_EQUALS("", errout_str());
3382 :
3383 : // #8206 - knownCondition always false
3384 1 : check("void f(int i)\n"
3385 : "{\n"
3386 : " if(i > 4)\n"
3387 : " for( int x = 0; i < 3; ++x){}\n" // <<
3388 : "}");
3389 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Condition 'i<3' is always false\n", errout_str());
3390 :
3391 : // Skip literals
3392 1 : check("void f() { if(true) {} }");
3393 1 : ASSERT_EQUALS("", errout_str());
3394 :
3395 1 : check("void f() { if(false) {} }");
3396 1 : ASSERT_EQUALS("", errout_str());
3397 :
3398 1 : check("void f() { if(!true) {} }");
3399 1 : ASSERT_EQUALS("", errout_str());
3400 :
3401 1 : check("void f() { if(!false) {} }");
3402 1 : ASSERT_EQUALS("", errout_str());
3403 :
3404 1 : check("void f() { if(0) {} }");
3405 1 : ASSERT_EQUALS("", errout_str());
3406 :
3407 1 : check("void f() { if(1) {} }");
3408 1 : ASSERT_EQUALS("", errout_str());
3409 :
3410 1 : check("void f(int i) {\n"
3411 : " bool b = false;\n"
3412 : " if (i == 0) b = true;\n"
3413 : " else if (!b && i == 1) {}\n"
3414 : " if (b)\n"
3415 : " {}\n"
3416 : "}");
3417 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition '!b' is always true\n", errout_str());
3418 :
3419 1 : check("bool f() { return nullptr; }");
3420 1 : ASSERT_EQUALS("", errout_str());
3421 :
3422 1 : check("enum E { A };\n"
3423 : "bool f() { return A; }");
3424 1 : ASSERT_EQUALS("", errout_str());
3425 :
3426 1 : check("bool f() {\n"
3427 : " const int x = 0;\n"
3428 : " return x;\n"
3429 : "}");
3430 1 : ASSERT_EQUALS("", errout_str());
3431 :
3432 1 : check("int f(void){return 1/abs(10);}");
3433 1 : ASSERT_EQUALS("", errout_str());
3434 :
3435 1 : check("bool f() {\n"
3436 : " int x = 0;\n"
3437 : " return x;\n"
3438 : "}");
3439 1 : ASSERT_EQUALS("", errout_str());
3440 :
3441 1 : check("bool f() {\n"
3442 : " const int a = 50;\n"
3443 : " const int b = 52;\n"
3444 : " return a+b;\n"
3445 : "}");
3446 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Return value 'a+b' is always true\n", errout_str());
3447 :
3448 1 : check("int f() {\n"
3449 : " int a = 50;\n"
3450 : " int b = 52;\n"
3451 : " a++;\n"
3452 : " b++;\n"
3453 : " return a+b;\n"
3454 : "}");
3455 1 : ASSERT_EQUALS("", errout_str());
3456 :
3457 1 : check("bool& g();\n"
3458 : "bool f() {\n"
3459 : " bool & b = g();\n"
3460 : " b = false;\n"
3461 : " return b;\n"
3462 : "}");
3463 1 : ASSERT_EQUALS("", errout_str());
3464 :
3465 1 : check("struct A {\n"
3466 : " bool b;\n"
3467 : " bool f() {\n"
3468 : " b = false;\n"
3469 : " return b;\n"
3470 : " }\n"
3471 : "};");
3472 1 : ASSERT_EQUALS("", errout_str());
3473 :
3474 1 : check("bool f(long maxtime) {\n"
3475 : " if (std::time(0) > maxtime)\n"
3476 : " return std::time(0) > maxtime;\n"
3477 : "}");
3478 1 : ASSERT_EQUALS("", errout_str());
3479 :
3480 1 : check("void foo(double param) {\n"
3481 : " while(bar()) {\n"
3482 : " if (param<0.)\n"
3483 : " return;\n"
3484 : " }\n"
3485 : " if (param<0.)\n"
3486 : " return;\n"
3487 : "}");
3488 1 : ASSERT_EQUALS("", errout_str());
3489 :
3490 1 : check("void foo(int i) {\n"
3491 : " if (i==42)\n"
3492 : " {\n"
3493 : " bar();\n"
3494 : " }\n"
3495 : " if (cond && (42==i))\n"
3496 : " return;\n"
3497 : "}");
3498 1 : ASSERT_EQUALS("", errout_str());
3499 :
3500 : // 8842 crash
3501 1 : check("class a {\n"
3502 : " int b;\n"
3503 : " c(b);\n"
3504 : " void f() {\n"
3505 : " if (b) return;\n"
3506 : " }\n"
3507 : "};");
3508 1 : ASSERT_EQUALS("", errout_str());
3509 :
3510 1 : check("void f(const char* x, const char* t) {\n"
3511 : " if (!(strcmp(x, y) == 0)) { return; }\n"
3512 : "}");
3513 1 : ASSERT_EQUALS("", errout_str());
3514 :
3515 1 : check("void f(const int a[]){ if (a == 0){} }");
3516 1 : ASSERT_EQUALS("", errout_str());
3517 :
3518 1 : check("struct S {\n"
3519 : " bool operator<(const S&);\n"
3520 : "};\n"
3521 : "int main() {\n"
3522 : " S s;\n"
3523 : " bool c = s<s;\n"
3524 : " if (c) return 0;\n"
3525 : " else return 42;\n"
3526 : "}");
3527 1 : ASSERT_EQUALS("", errout_str());
3528 :
3529 1 : check("long X::g(bool unknown, int& result) {\n"
3530 : " long ret = 0;\n"
3531 : " bool f = false;\n"
3532 : " f = f || unknown;\n"
3533 : " f ? result = 42 : ret = -1;\n"
3534 : " return ret;\n"
3535 : "}");
3536 1 : ASSERT_EQUALS("", errout_str());
3537 :
3538 1 : check("int f(void *handle) {\n"
3539 : " if (!handle) return 0;\n"
3540 : " if (handle) return 1;\n"
3541 : " else return 0;\n"
3542 : "}");
3543 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Condition 'handle' is always true\n", errout_str());
3544 :
3545 1 : check("int f(void *handle) {\n"
3546 : " if (handle == 0) return 0;\n"
3547 : " if (handle) return 1;\n"
3548 : " else return 0;\n"
3549 : "}");
3550 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'handle' is always true\n", errout_str());
3551 :
3552 1 : check("int f(void *handle) {\n"
3553 : " if (handle != 0) return 0;\n"
3554 : " if (handle) return 1;\n"
3555 : " else return 0;\n"
3556 : "}");
3557 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'handle!=0', second condition is always false\n", errout_str());
3558 :
3559 1 : check("int f(void *handle) {\n"
3560 : " if (handle != nullptr) return 0;\n"
3561 : " if (handle) return 1;\n"
3562 : " else return 0;\n"
3563 : "}");
3564 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'handle!=nullptr', second condition is always false\n", errout_str());
3565 :
3566 1 : check("void f(void* x, void* y) {\n"
3567 : " if (x == nullptr && y == nullptr)\n"
3568 : " return;\n"
3569 : " if (x == nullptr || y == nullptr)\n"
3570 : " return;\n"
3571 : "}");
3572 1 : ASSERT_EQUALS("", errout_str());
3573 :
3574 1 : check("void* g();\n"
3575 : "void f(void* a, void* b) {\n"
3576 : " while (a) {\n"
3577 : " a = g();\n"
3578 : " if (a == b)\n"
3579 : " break;\n"
3580 : " }\n"
3581 : " if (a) {}\n"
3582 : "}");
3583 1 : ASSERT_EQUALS("", errout_str());
3584 :
3585 1 : check("void* g();\n"
3586 : "void f(void* a, void* b) {\n"
3587 : " while (a) {\n"
3588 : " a = g();\n"
3589 : " }\n"
3590 : " if (a) {}\n"
3591 : "}");
3592 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'a' is always false\n", errout_str());
3593 :
3594 1 : check("void f(int * x, bool b) {\n"
3595 : " if (!x && b) {}\n"
3596 : " else if (x) {}\n"
3597 : "}");
3598 1 : ASSERT_EQUALS("", errout_str());
3599 :
3600 1 : check("void f() {\n"
3601 : " const std::string x=\"xyz\";\n"
3602 : " if(!x.empty()){}\n"
3603 : "}");
3604 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!x.empty()' is always true\n", errout_str());
3605 :
3606 1 : check("std::string g();\n"
3607 : "void f() {\n"
3608 : " const std::string msg = g();\n"
3609 : " if(!msg.empty()){}\n"
3610 : "}");
3611 1 : ASSERT_EQUALS("", errout_str());
3612 :
3613 1 : check("void f(int *array, int size ) {\n"
3614 : " for(int i = 0; i < size; ++i) {\n"
3615 : " if(array == 0)\n"
3616 : " continue;\n"
3617 : " if(array){}\n"
3618 : " }\n"
3619 : "}");
3620 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'array' is always true\n", errout_str());
3621 :
3622 1 : check("void f(int *array, int size ) {\n"
3623 : " for(int i = 0; i < size; ++i) {\n"
3624 : " if(array == 0)\n"
3625 : " continue;\n"
3626 : " else if(array){}\n"
3627 : " }\n"
3628 : "}");
3629 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'array' is always true\n", errout_str());
3630 :
3631 : // #9277
3632 1 : check("int f() {\n"
3633 : " constexpr bool x = true;\n"
3634 : " if constexpr (x)\n"
3635 : " return 0;\n"
3636 : " else\n"
3637 : " return 1;\n"
3638 : "}");
3639 1 : ASSERT_EQUALS("", errout_str());
3640 :
3641 : // #9954
3642 1 : check("void f() {\n"
3643 : " const size_t a(8 * sizeof(short));\n"
3644 : " const size_t b(8 * sizeof(int));\n"
3645 : " if constexpr (a == 16 && b == 16) {}\n"
3646 : " else if constexpr (a == 16 && b == 32) {}\n"
3647 : "}\n");
3648 1 : ASSERT_EQUALS("", errout_str());
3649 :
3650 : // #9319
3651 1 : check("struct S {\n"
3652 : " int a;\n"
3653 : " int b;\n"
3654 : "};\n"
3655 : "void g(S s, bool& x);\n"
3656 : "void f() {\n"
3657 : " bool x = false;\n"
3658 : " g({0, 1}, x);\n"
3659 : " if (x) {}\n"
3660 : "}");
3661 1 : ASSERT_EQUALS("", errout_str());
3662 :
3663 : // #9318
3664 1 : check("class A {};\n"
3665 : "class B : public A {};\n"
3666 : "void f(A* x) {\n"
3667 : " if (!x)\n"
3668 : " return;\n"
3669 : " auto b = dynamic_cast<B*>(x);\n"
3670 : " if (b) {}\n"
3671 : "}");
3672 1 : ASSERT_EQUALS("", errout_str());
3673 :
3674 1 : check("int foo() {\n"
3675 : " auto x = getX();\n"
3676 : " if (x == nullptr)\n"
3677 : " return 1;\n"
3678 : " auto y = dynamic_cast<Y*>(x)\n"
3679 : " if (y == nullptr)\n"
3680 : " return 2;\n"
3681 : " return 3;\n"
3682 : "}\n");
3683 1 : ASSERT_EQUALS("", errout_str());
3684 :
3685 : // handleKnownValuesInLoop
3686 1 : check("bool g();\n"
3687 : "void f(bool x) {\n"
3688 : " if (x) while(x) x = g();\n"
3689 : "}");
3690 1 : ASSERT_EQUALS("", errout_str());
3691 :
3692 : // isLikelyStream
3693 1 : check("void f(std::istringstream& iss) {\n"
3694 : " std::string x;\n"
3695 : " while (iss) {\n"
3696 : " iss >> x;\n"
3697 : " if (!iss) break;\n"
3698 : " }\n"
3699 : "}");
3700 1 : ASSERT_EQUALS("", errout_str());
3701 :
3702 : // #9332
3703 1 : check("struct A { void* g(); };\n"
3704 : "void f() {\n"
3705 : " A a;\n"
3706 : " void* b = a.g();\n"
3707 : " if (!b) return;\n"
3708 : " void* c = a.g();\n"
3709 : " if (!c) return;\n"
3710 : " bool compare = c == b;\n"
3711 : "}");
3712 1 : ASSERT_EQUALS("", errout_str());
3713 :
3714 : // #9361
3715 1 : check("void f(char c) {\n"
3716 : " if (c == '.') {}\n"
3717 : " else if (isdigit(c) != 0) {}\n"
3718 : "}");
3719 1 : ASSERT_EQUALS("", errout_str());
3720 :
3721 : // #9351
3722 1 : check("int f(int x) {\n"
3723 : " const bool b = x < 42;\n"
3724 : " if(b) return b?0:-1;\n"
3725 : " return 42;\n"
3726 : "}");
3727 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (style) Condition 'b' is always true\n", errout_str());
3728 :
3729 : // #9362
3730 1 : check("uint8_t g();\n"
3731 : "void f() {\n"
3732 : " const uint8_t v = g();\n"
3733 : " if((v != 0x00)) {\n"
3734 : " if( (v & 0x01) == 0x00) {}\n"
3735 : " }\n"
3736 : "}");
3737 1 : ASSERT_EQUALS("", errout_str());
3738 :
3739 : // #9367
3740 1 : check("void f(long x) {\n"
3741 : " if (x <= 0L)\n"
3742 : " return;\n"
3743 : " if (x % 360L == 0)\n"
3744 : " return;\n"
3745 : "}");
3746 1 : ASSERT_EQUALS("", errout_str());
3747 :
3748 1 : check("int f(int a, int b) {\n"
3749 : " static const int x = 10;\n"
3750 : " return x == 1 ? a : b;\n"
3751 : "}");
3752 1 : ASSERT_EQUALS("", errout_str());
3753 :
3754 1 : check("const bool x = false;\n"
3755 : "void f() {\n"
3756 : " if (x) {}\n"
3757 : "}");
3758 1 : ASSERT_EQUALS("", errout_str());
3759 :
3760 1 : check("const bool x = false;\n"
3761 : "void f() {\n"
3762 : " if (!x) {}\n"
3763 : "}");
3764 1 : ASSERT_EQUALS("", errout_str());
3765 :
3766 : // #9709
3767 1 : check("void f(int a) {\n"
3768 : " bool ok = false;\n"
3769 : " const char * r = nullptr;\n"
3770 : " do_something(&r);\n"
3771 : " if (r != nullptr)\n"
3772 : " ok = a != 0;\n"
3773 : " if (ok) {}\n"
3774 : "}");
3775 1 : ASSERT_EQUALS("", errout_str());
3776 :
3777 : // #9816
3778 1 : check("bool g();\n"
3779 : "void f() {\n"
3780 : " bool b = false;\n"
3781 : " do {\n"
3782 : " do {\n"
3783 : " if (g())\n"
3784 : " break;\n"
3785 : " b = true;\n"
3786 : " } while(false);\n"
3787 : " } while(!b);\n"
3788 : "}\n");
3789 1 : ASSERT_EQUALS("", errout_str());
3790 :
3791 : // #9865
3792 1 : check("void f(const std::string &s) {\n"
3793 : " for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {\n"
3794 : " const unsigned char c = static_cast<unsigned char>(*it);\n"
3795 : " if (c == '0') {}\n"
3796 : " else if ((c == 'a' || c == 'A')\n"
3797 : " || (c == 'b' || c == 'B')) {}\n"
3798 : " else {}\n"
3799 : " }\n"
3800 : "}\n");
3801 1 : ASSERT_EQUALS("", errout_str());
3802 :
3803 : // #9711
3804 1 : check("int main(int argc, char* argv[]) {\n"
3805 : " int foo = 0;\n"
3806 : " struct option options[] = {\n"
3807 : " {\"foo\", no_argument, &foo, \'f\'},\n"
3808 : " {NULL, 0, NULL, 0},\n"
3809 : " };\n"
3810 : " getopt_long(argc, argv, \"f\", options, NULL);\n"
3811 : " if (foo) {}\n"
3812 : "}\n");
3813 1 : ASSERT_EQUALS("", errout_str());
3814 :
3815 : // TODO: if (!v) is a known condition as well
3816 1 : check("struct a {\n"
3817 : " int *b();\n"
3818 : "};\n"
3819 : "bool g(a c, a* d) {\n"
3820 : " a *v, *e = v = &c;\n"
3821 : " if (!v)\n"
3822 : " return true;\n"
3823 : " int *f = v->b();\n"
3824 : " if (f)\n"
3825 : " v = nullptr;\n"
3826 : " if (v == nullptr && e) {}\n"
3827 : " return d;\n"
3828 : "}\n");
3829 1 : ASSERT_EQUALS("[test.cpp:11]: (style) Condition 'e' is always true\n", errout_str());
3830 :
3831 : // #10037
3832 1 : check("struct a {\n"
3833 : " int* p;\n"
3834 : "};\n"
3835 : "void g(a*);\n"
3836 : "void f() {\n"
3837 : " struct a b;\n"
3838 : " uint32_t p = (uint32_t) -1;\n"
3839 : " b.p = (void *) &p;\n"
3840 : " int r = g(&b);\n"
3841 : " if (r == 0)\n"
3842 : " if (p != (uint32_t) -1) {}\n"
3843 : "}\n");
3844 1 : ASSERT_EQUALS("", errout_str());
3845 :
3846 : // #9890
3847 1 : check("int g(int);\n"
3848 : "bool h(int*);\n"
3849 : "int f(int *x) {\n"
3850 : " int y = g(0);\n"
3851 : " if (!y) {\n"
3852 : " if (h(x)) {\n"
3853 : " y = g(1);\n"
3854 : " if (y) {}\n"
3855 : " return 0;\n"
3856 : " }\n"
3857 : " if (!y) {}\n"
3858 : " }\n"
3859 : " return 0;\n"
3860 : "}\n");
3861 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:11]: (style) Condition '!y' is always true\n", errout_str());
3862 :
3863 : // #10134
3864 1 : check("bool foo(bool b);\n"
3865 : "bool thud(const std::vector<std::wstring>& Arr, const std::wstring& Str) {\n"
3866 : " if (Arr.empty() && Str.empty())\n"
3867 : " return false;\n"
3868 : " bool OldFormat = Arr.empty() && !Str.empty();\n"
3869 : " if (OldFormat)\n"
3870 : " return foo(OldFormat);\n"
3871 : " return false;\n"
3872 : "}\n");
3873 1 : ASSERT_EQUALS("", errout_str());
3874 :
3875 : // #10208
3876 1 : check("bool GetFirst(std::string &first);\n"
3877 : "bool GetNext(std::string &next);\n"
3878 : "void g(const std::string& name);\n"
3879 : "void f() {\n"
3880 : " for (std::string name; name.empty() ? GetFirst(name) : GetNext(name);)\n"
3881 : " g(name);\n"
3882 : "}\n");
3883 1 : ASSERT_EQUALS("", errout_str());
3884 :
3885 1 : check("bool GetFirst(std::string &first);\n"
3886 : "bool GetNext(std::string &next);\n"
3887 : "void g(const std::string& name);\n"
3888 : "void f() {\n"
3889 : " for (std::string name{}; name.empty() ? GetFirst(name) : GetNext(name);)\n"
3890 : " g(name);\n"
3891 : "}\n");
3892 1 : ASSERT_EQUALS("", errout_str());
3893 :
3894 1 : check("bool GetFirst(std::string &first);\n"
3895 : "bool GetNext(std::string &next);\n"
3896 : "void g(const std::string& name);\n"
3897 : "void f() {\n"
3898 : " for (std::string name{'a', 'b'}; name.empty() ? GetFirst(name) : GetNext(name);)\n"
3899 : " g(name);\n"
3900 : "}\n");
3901 1 : ASSERT_EQUALS("", errout_str());
3902 :
3903 1 : check("bool GetFirst(const std::string &first);\n"
3904 : "bool GetNext(const std::string &next);\n"
3905 : "void g(const std::string& name);\n"
3906 : "void f() {\n"
3907 : " for (std::string name; name.empty() ? GetFirst(name) : GetNext(name);)\n"
3908 : " g(name);\n"
3909 : "}\n");
3910 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'name.empty()' is always true\n", errout_str());
3911 :
3912 : // #10278
3913 1 : check("void foo(unsigned int x) {\n"
3914 : " if ((100 - x) > 0) {}\n"
3915 : "}\n");
3916 1 : ASSERT_EQUALS("", errout_str());
3917 :
3918 : // #10298
3919 1 : check("void foo(unsigned int x) {\n"
3920 : " if (x == -1) {}\n"
3921 : "}\n");
3922 1 : ASSERT_EQUALS("", errout_str());
3923 :
3924 : // #10121
3925 1 : check("struct AB {\n"
3926 : " int a;\n"
3927 : "};\n"
3928 : "struct ABC {\n"
3929 : " AB* ab;\n"
3930 : "};\n"
3931 : "void g(ABC*);\n"
3932 : "int f(struct ABC *abc) {\n"
3933 : " int err = 0;\n"
3934 : " AB *ab = abc->ab;\n"
3935 : " if (ab->a == 123){\n"
3936 : " g(abc);\n"
3937 : " if (ab->a != 123) {\n"
3938 : " err = 1;\n"
3939 : " }\n"
3940 : " }\n"
3941 : " return err;\n"
3942 : "}\n");
3943 1 : ASSERT_EQUALS("", errout_str());
3944 :
3945 : // #10323
3946 1 : check("void foo(int x) {\n"
3947 : " if(x)\n"
3948 : " if(x == 1) {}\n"
3949 : "}\n");
3950 1 : ASSERT_EQUALS("", errout_str());
3951 :
3952 1 : check("void foo(int x) {\n"
3953 : " if(x) {}\n"
3954 : " else\n"
3955 : " if(x == 1) {}\n"
3956 : "}\n");
3957 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==1' is always false\n", errout_str());
3958 :
3959 : // do not report both unsignedLessThanZero and knownConditionTrueFalse
3960 1 : check("void foo(unsigned int max) {\n"
3961 : " unsigned int num = max - 1;\n"
3962 : " if (num < 0) {}\n" // <- do not report knownConditionTrueFalse
3963 : "}");
3964 1 : ASSERT_EQUALS("", errout_str());
3965 :
3966 : // #10297
3967 1 : check("void foo(size_t len, int start) {\n"
3968 : " if (start < 0) {\n"
3969 : " start = len+start;\n"
3970 : " if (start < 0) {}\n"
3971 : " }\n"
3972 : "}\n");
3973 1 : ASSERT_EQUALS("", errout_str());
3974 :
3975 : // #10362
3976 1 : check("int tok;\n"
3977 : "void next();\n"
3978 : "void parse_attribute() {\n"
3979 : " if (tok == '(') {\n"
3980 : " int parenthesis = 0;\n"
3981 : " do {\n"
3982 : " if (tok == '(')\n"
3983 : " parenthesis++;\n"
3984 : " else if (tok == ')')\n"
3985 : " parenthesis--;\n"
3986 : " next();\n"
3987 : " } while (parenthesis && tok != -1);\n"
3988 : " }\n"
3989 : "}\n");
3990 1 : ASSERT_EQUALS("", errout_str());
3991 :
3992 : // #7843
3993 1 : check("void f(int i) {\n"
3994 : " if(abs(i) == -1) {}\n"
3995 : "}\n");
3996 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'abs(i)==-1' is always false\n", errout_str());
3997 :
3998 : // #7844
3999 1 : check("void f(int i) {\n"
4000 : " if(i > 0 && abs(i) == i) {}\n"
4001 : "}\n");
4002 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'abs(i)==i' is always true\n", errout_str());
4003 :
4004 1 : check("void f(int i) {\n"
4005 : " if(i < 0 && abs(i) == i) {}\n"
4006 : "}\n");
4007 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'abs(i)==i' is always false\n", errout_str());
4008 :
4009 1 : check("void f(int i) {\n"
4010 : " if(i > -3 && abs(i) == i) {}\n"
4011 : "}\n");
4012 1 : ASSERT_EQUALS("", errout_str());
4013 :
4014 : // #9948
4015 1 : check("bool f(bool a, bool b) {\n"
4016 : " return a || ! b || ! a;\n"
4017 : "}\n");
4018 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Return value '!a' is always true\n", errout_str());
4019 :
4020 : // #10148
4021 1 : check("void f(int i) {\n"
4022 : " if (i >= 64) {}\n"
4023 : " else if (i >= 32) {\n"
4024 : " i &= 31;\n"
4025 : " if (i == 0) {}\n"
4026 : " else {}\n"
4027 : " }\n"
4028 : "}\n");
4029 1 : ASSERT_EQUALS("", errout_str());
4030 :
4031 : // #10548
4032 1 : check("void f() {\n"
4033 : " int i = 0;\n"
4034 : " do {} while (i++ == 0);\n"
4035 : "}\n");
4036 1 : ASSERT_EQUALS("", errout_str());
4037 :
4038 : // #10582
4039 1 : check("static void fun(message_t *message) {\n"
4040 : " if (message->length >= 1) {\n"
4041 : " switch (data[0]) {}\n"
4042 : " }\n"
4043 : " uint8_t d0 = message->length > 0 ? data[0] : 0xff;\n"
4044 : "}\n");
4045 1 : ASSERT_EQUALS("", errout_str());
4046 :
4047 : // #8266
4048 1 : check("void f(bool b) {\n"
4049 : " if (b)\n"
4050 : " return;\n"
4051 : " if (g(&b) || b)\n"
4052 : " return;\n"
4053 : "}\n");
4054 1 : ASSERT_EQUALS("", errout_str());
4055 :
4056 : // #9720
4057 1 : check("bool bar(int &);\n"
4058 : "void f(int a, int b) {\n"
4059 : " if (a + b == 3)\n"
4060 : " return;\n"
4061 : " if (bar(a) && (a + b == 3)) {}\n"
4062 : "}\n");
4063 1 : ASSERT_EQUALS("", errout_str());
4064 :
4065 : // #10437
4066 1 : check("void f() {\n"
4067 : " Obj* PObj = nullptr;\n"
4068 : " bool b = false;\n"
4069 : " if (GetObj(PObj) && PObj != nullptr)\n"
4070 : " b = true;\n"
4071 : " if (b) {}\n"
4072 : "}\n");
4073 1 : ASSERT_EQUALS("", errout_str());
4074 :
4075 : // #10223
4076 1 : check("static volatile sig_atomic_t is_running;\n"
4077 : "static void handler(int signum) {\n"
4078 : " is_running = 0;\n"
4079 : "}\n"
4080 : "void f() {\n"
4081 : " signal(SIGINT, &handler);\n"
4082 : " is_running = 1;\n"
4083 : " while (is_running) {}\n"
4084 : "}\n");
4085 1 : ASSERT_EQUALS("", errout_str());
4086 :
4087 : // #10659
4088 1 : check("auto func(const std::tuple<int, int>& t) {\n"
4089 : " auto& [foo, bar] = t;\n"
4090 : " std::cout << foo << bar << std::endl;\n"
4091 : " return foo < bar;\n"
4092 : "}\n");
4093 1 : ASSERT_EQUALS("", errout_str());
4094 :
4095 : // #10484
4096 1 : check("void f() {\n"
4097 : " static bool init = true;\n"
4098 : " if (init)\n"
4099 : " init = false;\n"
4100 : "}\n");
4101 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'.\n", errout_str());
4102 :
4103 1 : check("void f() {\n"
4104 : " static bool init(true);\n"
4105 : " if (init)\n"
4106 : " init = false;\n"
4107 : "}\n");
4108 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'.\n", errout_str());
4109 :
4110 1 : check("void f() {\n"
4111 : " static bool init{ true };\n"
4112 : " if (init)\n"
4113 : " init = false;\n"
4114 : "}\n");
4115 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'.\n", errout_str());
4116 :
4117 : // #10248
4118 1 : check("void f() {\n"
4119 : " static int var(1);\n"
4120 : " if (var == 1) {}\n"
4121 : "}\n");
4122 1 : ASSERT_EQUALS("", errout_str());
4123 :
4124 1 : check("void f() {\n"
4125 : " static int var{ 1 };\n"
4126 : " if (var == 1) {}\n"
4127 : "}\n");
4128 1 : ASSERT_EQUALS("", errout_str());
4129 :
4130 1 : check("void Fun();\n"
4131 : "using Fn = void (*)();\n"
4132 : "void f() {\n"
4133 : " static Fn logger = nullptr;\n"
4134 : " if (logger == nullptr)\n"
4135 : " logger = Fun;\n"
4136 : "}\n");
4137 1 : ASSERT_EQUALS("", errout_str());
4138 :
4139 1 : check("void Fun();\n"
4140 : "using Fn = void (*)();\n"
4141 : "void f() {\n"
4142 : " static Fn logger(nullptr);\n"
4143 : " if (logger == nullptr)\n"
4144 : " logger = Fun;\n"
4145 : "}\n");
4146 1 : ASSERT_EQUALS("", errout_str());
4147 :
4148 1 : check("void Fun();\n"
4149 : "using Fn = void (*)();\n"
4150 : "void f() {\n"
4151 : " static Fn logger{ nullptr };\n"
4152 : " if (logger == nullptr)\n"
4153 : " logger = Fun;\n"
4154 : "}\n");
4155 1 : ASSERT_EQUALS("", errout_str());
4156 :
4157 1 : check("void Fun();\n"
4158 : "typedef void (*Fn)();\n"
4159 : "void f() {\n"
4160 : " static Fn logger = nullptr;\n"
4161 : " if (logger == nullptr)\n"
4162 : " logger = Fun;\n"
4163 : "}\n");
4164 1 : ASSERT_EQUALS("", errout_str());
4165 :
4166 1 : check("void Fun();\n"
4167 : "typedef void (*Fn)();\n"
4168 : "void f() {\n"
4169 : " static Fn logger(nullptr);\n"
4170 : " if (logger == nullptr)\n"
4171 : " logger = Fun;\n"
4172 : "}\n");
4173 1 : ASSERT_EQUALS("", errout_str());
4174 :
4175 1 : check("void Fun();\n"
4176 : "typedef void (*Fn)();\n"
4177 : "void f() {\n"
4178 : " static Fn logger{ nullptr };\n"
4179 : " if (logger == nullptr)\n"
4180 : " logger = Fun;\n"
4181 : "}\n");
4182 1 : ASSERT_EQUALS("", errout_str());
4183 :
4184 : // #9256
4185 1 : check("bool f() {\n"
4186 : " bool b = false;\n"
4187 : " b = true;\n"
4188 : " return b;\n"
4189 : "}\n");
4190 1 : ASSERT_EQUALS("", errout_str());
4191 :
4192 : // #10702
4193 1 : check("struct Object {\n"
4194 : " int _count=0;\n"
4195 : " void increment() { ++_count;}\n"
4196 : " auto get() const { return _count; }\n"
4197 : "};\n"
4198 : "struct Modifier {\n"
4199 : "Object & _object;\n"
4200 : " explicit Modifier(Object & object) : _object(object) {}\n"
4201 : " void do_something() { _object.increment(); }\n"
4202 : "};\n"
4203 : "struct Foo {\n"
4204 : " Object _object;\n"
4205 : " void foo() {\n"
4206 : " Modifier mod(_object);\n"
4207 : " if (_object.get()>0)\n"
4208 : " return;\n"
4209 : " mod.do_something();\n"
4210 : " if (_object.get()>0)\n"
4211 : " return;\n"
4212 : " }\n"
4213 : "};\n");
4214 1 : ASSERT_EQUALS("", errout_str());
4215 :
4216 1 : check("struct Object {\n"
4217 : " int _count=0;\n"
4218 : " auto get() const;\n"
4219 : "};\n"
4220 : "struct Modifier {\n"
4221 : "Object & _object;\n"
4222 : " explicit Modifier(Object & object);\n"
4223 : " void do_something();\n"
4224 : "};\n"
4225 : "struct Foo {\n"
4226 : " Object _object;\n"
4227 : " void foo() {\n"
4228 : " Modifier mod(_object);\n"
4229 : " if (_object.get()>0)\n"
4230 : " return;\n"
4231 : " mod.do_something();\n"
4232 : " if (_object.get()>0)\n"
4233 : " return;\n"
4234 : " }\n"
4235 : "};\n");
4236 1 : ASSERT_EQUALS("", errout_str());
4237 :
4238 1 : check("void f(const uint32_t u) {\n"
4239 : " const uint32_t v = u < 4;\n"
4240 : " if (v) {\n"
4241 : " const uint32_t w = v < 2;\n"
4242 : " if (w) {}\n"
4243 : " }\n"
4244 : "}\n");
4245 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'v<2' is always true\n"
4246 : "[test.cpp:5]: (style) Condition 'w' is always true\n",
4247 : errout_str());
4248 :
4249 1 : check("void f(double d) {\n" // #10792
4250 : " if (d != 0) {\n"
4251 : " int i = (int)d;\n"
4252 : " if (i == 0) {}\n"
4253 : " }\n"
4254 : "}\n");
4255 1 : ASSERT_EQUALS("", errout_str());
4256 :
4257 1 : check("void f(double d) {\n"
4258 : " if (0 != d) {\n"
4259 : " int i = (int)d;\n"
4260 : " if (i == 0) {}\n"
4261 : " }\n"
4262 : "}\n");
4263 1 : ASSERT_EQUALS("", errout_str());
4264 :
4265 1 : check("struct A { double d; }\n"
4266 : "void f(A a) {\n"
4267 : " if (a.d != 0) {\n"
4268 : " int i = a.d;\n"
4269 : " if (i == 0) {}\n"
4270 : " }\n"
4271 : "}\n");
4272 1 : ASSERT_EQUALS("", errout_str());
4273 :
4274 1 : check("void f() {\n"
4275 : " if(strlen(\"abc\") == 3) {;}\n"
4276 : " if(strlen(\"abc\") == 1) {;}\n"
4277 : " if(wcslen(L\"abc\") == 3) {;}\n"
4278 : " if(wcslen(L\"abc\") == 1) {;}\n"
4279 : "}\n");
4280 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'strlen(\"abc\")==3' is always true\n"
4281 : "[test.cpp:3]: (style) Condition 'strlen(\"abc\")==1' is always false\n"
4282 : "[test.cpp:4]: (style) Condition 'wcslen(L\"abc\")==3' is always true\n"
4283 : "[test.cpp:5]: (style) Condition 'wcslen(L\"abc\")==1' is always false\n",
4284 : errout_str());
4285 :
4286 1 : check("int foo(bool a, bool b) {\n"
4287 : " if(!a && b && (!a == !b))\n"
4288 : " return 1;\n"
4289 : " return 0;\n"
4290 : "}\n");
4291 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition '!a==!b' is always false\n", errout_str());
4292 :
4293 : // #10454
4294 1 : check("struct S {\n"
4295 : " int f() const { return g() ? 0 : 1; }\n"
4296 : " bool g() const { return u == 18446744073709551615ULL; }\n"
4297 : " unsigned long long u{};\n"
4298 : "};\n");
4299 1 : ASSERT_EQUALS("", errout_str());
4300 :
4301 : // #8358
4302 1 : check("void f(double d) { if ((d * 0) != 0) {} }");
4303 1 : ASSERT_EQUALS("", errout_str());
4304 :
4305 : // #6870
4306 1 : check("struct S {\n"
4307 : " int* p;\n"
4308 : " void f() const;\n"
4309 : " int g();\n"
4310 : "};\n"
4311 : "void S::f() {\n"
4312 : " if ((p == NULL) || ((p) && (g() >= *p))) {}\n"
4313 : "}\n");
4314 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Condition 'p' is always true\n", errout_str());
4315 :
4316 : // #10749
4317 1 : check("struct Interface {\n"
4318 : " virtual int method() = 0;\n"
4319 : "};\n"
4320 : "struct Child : Interface {\n"
4321 : " int method() override { return 0; }\n"
4322 : " auto foo() {\n"
4323 : " if (method() == 0)\n"
4324 : " return true;\n"
4325 : " else\n"
4326 : " return false;\n"
4327 : " }\n"
4328 : "};\n"
4329 : "struct GrandChild : Child {\n"
4330 : " int method() override { return 1; }\n"
4331 : "};\n");
4332 1 : ASSERT_EQUALS("", errout_str());
4333 :
4334 : // #6855
4335 1 : check("struct S { int i; };\n"
4336 : "void f(S& s) {\n"
4337 : " if (!(s.i > 0) && (s.i != 0))\n"
4338 : " s.i = 0;\n"
4339 : " else if (s.i < 0)\n"
4340 : " s.s = 0;\n"
4341 : "}\n");
4342 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Condition 's.i<0' is always false\n", errout_str());
4343 :
4344 : // #6857
4345 1 : check("int bar(int i) { return i; }\n"
4346 : "void foo() {\n"
4347 : " if (bar(1) == 0 && bar(1) > 0) {}\n"
4348 : "}\n");
4349 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'bar(1)==0' is always false\n"
4350 : "[test.cpp:3]: (style) Condition 'bar(1)>0' is always true\n",
4351 : errout_str());
4352 :
4353 1 : check("struct S { int bar(int i) const; };\n"
4354 : "void foo(const S& s) {\n"
4355 : " if (s.bar(1) == 0 && s.bar(1) > 0) {}\n"
4356 : "}\n");
4357 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Logical conjunction always evaluates to false: s.bar(1) == 0 && s.bar(1) > 0.\n",
4358 : errout_str());
4359 :
4360 1 : check("struct B {\n" // #10618
4361 : " void Modify();\n"
4362 : " static void Static();\n"
4363 : " virtual void CalledByModify();\n"
4364 : "};\n"
4365 : "struct D : B {\n"
4366 : " int i{};\n"
4367 : " void testV();\n"
4368 : " void testS();\n"
4369 : " void CalledByModify() override { i = 0; }\n"
4370 : "};\n"
4371 : "void D::testV() {\n"
4372 : " i = 1;\n"
4373 : " B::Modify();\n"
4374 : " if (i == 1) {}\n"
4375 : "}\n"
4376 : "void D::testS() {\n"
4377 : " i = 1;\n"
4378 : " B::Static();\n"
4379 : " if (i == 1) {}\n"
4380 : "}\n");
4381 1 : ASSERT_EQUALS("[test.cpp:20]: (style) Condition 'i==1' is always true\n", errout_str());
4382 :
4383 1 : check("typedef struct { bool x; } s_t;\n" // #8446
4384 : "unsigned f(bool a, bool b) {\n"
4385 : " s_t s;\n"
4386 : " const unsigned col = a ? (s.x = false) : (b = true);\n"
4387 : " if (!s.x) {}\n"
4388 : " return col;\n"
4389 : "}\n");
4390 1 : ASSERT_EQUALS("", errout_str());
4391 :
4392 1 : check("struct S {\n" // #11233
4393 : " static std::string m;\n"
4394 : " static void f() { m = \"abc\"; }\n"
4395 : " static void g() {\n"
4396 : " m.clear();\n"
4397 : " f();\n"
4398 : " if (m.empty()) {}\n"
4399 : " }\n"
4400 : "};\n");
4401 1 : ASSERT_EQUALS("", errout_str());
4402 :
4403 : // #11203
4404 1 : check("void f() {\n"
4405 : " int i = 10;\n"
4406 : " if(i > 9.9){}\n"
4407 : " float f = 9.9f;\n"
4408 : " if(f < 10) {}\n"
4409 : "}\n");
4410 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'i>9.9' is always true\n"
4411 : "[test.cpp:5]: (style) Condition 'f<10' is always true\n",
4412 : errout_str());
4413 1 : check("constexpr int f() {\n" // #11238
4414 : " return 1;\n"
4415 : "}\n"
4416 : "constexpr bool g() {\n"
4417 : " return f() == 1;\n"
4418 : "}\n");
4419 1 : ASSERT_EQUALS("", errout_str());
4420 :
4421 1 : check("int g() { return -1; }\n"
4422 : "void f() {\n"
4423 : " if (g() == 1 && g() == -1) {}\n"
4424 : "}\n");
4425 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'g()==1' is always false\n"
4426 : "[test.cpp:3]: (style) Condition 'g()==-1' is always true\n",
4427 : errout_str());
4428 :
4429 : // #9817
4430 1 : check("void f(float x) {\n"
4431 : " if (x <= 0) {}\n"
4432 : " else if (x < 1) {}\n"
4433 : "}\n");
4434 1 : ASSERT_EQUALS("", errout_str());
4435 :
4436 : // #10426
4437 1 : check("int f() {\n"
4438 : " std::string s;\n"
4439 : " for (; !s.empty();) {}\n"
4440 : " for (; s.empty();) {}\n"
4441 : " if (s.empty()) {}\n"
4442 : " if ((bool)0) {}\n"
4443 : " return s.empty();"
4444 : "}\n");
4445 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!s.empty()' is always false\n"
4446 : "[test.cpp:4]: (style) Condition 's.empty()' is always true\n"
4447 : "[test.cpp:5]: (style) Condition 's.empty()' is always true\n"
4448 : "[test.cpp:6]: (style) Condition '(bool)0' is always false\n"
4449 : "[test.cpp:7]: (style) Return value 's.empty()' is always true\n",
4450 : errout_str());
4451 :
4452 1 : check("int f(bool b) {\n"
4453 : " if (b) return static_cast<int>(1);\n"
4454 : " return (int)0;\n"
4455 : "}\n"
4456 : "bool g(bool b) {\n"
4457 : " if (b) return static_cast<int>(1);\n"
4458 : " return (int)0;\n"
4459 : "}\n");
4460 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Return value 'static_cast<int>(1)' is always true\n"
4461 : "[test.cpp:7]: (style) Return value '(int)0' is always false\n",
4462 : errout_str());
4463 :
4464 1 : check("int f() { return 3; }\n"
4465 : "int g() { return f(); }\n"
4466 : "int h() { if (f()) {} }\n"
4467 : "int i() { return f() == 3; }\n");
4468 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'f()' is always true\n"
4469 : "[test.cpp:4]: (style) Return value 'f()==3' is always true\n",
4470 : errout_str());
4471 :
4472 1 : check("int f() {\n"
4473 : " const char *n;\n"
4474 : " return((n=42) &&\n"
4475 : " *n == 'A');\n"
4476 : "}\n");
4477 1 : ASSERT_EQUALS("", errout_str());
4478 :
4479 1 : check("void f(std::istringstream& i) {\n" // #9327
4480 : " std::string s;\n"
4481 : " if (!(i >> s))\n"
4482 : " return;\n"
4483 : " if (!(i >> s))\n"
4484 : " return;\n"
4485 : "}\n");
4486 1 : ASSERT_EQUALS("", errout_str());
4487 :
4488 : // #11227
4489 1 : check("struct S {\n"
4490 : " int get();\n"
4491 : "};\n"
4492 : "void f(const S* s) {\n"
4493 : " if (!s)\n"
4494 : " return;\n"
4495 : " g(s ? s->get() : 0);\n"
4496 : "}\n");
4497 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:7]: (style) Condition 's' is always true\n", errout_str());
4498 :
4499 1 : check("void f(const char* o) {\n" // #11558
4500 : " if (!o || !o[0])\n"
4501 : " return;\n"
4502 : " if (o[0] == '-' && o[1]) {\n"
4503 : " if (o[1] == '-') {}\n"
4504 : " if (o[1] == '\\0') {}\n"
4505 : " }\n"
4506 : "}\n");
4507 : if (std::numeric_limits<char>::is_signed) {
4508 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout_str());
4509 : } else {
4510 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout_str());
4511 : }
4512 :
4513 1 : check("void f(int x) {\n" // #11449
4514 : " int i = x;\n"
4515 : " i = (std::min)(i, 1);\n"
4516 : " if (i == 1) {}\n"
4517 : " int j = x;\n"
4518 : " j = (::std::min)(j, 1);\n"
4519 : " if (j == 1) {}\n"
4520 : "}\n");
4521 1 : ASSERT_EQUALS("", errout_str());
4522 :
4523 1 : check("void h(int);\n" // #11679
4524 : "bool g(int a) { h(a); return false; }\n"
4525 : "bool f(int i) {\n"
4526 : " return g(i);\n"
4527 : "}\n");
4528 1 : ASSERT_EQUALS("", errout_str());
4529 :
4530 1 : check("void f(std::string a) {\n" // #11051
4531 : " a = \"x\";\n"
4532 : " if (a == \"x\") {}\n"
4533 : " return a;\n"
4534 : "}\n");
4535 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'a==\"x\"' is always true\n", errout_str());
4536 :
4537 1 : check("void g(bool);\n"
4538 : "void f() {\n"
4539 : " int i = 5;\n"
4540 : " int* p = &i;\n"
4541 : " g(i == 7);\n"
4542 : " g(p == nullptr);\n"
4543 : "}\n");
4544 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'i==7' is always false\n"
4545 : "[test.cpp:6]: (style) Condition 'p==nullptr' is always false\n",
4546 : errout_str());
4547 :
4548 1 : check("enum E { E0, E1 };\n"
4549 : "void f() {\n"
4550 : " static_assert(static_cast<int>(E::E1) == 1);\n"
4551 : "}\n");
4552 1 : ASSERT_EQUALS("", errout_str());
4553 :
4554 1 : check("struct a {\n"
4555 : " bool g();\n"
4556 : " int h();\n"
4557 : "};\n"
4558 : "void f(a c, int d, int e) {\n"
4559 : " if (c.g() && c.h()) {}\n"
4560 : " else {\n"
4561 : " bool u = false;\n"
4562 : " if (d && e)\n"
4563 : " u = true;\n"
4564 : " if (u) {}\n"
4565 : " }\n"
4566 : "}\n");
4567 1 : ASSERT_EQUALS("", errout_str());
4568 :
4569 1 : check("int f(int i) {\n" // #11741
4570 : " i = -i - 1;\n"
4571 : " if (i < 0 || i >= 20)\n"
4572 : " return 0;\n"
4573 : " return 1;\n"
4574 : "}\n");
4575 1 : ASSERT_EQUALS("", errout_str());
4576 : }
4577 :
4578 1 : void alwaysTrueSymbolic()
4579 : {
4580 1 : check("void f(const uint32_t x) {\n"
4581 : " uint32_t y[1];\n"
4582 : " y[0]=x;\n"
4583 : " if(x > 0 || y[0] < 42){}\n"
4584 : "}\n");
4585 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:4]: (style) Condition 'y[0]<42' is always true\n", errout_str());
4586 :
4587 1 : check("void f(int x, int y) {\n"
4588 : " if(x < y && x < 42) {\n"
4589 : " --x;\n"
4590 : " if(x == y) {}\n"
4591 : " }\n"
4592 : "}\n");
4593 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==y' is always false\n", errout_str());
4594 :
4595 1 : check("void f(bool a, bool b) { if (a == b && a && !b){} }");
4596 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Condition '!b' is always false\n", errout_str());
4597 :
4598 1 : check("bool f(bool a, bool b) { if(a && b && (!a)){} }");
4599 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Condition '!a' is always false\n", errout_str());
4600 :
4601 1 : check("void f(int x, int y) {\n"
4602 : " if (x < y) {\n"
4603 : " auto z = y - x;\n"
4604 : " if (z < 1) {}\n"
4605 : " }\n"
4606 : "}\n");
4607 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'z<1' is always false\n", errout_str());
4608 :
4609 1 : check("bool f(int &index, const int s, const double * const array, double & x) {\n"
4610 : " if (index >= s)\n"
4611 : " return false;\n"
4612 : " else {\n"
4613 : " x = array[index];\n"
4614 : " return (index++) >= s;\n"
4615 : " }\n"
4616 : "}\n");
4617 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:6]: (style) Return value '(index++)>=s' is always false\n", errout_str());
4618 :
4619 1 : check("struct a {\n"
4620 : " a *b() const;\n"
4621 : "} c;\n"
4622 : "void d() {\n"
4623 : " a *e = nullptr;\n"
4624 : " e = c.b();\n"
4625 : " if (e) {}\n"
4626 : "}\n");
4627 1 : ASSERT_EQUALS("", errout_str());
4628 :
4629 1 : check("int g(int i) {\n"
4630 : " if (i < 256)\n"
4631 : " return 1;\n"
4632 : " const int N = 2 * i;\n"
4633 : " i -= 256;\n"
4634 : " if (i == 0)\n"
4635 : " return 0;\n"
4636 : " return N;\n"
4637 : "}\n");
4638 1 : ASSERT_EQUALS("", errout_str());
4639 :
4640 1 : check("void f(int i, int j) {\n"
4641 : " if (i < j) {\n"
4642 : " i++;\n"
4643 : " if (i >= j)\n"
4644 : " return;\n"
4645 : " i++;\n"
4646 : " if (i >= j) {}\n"
4647 : " }\n"
4648 : "}\n");
4649 1 : ASSERT_EQUALS("", errout_str());
4650 :
4651 1 : check("int get_delta() {\n"
4652 : " clock_t now_ms = (clock() / (CLOCKS_PER_SEC / 1000));\n"
4653 : " static clock_t last_clock_ms = now_ms;\n"
4654 : " clock_t delta = now_ms - last_clock_ms;\n"
4655 : " last_clock_ms = now_ms;\n"
4656 : " if (delta > 50)\n"
4657 : " delta = 50;\n"
4658 : " return delta;\n"
4659 : "}\n");
4660 1 : ASSERT_EQUALS("", errout_str());
4661 :
4662 : // #10555
4663 1 : check("struct C {\n"
4664 : " int GetI() const { return i; }\n"
4665 : " int i{};\n"
4666 : "};\n"
4667 : "struct B {\n"
4668 : " C *m_PC{};\n"
4669 : " Modify();\n"
4670 : "};\n"
4671 : "struct D : B {\n"
4672 : " void test(); \n"
4673 : "};\n"
4674 : "void D::test() {\n"
4675 : " const int I = m_PC->GetI();\n"
4676 : " Modify();\n"
4677 : " if (m_PC->GetI() != I) {}\n"
4678 : "}\n");
4679 1 : ASSERT_EQUALS("", errout_str());
4680 :
4681 : // #10624
4682 1 : check("struct Data {\n"
4683 : " Base* PBase{};\n"
4684 : "};\n"
4685 : "void f(Data* BaseData) {\n"
4686 : " Base* PObj = BaseData->PBase;\n"
4687 : " if (PObj == nullptr)\n"
4688 : " return;\n"
4689 : " Derived* pD = dynamic_cast<Derived*>(PObj);\n"
4690 : " if (pD) {}\n"
4691 : "}\n");
4692 1 : ASSERT_EQUALS("", errout_str());
4693 :
4694 : // #9549
4695 1 : check("void f(const uint32_t v) {\n"
4696 : " const uint32_t v16 = v >> 16;\n"
4697 : " if (v16) {\n"
4698 : " const uint32_t v8 = v16 >> 8;\n"
4699 : " if (v8) {}\n"
4700 : " }\n"
4701 : "}\n");
4702 1 : ASSERT_EQUALS("", errout_str());
4703 :
4704 : // #10649
4705 1 : check("void foo(struct diag_msg *msg) {\n"
4706 : " msg = msg->next;\n"
4707 : " if (msg == NULL)\n"
4708 : " return CMD_OK;\n"
4709 : " msg = msg->next;\n"
4710 : " if (msg == NULL)\n"
4711 : " return CMD_OK;\n"
4712 : "}\n");
4713 1 : ASSERT_EQUALS("", errout_str());
4714 :
4715 1 : check("int foo(bool a, bool b) {\n"
4716 : " if((!a == !b) && !a && b)\n"
4717 : " return 1;\n"
4718 : " return 0;\n"
4719 : "}\n");
4720 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'b' is always false\n", errout_str());
4721 :
4722 : // #11124
4723 1 : check("struct Basket {\n"
4724 : " std::vector<int> getApples() const;\n"
4725 : " std::vector<int> getBananas() const; \n"
4726 : "};\n"
4727 : "int getFruit(const Basket & b, bool preferApples)\n"
4728 : "{\n"
4729 : " std::vector<int> apples = b.getApples();\n"
4730 : " int apple = apples.empty() ? -1 : apples.front();\n"
4731 : " std::vector<int> bananas = b.getBananas();\n"
4732 : " int banana = bananas.empty() ? -1 : bananas.front();\n"
4733 : " int fruit = std::max(apple, banana);\n"
4734 : " if (fruit == -1)\n"
4735 : " return fruit;\n"
4736 : " if (std::min(apple, banana) != -1)\n"
4737 : " fruit = preferApples ? apple : banana;\n"
4738 : " return fruit;\n"
4739 : "}\n");
4740 1 : ASSERT_EQUALS("", errout_str());
4741 :
4742 1 : check("void f(const std::string & s, int i) {\n"
4743 : " const char c = s[i];\n"
4744 : " if (!std::isalnum(c)) {}\n"
4745 : "}\n");
4746 1 : ASSERT_EQUALS("", errout_str());
4747 :
4748 1 : check("struct S {\n" // #11404
4749 : " int f() const;\n"
4750 : " void g();\n"
4751 : "};\n"
4752 : "void h(std::vector<S*>::iterator it) {\n"
4753 : " auto i = (*it)->f();\n"
4754 : " (*it)->g();\n"
4755 : " auto j = (*it)->f();\n"
4756 : " if (i == j) {}\n"
4757 : "}\n");
4758 1 : ASSERT_EQUALS("", errout_str());
4759 :
4760 : // #11384
4761 1 : check("bool f(const int* it, const int* end) {\n"
4762 : " return (it != end) && *it++ &&\n"
4763 : " (it != end) && *it;\n"
4764 : "}\n");
4765 1 : ASSERT_EQUALS("", errout_str());
4766 :
4767 : // #12116
4768 1 : check("void f(int n) {\n"
4769 : " for (int i = 0; i < N; ++i) {\n"
4770 : " if (i < n) {}\n"
4771 : " else if (i > n) {}\n"
4772 : " else {}\n"
4773 : " }\n"
4774 : "}\n");
4775 1 : ASSERT_EQUALS("", errout_str());
4776 : }
4777 :
4778 1 : void alwaysTrueInfer() {
4779 1 : check("void f(int x) {\n"
4780 : " if (x > 5) {\n"
4781 : " x++;\n"
4782 : " if (x == 1) {}\n"
4783 : " }\n"
4784 : "}");
4785 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==1' is always false\n", errout_str());
4786 :
4787 1 : check("void f(int x) {\n"
4788 : " if (x > 5) {\n"
4789 : " x++;\n"
4790 : " if (x != 1) {}\n"
4791 : " }\n"
4792 : "}");
4793 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Condition 'x!=1' is always true\n", errout_str());
4794 :
4795 : // #6890
4796 1 : check("void f(int i) {\n"
4797 : " int x = i;\n"
4798 : " if (x >= 1) {}\n"
4799 : " else {\n"
4800 : " x = 8 - x;\n"
4801 : " if (x == -1) {}\n"
4802 : " else {}\n"
4803 : " }\n"
4804 : "}");
4805 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x==-1' is always false\n", errout_str());
4806 :
4807 1 : check("void f(int i) {\n"
4808 : " int x = i;\n"
4809 : " if (x >= 1) {}\n"
4810 : " else {\n"
4811 : " x = 8 - x;\n"
4812 : " if (x != -1) {}\n"
4813 : " else {}\n"
4814 : " }\n"
4815 : "}");
4816 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x!=-1' is always true\n", errout_str());
4817 :
4818 1 : check("void f(int i) {\n"
4819 : " int x = i;\n"
4820 : " if (x >= 1) {}\n"
4821 : " else {\n"
4822 : " x = 8 - x;\n"
4823 : " if (x >= -1) {}\n"
4824 : " else {}\n"
4825 : " }\n"
4826 : "}");
4827 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>=-1' is always true\n", errout_str());
4828 :
4829 1 : check("void f(int i) {\n"
4830 : " int x = i;\n"
4831 : " if (x >= 1) {}\n"
4832 : " else {\n"
4833 : " x = 8 - x;\n"
4834 : " if (x > -1) {}\n"
4835 : " else {}\n"
4836 : " }\n"
4837 : "}");
4838 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>-1' is always true\n", errout_str());
4839 :
4840 1 : check("void f(int i) {\n"
4841 : " int x = i;\n"
4842 : " if (x >= 1) {}\n"
4843 : " else {\n"
4844 : " x = 8 - x;\n"
4845 : " if (x < -1) {}\n"
4846 : " else {}\n"
4847 : " }\n"
4848 : "}");
4849 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x<-1' is always false\n", errout_str());
4850 :
4851 1 : check("void f(int i) {\n"
4852 : " int x = i;\n"
4853 : " if (x >= 1) {}\n"
4854 : " else {\n"
4855 : " x = 8 - x;\n"
4856 : " if (x <= -1) {}\n"
4857 : " else {}\n"
4858 : " }\n"
4859 : "}");
4860 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x<=-1' is always false\n", errout_str());
4861 :
4862 1 : check("void f(int i) {\n"
4863 : " int x = i;\n"
4864 : " if (x >= 1) {}\n"
4865 : " else {\n"
4866 : " x = 8 - x;\n"
4867 : " if (x > 7) {}\n"
4868 : " else {}\n"
4869 : " }\n"
4870 : "}");
4871 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>7' is always true\n", errout_str());
4872 :
4873 1 : check("void f(int i) {\n"
4874 : " int x = i;\n"
4875 : " if (x >= 1) {}\n"
4876 : " else {\n"
4877 : " x = 8 - x;\n"
4878 : " if (x > 9) {}\n"
4879 : " else {}\n"
4880 : " }\n"
4881 : "}");
4882 1 : ASSERT_EQUALS("", errout_str());
4883 :
4884 1 : check("void f(int i) {\n"
4885 : " int x = i;\n"
4886 : " if (x >= 1) {}\n"
4887 : " else {\n"
4888 : " x = 8 - x;\n"
4889 : " if (x > 10) {}\n"
4890 : " else {}\n"
4891 : " }\n"
4892 : "}");
4893 1 : ASSERT_EQUALS("", errout_str());
4894 :
4895 : // #11100
4896 1 : check("struct T {\n"
4897 : " bool m{};\n"
4898 : " void f(bool b);\n"
4899 : " bool get() const { return m; }\n"
4900 : " void set(bool v) { m = v; }\n"
4901 : "};\n"
4902 : "void T::f(bool b) {\n"
4903 : " bool tmp = get();\n"
4904 : " set(b);\n"
4905 : " if (tmp != get()) {}\n"
4906 : "}\n");
4907 1 : ASSERT_EQUALS("", errout_str());
4908 :
4909 : // #9541
4910 1 : check("int f(int pos, int a) {\n"
4911 : " if (pos <= 0)\n"
4912 : " pos = 0;\n"
4913 : " else if (pos < a)\n"
4914 : " if(pos > 0)\n"
4915 : " --pos;\n"
4916 : " return pos;\n"
4917 : "}");
4918 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (style) Condition 'pos>0' is always true\n", errout_str());
4919 :
4920 : // #9721
4921 1 : check("void f(int x) {\n"
4922 : " if (x > 127) {\n"
4923 : " if ( (x>255) || (-128>x) )\n"
4924 : " return;\n"
4925 : " }\n"
4926 : "}");
4927 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Condition '-128>x' is always false\n", errout_str());
4928 :
4929 : // #8778
4930 1 : check("void f() {\n"
4931 : " for(int i = 0; i < 19; ++i)\n"
4932 : " if(i<=18) {}\n"
4933 : "}\n");
4934 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'i<=18' is always true\n", errout_str());
4935 :
4936 : // #8209
4937 1 : check("void f() {\n"
4938 : " for(int x = 0; x < 3; ++x)\n"
4939 : " if(x == -5) {}\n"
4940 : "}");
4941 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'x==-5' is always false\n", errout_str());
4942 :
4943 : // #8407
4944 1 : check("int f(void) {\n"
4945 : " for(int i = 0; i <1; ++i)\n"
4946 : " if(i == 0) return 1; \n" // <<
4947 : " else return 0;\n"
4948 : " return -1;\n"
4949 : "}");
4950 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'i==0' is always true\n", errout_str());
4951 :
4952 1 : check("void f(unsigned int u1, unsigned int u2) {\n"
4953 : " if (u1 <= 10 && u2 >= 20) {\n"
4954 : " if (u1 != u2) {}\n"
4955 : " }\n"
4956 : "}\n");
4957 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Condition 'u1!=u2' is always true\n", errout_str());
4958 :
4959 : // #10544
4960 1 : check("void f(int N) {\n"
4961 : " if (N > 0) {\n"
4962 : " while (N)\n"
4963 : " N = test();\n"
4964 : " }\n"
4965 : "}\n");
4966 1 : ASSERT_EQUALS("", errout_str());
4967 :
4968 : // #11098
4969 1 : check("void f(unsigned int x) { if (x == -1u) {} }\n");
4970 1 : ASSERT_EQUALS("", errout_str());
4971 :
4972 1 : check("bool f(const int *p, const int *q) {\n"
4973 : " return p != NULL && q != NULL && p == NULL;\n"
4974 : "}\n");
4975 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Return value 'p==NULL' is always false\n", errout_str());
4976 :
4977 1 : check("struct S {\n" // #11789
4978 : " std::vector<int> v;\n"
4979 : " void f(int i) const;\n"
4980 : "};\n"
4981 : "void S::f(int i) const {\n"
4982 : " int j = i - v.size();\n"
4983 : " if (j >= 0) {}\n"
4984 : "}\n");
4985 1 : ASSERT_EQUALS("", errout_str());
4986 :
4987 1 : check("void f(int i) {\n" // #12039
4988 : " if ((128 + i < 255 ? 128 + i : 255) > 0) {}\n"
4989 : "}\n");
4990 1 : ASSERT_EQUALS("", errout_str());
4991 : }
4992 :
4993 1 : void alwaysTrueContainer() {
4994 : // #9329
4995 1 : check("void c1(std::vector<double>&);\n"
4996 : "void c2(std::vector<double>&);\n"
4997 : "void foo(int flag) {\n"
4998 : " std::vector<double> g;\n"
4999 : " if (flag)\n"
5000 : " c1(g );\n"
5001 : " else\n"
5002 : " c2(g );\n"
5003 : " if ( !g.empty() )\n"
5004 : " return;\n"
5005 : "}");
5006 1 : ASSERT_EQUALS("", errout_str());
5007 :
5008 1 : check("void foo(int flag) {\n"
5009 : " std::vector<double> g;\n"
5010 : " if (flag)\n"
5011 : " c1(g );\n"
5012 : " else\n"
5013 : " c2(g );\n"
5014 : " if ( !g.empty() )\n"
5015 : " return;\n"
5016 : "}");
5017 1 : ASSERT_EQUALS("", errout_str());
5018 :
5019 1 : check("struct A {\n"
5020 : " std::vector<int> v;\n"
5021 : " void g();\n"
5022 : " void f(bool b) {\n"
5023 : " v.clear();\n"
5024 : " g();\n"
5025 : " return !v.empty();\n"
5026 : " }\n"
5027 : "};\n");
5028 1 : ASSERT_EQUALS("", errout_str());
5029 :
5030 : // #10409
5031 1 : check("void foo(const std::string& s) {\n"
5032 : " if( s.size() < 2 ) return;\n"
5033 : " if( s == \"ab\" ) return;\n"
5034 : " if( s.size() < 3 ) return;\n"
5035 : "}\n");
5036 1 : ASSERT_EQUALS("", errout_str());
5037 :
5038 1 : check("void foo(const std::string& s) {\n"
5039 : " if( s.size() < 2 ) return;\n"
5040 : " if( s != \"ab\" )\n"
5041 : " if( s.size() < 3 ) return;\n"
5042 : "}\n");
5043 1 : ASSERT_EQUALS("", errout_str());
5044 :
5045 : // #10226
5046 1 : check("int f(std::vector<int>::iterator it, const std::vector<int>& vector) {\n"
5047 : " if (!(it != vector.end() && it != vector.begin()))\n"
5048 : " throw 0;\n"
5049 : " if (it != vector.end() && *it == 0)\n"
5050 : " return -1;\n"
5051 : " return *it;\n"
5052 : "}\n");
5053 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'it!=vector.end()' is always true\n", errout_str());
5054 :
5055 : // #11303
5056 1 : check("void f(int n) {\n"
5057 : " std::vector<char> buffer(n);\n"
5058 : " if(buffer.back() == 0 ||\n"
5059 : " buffer.back() == '\\n' ||\n"
5060 : " buffer.back() == '\\0') {}\n"
5061 : "}\n");
5062 : if (std::numeric_limits<char>::is_signed) {
5063 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'buffer.back()=='\\0'' is always false\n", errout_str());
5064 : } else {
5065 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Condition 'buffer.back()=='\\0'' is always false\n", errout_str());
5066 : }
5067 :
5068 : // #9353
5069 1 : check("struct X { std::string s; };\n"
5070 : "void f(const std::vector<X>&v) {\n"
5071 : " for (std::vector<X>::const_iterator it = v.begin(); it != v.end(); ++it)\n"
5072 : " if (!it->s.empty()) {\n"
5073 : " if (!it->s.empty()) {}\n"
5074 : " }\n"
5075 : "}\n");
5076 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style) Condition '!it->s.empty()' is always true\n", errout_str());
5077 :
5078 1 : check("struct X { std::string s; };\n"
5079 : "void f(const std::vector<struct X>&v) {\n"
5080 : " for (std::vector<struct X>::const_iterator it = v.begin(); it != v.end(); ++it)\n"
5081 : " if (!it->s.empty()) {\n"
5082 : " if (!it->s.empty()) {}\n"
5083 : " }\n"
5084 : "}\n");
5085 1 : TODO_ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style) Condition '!it->s.empty()' is always true\n", "", errout_str());
5086 :
5087 : // #10508
5088 1 : check("bool f(const std::string& a, const std::string& b) {\n"
5089 : " return a.empty() || (b.empty() && a.empty());\n"
5090 : "}\n");
5091 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Return value 'a.empty()' is always false\n", errout_str());
5092 :
5093 1 : check("struct A {\n"
5094 : " struct iterator;\n"
5095 : " iterator begin() const;\n"
5096 : " iterator end() const;\n"
5097 : "};\n"
5098 : "A g();\n"
5099 : "void f(bool b) {\n"
5100 : " std::set<int> s;\n"
5101 : " auto v = g();\n"
5102 : " s.insert(v.begin(), v.end());\n"
5103 : " if(!b && s.size() != 1)\n"
5104 : " return;\n"
5105 : " if(!s.empty()) {}\n"
5106 : "}\n");
5107 1 : ASSERT_EQUALS("", errout_str());
5108 :
5109 1 : check("int f(std::string s) {\n"
5110 : " if (s.empty())\n"
5111 : " return -1;\n"
5112 : " s += '\\n';\n"
5113 : " if (s.empty())\n"
5114 : " return -1;\n"
5115 : " return -1;\n"
5116 : "}\n");
5117 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Condition 's.empty()' is always false\n", errout_str());
5118 :
5119 1 : check("void f(std::string& p) {\n"
5120 : " const std::string d{ \"abc\" };\n"
5121 : " p += d;\n"
5122 : " if(p.empty()) {}\n"
5123 : "}\n");
5124 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'p.empty()' is always false\n", errout_str());
5125 :
5126 1 : check("bool f(int i, FILE* fp) {\n"
5127 : " std::string s = \"abc\";\n"
5128 : " s += std::to_string(i);\n"
5129 : " s += \"\\n\";\n"
5130 : " return fwrite(s.c_str(), 1, s.length(), fp) == s.length();\n"
5131 : "}\n");
5132 1 : ASSERT_EQUALS("", errout_str());
5133 :
5134 1 : check("void f(const std::string& s) {\n" // #9148
5135 : " if (s.empty() || s.size() < 1) {}\n"
5136 : "}\n");
5137 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 's.size()<1' is always false\n", errout_str());
5138 :
5139 1 : check("void bar(std::vector<int>& vv) {\n" // #11464
5140 : " class F {\n"
5141 : " public:\n"
5142 : " F(int, std::vector<int>& lv) : mV(lv) {\n"
5143 : " mV.push_back(0);\n"
5144 : " }\n"
5145 : " private:\n"
5146 : " std::vector<int>& mV;\n"
5147 : " } fi(1, vv);\n"
5148 : "}\n"
5149 : "void g() {\n"
5150 : " std::vector<int> v;\n"
5151 : " bar(v);\n"
5152 : " if (v.empty()) {}\n"
5153 : "}\n");
5154 1 : ASSERT_EQUALS("", errout_str());
5155 :
5156 1 : check("struct F {\n"
5157 : " F(int, std::vector<int>&lv) : mV(lv) {\n"
5158 : " mV.push_back(0);\n"
5159 : " }\n"
5160 : " std::vector<int>& mV;\n"
5161 : "};\n"
5162 : "void g(std::vector<int>& vv) {\n"
5163 : " F(1, vv);\n"
5164 : "}\n"
5165 : "void f() {\n"
5166 : " std::vector<int> v;\n"
5167 : " g(v);\n"
5168 : " if (v.empty()) {}\n"
5169 : "}\n");
5170 1 : ASSERT_EQUALS("", errout_str());
5171 : }
5172 :
5173 1 : void alwaysTrueLoop()
5174 : {
5175 1 : check("long foo() {\n"
5176 : " bool bUpdated = false;\n"
5177 : " long Ret{};\n"
5178 : " do {\n"
5179 : " Ret = bar();\n"
5180 : " if (Ret == 0) {\n"
5181 : " if (bUpdated)\n"
5182 : " return 1;\n"
5183 : " bUpdated = true;\n"
5184 : " }\n"
5185 : " else\n"
5186 : " bUpdated = false;\n"
5187 : " }\n"
5188 : " while (bUpdated);\n"
5189 : " return Ret;\n"
5190 : "}\n");
5191 1 : ASSERT_EQUALS("", errout_str());
5192 :
5193 1 : check("bool foo() {\n"
5194 : " bool bFirst = true;\n"
5195 : " do {\n"
5196 : " if (bFirst)\n"
5197 : " bar();\n"
5198 : " if (baz())\n"
5199 : " break; \n"
5200 : " bFirst = false;\n"
5201 : " } while (true);\n"
5202 : " return bFirst;\n"
5203 : "}\n");
5204 1 : ASSERT_EQUALS("", errout_str());
5205 :
5206 1 : check("void f() {\n"
5207 : " void * pool = NULL;\n"
5208 : " do {\n"
5209 : " pool = malloc(40);\n"
5210 : " if (dostuff())\n"
5211 : " break;\n"
5212 : " pool = NULL;\n"
5213 : " }\n"
5214 : " while (0);\n"
5215 : " if (pool) {}\n"
5216 : "}\n");
5217 1 : ASSERT_EQUALS("", errout_str());
5218 :
5219 : // #8499
5220 1 : check("void f(void)\n"
5221 : "{\n"
5222 : " for (int i = 0; i < 2; ++i)\n"
5223 : " {\n"
5224 : " for (int j = 0; j < 8; ++j)\n"
5225 : " {\n"
5226 : " if ( (i==0|| i==1)\n" // << always true
5227 : " && (j==0) )\n"
5228 : " {;}\n"
5229 : " }\n"
5230 : " }\n"
5231 : "}");
5232 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:7]: (style) Condition 'i==1' is always true\n", errout_str());
5233 :
5234 : // #10863
5235 1 : check("void f(const int A[], int Len) {\n"
5236 : " if (Len <= 0)\n"
5237 : " return;\n"
5238 : " int I = 0;\n"
5239 : " while (I < Len) {\n"
5240 : " int K = I + 1;\n"
5241 : " for (; K < Len; K++) {\n"
5242 : " if (A[I] != A[K])\n"
5243 : " break;\n"
5244 : " } \n"
5245 : " I = K; \n"
5246 : " }\n"
5247 : "}\n");
5248 1 : ASSERT_EQUALS("", errout_str());
5249 :
5250 1 : check("void f() {\n" // #11434
5251 : " const int N = 5;\n"
5252 : " bool a[N];\n"
5253 : " for (int i = 0; i < N; a[i++] = false);\n"
5254 : "}\n");
5255 1 : ASSERT_EQUALS("", errout_str());
5256 :
5257 1 : check("void f() {\n" // #8192
5258 : " for (int i = 0; i > 10; ++i) {}\n"
5259 : "}\n");
5260 1 : TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i>10' is always false\n", "", errout_str());
5261 :
5262 1 : check("void f() {\n"
5263 : " for (int i = 1000; i < 20; ++i) {}\n"
5264 : "}\n");
5265 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i<20' is always false\n", errout_str());
5266 : }
5267 :
5268 1 : void alwaysTrueTryCatch()
5269 : {
5270 1 : check("void g();\n"
5271 : "void f(int x)\n"
5272 : "{\n"
5273 : " if( x ) {\n"
5274 : " try {\n"
5275 : " g();\n"
5276 : " }\n"
5277 : " catch(...) {\n"
5278 : " return;\n"
5279 : " }\n"
5280 : " }\n"
5281 : " g();\n"
5282 : " if( x ) {\n"
5283 : " g();\n"
5284 : " }\n"
5285 : "}\n");
5286 1 : ASSERT_EQUALS("", errout_str());
5287 :
5288 1 : check("void g();\n"
5289 : "void h();\n"
5290 : "void f(int x) {\n"
5291 : " if( x ) {\n"
5292 : " try {\n"
5293 : " g();\n"
5294 : " return;\n"
5295 : " }\n"
5296 : " catch( ... ) {}\n"
5297 : " }\n"
5298 : " h();\n"
5299 : " if( x ) {\n"
5300 : " g();\n"
5301 : " }\n"
5302 : "}\n");
5303 1 : ASSERT_EQUALS("", errout_str());
5304 :
5305 1 : check("void f() {\n" // #10701
5306 : " std::string s;\n"
5307 : " try {\n"
5308 : " try {\n"
5309 : " s = g();\n"
5310 : " }\n"
5311 : " catch (const Err& err) {}\n"
5312 : " }\n"
5313 : " catch (const std::exception& e) {}\n"
5314 : " if (s != \"abc\") {}\n"
5315 : "}\n");
5316 1 : ASSERT_EQUALS("", errout_str());
5317 : }
5318 :
5319 1 : void multiConditionAlwaysTrue() {
5320 1 : check("void f() {\n"
5321 : " int val = 0;\n"
5322 : " if (val < 0) continue;\n"
5323 : " if (val > 0) {}\n"
5324 : "}");
5325 1 : ASSERT_EQUALS("", errout_str());
5326 :
5327 1 : check("void f() {\n"
5328 : " int val = 0;\n"
5329 : " if (val < 0) {\n"
5330 : " if (val > 0) {}\n"
5331 : " }\n"
5332 : "}");
5333 1 : ASSERT_EQUALS("", errout_str());
5334 :
5335 1 : check("void f() {\n"
5336 : " int val = 0;\n"
5337 : " if (val < 0) {\n"
5338 : " if (val < 0) {}\n"
5339 : " }\n"
5340 : "}");
5341 1 : ASSERT_EQUALS("", errout_str());
5342 :
5343 1 : check("void f() {\n"
5344 : " int activate = 0;\n"
5345 : " int foo = 0;\n"
5346 : " if (activate) {}\n"
5347 : " else if (foo) {}\n"
5348 : "}");
5349 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'activate' is always false\n"
5350 : "[test.cpp:5]: (style) Condition 'foo' is always false\n", errout_str());
5351 :
5352 : // #6904
5353 1 : check("void f() {\n"
5354 : " const int b[2] = { 1,0 };\n"
5355 : " if(b[1] == 2) {}\n"
5356 : "}");
5357 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'b[1]==2' is always false\n", errout_str());
5358 :
5359 : // #9878
5360 1 : check("void f(bool a, bool b) {\n"
5361 : " if (a && b){;}\n"
5362 : " else if (!a && b){;}\n"
5363 : " else if (!a && !b){;}\n"
5364 : " else {;}\n"
5365 : "}\n");
5366 1 : ASSERT_EQUALS("", errout_str());
5367 : }
5368 :
5369 1 : void duplicateCondition() {
5370 1 : check("void f(bool x) {\n"
5371 : " if(x) {}\n"
5372 : " if(x) {}\n"
5373 : "}");
5374 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition\n",
5375 : errout_str());
5376 :
5377 1 : check("void f(int x) {\n"
5378 : " if(x == 1) {}\n"
5379 : " if(x == 1) {}\n"
5380 : "}");
5381 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition\n",
5382 : errout_str());
5383 :
5384 1 : check("void f(int x) {\n"
5385 : " if(x == 1) {}\n"
5386 : " if(x == 2) {}\n"
5387 : "}");
5388 1 : ASSERT_EQUALS("", errout_str());
5389 :
5390 1 : check("void f(int x) {\n"
5391 : " if(x == 1) {}\n"
5392 : " if(x != 1) {}\n"
5393 : "}");
5394 1 : ASSERT_EQUALS("", errout_str());
5395 :
5396 1 : check("void f(bool x) {\n"
5397 : " if(x) {}\n"
5398 : " g();\n"
5399 : " if(x) {}\n"
5400 : "}");
5401 1 : ASSERT_EQUALS("", errout_str());
5402 :
5403 1 : check("void f(int x) {\n"
5404 : " if(x == 1) { x++; }\n"
5405 : " if(x == 1) {}\n"
5406 : "}");
5407 1 : ASSERT_EQUALS("", errout_str());
5408 :
5409 : // #8996
5410 1 : check("void g(int** v);\n"
5411 : "void f() {\n"
5412 : " int a = 0;\n"
5413 : " int b = 0;\n"
5414 : " int* d[] = {&a, &b};\n"
5415 : " g(d);\n"
5416 : " if (a) {}\n"
5417 : " if (b) {}\n"
5418 : "}");
5419 1 : ASSERT_EQUALS("", errout_str());
5420 :
5421 : // #9311
5422 1 : check("struct c {\n"
5423 : " int* p;\n"
5424 : "};\n"
5425 : "void g(struct c* v);\n"
5426 : "void f() {\n"
5427 : " int a = 0;\n"
5428 : " int b = 0;\n"
5429 : " struct c d[] = {{&a}, {&b}};\n"
5430 : " g(d);\n"
5431 : " if (a) {}\n"
5432 : " if (b) {}\n"
5433 : "}");
5434 1 : ASSERT_EQUALS("", errout_str());
5435 :
5436 : // #8993
5437 1 : check("void f(const std::string& x) {\n"
5438 : " auto y = x;\n"
5439 : " if (x.empty()) y = \"1\";\n"
5440 : " if (y.empty()) return;\n"
5441 : "}");
5442 1 : ASSERT_EQUALS("", errout_str());
5443 :
5444 : // #9106
5445 1 : check("struct A {int b;};\n"
5446 : "void f(A a, int c) {\n"
5447 : " if (a.b) a.b = c;\n"
5448 : " if (a.b) {}\n"
5449 : "}");
5450 1 : ASSERT_EQUALS("", errout_str());
5451 :
5452 1 : check("struct A {\n"
5453 : " int a;\n"
5454 : " void b() const {\n"
5455 : " return a == 1;\n"
5456 : " }\n"
5457 : " void c();\n"
5458 : " void d() {\n"
5459 : " if(b()) {\n"
5460 : " c();\n"
5461 : " }\n"
5462 : " if (b()) {\n"
5463 : " a = 3;\n"
5464 : " }\n"
5465 : " }\n"
5466 : "}\n");
5467 1 : ASSERT_EQUALS("", errout_str());
5468 :
5469 1 : check("struct A {\n"
5470 : " int a;\n"
5471 : " void b() const {\n"
5472 : " return a == 1;\n"
5473 : " }\n"
5474 : " void d() {\n"
5475 : " if(b()) {\n"
5476 : " a = 2;\n"
5477 : " }\n"
5478 : " if (b()) {\n"
5479 : " a = 3;\n"
5480 : " }\n"
5481 : " }\n"
5482 : "}\n");
5483 1 : ASSERT_EQUALS("", errout_str());
5484 :
5485 1 : check("struct A {\n"
5486 : " int a;\n"
5487 : " void b() const {\n"
5488 : " return a == 1;\n"
5489 : " }\n"
5490 : " void d() {\n"
5491 : " if(b()) {\n"
5492 : " }\n"
5493 : " if (b()) {\n"
5494 : " a = 3;\n"
5495 : " }\n"
5496 : " }\n"
5497 : "}\n");
5498 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) The if condition is the same as the previous if condition\n",
5499 : errout_str());
5500 :
5501 1 : check("void f(bool a, bool b) {\n"
5502 : " auto g = [&] { b = !a; };\n"
5503 : " if (b)\n"
5504 : " g();\n"
5505 : " if (b) {}\n"
5506 : "}\n");
5507 1 : ASSERT_EQUALS("", errout_str());
5508 :
5509 1 : check("void g(bool& a);\n"
5510 : "void f(bool b) {\n"
5511 : " auto h = std::bind(&g, std::ref(b));\n"
5512 : " if (b)\n"
5513 : " h();\n"
5514 : " if (b) {}\n"
5515 : "}\n");
5516 1 : ASSERT_EQUALS("", errout_str());
5517 :
5518 1 : check("void f(int *i) {\n"
5519 : " if (*i == 0) {\n"
5520 : " *i = 1;\n"
5521 : " }\n"
5522 : " if (*i == 0) {\n"
5523 : " }\n"
5524 : "}\n");
5525 1 : ASSERT_EQUALS("", errout_str());
5526 :
5527 1 : check("void g(std::function<void()>);\n"
5528 : "void f(std::vector<int> v) {\n"
5529 : " auto x = [&v] { v.push_back(1); };\n"
5530 : " if(v.empty()) {\n"
5531 : " g(x);\n"
5532 : " }\n"
5533 : " if(v.empty())\n"
5534 : " return;\n"
5535 : " return;\n"
5536 : "}\n");
5537 1 : ASSERT_EQUALS("", errout_str());
5538 :
5539 1 : check("struct S { int i; };\n"
5540 : "int f(const S& s) {\n"
5541 : " int a = 0, b = 0;\n"
5542 : " if (s.i == 0)\n"
5543 : " a = 1;\n"
5544 : " if (s.i == 0)\n"
5545 : " b = 1;\n"
5546 : " return a + b;\n"
5547 : "}\n");
5548 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (style) The if condition is the same as the previous if condition\n", errout_str());
5549 :
5550 : // do not crash
5551 1 : check("void assign(const MMA& other) {\n"
5552 : " if (mPA.cols != other.mPA.cols || mPA.rows != other.mPA.rows)\n"
5553 : " ;\n"
5554 : " if (other.mPA.cols > 0 && other.mPA.rows > 0)\n"
5555 : " ;\n"
5556 : "}");
5557 : }
5558 :
5559 1 : void checkInvalidTestForOverflow() {
5560 1 : check("void f(char *p, unsigned int x) {\n"
5561 : " assert((p + x) < p);\n"
5562 : "}");
5563 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)<p'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always false.\n", errout_str());
5564 :
5565 1 : check("void f(char *p, unsigned int x) {\n"
5566 : " assert((p + x) >= p);\n"
5567 : "}");
5568 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)>=p'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always true.\n", errout_str());
5569 :
5570 1 : check("void f(char *p, unsigned int x) {\n"
5571 : " assert(p > (p + x));\n"
5572 : "}");
5573 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p>(p+x)'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always false.\n", errout_str());
5574 :
5575 1 : check("void f(char *p, unsigned int x) {\n"
5576 : " assert(p <= (p + x));\n"
5577 : "}");
5578 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p<=(p+x)'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always true.\n", errout_str());
5579 :
5580 1 : check("void f(signed int x) {\n" // unsigned overflow => don't warn
5581 : " assert(x + 100U < x);\n"
5582 : "}");
5583 1 : ASSERT_EQUALS("", errout_str());
5584 :
5585 :
5586 : // x + c < x
5587 :
5588 : #define MSG(EXPR, RESULT) "[test.cpp:1]: (warning) Invalid test for overflow '" EXPR "'; signed integer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always " RESULT ".\n"
5589 :
5590 1 : check("int f(int x) { return x + 10 > x; }");
5591 1 : ASSERT_EQUALS(MSG("x+10>x", "true"), errout_str());
5592 :
5593 1 : check("int f(int x) { return x + 10 >= x; }");
5594 1 : ASSERT_EQUALS(MSG("x+10>=x", "true"), errout_str());
5595 :
5596 1 : check("int f(int x) { return x + 10 < x; }");
5597 1 : ASSERT_EQUALS(MSG("x+10<x", "false"), errout_str());
5598 :
5599 1 : check("int f(int x) { return x + 10 <= x; }");
5600 1 : ASSERT_EQUALS(MSG("x+10<=x", "false"), errout_str());
5601 :
5602 1 : check("int f(int x) { return x - 10 > x; }");
5603 1 : ASSERT_EQUALS(MSG("x-10>x", "false"), errout_str());
5604 :
5605 1 : check("int f(int x) { return x - 10 >= x; }");
5606 1 : ASSERT_EQUALS(MSG("x-10>=x", "false"), errout_str());
5607 :
5608 1 : check("int f(int x) { return x - 10 < x; }");
5609 1 : ASSERT_EQUALS(MSG("x-10<x", "true"), errout_str());
5610 :
5611 1 : check("int f(int x) { return x - 10 <= x; }");
5612 1 : ASSERT_EQUALS(MSG("x-10<=x", "true"), errout_str());
5613 :
5614 : // x + y < x
5615 : #undef MSG
5616 : #define MSG(EXPR, RESULT) "[test.cpp:1]: (warning) Invalid test for overflow '" EXPR "'; signed integer overflow is undefined behavior. Some mainstream compilers removes handling of overflows when optimising the code and change the code to '" RESULT "'.\n"
5617 :
5618 1 : check("int f(int x, int y) { return x + y < x; }");
5619 1 : ASSERT_EQUALS(MSG("x+y<x", "y<0"), errout_str());
5620 :
5621 1 : check("int f(int x, int y) { return x + y <= x; }");
5622 1 : ASSERT_EQUALS(MSG("x+y<=x", "y<=0"), errout_str());
5623 :
5624 1 : check("int f(int x, int y) { return x + y > x; }");
5625 1 : ASSERT_EQUALS(MSG("x+y>x", "y>0"), errout_str());
5626 :
5627 1 : check("int f(int x, int y) { return x + y >= x; }");
5628 1 : ASSERT_EQUALS(MSG("x+y>=x", "y>=0"), errout_str());
5629 :
5630 : // x - y < x
5631 1 : check("int f(int x, int y) { return x - y < x; }");
5632 1 : ASSERT_EQUALS(MSG("x-y<x", "y>0"), errout_str());
5633 :
5634 1 : check("int f(int x, int y) { return x - y <= x; }");
5635 1 : ASSERT_EQUALS(MSG("x-y<=x", "y>=0"), errout_str());
5636 :
5637 1 : check("int f(int x, int y) { return x - y > x; }");
5638 1 : ASSERT_EQUALS(MSG("x-y>x", "y<0"), errout_str());
5639 :
5640 1 : check("int f(int x, int y) { return x - y >= x; }");
5641 1 : ASSERT_EQUALS(MSG("x-y>=x", "y<=0"), errout_str());
5642 : }
5643 :
5644 1 : void checkConditionIsAlwaysTrueOrFalseInsideIfWhile() {
5645 1 : check("void f() {\n"
5646 : " enum states {A,B,C};\n"
5647 : " const unsigned g_flags = B|C;\n"
5648 : " if(g_flags & A) {}\n"
5649 : "}");
5650 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'g_flags&A' is always false\n", errout_str());
5651 :
5652 1 : check("void f() {\n"
5653 : " int a = 5;"
5654 : " if(a) {}\n"
5655 : "}");
5656 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'a' is always true\n", errout_str());
5657 :
5658 1 : check("void f() {\n"
5659 : " int a = 5;"
5660 : " while(a + 1) { a--; }\n"
5661 : "}");
5662 1 : ASSERT_EQUALS("", errout_str());
5663 :
5664 1 : check("void f() {\n"
5665 : " int a = 5;"
5666 : " while(a + 1) { return; }\n"
5667 : "}");
5668 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'a+1' is always true\n", errout_str());
5669 : }
5670 :
5671 1 : void alwaysTrueFalseInLogicalOperators() {
5672 1 : check("bool f();\n"
5673 : "void foo() { bool x = true; if(x||f()) {}}");
5674 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'x' is always true\n", errout_str());
5675 :
5676 1 : check("void foo(bool b) { bool x = true; if(x||b) {}}");
5677 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Condition 'x' is always true\n", errout_str());
5678 :
5679 1 : check("void foo(bool b) { if(true||b) {}}");
5680 1 : ASSERT_EQUALS("", errout_str());
5681 :
5682 1 : check("bool f();\n"
5683 : "void foo() { bool x = false; if(x||f()) {}}");
5684 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'x' is always false\n", errout_str());
5685 :
5686 1 : check("bool f();\n"
5687 : "void foo() { bool x = false; if(x&&f()) {}}");
5688 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'x' is always false\n", errout_str());
5689 :
5690 1 : check("void foo(bool b) { bool x = false; if(x&&b) {}}");
5691 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Condition 'x' is always false\n", errout_str());
5692 :
5693 1 : check("void foo(bool b) { if(false&&b) {}}");
5694 1 : ASSERT_EQUALS("", errout_str());
5695 :
5696 1 : check("bool f();\n"
5697 : "void foo() { bool x = true; if(x&&f()) {}}");
5698 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'x' is always true\n", errout_str());
5699 :
5700 : // #9578
5701 1 : check("bool f(const std::string &s) {\n"
5702 : " return s.size()>2U && s[0]=='4' && s[0]=='2';\n"
5703 : "}\n");
5704 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Return value 's[0]=='2'' is always false\n", errout_str());
5705 :
5706 1 : check("void f(int i) { if (i == 1 || 2) {} }\n"); // #12487
5707 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Condition 'i==1||2' is always true\n", errout_str());
5708 :
5709 1 : check("enum E { E1 = 1, E2 = 2 };\n"
5710 : "void f(int i) { if (i == E1 || E2) {} }\n");
5711 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i==E1||E2' is always true\n", errout_str());
5712 : }
5713 :
5714 1 : void pointerAdditionResultNotNull() {
5715 1 : check("void f(char *ptr) {\n"
5716 : " if (ptr + 1 != 0);\n"
5717 : "}");
5718 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison is wrong. Result of 'ptr+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour.\n", errout_str());
5719 : }
5720 :
5721 1 : void duplicateConditionalAssign() {
5722 1 : setMultiline();
5723 :
5724 1 : check("void f(int& x, int y) {\n"
5725 : " if (x == y)\n"
5726 : " x = y;\n"
5727 : "}");
5728 1 : ASSERT_EQUALS("test.cpp:3:style:Assignment 'x=y' is redundant with condition 'x==y'.\n"
5729 : "test.cpp:2:note:Condition 'x==y'\n"
5730 : "test.cpp:3:note:Assignment 'x=y' is redundant\n", errout_str());
5731 :
5732 1 : check("void f(int& x, int y) {\n"
5733 : " if (x != y)\n"
5734 : " x = y;\n"
5735 : "}");
5736 1 : ASSERT_EQUALS("test.cpp:2:style:The statement 'if (x!=y) x=y' is logically equivalent to 'x=y'.\n"
5737 : "test.cpp:3:note:Assignment 'x=y'\n"
5738 : "test.cpp:2:note:Condition 'x!=y' is redundant\n", errout_str());
5739 :
5740 1 : check("void f(int& x, int y) {\n"
5741 : " if (x == y)\n"
5742 : " x = y;\n"
5743 : " else\n"
5744 : " x = 1;\n"
5745 : "}");
5746 1 : ASSERT_EQUALS("test.cpp:3:style:Assignment 'x=y' is redundant with condition 'x==y'.\n"
5747 : "test.cpp:2:note:Condition 'x==y'\n"
5748 : "test.cpp:3:note:Assignment 'x=y' is redundant\n", errout_str());
5749 :
5750 1 : check("void f(int& x, int y) {\n"
5751 : " if (x != y)\n"
5752 : " x = y;\n"
5753 : " else\n"
5754 : " x = 1;\n"
5755 : "}");
5756 1 : ASSERT_EQUALS("", errout_str());
5757 :
5758 1 : check("void f(int& x, int y) {\n"
5759 : " if (x == y)\n"
5760 : " x = y + 1;\n"
5761 : "}");
5762 1 : ASSERT_EQUALS("", errout_str());
5763 :
5764 1 : check("void g();\n"
5765 : "void f(int& x, int y) {\n"
5766 : " if (x == y) {\n"
5767 : " x = y;\n"
5768 : " g();\n"
5769 : " }\n"
5770 : "}");
5771 1 : ASSERT_EQUALS("", errout_str());
5772 :
5773 1 : check("bool f(bool b) {\n"
5774 : " if (b)\n"
5775 : " b = false;\n"
5776 : " else\n"
5777 : " g();\n"
5778 : " return b;\n"
5779 : "}\n");
5780 1 : ASSERT_EQUALS("", errout_str());
5781 :
5782 1 : check("void f(int& i) {\n"
5783 : " if (!i)\n"
5784 : " i = 1; \n"
5785 : "}\n");
5786 1 : ASSERT_EQUALS("", errout_str());
5787 :
5788 1 : check("struct S {\n" // #9406
5789 : " S() : b(false) {}\n"
5790 : " void f() {\n"
5791 : " if (b) b = true;\n"
5792 : " if (b) b = false;\n"
5793 : " if (!b) b = true;\n"
5794 : " if (!b) b = false;\n"
5795 : " }\n"
5796 : " bool b;\n"
5797 : "};\n");
5798 1 : ASSERT_EQUALS("test.cpp:4:style:The statement 'if (b) b=true' is redundant.\n"
5799 : "test.cpp:4:note:Assignment 'b=true'\n"
5800 : "test.cpp:4:note:Condition 'b' is redundant\n"
5801 : "test.cpp:5:style:The statement 'if (b) b=false' is logically equivalent to 'b=false'.\n"
5802 : "test.cpp:5:note:Assignment 'b=false'\n"
5803 : "test.cpp:5:note:Condition 'b' is redundant\n"
5804 : "test.cpp:6:style:The statement 'if (!b) b=true' is logically equivalent to 'b=true'.\n"
5805 : "test.cpp:6:note:Assignment 'b=true'\n"
5806 : "test.cpp:6:note:Condition '!b' is redundant\n"
5807 : "test.cpp:7:style:The statement 'if (!b) b=false' is redundant.\n"
5808 : "test.cpp:7:note:Assignment 'b=false'\n"
5809 : "test.cpp:7:note:Condition '!b' is redundant\n",
5810 : errout_str());
5811 : }
5812 :
5813 1 : void checkAssignmentInCondition() {
5814 1 : check("void f(std::string s) {\n"
5815 : " if (s=\"123\"){}\n"
5816 : "}");
5817 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Suspicious assignment in condition. Condition 's=\"123\"' is always true.\n", errout_str());
5818 :
5819 1 : check("void f(std::string *p) {\n"
5820 : " if (p=foo()){}\n"
5821 : "}");
5822 1 : ASSERT_EQUALS("", errout_str());
5823 :
5824 1 : check("void f(uint32_t u) {\n" // #2490
5825 : " if ((u = 0x00000000) || (u = 0xffffffff)) {}\n"
5826 : "}\n");
5827 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'u=0x00000000' is always false\n"
5828 : "[test.cpp:2]: (style) Condition 'u=0xffffffff' is always true\n",
5829 : errout_str());
5830 : }
5831 :
5832 1 : void compareOutOfTypeRange() {
5833 1 : const Settings settingsUnix64 = settingsBuilder().severity(Severity::style).platform(Platform::Type::Unix64).build();
5834 :
5835 1 : check("void f(unsigned char c) {\n"
5836 : " if (c == 256) {}\n"
5837 : "}", settingsUnix64);
5838 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false.\n", errout_str());
5839 :
5840 1 : check("void f(unsigned char* b, int i) {\n" // #6372
5841 : " if (b[i] == 256) {}\n"
5842 : "}", settingsUnix64);
5843 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false.\n", errout_str());
5844 :
5845 1 : check("void f(unsigned char c) {\n"
5846 : " if (c == 255) {}\n"
5847 : "}", settingsUnix64);
5848 1 : ASSERT_EQUALS("", errout_str());
5849 :
5850 1 : check("void f(bool b) {\n"
5851 : " if (b == true) {}\n"
5852 : "}", settingsUnix64);
5853 1 : ASSERT_EQUALS("", errout_str());
5854 :
5855 : // #10372
5856 1 : check("void f(signed char x) {\n"
5857 : " if (x == 0xff) {}\n"
5858 : "}", settingsUnix64);
5859 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'signed char' against value 255. Condition is always false.\n", errout_str());
5860 :
5861 1 : check("void f(short x) {\n"
5862 : " if (x == 0xffff) {}\n"
5863 : "}", settingsUnix64);
5864 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'signed short' against value 65535. Condition is always false.\n", errout_str());
5865 :
5866 1 : check("void f(int x) {\n"
5867 : " if (x == 0xffffffff) {}\n"
5868 : "}", settingsUnix64);
5869 1 : ASSERT_EQUALS("", errout_str());
5870 :
5871 1 : check("void f(long x) {\n"
5872 : " if (x == ~0L) {}\n"
5873 : "}", settingsUnix64);
5874 1 : ASSERT_EQUALS("", errout_str());
5875 :
5876 1 : check("void f(long long x) {\n"
5877 : " if (x == ~0LL) {}\n"
5878 : "}", settingsUnix64);
5879 1 : ASSERT_EQUALS("", errout_str());
5880 :
5881 1 : check("int f(int x) {\n"
5882 : " const int i = 0xFFFFFFFF;\n"
5883 : " if (x == i) {}\n"
5884 : "}", settingsUnix64);
5885 1 : ASSERT_EQUALS("", errout_str());
5886 :
5887 1 : check("void f() {\n"
5888 : " char c;\n"
5889 : " if ((c = foo()) != -1) {}\n"
5890 : "}", settingsUnix64);
5891 1 : ASSERT_EQUALS("", errout_str());
5892 :
5893 1 : check("void f(int x) {\n"
5894 : " if (x < 3000000000) {}\n"
5895 : "}", settingsUnix64);
5896 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'signed int' against value 3000000000. Condition is always true.\n", errout_str());
5897 :
5898 1 : check("void f(const signed char i) {\n" // #8545
5899 : " if (i > -129) {}\n" // warn
5900 : " if (i >= -128) {}\n" // warn
5901 : " if (i >= -127) {}\n"
5902 : " if (i < +128) {}\n" // warn
5903 : " if (i <= +127) {}\n" // warn
5904 : " if (i <= +126) {}\n"
5905 : "}\n", settingsUnix64);
5906 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'const signed char' against value -129. Condition is always true.\n"
5907 : "[test.cpp:3]: (style) Comparing expression of type 'const signed char' against value -128. Condition is always true.\n"
5908 : "[test.cpp:5]: (style) Comparing expression of type 'const signed char' against value 128. Condition is always true.\n"
5909 : "[test.cpp:6]: (style) Comparing expression of type 'const signed char' against value 127. Condition is always true.\n",
5910 : errout_str());
5911 :
5912 1 : check("void f(const unsigned char u) {\n"
5913 : " if (u > 0) {}\n"
5914 : " if (u < 0) {}\n" // warn
5915 : " if (u >= 0) {}\n" // warn
5916 : " if (u <= 0) {}\n"
5917 : " if (u > 255) {}\n" // warn
5918 : " if (u < 255) {}\n"
5919 : " if (u >= 255) {}\n"
5920 : " if (u <= 255) {}\n" // warn
5921 : " if (0 < u) {}\n"
5922 : " if (0 > u) {}\n" // warn
5923 : " if (0 <= u) {}\n" // warn
5924 : " if (0 >= u) {}\n"
5925 : " if (255 < u) {}\n" // warn
5926 : " if (255 > u) {}\n"
5927 : " if (255 <= u) {}\n"
5928 : " if (255 >= u) {}\n" // warn
5929 : "}\n", settingsUnix64);
5930 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false.\n"
5931 : "[test.cpp:4]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true.\n"
5932 : "[test.cpp:6]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false.\n"
5933 : "[test.cpp:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true.\n"
5934 : "[test.cpp:11]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false.\n"
5935 : "[test.cpp:12]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true.\n"
5936 : "[test.cpp:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false.\n"
5937 : "[test.cpp:17]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true.\n",
5938 : errout_str());
5939 : }
5940 :
5941 1 : void knownConditionCast() { // #9976
5942 1 : check("void f(int i) {\n"
5943 : " if (i < 0 || (unsigned)i > 5) {}\n"
5944 : "}\n");
5945 1 : ASSERT_EQUALS("", errout_str());
5946 : }
5947 :
5948 1 : void knownConditionIncrementLoop() { // #9808
5949 1 : check("void f() {\n"
5950 : " int a = 0;\n"
5951 : " while (++a < 5) {}\n"
5952 : " if (a == 1) {}\n"
5953 : " std::cout << a;\n"
5954 : "}\n");
5955 1 : ASSERT_EQUALS("", errout_str());
5956 : }
5957 :
5958 1 : void knownConditionAfterBailout() { // #12526
5959 1 : check(
5960 : "#include <list>\n"
5961 : "int func()\n"
5962 : "{\n"
5963 : " return VALUE_1;"
5964 : "}\n"
5965 : "\n"
5966 : "struct S1 {\n"
5967 : " bool b{};\n"
5968 : "};\n"
5969 : "\n"
5970 : "struct S {\n"
5971 : " void f(const std::list<int>& l) const\n"
5972 : " {\n"
5973 : " if (mS.b)\n"
5974 : " return;\n"
5975 : " for (int i : l)\n"
5976 : " {\n"
5977 : " (void)i;\n"
5978 : " if (mS.b)\n"
5979 : " continue;\n"
5980 : " }\n"
5981 : " }\n"
5982 : "\n"
5983 : " S1 mS;\n"
5984 : "};"
5985 : );
5986 1 : ASSERT_EQUALS("[test.cpp:13] -> [test.cpp:18]: (style) Condition 'mS.b' is always false\n", errout_str());
5987 : }
5988 : };
5989 :
5990 : REGISTER_TEST(TestCondition)
|