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 "checkother.h"
20 : #include "errortypes.h"
21 : #include "fixture.h"
22 : #include "helpers.h"
23 : #include "platform.h"
24 : #include "settings.h"
25 : #include "standards.h"
26 : #include "tokenize.h"
27 :
28 : #include <string>
29 : #include <vector>
30 :
31 : class TestOther : public TestFixture {
32 : public:
33 1 : TestOther() : TestFixture("TestOther") {}
34 :
35 : private:
36 1 : /*const*/ Settings _settings = settingsBuilder().library("std.cfg").build();
37 :
38 1 : void run() override {
39 1 : TEST_CASE(emptyBrackets);
40 :
41 1 : TEST_CASE(zeroDiv1);
42 1 : TEST_CASE(zeroDiv2);
43 1 : TEST_CASE(zeroDiv3);
44 1 : TEST_CASE(zeroDiv4);
45 1 : TEST_CASE(zeroDiv5);
46 1 : TEST_CASE(zeroDiv6);
47 1 : TEST_CASE(zeroDiv7); // #4930
48 1 : TEST_CASE(zeroDiv8);
49 1 : TEST_CASE(zeroDiv9);
50 1 : TEST_CASE(zeroDiv10);
51 1 : TEST_CASE(zeroDiv11);
52 1 : TEST_CASE(zeroDiv12);
53 1 : TEST_CASE(zeroDiv13);
54 1 : TEST_CASE(zeroDiv14); // #1169
55 1 : TEST_CASE(zeroDiv15); // #8319
56 1 : TEST_CASE(zeroDiv16); // #11158
57 1 : TEST_CASE(zeroDiv17); // #9931
58 1 : TEST_CASE(zeroDiv18);
59 1 : TEST_CASE(zeroDiv19);
60 :
61 1 : TEST_CASE(zeroDivCond); // division by zero / useless condition
62 :
63 1 : TEST_CASE(nanInArithmeticExpression);
64 :
65 1 : TEST_CASE(varScope1);
66 1 : TEST_CASE(varScope2);
67 1 : TEST_CASE(varScope3);
68 1 : TEST_CASE(varScope4);
69 1 : TEST_CASE(varScope5);
70 1 : TEST_CASE(varScope6);
71 1 : TEST_CASE(varScope7);
72 1 : TEST_CASE(varScope8);
73 1 : TEST_CASE(varScope9); // classes may have extra side-effects
74 1 : TEST_CASE(varScope10); // Undefined macro FOR
75 1 : TEST_CASE(varScope11); // #2475 - struct initialization is not inner scope
76 1 : TEST_CASE(varScope12);
77 1 : TEST_CASE(varScope13); // variable usage in inner loop
78 1 : TEST_CASE(varScope14);
79 1 : TEST_CASE(varScope15); // #4573 if-else-if
80 1 : TEST_CASE(varScope16);
81 1 : TEST_CASE(varScope17);
82 1 : TEST_CASE(varScope18);
83 1 : TEST_CASE(varScope20); // Ticket #5103
84 1 : TEST_CASE(varScope21); // Ticket #5382
85 1 : TEST_CASE(varScope22); // Ticket #5684
86 1 : TEST_CASE(varScope23); // Ticket #6154
87 1 : TEST_CASE(varScope24); // pointer / reference
88 1 : TEST_CASE(varScope25); // time_t
89 1 : TEST_CASE(varScope26); // range for loop, map
90 1 : TEST_CASE(varScope27); // #7733 - #if
91 1 : TEST_CASE(varScope28); // #10527
92 1 : TEST_CASE(varScope29); // #10888
93 1 : TEST_CASE(varScope30); // #8541
94 1 : TEST_CASE(varScope31); // #11099
95 1 : TEST_CASE(varScope32); // #11441
96 1 : TEST_CASE(varScope33);
97 1 : TEST_CASE(varScope34);
98 1 : TEST_CASE(varScope35);
99 1 : TEST_CASE(varScope36); // #12158
100 1 : TEST_CASE(varScope37); // #12158
101 1 : TEST_CASE(varScope38);
102 1 : TEST_CASE(varScope39);
103 1 : TEST_CASE(varScope40);
104 :
105 1 : TEST_CASE(oldStylePointerCast);
106 1 : TEST_CASE(invalidPointerCast);
107 :
108 1 : TEST_CASE(passedByValue);
109 1 : TEST_CASE(passedByValue_nonConst);
110 1 : TEST_CASE(passedByValue_externC);
111 :
112 1 : TEST_CASE(constVariable);
113 1 : TEST_CASE(constParameterCallback);
114 1 : TEST_CASE(constPointer);
115 :
116 1 : TEST_CASE(switchRedundantAssignmentTest);
117 1 : TEST_CASE(switchRedundantOperationTest);
118 1 : TEST_CASE(switchRedundantBitwiseOperationTest);
119 1 : TEST_CASE(unreachableCode);
120 1 : TEST_CASE(redundantContinue);
121 :
122 1 : TEST_CASE(suspiciousCase);
123 1 : TEST_CASE(suspiciousEqualityComparison);
124 1 : TEST_CASE(suspiciousUnaryPlusMinus); // #8004
125 :
126 1 : TEST_CASE(selfAssignment);
127 1 : TEST_CASE(trac1132);
128 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickFunction1);
129 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickFunction2);
130 1 : TEST_CASE(testMisusedScopeObjectPicksClass);
131 1 : TEST_CASE(testMisusedScopeObjectPicksStruct);
132 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickIf);
133 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickConstructorDeclaration);
134 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickFunctor);
135 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors);
136 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject);
137 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickPureC);
138 1 : TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass);
139 1 : TEST_CASE(testMisusedScopeObjectInConstructor);
140 1 : TEST_CASE(testMisusedScopeObjectStandardType);
141 1 : TEST_CASE(testMisusedScopeObjectNamespace);
142 1 : TEST_CASE(testMisusedScopeObjectAssignment); // #11371
143 1 : TEST_CASE(trac2071);
144 1 : TEST_CASE(trac2084);
145 1 : TEST_CASE(trac3693);
146 :
147 1 : TEST_CASE(clarifyCalculation);
148 1 : TEST_CASE(clarifyStatement);
149 :
150 1 : TEST_CASE(duplicateBranch);
151 1 : TEST_CASE(duplicateBranch1); // tests extracted by http://www.viva64.com/en/b/0149/ ( Comparison between PVS-Studio and cppcheck ): Errors detected in Quake 3: Arena by PVS-Studio: Fragment 2
152 1 : TEST_CASE(duplicateBranch2); // empty macro
153 1 : TEST_CASE(duplicateBranch3);
154 1 : TEST_CASE(duplicateBranch4);
155 1 : TEST_CASE(duplicateBranch5); // make sure the Token attributes are compared
156 1 : TEST_CASE(duplicateBranch6);
157 1 : TEST_CASE(duplicateExpression1);
158 1 : TEST_CASE(duplicateExpression2); // ticket #2730
159 1 : TEST_CASE(duplicateExpression3); // ticket #3317
160 1 : TEST_CASE(duplicateExpression4); // ticket #3354 (++)
161 1 : TEST_CASE(duplicateExpression5); // ticket #3749 (macros with same values)
162 1 : TEST_CASE(duplicateExpression6); // ticket #4639
163 1 : TEST_CASE(duplicateExpression7);
164 1 : TEST_CASE(duplicateExpression8);
165 1 : TEST_CASE(duplicateExpression9); // #9320
166 1 : TEST_CASE(duplicateExpression10); // #9485
167 1 : TEST_CASE(duplicateExpression11); // #8916 (function call)
168 1 : TEST_CASE(duplicateExpression12); // #10026
169 1 : TEST_CASE(duplicateExpression13); // #7899
170 1 : TEST_CASE(duplicateExpression14); // #9871
171 1 : TEST_CASE(duplicateExpression15); // #10650
172 1 : TEST_CASE(duplicateExpression16); // #10569
173 1 : TEST_CASE(duplicateExpression17); // #12036
174 1 : TEST_CASE(duplicateExpressionLoop);
175 1 : TEST_CASE(duplicateValueTernary);
176 1 : TEST_CASE(duplicateExpressionTernary); // #6391
177 1 : TEST_CASE(duplicateExpressionTemplate); // #6930
178 1 : TEST_CASE(duplicateExpressionCompareWithZero);
179 1 : TEST_CASE(oppositeExpression);
180 1 : TEST_CASE(duplicateVarExpression);
181 1 : TEST_CASE(duplicateVarExpressionUnique);
182 1 : TEST_CASE(duplicateVarExpressionAssign);
183 1 : TEST_CASE(duplicateVarExpressionCrash);
184 1 : TEST_CASE(multiConditionSameExpression);
185 :
186 1 : TEST_CASE(checkSignOfUnsignedVariable);
187 1 : TEST_CASE(checkSignOfPointer);
188 :
189 1 : TEST_CASE(checkSuspiciousSemicolon1);
190 1 : TEST_CASE(checkSuspiciousSemicolon2);
191 1 : TEST_CASE(checkSuspiciousSemicolon3);
192 1 : TEST_CASE(checkSuspiciousComparison);
193 :
194 1 : TEST_CASE(checkInvalidFree);
195 :
196 1 : TEST_CASE(checkRedundantCopy);
197 :
198 1 : TEST_CASE(checkNegativeShift);
199 :
200 1 : TEST_CASE(incompleteArrayFill);
201 :
202 1 : TEST_CASE(redundantVarAssignment);
203 1 : TEST_CASE(redundantVarAssignment_trivial);
204 1 : TEST_CASE(redundantVarAssignment_struct);
205 1 : TEST_CASE(redundantVarAssignment_7133);
206 1 : TEST_CASE(redundantVarAssignment_stackoverflow);
207 1 : TEST_CASE(redundantVarAssignment_lambda);
208 1 : TEST_CASE(redundantVarAssignment_loop);
209 1 : TEST_CASE(redundantVarAssignment_after_switch);
210 1 : TEST_CASE(redundantVarAssignment_pointer);
211 1 : TEST_CASE(redundantVarAssignment_pointer_parameter);
212 1 : TEST_CASE(redundantVarAssignment_array);
213 1 : TEST_CASE(redundantVarAssignment_switch_break);
214 1 : TEST_CASE(redundantInitialization);
215 1 : TEST_CASE(redundantMemWrite);
216 :
217 1 : TEST_CASE(varFuncNullUB);
218 :
219 1 : TEST_CASE(checkCastIntToCharAndBack); // ticket #160
220 :
221 1 : TEST_CASE(checkCommaSeparatedReturn);
222 1 : TEST_CASE(checkPassByReference);
223 :
224 1 : TEST_CASE(checkComparisonFunctionIsAlwaysTrueOrFalse);
225 :
226 1 : TEST_CASE(integerOverflow); // #5895
227 :
228 1 : TEST_CASE(redundantPointerOp);
229 1 : TEST_CASE(test_isSameExpression);
230 1 : TEST_CASE(raceAfterInterlockedDecrement);
231 :
232 1 : TEST_CASE(testUnusedLabel);
233 :
234 1 : TEST_CASE(testEvaluationOrder);
235 1 : TEST_CASE(testEvaluationOrderSelfAssignment);
236 1 : TEST_CASE(testEvaluationOrderMacro);
237 1 : TEST_CASE(testEvaluationOrderSequencePointsFunctionCall);
238 1 : TEST_CASE(testEvaluationOrderSequencePointsComma);
239 1 : TEST_CASE(testEvaluationOrderSizeof);
240 :
241 1 : TEST_CASE(testUnsignedLessThanZero);
242 :
243 1 : TEST_CASE(doubleMove1);
244 1 : TEST_CASE(doubleMoveMemberInitialization1);
245 1 : TEST_CASE(doubleMoveMemberInitialization2);
246 1 : TEST_CASE(doubleMoveMemberInitialization3); // #9974
247 1 : TEST_CASE(doubleMoveMemberInitialization4);
248 1 : TEST_CASE(moveAndAssign1);
249 1 : TEST_CASE(moveAndAssign2);
250 1 : TEST_CASE(moveAssignMoveAssign);
251 1 : TEST_CASE(moveAndReset1);
252 1 : TEST_CASE(moveAndReset2);
253 1 : TEST_CASE(moveResetMoveReset);
254 1 : TEST_CASE(moveAndFunctionParameter);
255 1 : TEST_CASE(moveAndFunctionParameterReference);
256 1 : TEST_CASE(moveAndFunctionParameterConstReference);
257 1 : TEST_CASE(moveAndFunctionParameterUnknown);
258 1 : TEST_CASE(moveAndReturn);
259 1 : TEST_CASE(moveAndClear);
260 1 : TEST_CASE(movedPointer);
261 1 : TEST_CASE(moveAndAddressOf);
262 1 : TEST_CASE(partiallyMoved);
263 1 : TEST_CASE(moveAndLambda);
264 1 : TEST_CASE(moveInLoop);
265 1 : TEST_CASE(moveCallback);
266 1 : TEST_CASE(moveClassVariable);
267 1 : TEST_CASE(forwardAndUsed);
268 1 : TEST_CASE(moveAndReference);
269 1 : TEST_CASE(moveForRange);
270 1 : TEST_CASE(moveTernary);
271 :
272 1 : TEST_CASE(funcArgNamesDifferent);
273 1 : TEST_CASE(funcArgOrderDifferent);
274 1 : TEST_CASE(cpp11FunctionArgInit); // #7846 - "void foo(int declaration = {}) {"
275 :
276 1 : TEST_CASE(shadowVariables);
277 1 : TEST_CASE(knownArgument);
278 1 : TEST_CASE(knownArgumentHiddenVariableExpression);
279 1 : TEST_CASE(knownArgumentTernaryOperator);
280 1 : TEST_CASE(checkComparePointers);
281 :
282 1 : TEST_CASE(unusedVariableValueTemplate); // #8994
283 :
284 1 : TEST_CASE(moduloOfOne);
285 :
286 1 : TEST_CASE(sameExpressionPointers);
287 :
288 1 : TEST_CASE(checkOverlappingWrite);
289 :
290 1 : TEST_CASE(constVariableArrayMember); // #10371
291 :
292 1 : TEST_CASE(knownPointerToBool);
293 1 : TEST_CASE(iterateByValue);
294 1 : }
295 :
296 : #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
297 1299 : void check_(const char* file, int line, const char code[], bool cpp = true, bool inconclusive = true, bool runSimpleChecks=true, bool verbose=false, Settings* settings = nullptr) {
298 1299 : if (!settings) {
299 1257 : settings = &_settings;
300 : }
301 1299 : settings->severity.enable(Severity::style);
302 1299 : settings->severity.enable(Severity::warning);
303 1299 : settings->severity.enable(Severity::portability);
304 1299 : settings->severity.enable(Severity::performance);
305 1299 : settings->standards.c = Standards::CLatest;
306 1299 : settings->standards.cpp = Standards::CPPLatest;
307 1299 : settings->certainty.setEnabled(Certainty::inconclusive, inconclusive);
308 1299 : settings->verbose = verbose;
309 :
310 : // Tokenize..
311 2598 : SimpleTokenizer tokenizer(*settings, *this);
312 1299 : ASSERT_LOC(tokenizer.tokenize(code, cpp), file, line);
313 :
314 : // Check..
315 1298 : runChecks<CheckOther>(tokenizer, this);
316 :
317 : (void)runSimpleChecks; // TODO Remove this
318 1298 : }
319 :
320 5 : void check_(const char* file, int line, const char code[], Settings *s) {
321 5 : check_(file, line, code, true, true, true, false, s);
322 5 : }
323 :
324 : #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__)
325 16 : void checkP_(const char* file, int line, const char code[], const char *filename = "test.cpp") {
326 16 : Settings* settings = &_settings;
327 16 : settings->severity.enable(Severity::style);
328 16 : settings->severity.enable(Severity::warning);
329 16 : settings->severity.enable(Severity::portability);
330 16 : settings->severity.enable(Severity::performance);
331 16 : settings->standards.c = Standards::CLatest;
332 16 : settings->standards.cpp = Standards::CPPLatest;
333 16 : settings->certainty.enable(Certainty::inconclusive);
334 :
335 48 : std::vector<std::string> files(1, filename);
336 32 : Tokenizer tokenizer(*settings, *this);
337 16 : PreprocessorHelper::preprocess(code, files, tokenizer, *this);
338 :
339 : // Tokenizer..
340 16 : ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line);
341 :
342 : // Check..
343 16 : runChecks<CheckOther>(tokenizer, this);
344 16 : }
345 :
346 27 : void checkInterlockedDecrement(const char code[]) {
347 54 : /*const*/ Settings settings = settingsBuilder().platform(Platform::Type::Win32A).build();
348 :
349 27 : check(code, true, false, true, false, &settings);
350 27 : }
351 :
352 1 : void emptyBrackets() {
353 1 : check("{\n"
354 : "}");
355 1 : ASSERT_EQUALS("", errout_str());
356 : }
357 :
358 :
359 1 : void zeroDiv1() { // floating point division by zero => no error
360 1 : check("void foo() {\n"
361 : " cout << 1. / 0;\n"
362 : "}");
363 1 : ASSERT_EQUALS("", errout_str());
364 :
365 1 : check("void foo() {\n"
366 : " cout << 42 / (double)0;\n"
367 : "}");
368 1 : ASSERT_EQUALS("", errout_str());
369 :
370 1 : check("void foo() {\n"
371 : " cout << 42 / (float)0;\n"
372 : "}");
373 1 : ASSERT_EQUALS("", errout_str());
374 :
375 1 : check("void foo() {\n"
376 : " cout << 42 / (int)0;\n"
377 : "}");
378 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
379 : }
380 :
381 1 : void zeroDiv2() {
382 1 : check("void foo()\n"
383 : "{\n"
384 : " int sum = 0;\n"
385 : " for(int i = 0; i < n; i ++)\n"
386 : " {\n"
387 : " sum += i;\n"
388 : " }\n"
389 : " cout<<b/sum;\n"
390 : "}");
391 1 : ASSERT_EQUALS("", errout_str());
392 : }
393 :
394 1 : void zeroDiv3() {
395 1 : check("int foo(int i) {\n"
396 : " return i / 0;\n"
397 : "}");
398 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
399 :
400 1 : check("int foo(int i) {\n"
401 : " return i % 0;\n"
402 : "}");
403 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
404 :
405 1 : check("void foo(int& i) {\n"
406 : " i /= 0;\n"
407 : "}");
408 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
409 :
410 1 : check("void foo(int& i) {\n"
411 : " i %= 0;\n"
412 : "}");
413 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
414 :
415 1 : check("uint8_t foo(uint8_t i) {\n"
416 : " return i / 0;\n"
417 : "}");
418 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
419 : }
420 :
421 1 : void zeroDiv4() {
422 1 : check("void f()\n"
423 : "{\n"
424 : " long a = b / 0x6;\n"
425 : "}");
426 1 : ASSERT_EQUALS("", errout_str());
427 :
428 1 : check("void f()\n"
429 : "{\n"
430 : " long a = b / 0x0;\n"
431 : "}");
432 1 : ASSERT_EQUALS("", errout_str());
433 1 : check("void f(long b)\n"
434 : "{\n"
435 : " long a = b / 0x0;\n"
436 : "}");
437 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
438 :
439 1 : check("void f()\n"
440 : "{\n"
441 : " long a = b / 0L;\n"
442 : "}");
443 1 : ASSERT_EQUALS("", errout_str());
444 1 : check("void f(long b)\n"
445 : "{\n"
446 : " long a = b / 0L;\n"
447 : "}");
448 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
449 :
450 1 : check("void f()\n"
451 : "{\n"
452 : " long a = b / 0ul;\n"
453 : "}");
454 1 : ASSERT_EQUALS("", errout_str());
455 1 : check("void f(long b)\n"
456 : "{\n"
457 : " long a = b / 0ul;\n"
458 : "}");
459 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
460 :
461 : // Don't warn about floating points (gcc doesn't warn either)
462 : // and floating points are handled differently than integers.
463 1 : check("void f()\n"
464 : "{\n"
465 : " long a = b / 0.0;\n"
466 : "}");
467 1 : ASSERT_EQUALS("", errout_str());
468 :
469 1 : check("void f()\n"
470 : "{\n"
471 : " long a = b / 0.5;\n"
472 : "}");
473 1 : ASSERT_EQUALS("", errout_str());
474 : }
475 :
476 1 : void zeroDiv5() {
477 1 : check("void f()\n"
478 : "{ { {\n"
479 : " long a = b / 0;\n"
480 : "} } }");
481 1 : ASSERT_EQUALS("", errout_str());
482 1 : check("void f(long b)\n"
483 : "{ { {\n"
484 : " long a = b / 0;\n"
485 : "} } }");
486 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
487 : }
488 :
489 1 : void zeroDiv6() {
490 1 : check("void f()\n"
491 : "{ { {\n"
492 : " int a = b % 0;\n"
493 : "} } }");
494 1 : ASSERT_EQUALS("", errout_str());
495 1 : check("void f(int b)\n"
496 : "{ { {\n"
497 : " int a = b % 0;\n"
498 : "} } }");
499 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
500 : }
501 :
502 1 : void zeroDiv7() {
503 : // unknown types for x and y --> do not warn
504 1 : check("void f() {\n"
505 : " int a = x/2*3/0;\n"
506 : " int b = y/2*3%0;\n"
507 : "}");
508 1 : ASSERT_EQUALS("", errout_str());
509 1 : check("void f(int x, int y) {\n"
510 : " int a = x/2*3/0;\n"
511 : " int b = y/2*3%0;\n"
512 : "}");
513 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n"
514 : "[test.cpp:3]: (error) Division by zero.\n", errout_str());
515 : }
516 :
517 1 : void zeroDiv8() {
518 : // #5584 - FP when function is unknown
519 1 : check("void f() {\n"
520 : " int a = 0;\n"
521 : " do_something(a);\n"
522 : " return 4 / a;\n"
523 : "}");
524 1 : ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Division by zero.\n", errout_str());
525 : }
526 :
527 1 : void zeroDiv9() {
528 : // #6403 FP zerodiv - inside protecting if-clause
529 1 : check("void foo() {\n"
530 : " double fStepHelp = 0;\n"
531 : " if( (rOuterValue >>= fStepHelp) ) {\n"
532 : " if( fStepHelp != 0.0) {\n"
533 : " double fStepMain = 1;\n"
534 : " sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepMain / fStepHelp);\n"
535 : " }\n"
536 : " }\n"
537 : "}");
538 1 : ASSERT_EQUALS("", errout_str());
539 : }
540 :
541 1 : void zeroDiv10() {
542 : // #5402 false positive: (error) Division by zero -- with boost::format
543 1 : check("int main() {\n"
544 : " std::cout\n"
545 : " << boost::format(\" %d :: %s <> %s\") % 0 % \"a\" % \"b\"\n"
546 : " << std::endl;\n"
547 : " return 0;\n"
548 : "}");
549 1 : ASSERT_EQUALS("", errout_str());
550 : }
551 :
552 1 : void zeroDiv11() {
553 1 : check("void f(int a) {\n"
554 : " int res = (a+2)/0;\n"
555 : " int res = (a*2)/0;\n"
556 : "}");
557 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n"
558 : "[test.cpp:3]: (error) Division by zero.\n", errout_str());
559 1 : check("void f() {\n"
560 : " int res = (a+2)/0;\n"
561 : " int res = (a*2)/0;\n"
562 : "}");
563 1 : ASSERT_EQUALS("", errout_str());
564 : }
565 :
566 1 : void zeroDiv12() {
567 : // #8141
568 1 : check("intmax_t f() {\n"
569 : " return 1 / imaxabs(0);\n"
570 : "}");
571 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
572 : }
573 1 : void zeroDiv13() {
574 : // #7324
575 1 : check("int f () {\n"
576 : " int dividend = 10;\n"
577 : " int divisor = 1;\n"
578 : " dividend = dividend / (--divisor);\n"
579 : " return dividend;\n"
580 : "}\n");
581 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Division by zero.\n", errout_str());
582 : }
583 :
584 1 : void zeroDiv14() {
585 1 : check("void f() {\n" // #1169
586 : " double dx = 1.;\n"
587 : " int ix = 1;\n"
588 : " int i = 1;\n"
589 : " std::cout << ix / (i >> 1) << std::endl;\n"
590 : " std::cout << dx / (i >> 1) << std::endl;\n"
591 : "}\n");
592 1 : ASSERT_EQUALS("[test.cpp:5]: (error) Division by zero.\n", errout_str());
593 : }
594 :
595 1 : void zeroDiv15() { // #8319
596 1 : check("int f(int i) { return i - 1; }\n"
597 : "int f() {\n"
598 : " const int d = 1;\n"
599 : " const int r = 1 / f(d);\n"
600 : " return r;\n"
601 : "}\n");
602 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Division by zero.\n", errout_str());
603 : }
604 :
605 : // #11158
606 1 : void zeroDiv16()
607 : {
608 1 : check("int f(int i) {\n"
609 : " int number = 10, a = 0;\n"
610 : " for (int count = 0; count < 2; count++) {\n"
611 : " a += (i / number) % 10;\n"
612 : " number = number / 10;\n"
613 : " }\n"
614 : " return a;\n"
615 : "}\n");
616 1 : ASSERT_EQUALS("", errout_str());
617 :
618 1 : check("int f(int i) {\n"
619 : " int number = 10, a = 0;\n"
620 : " for (int count = 0; count < 2; count++) {\n"
621 : " int x = number / 10;\n"
622 : " a += (i / number) % 10;\n"
623 : " number = x;\n"
624 : " }\n"
625 : " return a;\n"
626 : "}\n");
627 1 : ASSERT_EQUALS("", errout_str());
628 : }
629 :
630 1 : void zeroDiv17() { // #9931
631 1 : check("int f(int len) {\n"
632 : " int sz = sizeof(void*[255]) / 255;\n"
633 : " int x = len % sz;\n"
634 : " return x;\n"
635 : "}\n");
636 1 : ASSERT_EQUALS("", errout_str());
637 : }
638 :
639 1 : void zeroDiv18()
640 : {
641 1 : check("int f(int x, int y) {\n"
642 : " if (x == y) {}\n"
643 : " return 1 / (x-y);\n"
644 : "}\n");
645 1 : ASSERT_EQUALS(
646 : "[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'x==y' is redundant or there is division by zero at line 3.\n",
647 : errout_str());
648 : }
649 :
650 1 : void zeroDiv19()
651 : {
652 1 : check("void f() {\n" // #2456
653 : " for (int i = 0;;)\n"
654 : " int j = 10 / i;\n"
655 : "}\n");
656 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout_str());
657 : }
658 :
659 1 : void zeroDivCond() {
660 1 : check("void f(unsigned int x) {\n"
661 : " int y = 17 / x;\n"
662 : " if (x > 0) {}\n"
663 : "}");
664 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x>0' is redundant or there is division by zero at line 2.\n", errout_str());
665 :
666 1 : check("void f(unsigned int x) {\n"
667 : " int y = 17 / x;\n"
668 : " if (x >= 1) {}\n"
669 : "}");
670 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x>=1' is redundant or there is division by zero at line 2.\n", errout_str());
671 :
672 1 : check("void f(int x) {\n"
673 : " int y = 17 / x;\n"
674 : " if (x == 0) {}\n"
675 : "}");
676 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x==0' is redundant or there is division by zero at line 2.\n", errout_str());
677 :
678 1 : check("void f(unsigned int x) {\n"
679 : " int y = 17 / x;\n"
680 : " if (x != 0) {}\n"
681 : "}");
682 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x!=0' is redundant or there is division by zero at line 2.\n", errout_str());
683 :
684 : // function call
685 1 : check("void f1(int x, int y) { c=x/y; }\n"
686 : "void f2(unsigned int y) {\n"
687 : " f1(123,y);\n"
688 : " if (y>0){}\n"
689 : "}");
690 1 : ASSERT_EQUALS(
691 : "[test.cpp:4] -> [test.cpp:1]: (warning) Either the condition 'y>0' is redundant or there is division by zero at line 1.\n",
692 : errout_str());
693 :
694 : // avoid false positives when variable is changed after division
695 1 : check("void f() {\n"
696 : " unsigned int x = do_something();\n"
697 : " int y = 17 / x;\n"
698 : " x = some+calculation;\n"
699 : " if (x != 0) {}\n"
700 : "}");
701 1 : ASSERT_EQUALS("", errout_str());
702 :
703 : {
704 : // function is called that might modify global variable
705 1 : check("void do_something();\n"
706 : "int x;\n"
707 : "void f() {\n"
708 : " int y = 17 / x;\n"
709 : " do_something();\n"
710 : " if (x != 0) {}\n"
711 : "}");
712 1 : ASSERT_EQUALS("", errout_str());
713 :
714 : // function is called. but don't care, variable is local
715 1 : check("void do_something();\n"
716 : "void f() {\n"
717 : " int x = some + calculation;\n"
718 : " int y = 17 / x;\n"
719 : " do_something();\n"
720 : " if (x != 0) {}\n"
721 : "}");
722 1 : ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'x!=0' is redundant or there is division by zero at line 4.\n", errout_str());
723 : }
724 :
725 1 : check("void do_something(int value);\n"
726 : "void f(int x) {\n"
727 : " int y = 17 / x;\n"
728 : " do_something(x);\n"
729 : "}");
730 1 : ASSERT_EQUALS("", errout_str());
731 :
732 1 : check("int x;\n"
733 : "void f() {\n"
734 : " int y = 17 / x;\n"
735 : " while (y || x == 0) { x--; }\n"
736 : "}");
737 1 : ASSERT_EQUALS("", errout_str());
738 :
739 : // ticket 5033 segmentation fault (valid code) in CheckOther::checkZeroDivisionOrUselessCondition
740 1 : check("void f() {\n"
741 : "double* p1= new double[1];\n"
742 : "double* p2= new double[1];\n"
743 : "double* p3= new double[1];\n"
744 : "double* pp[3] = {p1,p2,p3};\n"
745 : "}");
746 1 : ASSERT_EQUALS("", errout_str());
747 :
748 : // #5105 - FP
749 1 : check("int f(int a, int b) {\n"
750 : " int r = a / b;\n"
751 : " if (func(b)) {}\n"
752 : "}");
753 1 : ASSERT_EQUALS("", errout_str());
754 :
755 : // Unknown types for b and c --> do not warn
756 1 : check("int f(int d) {\n"
757 : " int r = (a?b:c) / d;\n"
758 : " if (d == 0) {}\n"
759 : "}");
760 1 : ASSERT_EQUALS("", errout_str());
761 :
762 1 : check("int f(int a) {\n"
763 : " int r = a ? 1 / a : 0;\n"
764 : " if (a == 0) {}\n"
765 : "}");
766 1 : ASSERT_EQUALS("", errout_str());
767 :
768 1 : check("int f(int a) {\n"
769 : " int r = (a == 0) ? 0 : 1 / a;\n"
770 : " if (a == 0) {}\n"
771 : "}");
772 1 : ASSERT_EQUALS("", errout_str());
773 :
774 1 : check("int g();\n"
775 : "void f(int b) {\n"
776 : " int x = g();\n"
777 : " if (x == 0) {}\n"
778 : " else if (x > 0) {}\n"
779 : " else\n"
780 : " a = b / -x;\n"
781 : "}");
782 1 : ASSERT_EQUALS("", errout_str());
783 :
784 1 : check("struct A {\n"
785 : " int x;\n"
786 : "};\n"
787 : "int f(A* a) {\n"
788 : " if (a->x == 0) \n"
789 : " a->x = 1;\n"
790 : " return 1/a->x;\n"
791 : "}\n");
792 1 : ASSERT_EQUALS("", errout_str());
793 :
794 : // #10049
795 1 : check("int f(int argc) {\n"
796 : " int quotient, remainder;\n"
797 : " remainder = argc % 2;\n"
798 : " argc = 2;\n"
799 : " quotient = argc;\n"
800 : " if (quotient != 0) \n"
801 : " return quotient;\n"
802 : " return remainder;\n"
803 : "}\n");
804 1 : ASSERT_EQUALS("", errout_str());
805 :
806 : // #11315
807 1 : checkP("#define STATIC_ASSERT(c) \\\n"
808 : "do { enum { sa = 1/(int)(!!(c)) }; } while (0)\n"
809 : "void f() {\n"
810 : " STATIC_ASSERT(sizeof(int) == sizeof(FOO));\n"
811 : "}\n");
812 1 : ASSERT_EQUALS("", errout_str());
813 :
814 : // #11505
815 1 : check("void f(uint16_t num, uint8_t radix) {\n"
816 : " int c = num % radix;\n"
817 : " num /= radix;\n"
818 : " if (!num) {}\n"
819 : "}\n");
820 1 : ASSERT_EQUALS("", errout_str());
821 : }
822 :
823 1 : void nanInArithmeticExpression() {
824 1 : check("void f()\n"
825 : "{\n"
826 : " double x = 3.0 / 0.0 + 1.0;\n"
827 : " printf(\"%f\", x);\n"
828 : "}");
829 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout_str());
830 :
831 1 : check("void f()\n"
832 : "{\n"
833 : " double x = 3.0 / 0.0 - 1.0;\n"
834 : " printf(\"%f\", x);\n"
835 : "}");
836 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout_str());
837 :
838 1 : check("void f()\n"
839 : "{\n"
840 : " double x = 1.0 + 3.0 / 0.0;\n"
841 : " printf(\"%f\", x);\n"
842 : "}");
843 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout_str());
844 :
845 1 : check("void f()\n"
846 : "{\n"
847 : " double x = 1.0 - 3.0 / 0.0;\n"
848 : " printf(\"%f\", x);\n"
849 : "}");
850 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout_str());
851 :
852 1 : check("void f()\n"
853 : "{\n"
854 : " double x = 3.0 / 0.0;\n"
855 : " printf(\"%f\", x);\n"
856 : "}");
857 1 : ASSERT_EQUALS("", errout_str());
858 :
859 : }
860 :
861 1 : void varScope1() {
862 1 : check("unsigned short foo()\n"
863 : "{\n"
864 : " test_client CClient;\n"
865 : " try\n"
866 : " {\n"
867 : " if (CClient.Open())\n"
868 : " {\n"
869 : " return 0;\n"
870 : " }\n"
871 : " }\n"
872 : " catch (...)\n"
873 : " {\n"
874 : " return 2;\n"
875 : " }\n"
876 : "\n"
877 : " try\n"
878 : " {\n"
879 : " CClient.Close();\n"
880 : " }\n"
881 : " catch (...)\n"
882 : " {\n"
883 : " return 2;\n"
884 : " }\n"
885 : "\n"
886 : " return 1;\n"
887 : "}");
888 1 : ASSERT_EQUALS("", errout_str());
889 : }
890 :
891 1 : void varScope2() {
892 1 : check("int foo()\n"
893 : "{\n"
894 : " Error e;\n"
895 : " e.SetValue(12);\n"
896 : " throw e;\n"
897 : "}");
898 1 : ASSERT_EQUALS("", errout_str());
899 : }
900 :
901 1 : void varScope3() {
902 1 : check("void foo()\n"
903 : "{\n"
904 : " int i;\n"
905 : " int *p = 0;\n"
906 : " if (abc)\n"
907 : " {\n"
908 : " p = &i;\n"
909 : " }\n"
910 : " *p = 1;\n"
911 : "}");
912 1 : ASSERT_EQUALS("", errout_str());
913 : }
914 :
915 1 : void varScope4() {
916 1 : check("void foo()\n"
917 : "{\n"
918 : " int i;\n"
919 : "}");
920 1 : ASSERT_EQUALS("", errout_str());
921 : }
922 :
923 1 : void varScope5() {
924 1 : check("void f(int x)\n"
925 : "{\n"
926 : " int i = 0;\n"
927 : " if (x) {\n"
928 : " for ( ; i < 10; ++i) ;\n"
929 : " }\n"
930 : "}");
931 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout_str());
932 :
933 1 : check("void f(int x) {\n"
934 : " const unsigned char i = 0;\n"
935 : " if (x) {\n"
936 : " for ( ; i < 10; ++i) ;\n"
937 : " }\n"
938 : "}");
939 1 : ASSERT_EQUALS("", errout_str());
940 :
941 1 : check("void f(int x)\n"
942 : "{\n"
943 : " int i = 0;\n"
944 : " if (x) {b()}\n"
945 : " else {\n"
946 : " for ( ; i < 10; ++i) ;\n"
947 : " }\n"
948 : "}");
949 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout_str());
950 : }
951 :
952 1 : void varScope6() {
953 1 : check("void f(int x)\n"
954 : "{\n"
955 : " int i = x;\n"
956 : " if (a) {\n"
957 : " x++;\n"
958 : " }\n"
959 : " if (b) {\n"
960 : " c(i);\n"
961 : " }\n"
962 : "}");
963 1 : ASSERT_EQUALS("", errout_str());
964 :
965 1 : check("void f() {\n" // #5398
966 : " bool success = false;\n"
967 : " int notReducable(someClass.getX(&success));\n"
968 : " if (success) {\n"
969 : " foo(notReducable);\n"
970 : " }\n"
971 : "}");
972 1 : ASSERT_EQUALS("", errout_str());
973 :
974 1 : check("void foo(Test &test) {\n"
975 : " int& x = test.getData();\n"
976 : " if (test.process())\n"
977 : " x = 0;\n"
978 : "}");
979 1 : ASSERT_EQUALS("", errout_str());
980 :
981 1 : check("void f()\n"
982 : "{\n"
983 : "int foo = 0;\n"
984 : "std::vector<int> vec(10);\n"
985 : "BOOST_FOREACH(int& i, vec)\n"
986 : "{\n"
987 : " foo += 1;\n"
988 : " if(foo == 10)\n"
989 : " {\n"
990 : " return 0;\n"
991 : " }\n"
992 : "}\n"
993 : "}");
994 1 : ASSERT_EQUALS("", errout_str());
995 :
996 1 : check("void f(int &x)\n"
997 : "{\n"
998 : " int n = 1;\n"
999 : " do\n"
1000 : " {\n"
1001 : " ++n;\n"
1002 : " ++x;\n"
1003 : " } while (x);\n"
1004 : "}");
1005 1 : ASSERT_EQUALS("", errout_str());
1006 : }
1007 :
1008 1 : void varScope7() {
1009 1 : check("void f(int x)\n"
1010 : "{\n"
1011 : " int y = 0;\n"
1012 : " b(y);\n"
1013 : " if (x) {\n"
1014 : " y++;\n"
1015 : " }\n"
1016 : "}");
1017 1 : ASSERT_EQUALS("", errout_str());
1018 : }
1019 :
1020 1 : void varScope8() {
1021 1 : check("void test() {\n"
1022 : " float edgeResistance=1;\n"
1023 : " std::vector<int> edges;\n"
1024 : " BOOST_FOREACH(int edge, edges) {\n"
1025 : " edgeResistance = (edge+1) / 2.0;\n"
1026 : " }\n"
1027 : "}");
1028 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'edgeResistance' can be reduced.\n", errout_str());
1029 : }
1030 :
1031 1 : void varScope9() {
1032 : // classes may have extra side effects
1033 1 : check("class fred {\n"
1034 : "public:\n"
1035 : " void x();\n"
1036 : "};\n"
1037 : "void test(int a) {\n"
1038 : " fred f;\n"
1039 : " if (a == 2) {\n"
1040 : " f.x();\n"
1041 : " }\n"
1042 : "}");
1043 1 : ASSERT_EQUALS("", errout_str());
1044 : }
1045 :
1046 1 : void varScope10() {
1047 1 : check("int f()\n"
1048 : "{\n"
1049 : " int x = 0;\n"
1050 : " FOR {\n"
1051 : " foo(x++);\n"
1052 : " }\n"
1053 : "}");
1054 1 : ASSERT_EQUALS("", errout_str());
1055 : }
1056 :
1057 1 : void varScope11() {
1058 1 : check("int f() {\n"
1059 : " int x = 0;\n"
1060 : " AB ab = { x, 0 };\n"
1061 : "}");
1062 1 : ASSERT_EQUALS("", errout_str());
1063 :
1064 1 : check("int f() {\n"
1065 : " int x = 0;\n"
1066 : " if (a == 0) { ++x; }\n"
1067 : " AB ab = { x, 0 };\n"
1068 : "}");
1069 1 : ASSERT_EQUALS("", errout_str());
1070 :
1071 1 : check("int f() {\n"
1072 : " int x = 0;\n"
1073 : " if (a == 0) { ++x; }\n"
1074 : " if (a == 1) { AB ab = { x, 0 }; }\n"
1075 : "}");
1076 1 : ASSERT_EQUALS("", errout_str());
1077 : }
1078 :
1079 1 : void varScope12() {
1080 1 : check("void f(int x) {\n"
1081 : " int i[5];\n"
1082 : " int* j = y;\n"
1083 : " if (x)\n"
1084 : " foo(i);\n"
1085 : " foo(j);\n"
1086 : "}");
1087 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'i' can be reduced.\n", errout_str());
1088 :
1089 1 : check("void f(int x) {\n"
1090 : " int i[5];\n"
1091 : " int* j;\n"
1092 : " if (x)\n"
1093 : " j = i;\n"
1094 : " foo(j);\n"
1095 : "}");
1096 1 : ASSERT_EQUALS("", errout_str());
1097 :
1098 1 : check("void f(int x) {\n"
1099 : " const bool b = true;\n"
1100 : " x++;\n"
1101 : " if (x == 5)\n"
1102 : " foo(b);\n"
1103 : "}");
1104 1 : ASSERT_EQUALS("", errout_str());
1105 :
1106 1 : check("void f(int x) {\n"
1107 : " const bool b = x;\n"
1108 : " x++;\n"
1109 : " if (x == 5)\n"
1110 : " foo(b);\n"
1111 : "}");
1112 1 : ASSERT_EQUALS("", errout_str());
1113 : }
1114 :
1115 1 : void varScope13() {
1116 : // #2770
1117 1 : check("void f() {\n"
1118 : " int i = 0;\n"
1119 : " forever {\n"
1120 : " if (i++ == 42) { break; }\n"
1121 : " }\n"
1122 : "}");
1123 1 : ASSERT_EQUALS("", errout_str());
1124 : }
1125 :
1126 1 : void varScope14() {
1127 : // #3941
1128 1 : check("void f() {\n"
1129 : " const int i( foo());\n"
1130 : " if(a) {\n"
1131 : " for ( ; i < 10; ++i) ;\n"
1132 : " }\n"
1133 : "}");
1134 1 : ASSERT_EQUALS("", errout_str());
1135 : }
1136 :
1137 1 : void varScope15() {
1138 : // #4573
1139 1 : check("void f() {\n"
1140 : " int a,b,c;\n"
1141 : " if (a);\n"
1142 : " else if(b);\n"
1143 : " else if(c);\n"
1144 : " else;\n"
1145 : "}", true, false);
1146 1 : ASSERT_EQUALS("", errout_str());
1147 : }
1148 :
1149 1 : void varScope16() {
1150 1 : check("void f() {\n"
1151 : " int a = 0;\n"
1152 : " while((++a) < 56) {\n"
1153 : " foo();\n"
1154 : " }\n"
1155 : "}");
1156 1 : ASSERT_EQUALS("", errout_str());
1157 :
1158 1 : check("void f() {\n"
1159 : " int a = 0;\n"
1160 : " do {\n"
1161 : " foo();\n"
1162 : " } while((++a) < 56);\n"
1163 : "}");
1164 1 : ASSERT_EQUALS("", errout_str());
1165 :
1166 1 : check("void f() {\n"
1167 : " int a = 0;\n"
1168 : " do {\n"
1169 : " a = 64;\n"
1170 : " foo(a);\n"
1171 : " } while((++a) < 56);\n"
1172 : "}");
1173 1 : ASSERT_EQUALS("", errout_str());
1174 :
1175 1 : check("void f() {\n"
1176 : " int a = 0;\n"
1177 : " do {\n"
1178 : " a = 64;\n"
1179 : " foo(a);\n"
1180 : " } while(z());\n"
1181 : "}");
1182 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'a' can be reduced.\n", errout_str());
1183 : }
1184 :
1185 1 : void varScope17() {
1186 1 : check("void f() {\n"
1187 : " int x;\n"
1188 : " if (a) {\n"
1189 : " x = stuff(x);\n"
1190 : " morestuff(x);\n"
1191 : " }\n"
1192 : "}");
1193 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout_str());
1194 :
1195 1 : check("void f() {\n"
1196 : " int x;\n"
1197 : " if (a) {\n"
1198 : " x = stuff(x);\n"
1199 : " morestuff(x);\n"
1200 : " }\n"
1201 : " if (b) {}\n"
1202 : "}");
1203 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout_str());
1204 : }
1205 :
1206 1 : void varScope18() {
1207 1 : check("void f() {\n"
1208 : " short x;\n"
1209 : "\n"
1210 : " switch (ab) {\n"
1211 : " case A:\n"
1212 : " break;\n"
1213 : " case B:\n"
1214 : " default:\n"
1215 : " break;\n"
1216 : " }\n"
1217 : "\n"
1218 : " if (c) {\n"
1219 : " x = foo();\n"
1220 : " do_something(x);\n"
1221 : " }\n"
1222 : "}");
1223 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout_str());
1224 :
1225 1 : check("void f() {\n"
1226 : " short x;\n"
1227 : "\n"
1228 : " switch (ab) {\n"
1229 : " case A:\n"
1230 : " x = 10;\n"
1231 : " break;\n"
1232 : " case B:\n"
1233 : " default:\n"
1234 : " break;\n"
1235 : " }\n"
1236 : "\n"
1237 : " if (c) {\n"
1238 : " x = foo();\n"
1239 : " do_something(x);\n"
1240 : " }\n"
1241 : "}");
1242 1 : ASSERT_EQUALS("", errout_str());
1243 :
1244 1 : check("void f() {\n"
1245 : " short x;\n"
1246 : "\n"
1247 : " switch (ab) {\n"
1248 : " case A:\n"
1249 : " if(c)\n"
1250 : " do_something(x);\n"
1251 : " break;\n"
1252 : " case B:\n"
1253 : " default:\n"
1254 : " break;\n"
1255 : " }\n"
1256 : "}");
1257 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout_str());
1258 :
1259 1 : check("void f() {\n"
1260 : " short x;\n"
1261 : "\n"
1262 : " switch (ab) {\n"
1263 : " case A:\n"
1264 : " if(c)\n"
1265 : " do_something(x);\n"
1266 : " break;\n"
1267 : " case B:\n"
1268 : " default:\n"
1269 : " if(d)\n"
1270 : " do_something(x);\n"
1271 : " break;\n"
1272 : " }\n"
1273 : "}");
1274 1 : ASSERT_EQUALS("", errout_str());
1275 : }
1276 :
1277 1 : void varScope20() { // Ticket #5103 - constant variable only used in inner scope
1278 1 : check("int f(int a) {\n"
1279 : " const int x = 234;\n"
1280 : " int b = a;\n"
1281 : " if (b > 32) b = x;\n"
1282 : " return b;\n"
1283 : "}");
1284 1 : ASSERT_EQUALS("", errout_str());
1285 : }
1286 :
1287 1 : void varScope21() { // Ticket #5382 - initializing two-dimensional array
1288 1 : check("int test() {\n"
1289 : " int test_value = 3;\n"
1290 : " int test_array[1][1] = { { test_value } };\n"
1291 : " return sizeof(test_array);\n"
1292 : "}");
1293 1 : ASSERT_EQUALS("", errout_str());
1294 : }
1295 :
1296 1 : void varScope22() { // Ticket #5684 - "The scope of the variable 'p' can be reduced" - But it can not.
1297 1 : check("void foo() {\n"
1298 : " int* p( 42 );\n"
1299 : " int i = 0;\n"
1300 : " while ( i != 100 ) {\n"
1301 : " *p = i;\n"
1302 : " ++p;\n"
1303 : " ++i;\n"
1304 : " }\n"
1305 : "}");
1306 1 : ASSERT_EQUALS("", errout_str());
1307 : // try to avoid an obvious false negative after applying the fix for the example above:
1308 1 : check("void foo() {\n"
1309 : " int* p( 42 );\n"
1310 : " int i = 0;\n"
1311 : " int dummy = 0;\n"
1312 : " while ( i != 100 ) {\n"
1313 : " p = & dummy;\n"
1314 : " *p = i;\n"
1315 : " ++p;\n"
1316 : " ++i;\n"
1317 : " }\n"
1318 : "}");
1319 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'p' can be reduced.\n", errout_str());
1320 : }
1321 :
1322 1 : void varScope23() { // #6154: Don't suggest to reduce scope if inner scope is a lambda
1323 1 : check("int main() {\n"
1324 : " size_t myCounter = 0;\n"
1325 : " Test myTest([&](size_t aX){\n"
1326 : " std::cout << myCounter += aX << std::endl;\n"
1327 : " });\n"
1328 : "}");
1329 1 : ASSERT_EQUALS("", errout_str());
1330 : }
1331 :
1332 1 : void varScope24() {
1333 1 : check("void f(Foo x) {\n"
1334 : " Foo &r = x;\n"
1335 : " if (cond) {\n"
1336 : " r.dostuff();\n"
1337 : " }\n"
1338 : "}");
1339 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'r' can be reduced.\n", errout_str());
1340 :
1341 1 : check("void f(Foo x) {\n"
1342 : " Foo foo = x;\n"
1343 : " if (cond) {\n"
1344 : " foo.dostuff();\n"
1345 : " }\n"
1346 : "}");
1347 1 : ASSERT_EQUALS("", errout_str());
1348 : }
1349 :
1350 1 : void varScope25() {
1351 1 : check("void f() {\n"
1352 : " time_t currtime;\n"
1353 : " if (a) {\n"
1354 : " currtime = time(&dummy);\n"
1355 : " if (currtime > t) {}\n"
1356 : " }\n"
1357 : "}", false);
1358 1 : ASSERT_EQUALS("[test.c:2]: (style) The scope of the variable 'currtime' can be reduced.\n", errout_str());
1359 : }
1360 :
1361 1 : void varScope26() {
1362 1 : check("void f(const std::map<int,int> &m) {\n"
1363 : " for (auto it : m) {\n"
1364 : " if (cond1) {\n"
1365 : " int& key = it.first;\n"
1366 : " if (cond2) { dostuff(key); }\n"
1367 : " }\n"
1368 : " }\n"
1369 : "}");
1370 1 : ASSERT_EQUALS("", errout_str());
1371 : }
1372 :
1373 1 : void varScope27() {
1374 1 : checkP("void f() {\n"
1375 : " int x = 0;\n"
1376 : "#ifdef X\n"
1377 : "#endif\n"
1378 : " if (id == ABC) { return x; }\n"
1379 : "}");
1380 1 : ASSERT_EQUALS("", errout_str());
1381 :
1382 1 : checkP("void f() {\n"
1383 : "#ifdef X\n"
1384 : "#endif\n"
1385 : " int x = 0;\n"
1386 : " if (id == ABC) { return x; }\n"
1387 : "}");
1388 1 : ASSERT_EQUALS("[test.cpp:4]: (style) The scope of the variable 'x' can be reduced.\n", errout_str());
1389 : }
1390 :
1391 1 : void varScope28() {
1392 1 : check("void f() {\n" // #10527
1393 : " int i{};\n"
1394 : " if (double d = g(i); d == 1.0) {}\n"
1395 : "}\n");
1396 1 : ASSERT_EQUALS("", errout_str());
1397 : }
1398 :
1399 1 : void varScope29() { // #10888
1400 1 : check("enum E { E0 };\n"
1401 : "struct S { int i; };\n"
1402 : "void f(int b) {\n"
1403 : " enum E e;\n"
1404 : " struct S s;\n"
1405 : " if (b) {\n"
1406 : " e = E0;\n"
1407 : " s.i = 0;\n"
1408 : " g(e, s);\n"
1409 : " }\n"
1410 : "}\n", false);
1411 1 : ASSERT_EQUALS("[test.c:4]: (style) The scope of the variable 'e' can be reduced.\n"
1412 : "[test.c:5]: (style) The scope of the variable 's' can be reduced.\n",
1413 : errout_str());
1414 :
1415 1 : check("void f(bool b) {\n"
1416 : " std::string s;\n"
1417 : " if (b) {\n"
1418 : " s = \"abc\";\n"
1419 : " g(s);\n"
1420 : " }\n"
1421 : "}");
1422 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 's' can be reduced.\n", errout_str());
1423 :
1424 1 : check("auto foo(std::vector<int>& vec, bool flag) {\n"
1425 : " std::vector<int> dummy;\n"
1426 : " std::vector<int>::iterator iter;\n"
1427 : " if (flag)\n"
1428 : " iter = vec.begin();\n"
1429 : " else {\n"
1430 : " dummy.push_back(42);\n"
1431 : " iter = dummy.begin();\n"
1432 : " }\n"
1433 : " return *iter;\n"
1434 : "}");
1435 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'vec' can be declared as reference to const\n", errout_str());
1436 :
1437 1 : check("auto& foo(std::vector<int>& vec, bool flag) {\n"
1438 : " std::vector<int> dummy;\n"
1439 : " std::vector<int>::iterator iter;\n"
1440 : " if (flag)\n"
1441 : " iter = vec.begin();\n"
1442 : " else {\n"
1443 : " dummy.push_back(42);\n"
1444 : " iter = dummy.begin();\n"
1445 : " }\n"
1446 : " return *iter;\n"
1447 : "}");
1448 1 : ASSERT_EQUALS("", errout_str());
1449 : }
1450 :
1451 1 : void varScope30() { // #8541
1452 1 : check("bool f(std::vector<int>& v, int i) {\n"
1453 : " int n = 0;\n"
1454 : " bool b = false;\n"
1455 : " std::for_each(v.begin(), v.end(), [&](int j) {\n"
1456 : " if (j == i) {\n"
1457 : " ++n;\n"
1458 : " if (n > 5)\n"
1459 : " b = true;\n"
1460 : " }\n"
1461 : " });\n"
1462 : " return b;\n"
1463 : "}\n");
1464 1 : ASSERT_EQUALS("", errout_str());
1465 : }
1466 :
1467 1 : void varScope31() { // #11099
1468 1 : check("bool g(std::vector<int>&);\n"
1469 : "void h(std::vector<int>);\n"
1470 : "void f0(std::vector<int> v) {\n"
1471 : " std::vector<int> w{ v };\n"
1472 : " bool b = g(v);\n"
1473 : " if (b)\n"
1474 : " h(w);\n"
1475 : " h(v);\n"
1476 : "}\n"
1477 : "void f1(std::vector<int> v) {\n"
1478 : " std::vector<int> w{ v.begin(), v.end() };\n"
1479 : " bool b = g(v);\n"
1480 : " if (b)\n"
1481 : " h(w);\n"
1482 : " h(v);\n"
1483 : "}\n"
1484 : "void f2(std::vector<int> v) {\n"
1485 : " std::vector<int> w{ 10, 0, std::allocator<int>() };\n" // FN
1486 : " bool b = g(v);\n"
1487 : " if (b)\n"
1488 : " h(w);\n"
1489 : " h(v);\n"
1490 : "}\n"
1491 : "void f3(std::vector<int> v) {\n"
1492 : " std::vector<int> w{ 10, 0 };\n" // warn
1493 : " bool b = g(v);\n"
1494 : " if (b)\n"
1495 : " h(w);\n"
1496 : " h(v);\n"
1497 : "}\n"
1498 : "void f4(std::vector<int> v) {\n"
1499 : " std::vector<int> w{ 10 };\n" // warn
1500 : " bool b = g(v);\n"
1501 : " if (b)\n"
1502 : " h(w);\n"
1503 : " h(v);\n"
1504 : "}\n"
1505 : "void f5(std::vector<int> v) {\n"
1506 : " std::vector<int> w(v);\n"
1507 : " bool b = g(v);\n"
1508 : " if (b)\n"
1509 : " h(w);\n"
1510 : " h(v);\n"
1511 : "}\n"
1512 : "void f6(std::vector<int> v) {\n"
1513 : " std::vector<int> w(v.begin(), v.end());\n"
1514 : " bool b = g(v);\n"
1515 : " if (b)\n"
1516 : " h(w);\n"
1517 : " h(v);\n"
1518 : "}\n"
1519 : "void f7(std::vector<int> v) {\n"
1520 : " std::vector<int> w(10, 0, std::allocator<int>);\n" // FN
1521 : " bool b = g(v);\n"
1522 : " if (b)\n"
1523 : " h(w);\n"
1524 : " h(v);\n"
1525 : "}\n"
1526 : "void f8(std::vector<int> v) {\n"
1527 : " std::vector<int> w(10, 0);\n" // warn
1528 : " bool b = g(v);\n"
1529 : " if (b)\n"
1530 : " h(w);\n"
1531 : " h(v);\n"
1532 : "}\n"
1533 : "void f9(std::vector<int> v) {\n"
1534 : " std::vector<int> w(10);\n" // warn
1535 : " bool b = g(v);\n"
1536 : " if (b)\n"
1537 : " h(w);\n"
1538 : " h(v);\n"
1539 : "}\n"
1540 : "void f10(std::vector<int> v) {\n"
1541 : " std::vector<int> w{};\n" // warn
1542 : " bool b = g(v);\n"
1543 : " if (b)\n"
1544 : " h(w);\n"
1545 : " h(v);\n"
1546 : "}\n");
1547 1 : ASSERT_EQUALS("[test.cpp:25]: (style) The scope of the variable 'w' can be reduced.\n"
1548 : "[test.cpp:32]: (style) The scope of the variable 'w' can be reduced.\n"
1549 : "[test.cpp:60]: (style) The scope of the variable 'w' can be reduced.\n"
1550 : "[test.cpp:67]: (style) The scope of the variable 'w' can be reduced.\n"
1551 : "[test.cpp:74]: (style) The scope of the variable 'w' can be reduced.\n",
1552 : errout_str());
1553 : }
1554 :
1555 1 : void varScope32() { // #11441
1556 1 : check("template <class F>\n"
1557 : "std::vector<int> g(F, const std::vector<int>&);\n"
1558 : "void f(const std::vector<int>&v) {\n"
1559 : " std::vector<int> w;\n"
1560 : " for (auto x : v)\n"
1561 : " w = g([&]() { x; }, w);\n"
1562 : "}\n");
1563 1 : ASSERT_EQUALS("[test.cpp:6]: (warning) Unused variable value 'x'\n", errout_str());
1564 : }
1565 :
1566 1 : void varScope33() { // #11131
1567 1 : check("struct S {\n"
1568 : " const std::string& getStr() const;\n"
1569 : " void mutate();\n"
1570 : " bool getB() const;\n"
1571 : "};\n"
1572 : "void g(S& s) {\n"
1573 : " std::string str = s.getStr();\n"
1574 : " s.mutate();\n"
1575 : " if (s.getB()) {\n"
1576 : " if (str == \"abc\") {}\n"
1577 : " }\n"
1578 : "}\n"
1579 : "void g(char* s, bool b) {\n"
1580 : " int i = strlen(s);\n"
1581 : " s[0] = '\\0';\n"
1582 : " if (b) {\n"
1583 : " if (i == 5) {}\n"
1584 : " }\n"
1585 : "}\n"
1586 : "void f(const S& s) {\n"
1587 : " std::string str = s.getStr();\n"
1588 : " std::string str2{ s.getStr() };\n"
1589 : " std::string str3(s.getStr());\n"
1590 : " if (s.getB()) {\n"
1591 : " if (str == \"abc\") {}\n"
1592 : " if (str2 == \"abc\") {}\n"
1593 : " if (str3 == \"abc\") {}\n"
1594 : " }\n"
1595 : "}\n"
1596 : "void f(const char* s, bool b) {\n"
1597 : " int i = strlen(s);\n"
1598 : " if (b) {\n"
1599 : " if (i == 5) {}\n"
1600 : " }\n"
1601 : "}\n"
1602 : "void f(int j, bool b) {\n"
1603 : " int k = j;\n"
1604 : " if (b) {\n"
1605 : " if (k == 5) {}\n"
1606 : " }\n"
1607 : "}\n");
1608 1 : ASSERT_EQUALS("[test.cpp:21]: (style) The scope of the variable 'str' can be reduced.\n"
1609 : "[test.cpp:22]: (style) The scope of the variable 'str2' can be reduced.\n"
1610 : "[test.cpp:23]: (style) The scope of the variable 'str3' can be reduced.\n"
1611 : "[test.cpp:31]: (style) The scope of the variable 'i' can be reduced.\n"
1612 : "[test.cpp:37]: (style) The scope of the variable 'k' can be reduced.\n",
1613 : errout_str());
1614 : }
1615 :
1616 1 : void varScope34() { // #11742
1617 1 : check("void f() {\n"
1618 : " bool b = false;\n"
1619 : " int i = 1;\n"
1620 : " for (int k = 0; k < 20; ++k) {\n"
1621 : " b = !b;\n"
1622 : " if (b)\n"
1623 : " i++;\n"
1624 : " }\n"
1625 : "}\n");
1626 1 : ASSERT_EQUALS("", errout_str());
1627 : }
1628 :
1629 1 : void varScope35() { // #11845
1630 1 : check("void f(int err, const char* src) {\n"
1631 : " const char* msg = \"Success\";\n"
1632 : " char buf[42];\n"
1633 : " if (err != 0)\n"
1634 : " msg = strcpy(buf, src);\n"
1635 : " printf(\"%d: %s\\n\", err, msg);\n"
1636 : "}\n");
1637 1 : ASSERT_EQUALS("", errout_str());
1638 :
1639 1 : check("char* g(char* dst, const char* src);\n"
1640 : "void f(int err, const char* src) {\n"
1641 : " const char* msg = \"Success\";\n"
1642 : " char buf[42];\n"
1643 : " if (err != 0)\n"
1644 : " msg = g(buf, src);\n"
1645 : " printf(\"%d: %s\\n\", err, msg);\n"
1646 : "}\n");
1647 1 : ASSERT_EQUALS("", errout_str());
1648 :
1649 1 : check("char* g(char* dst, const char* src);\n"
1650 : "void f(int err, const char* src) {\n"
1651 : " const char* msg = \"Success\";\n"
1652 : " char buf[42];\n"
1653 : " if (err != 0)\n"
1654 : " g(buf, src);\n"
1655 : " printf(\"%d: %s\\n\", err, msg);\n"
1656 : "}\n");
1657 1 : ASSERT_EQUALS("[test.cpp:4]: (style) The scope of the variable 'buf' can be reduced.\n", errout_str());
1658 : }
1659 :
1660 1 : void varScope36() {
1661 : // #12158
1662 1 : check("void f( uint32_t value ) {\n"
1663 : " uint32_t i = 0U;\n"
1664 : " if ( value > 100U ) { }\n"
1665 : " else if( value > 50U ) { }\n"
1666 : " else{\n"
1667 : " for( i = 0U; i < 5U; i++ ) {}\n"
1668 : " }\n"
1669 : "}\n", true, false);
1670 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'i' can be reduced.\n", errout_str());
1671 : }
1672 :
1673 1 : void varScope37() {
1674 : // #12158
1675 1 : check("void f( uint32_t value ) {\n"
1676 : " uint32_t i = 0U;\n"
1677 : " if ( value > 100U ) { }\n"
1678 : " else {\n"
1679 : " if( value > 50U ) { }\n"
1680 : " else{\n"
1681 : " for( i = 0U; i < 5U; i++ ) {}\n"
1682 : " }\n"
1683 : " }\n"
1684 : "}\n", true, false);
1685 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'i' can be reduced.\n", errout_str());
1686 : }
1687 :
1688 1 : void varScope38() {
1689 1 : checkP("bool dostuff();\n" // #12519
1690 : "#define DOSTUFF(c) if (c < 5) { if (c) b = dostuff(); }\n"
1691 : "#define DOSTUFFEX(c) { bool b = false; DOSTUFF(c); }\n"
1692 : "void f(int a) {\n"
1693 : " DOSTUFFEX(a);\n"
1694 : "}\n");
1695 1 : ASSERT_EQUALS("", errout_str());
1696 : }
1697 :
1698 1 : void varScope39() {
1699 1 : check("struct S {\n" // #12405
1700 : " void f(const std::string&) const;\n"
1701 : " const int* g(std::string&) const;\n"
1702 : "};\n"
1703 : "void h(int);\n"
1704 : "void S::f(const std::string& s) const {\n"
1705 : " std::string n = s;\n"
1706 : " const int* a = g(n);\n"
1707 : " if (n == \"abc\") {\n"
1708 : " h(a[0]);\n"
1709 : " }\n"
1710 : "}\n");
1711 1 : ASSERT_EQUALS("", errout_str());
1712 : }
1713 :
1714 1 : void varScope40() {
1715 1 : checkP("#define NUM (-999.9)\n" // #8862
1716 : "double f(int i) {\n"
1717 : " double a = NUM;\n"
1718 : " double b = -NUM;\n"
1719 : " double c = -1.0 * NUM;\n"
1720 : " if (i == 1) {\n"
1721 : " return a;\n"
1722 : " }\n"
1723 : " if (i == 2) {\n"
1724 : " return b;\n"
1725 : " }\n"
1726 : " if (i == 3) {\n"
1727 : " return c;\n"
1728 : " }\n"
1729 : " return 0.0;\n"
1730 : "}\n");
1731 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'a' can be reduced.\n"
1732 : "[test.cpp:4]: (style) The scope of the variable 'b' can be reduced.\n"
1733 : "[test.cpp:5]: (style) The scope of the variable 'c' can be reduced.\n",
1734 : errout_str());
1735 :
1736 1 : check("struct S { int a; };\n" // #12618
1737 : "int f(const S* s, int i) {\n"
1738 : " int x = s->a;\n"
1739 : " const int b[] = { 1, 2, 3 };\n"
1740 : " int y = b[1];\n"
1741 : " if (i)\n"
1742 : " return x + y;\n"
1743 : " return 0;\n"
1744 : "}\n");
1745 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'x' can be reduced.\n"
1746 : "[test.cpp:5]: (style) The scope of the variable 'y' can be reduced.\n",
1747 : errout_str());
1748 : }
1749 :
1750 : #define checkOldStylePointerCast(code) checkOldStylePointerCast_(code, __FILE__, __LINE__)
1751 23 : void checkOldStylePointerCast_(const char code[], const char* file, int line) {
1752 : // #5560 - set c++03
1753 46 : const Settings settings = settingsBuilder().severity(Severity::style).cpp(Standards::CPP03).build();
1754 :
1755 : // Tokenize..
1756 46 : SimpleTokenizer tokenizerCpp(settings, *this);
1757 23 : ASSERT_LOC(tokenizerCpp.tokenize(code), file, line);
1758 :
1759 46 : CheckOther checkOtherCpp(&tokenizerCpp, &settings, this);
1760 23 : checkOtherCpp.warningOldStylePointerCast();
1761 23 : }
1762 :
1763 1 : void oldStylePointerCast() {
1764 1 : checkOldStylePointerCast("class Base;\n"
1765 : "void foo()\n"
1766 : "{\n"
1767 : " Base * b = (Base *) derived;\n"
1768 : "}");
1769 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1770 :
1771 1 : checkOldStylePointerCast("class Base;\n"
1772 : "void foo()\n"
1773 : "{\n"
1774 : " Base * b = (const Base *) derived;\n"
1775 : "}");
1776 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1777 :
1778 1 : checkOldStylePointerCast("class Base;\n"
1779 : "void foo()\n"
1780 : "{\n"
1781 : " Base * b = (const Base * const) derived;\n"
1782 : "}");
1783 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1784 :
1785 1 : checkOldStylePointerCast("class Base;\n"
1786 : "void foo()\n"
1787 : "{\n"
1788 : " Base * b = (volatile Base *) derived;\n"
1789 : "}");
1790 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1791 :
1792 1 : checkOldStylePointerCast("class Base;\n"
1793 : "void foo()\n"
1794 : "{\n"
1795 : " Base * b = (volatile Base * const) derived;\n"
1796 : "}");
1797 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1798 :
1799 1 : checkOldStylePointerCast("class Base;\n"
1800 : "void foo()\n"
1801 : "{\n"
1802 : " Base * b = (const volatile Base *) derived;\n"
1803 : "}");
1804 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1805 :
1806 1 : checkOldStylePointerCast("class Base;\n"
1807 : "void foo()\n"
1808 : "{\n"
1809 : " Base * b = (const volatile Base * const) derived;\n"
1810 : "}");
1811 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1812 :
1813 1 : checkOldStylePointerCast("class Base;\n"
1814 : "void foo()\n"
1815 : "{\n"
1816 : " Base * b = (const Base *) ( new Derived() );\n"
1817 : "}");
1818 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1819 :
1820 1 : checkOldStylePointerCast("class Base;\n"
1821 : "void foo()\n"
1822 : "{\n"
1823 : " Base * b = (const Base *) new Derived();\n"
1824 : "}");
1825 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1826 :
1827 1 : checkOldStylePointerCast("class Base;\n"
1828 : "void foo()\n"
1829 : "{\n"
1830 : " Base * b = (const Base *) new short[10];\n"
1831 : "}");
1832 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
1833 :
1834 1 : checkOldStylePointerCast("class B;\n"
1835 : "class A\n"
1836 : "{\n"
1837 : " virtual void abc(B *) const = 0;\n"
1838 : "}");
1839 1 : ASSERT_EQUALS("", errout_str());
1840 :
1841 1 : checkOldStylePointerCast("class B;\n"
1842 : "class A\n"
1843 : "{\n"
1844 : " virtual void abc(const B *) const = 0;\n"
1845 : "}");
1846 1 : ASSERT_EQUALS("", errout_str());
1847 :
1848 : // #3630
1849 1 : checkOldStylePointerCast("class SomeType;\n"
1850 : "class X : public Base {\n"
1851 : " X() : Base((SomeType*)7) {}\n"
1852 : "};");
1853 1 : ASSERT_EQUALS("[test.cpp:3]: (style) C-style pointer casting\n", errout_str());
1854 :
1855 1 : checkOldStylePointerCast("class SomeType;\n"
1856 : "class X : public Base {\n"
1857 : " X() : Base((SomeType*)var) {}\n"
1858 : "};");
1859 1 : ASSERT_EQUALS("[test.cpp:3]: (style) C-style pointer casting\n", errout_str());
1860 :
1861 1 : checkOldStylePointerCast("class SomeType;\n"
1862 : "class X : public Base {\n"
1863 : " X() : Base((SomeType*)0) {}\n"
1864 : "};");
1865 1 : ASSERT_EQUALS("", errout_str());
1866 :
1867 : // #5560
1868 1 : checkOldStylePointerCast("class C;\n"
1869 : "\n"
1870 : "class B\n"
1871 : "{ virtual G* createGui(S*, C*) const = 0; };\n"
1872 : "\n"
1873 : "class MS : public M\n"
1874 : "{ virtual void addController(C*) override {} };");
1875 1 : ASSERT_EQUALS("", errout_str());
1876 :
1877 : // #6164
1878 1 : checkOldStylePointerCast("class Base {};\n"
1879 : "class Derived: public Base {};\n"
1880 : "void testCC() {\n"
1881 : " std::vector<Base*> v;\n"
1882 : " v.push_back((Base*)new Derived);\n"
1883 : "}");
1884 1 : ASSERT_EQUALS("[test.cpp:5]: (style) C-style pointer casting\n", errout_str());
1885 :
1886 : // #7709
1887 1 : checkOldStylePointerCast("typedef struct S S;\n"
1888 : "typedef struct S SS;\n"
1889 : "typedef class C C;\n"
1890 : "typedef long LONG;\n"
1891 : "typedef long* LONGP;\n"
1892 : "struct T {};\n"
1893 : "typedef struct T TT;\n"
1894 : "typedef struct T2 {} TT2;\n"
1895 : "void f(int* i) {\n"
1896 : " S* s = (S*)i;\n"
1897 : " SS* ss = (SS*)i;\n"
1898 : " struct S2* s2 = (struct S2*)i;\n"
1899 : " C* c = (C*)i;\n"
1900 : " class C2* c2 = (class C2*)i;\n"
1901 : " long* l = (long*)i;\n"
1902 : " LONG* l2 = (LONG*)i;\n"
1903 : " LONGP l3 = (LONGP)i;\n"
1904 : " TT* tt = (TT*)i;\n"
1905 : " TT2* tt2 = (TT2*)i;\n"
1906 : "}\n");
1907 1 : ASSERT_EQUALS("[test.cpp:10]: (style) C-style pointer casting\n"
1908 : "[test.cpp:11]: (style) C-style pointer casting\n"
1909 : "[test.cpp:12]: (style) C-style pointer casting\n"
1910 : "[test.cpp:13]: (style) C-style pointer casting\n"
1911 : "[test.cpp:14]: (style) C-style pointer casting\n"
1912 : "[test.cpp:15]: (style) C-style pointer casting\n"
1913 : "[test.cpp:16]: (style) C-style pointer casting\n"
1914 : "[test.cpp:17]: (style) C-style pointer casting\n"
1915 : "[test.cpp:18]: (style) C-style pointer casting\n"
1916 : "[test.cpp:19]: (style) C-style pointer casting\n",
1917 : errout_str());
1918 :
1919 : // #8649
1920 1 : checkOldStylePointerCast("struct S {};\n"
1921 : "void g(S*& s);\n"
1922 : "void f(int i) {\n"
1923 : " g((S*&)i);\n"
1924 : " S*& r = (S*&)i;\n"
1925 : "}\n");
1926 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n"
1927 : "[test.cpp:5]: (style) C-style pointer casting\n",
1928 : errout_str());
1929 :
1930 : // #10823
1931 1 : checkOldStylePointerCast("void f(void* p) {\n"
1932 : " auto h = reinterpret_cast<void (STDAPICALLTYPE*)(int)>(p);\n"
1933 : "}\n");
1934 1 : ASSERT_EQUALS("", errout_str());
1935 :
1936 : // #5210
1937 1 : checkOldStylePointerCast("void f(void* v1, void* v2) {\n"
1938 : " T** p1 = (T**)v1;\n"
1939 : " T*** p2 = (T***)v2;\n"
1940 : "}\n");
1941 1 : ASSERT_EQUALS("[test.cpp:2]: (style) C-style pointer casting\n"
1942 : "[test.cpp:3]: (style) C-style pointer casting\n",
1943 : errout_str());
1944 :
1945 : // #12446
1946 1 : checkOldStylePointerCast("namespace N { struct S {}; }\n"
1947 : "union U {\n"
1948 : " int i;\n"
1949 : " char c[4];\n"
1950 : "};\n"
1951 : "void f(void* p) {\n"
1952 : " auto ps = (N::S*)p;\n"
1953 : " auto pu = (union U*)p;\n"
1954 : " auto pv = (std::vector<int>*)(p);\n"
1955 : "}\n");
1956 1 : ASSERT_EQUALS("[test.cpp:7]: (style) C-style pointer casting\n"
1957 : "[test.cpp:8]: (style) C-style pointer casting\n"
1958 : "[test.cpp:9]: (style) C-style pointer casting\n",
1959 : errout_str());
1960 :
1961 : // #12447
1962 1 : checkOldStylePointerCast("void f(const int& i) {\n"
1963 : " int& r = (int&)i;\n"
1964 : " r = 0;\n"
1965 : "}\n");
1966 1 : ASSERT_EQUALS("[test.cpp:2]: (style) C-style reference casting\n", errout_str());
1967 : }
1968 :
1969 : #define checkInvalidPointerCast(...) checkInvalidPointerCast_(__FILE__, __LINE__, __VA_ARGS__)
1970 12 : void checkInvalidPointerCast_(const char* file, int line, const char code[], bool portability = true, bool inconclusive = false) {
1971 24 : /*const*/ Settings settings = settingsBuilder().severity(Severity::warning).severity(Severity::portability, portability).certainty(Certainty::inconclusive, inconclusive).build();
1972 12 : settings.platform.defaultSign = 's';
1973 :
1974 : // Tokenize..
1975 24 : SimpleTokenizer tokenizer(settings, *this);
1976 12 : ASSERT_LOC(tokenizer.tokenize(code), file, line);
1977 :
1978 24 : CheckOther checkOtherCpp(&tokenizer, &settings, this);
1979 12 : checkOtherCpp.invalidPointerCast();
1980 12 : }
1981 :
1982 :
1983 1 : void invalidPointerCast() {
1984 1 : checkInvalidPointerCast("void test() {\n"
1985 : " float *f = new float[10];\n"
1986 : " delete [] (double*)f;\n"
1987 : " delete [] (long double const*)(new float[10]);\n"
1988 : "}");
1989 1 : ASSERT_EQUALS("[test.cpp:3]: (portability) Casting between float * and double * which have an incompatible binary data representation.\n"
1990 : "[test.cpp:4]: (portability) Casting between float * and const long double * which have an incompatible binary data representation.\n", errout_str());
1991 :
1992 1 : checkInvalidPointerCast("void test(const float* f) {\n"
1993 : " double *d = (double*)f;\n"
1994 : "}");
1995 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between const float * and double * which have an incompatible binary data representation.\n", errout_str());
1996 :
1997 1 : checkInvalidPointerCast("void test(double* d1) {\n"
1998 : " long double *ld = (long double*)d1;\n"
1999 : " double *d2 = (double*)ld;\n"
2000 : "}");
2001 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between double * and long double * which have an incompatible binary data representation.\n"
2002 : "[test.cpp:3]: (portability) Casting between long double * and double * which have an incompatible binary data representation.\n", errout_str());
2003 :
2004 1 : checkInvalidPointerCast("char* test(int* i) {\n"
2005 : " long double *d = (long double*)(i);\n"
2006 : " double *d = (double*)(i);\n"
2007 : " float *f = reinterpret_cast<float*>(i);\n"
2008 : "}");
2009 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between signed int * and long double * which have an incompatible binary data representation.\n"
2010 : "[test.cpp:3]: (portability) Casting between signed int * and double * which have an incompatible binary data representation.\n"
2011 : "[test.cpp:4]: (portability) Casting between signed int * and float * which have an incompatible binary data representation.\n", errout_str());
2012 :
2013 1 : checkInvalidPointerCast("float* test(unsigned int* i) {\n"
2014 : " return (float*)i;\n"
2015 : "}");
2016 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between unsigned int * and float * which have an incompatible binary data representation.\n", errout_str());
2017 :
2018 1 : checkInvalidPointerCast("float* test(unsigned int* i) {\n"
2019 : " return (float*)i[0];\n"
2020 : "}");
2021 1 : ASSERT_EQUALS("", errout_str());
2022 :
2023 1 : checkInvalidPointerCast("float* test(double& d) {\n"
2024 : " return (float*)&d;\n"
2025 : "}");
2026 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between double * and float * which have an incompatible binary data representation.\n", errout_str());
2027 :
2028 1 : checkInvalidPointerCast("void test(float* data) {\n"
2029 : " f.write((char*)data,sizeof(float));\n"
2030 : "}", true, false);
2031 1 : ASSERT_EQUALS("", errout_str());
2032 :
2033 1 : checkInvalidPointerCast("void test(float* data) {\n"
2034 : " f.write((char*)data,sizeof(float));\n"
2035 : "}", true, true); // #3639
2036 1 : ASSERT_EQUALS("[test.cpp:2]: (portability, inconclusive) Casting from float * to signed char * is not portable due to different binary data representations on different platforms.\n", errout_str());
2037 :
2038 :
2039 1 : checkInvalidPointerCast("long long* test(float* f) {\n"
2040 : " return (long long*)f;\n"
2041 : "}", false);
2042 1 : ASSERT_EQUALS("", errout_str());
2043 :
2044 1 : checkInvalidPointerCast("long long* test(float* f, char* c) {\n"
2045 : " foo((long long*)f);\n"
2046 : " return reinterpret_cast<long long*>(c);\n"
2047 : "}", true);
2048 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Casting from float * to signed long long * is not portable due to different binary data representations on different platforms.\n", errout_str());
2049 :
2050 1 : checkInvalidPointerCast("Q_DECLARE_METATYPE(int*)"); // #4135 - don't crash
2051 : }
2052 :
2053 :
2054 1 : void passedByValue() {
2055 1 : check("void f(const std::string str) {}");
2056 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2057 :
2058 1 : check("void f(std::unique_ptr<std::string> ptr) {}");
2059 1 : ASSERT_EQUALS("", errout_str());
2060 :
2061 1 : check("void f(const std::shared_ptr<std::string> ptr) {}");
2062 1 : ASSERT_EQUALS("", errout_str());
2063 :
2064 1 : check("void f(const std::function<F> ptr) {}");
2065 1 : ASSERT_EQUALS("", errout_str());
2066 :
2067 : {
2068 1 : check("void f(const std::pair<int,int> x) {}");
2069 1 : ASSERT_EQUALS("", errout_str());
2070 :
2071 1 : check("void f(const std::pair<std::string,std::string> x) {}");
2072 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
2073 : }
2074 :
2075 1 : check("void f(const std::string::size_type x) {}");
2076 1 : ASSERT_EQUALS("", errout_str());
2077 :
2078 1 : check("class Foo;\nvoid f(const Foo foo) {}"); // Unknown class
2079 1 : ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Function parameter 'foo' should be passed by const reference.\n", errout_str());
2080 :
2081 1 : check("class Foo { std::vector<int> v; };\nvoid f(const Foo foo) {}"); // Large class (STL member)
2082 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'foo' should be passed by const reference.\n", errout_str());
2083 :
2084 1 : check("class Foo { int i; };\nvoid f(const Foo foo) {}"); // Small class
2085 1 : ASSERT_EQUALS("", errout_str());
2086 :
2087 1 : check("class Foo { int i[6]; };\nvoid f(const Foo foo) {}"); // Large class (array)
2088 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'foo' should be passed by const reference.\n", errout_str());
2089 :
2090 1 : check("class Foo { std::string* s; };\nvoid f(const Foo foo) {}"); // Small class (pointer)
2091 1 : ASSERT_EQUALS("", errout_str());
2092 :
2093 1 : check("class Foo { static std::string s; };\nvoid f(const Foo foo) {}"); // Small class (static member)
2094 1 : ASSERT_EQUALS("", errout_str());
2095 :
2096 1 : check("class X { std::string s; }; class Foo : X { };\nvoid f(const Foo foo) {}"); // Large class (inherited)
2097 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'foo' should be passed by const reference.\n", errout_str());
2098 :
2099 1 : check("class X { std::string s; }; class Foo { X x; };\nvoid f(const Foo foo) {}"); // Large class (inherited)
2100 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'foo' should be passed by const reference.\n", errout_str());
2101 :
2102 1 : check("void f(const std::string &str) {}");
2103 1 : ASSERT_EQUALS("", errout_str());
2104 :
2105 : // The idiomatic way of passing a std::string_view is by value
2106 1 : check("void f(const std::string_view str) {}");
2107 1 : ASSERT_EQUALS("", errout_str());
2108 :
2109 1 : check("void f(std::string_view str) {}");
2110 1 : ASSERT_EQUALS("", errout_str());
2111 :
2112 1 : check("void f(const std::string_view &str) {}");
2113 1 : ASSERT_EQUALS("", errout_str());
2114 :
2115 1 : check("void f(const std::vector<int> v) {}");
2116 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2117 :
2118 1 : check("void f(const std::vector<std::string> v) {}");
2119 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2120 :
2121 1 : check("void f(const std::vector<std::string>::size_type s) {}");
2122 1 : ASSERT_EQUALS("", errout_str());
2123 :
2124 1 : check("void f(const std::vector<int> &v) {}");
2125 1 : ASSERT_EQUALS("", errout_str());
2126 :
2127 1 : check("void f(const std::map<int,int> &v) {}");
2128 1 : ASSERT_EQUALS("", errout_str());
2129 :
2130 1 : check("void f(const std::map<int,int> v) {}");
2131 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2132 :
2133 1 : check("void f(const std::map<std::string,std::string> v) {}");
2134 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2135 :
2136 1 : check("void f(const std::map<int,std::string> v) {}");
2137 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2138 :
2139 1 : check("void f(const std::map<std::string,int> v) {}");
2140 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2141 :
2142 1 : check("void f(const std::streamoff pos) {}");
2143 1 : ASSERT_EQUALS("", errout_str());
2144 :
2145 1 : check("void f(std::initializer_list<int> i) {}");
2146 1 : ASSERT_EQUALS("", errout_str());
2147 :
2148 : // #5824
2149 1 : check("void log(const std::string& file, int line, const std::string& function, const std::string str, ...) {}");
2150 1 : ASSERT_EQUALS("", errout_str());
2151 :
2152 : // #5534
2153 1 : check("struct float3 { };\n"
2154 : "typedef float3 vec;\n"
2155 : "class Plane {\n"
2156 : " vec Refract(vec &vec) const;\n"
2157 : " bool IntersectLinePlane(const vec &planeNormal);\n"
2158 : "};");
2159 1 : ASSERT_EQUALS("", errout_str());
2160 :
2161 1 : check("class X {\n"
2162 : " virtual void func(const std::string str) {}\n"
2163 : "};");
2164 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2165 :
2166 1 : check("enum X;\n"
2167 : "void foo(X x1){}\n");
2168 1 : ASSERT_EQUALS("", errout_str());
2169 :
2170 1 : check("enum X { a, b, c };\n"
2171 : "void foo(X x2){}\n");
2172 1 : ASSERT_EQUALS("", errout_str());
2173 :
2174 1 : check("enum X { a, b, c };\n"
2175 : "enum X;"
2176 : "void foo(X x3){}\n");
2177 1 : ASSERT_EQUALS("", errout_str());
2178 :
2179 1 : check("enum X;\n"
2180 : "enum X { a, b, c };"
2181 : "void foo(X x4){}\n");
2182 1 : ASSERT_EQUALS("", errout_str());
2183 :
2184 1 : check("union U {\n"
2185 : " char* pc;\n"
2186 : " short* ps;\n"
2187 : " int* pi;\n"
2188 : "};\n"
2189 : "void f(U u) {}\n");
2190 1 : ASSERT_EQUALS("", errout_str());
2191 :
2192 1 : check("struct S { char A[8][8]; };\n"
2193 : "void f(S s) {}\n");
2194 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 's' should be passed by const reference.\n", errout_str());
2195 :
2196 1 : check("union U {\n" // don't crash
2197 : " int a;\n"
2198 : " decltype(nullptr) b;\n"
2199 : "};\n"
2200 : "int* f(U u) { return u.b; }\n");
2201 1 : ASSERT_EQUALS("", errout_str());
2202 :
2203 1 : check("struct B { virtual int f(std::string s) = 0; };\n" // #11432
2204 : "struct D1 : B {\n"
2205 : " int f(std::string s) override { s += 'a'; return s.size(); }\n"
2206 : "}\n"
2207 : "struct D2 : B {\n"
2208 : " int f(std::string s) override { return s.size(); }\n"
2209 : "}\n");
2210 1 : ASSERT_EQUALS("", errout_str());
2211 :
2212 1 : check("int x(int);\n"
2213 : "void f(std::vector<int> v, int& j) {\n"
2214 : " for (int i : v)\n"
2215 : " j = i;\n"
2216 : "}\n"
2217 : "void fn(std::vector<int> v) {\n"
2218 : " for (int& i : v)\n"
2219 : " i = x(i);\n"
2220 : "}\n"
2221 : "void g(std::vector<int> v, int& j) {\n"
2222 : " for (int i = 0; i < v.size(); ++i)\n"
2223 : " j = v[i];\n"
2224 : "}\n"
2225 : "void gn(std::vector<int> v) {\n"
2226 : " for (int i = 0; i < v.size(); ++i)\n"
2227 : " v[i] = x(i);\n"
2228 : "}\n"
2229 : "void h(std::vector<std::vector<int>> v, int& j) {\n"
2230 : " for (int i = 0; i < v.size(); ++i)\n"
2231 : " j = v[i][0];\n"
2232 : "}\n"
2233 : "void hn(std::vector<std::vector<int>> v) {\n"
2234 : " for (int i = 0; i < v.size(); ++i)\n"
2235 : " v[i][0] = x(i);\n"
2236 : "}\n");
2237 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'v' should be passed by const reference.\n"
2238 : "[test.cpp:10]: (performance) Function parameter 'v' should be passed by const reference.\n"
2239 : "[test.cpp:18]: (performance) Function parameter 'v' should be passed by const reference.\n",
2240 : errout_str());
2241 :
2242 1 : check("struct S {\n" // #11995
2243 : " explicit S(std::string s) noexcept;\n"
2244 : " std::string m;\n"
2245 : "};\n"
2246 : "S::S(std::string s) noexcept : m(std::move(s)) {}\n"
2247 : "struct T {\n"
2248 : " explicit S(std::string s) noexcept(true);\n"
2249 : " std::string m;\n"
2250 : "};\n"
2251 : "T::T(std::string s) noexcept(true) : m(std::move(s)) {}\n");
2252 1 : ASSERT_EQUALS("", errout_str());
2253 :
2254 1 : check("namespace N {\n" // #12086
2255 : " void g(int);\n"
2256 : "}\n"
2257 : "void f(std::vector<int> v) {\n"
2258 : " N::g(v[0]);\n"
2259 : "}\n");
2260 1 : ASSERT_EQUALS("[test.cpp:4]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2261 :
2262 1 : check("void f(const std::string& s, std::string t) {\n" // #12083
2263 : " const std::string& v = !s.empty() ? s : t;\n"
2264 : "}\n");
2265 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 't' should be passed by const reference.\n", errout_str());
2266 :
2267 2 : /*const*/ Settings settings0 = settingsBuilder(_settings).platform(Platform::Type::Unix64).build();
2268 1 : check("struct S {\n" // #12138
2269 : " union {\n"
2270 : " int a = 0;\n"
2271 : " int x;\n"
2272 : " };\n"
2273 : " union {\n"
2274 : " int b = 0;\n"
2275 : " int y;\n"
2276 : " };\n"
2277 : " union {\n"
2278 : " int c = 0;\n"
2279 : " int z;\n"
2280 : " };\n"
2281 : "};\n"
2282 : "void f(S s) {\n"
2283 : " if (s.x > s.y) {}\n"
2284 : "}\n", /*cpp*/ true, /*inconclusive*/ true, /*runSimpleChecks*/ true, /*verbose*/ false, &settings0);
2285 1 : ASSERT_EQUALS("", errout_str());
2286 :
2287 1 : check("struct S { std::list<int> l; };\n" // #12147
2288 : "class C { public: std::list<int> l; };\n"
2289 : "bool f(S s) {\n"
2290 : " return s.l.empty();\n"
2291 : "}\n"
2292 : "bool f(C c) {\n"
2293 : " return c.l.empty();\n"
2294 : "}\n");
2295 1 : ASSERT_EQUALS("[test.cpp:3]: (performance) Function parameter 's' should be passed by const reference.\n"
2296 : "[test.cpp:6]: (performance) Function parameter 'c' should be passed by const reference.\n",
2297 : errout_str());
2298 :
2299 1 : check("struct S { std::list<int> a[1][1]; };\n"
2300 : "bool f(S s) {\n"
2301 : " return s.a[0][0].empty();\n"
2302 : "}\n");
2303 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 's' should be passed by const reference.\n",
2304 : errout_str());
2305 :
2306 1 : check("struct S {\n"
2307 : " enum class E : std::uint8_t { E0 };\n"
2308 : " static void f(S::E e) {\n"
2309 : " if (e == S::E::E0) {}\n"
2310 : " }\n"
2311 : " char a[20];\n"
2312 : "};\n");
2313 1 : ASSERT_EQUALS("", errout_str());
2314 :
2315 1 : /*const*/ Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build();
2316 1 : check("using ui64 = unsigned __int64;\n"
2317 : "ui64 Test(ui64 one, ui64 two) { return one + two; }\n",
2318 : /*cpp*/ true, /*inconclusive*/ true, /*runSimpleChecks*/ true, /*verbose*/ false, &settings1);
2319 1 : ASSERT_EQUALS("", errout_str());
2320 : }
2321 :
2322 1 : void passedByValue_nonConst() {
2323 1 : check("void f(std::string str) {}");
2324 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2325 :
2326 1 : check("void f(std::string str) {\n"
2327 : " return str + x;\n"
2328 : "}");
2329 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2330 :
2331 1 : check("void f(std::string str) {\n"
2332 : " std::cout << str;\n"
2333 : "}");
2334 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2335 :
2336 1 : check("void f(std::string str) {\n"
2337 : " std::cin >> str;\n"
2338 : "}");
2339 1 : ASSERT_EQUALS("", errout_str());
2340 :
2341 1 : check("void f(std::string str) {\n"
2342 : " std::string s2 = str;\n"
2343 : "}");
2344 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2345 :
2346 1 : check("void f(std::string str) {\n"
2347 : " std::string& s2 = str;\n"
2348 : "}");
2349 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n"
2350 : "[test.cpp:2]: (style) Variable 's2' can be declared as reference to const\n",
2351 : errout_str());
2352 :
2353 1 : check("void f(std::string str) {\n"
2354 : " const std::string& s2 = str;\n"
2355 : "}");
2356 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2357 :
2358 1 : check("void f(std::string str) {\n"
2359 : " str = \"\";\n"
2360 : "}");
2361 1 : ASSERT_EQUALS("", errout_str());
2362 :
2363 1 : check("void f(std::string str) {\n"
2364 : " foo(str);\n" // It could be that foo takes str as non-const-reference
2365 : "}");
2366 1 : ASSERT_EQUALS("", errout_str());
2367 :
2368 1 : check("void foo(const std::string& str);\n"
2369 : "void f(std::string str) {\n"
2370 : " foo(str);\n"
2371 : "}");
2372 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2373 :
2374 1 : check("void foo(std::string str);\n"
2375 : "void f(std::string str) {\n"
2376 : " foo(str);\n"
2377 : "}");
2378 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2379 :
2380 1 : check("void foo(std::string& str);\n"
2381 : "void f(std::string str) {\n"
2382 : " foo(str);\n"
2383 : "}");
2384 1 : ASSERT_EQUALS("", errout_str());
2385 :
2386 1 : check("void foo(std::string* str);\n"
2387 : "void f(std::string str) {\n"
2388 : " foo(&str);\n"
2389 : "}");
2390 1 : ASSERT_EQUALS("", errout_str());
2391 :
2392 1 : check("void foo(int& i1, const std::string& str, int& i2);\n"
2393 : "void f(std::string str) {\n"
2394 : " foo((a+b)*c, str, x);\n"
2395 : "}");
2396 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2397 :
2398 1 : check("std::string f(std::string str) {\n"
2399 : " str += x;\n"
2400 : " return str;\n"
2401 : "}");
2402 1 : ASSERT_EQUALS("", errout_str());
2403 :
2404 1 : check("class X {\n"
2405 : " std::string s;\n"
2406 : " void func() const;\n"
2407 : "};\n"
2408 : "Y f(X x) {\n"
2409 : " x.func();\n"
2410 : "}");
2411 1 : ASSERT_EQUALS("[test.cpp:5]: (performance) Function parameter 'x' should be passed by const reference.\n", errout_str());
2412 :
2413 1 : check("class X {\n"
2414 : " void func();\n"
2415 : "};\n"
2416 : "Y f(X x) {\n"
2417 : " x.func();\n"
2418 : "}");
2419 1 : ASSERT_EQUALS("", errout_str());
2420 :
2421 1 : check("class X {\n"
2422 : " void func(std::string str) {}\n"
2423 : "};");
2424 1 : ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'str' should be passed by const reference.\n", errout_str());
2425 :
2426 1 : check("class X {\n"
2427 : " virtual void func(std::string str) {}\n" // Do not warn about virtual functions, if 'str' is not declared as const
2428 : "};");
2429 1 : ASSERT_EQUALS("", errout_str());
2430 :
2431 1 : check("class X {\n"
2432 : " char a[1024];\n"
2433 : "};\n"
2434 : "class Y : X {\n"
2435 : " char b;\n"
2436 : "};\n"
2437 : "void f(Y y) {\n"
2438 : "}");
2439 1 : ASSERT_EQUALS("[test.cpp:7]: (performance) Function parameter 'y' should be passed by const reference.\n", errout_str());
2440 :
2441 1 : check("class X {\n"
2442 : " void* a;\n"
2443 : " void* b;\n"
2444 : "};\n"
2445 : "class Y {\n"
2446 : " void* a;\n"
2447 : " void* b;\n"
2448 : " char c;\n"
2449 : "};\n"
2450 : "void f(X x, Y y) {\n"
2451 : "}");
2452 1 : ASSERT_EQUALS("[test.cpp:10]: (performance) Function parameter 'y' should be passed by const reference.\n", errout_str());
2453 :
2454 : {
2455 : // 8-byte data should be passed by const reference on 32-bit platform but not on 64-bit platform
2456 1 : const char code[] = "class X {\n"
2457 : " uint64_t a;\n"
2458 : " uint64_t b;\n"
2459 : "};\n"
2460 : "void f(X x) {}";
2461 :
2462 2 : /*const*/ Settings s32 = settingsBuilder(_settings).platform(Platform::Type::Unix32).build();
2463 1 : check(code, &s32);
2464 1 : ASSERT_EQUALS("[test.cpp:5]: (performance) Function parameter 'x' should be passed by const reference.\n", errout_str());
2465 :
2466 2 : /*const*/ Settings s64 = settingsBuilder(_settings).platform(Platform::Type::Unix64).build();
2467 1 : check(code, &s64);
2468 1 : ASSERT_EQUALS("", errout_str());
2469 : }
2470 :
2471 1 : check("Writer* getWriter();\n"
2472 : "\n"
2473 : "void foo(Buffer& buffer) {\n"
2474 : " getWriter()->operator<<(buffer);\n"
2475 : "}");
2476 1 : ASSERT_EQUALS("", errout_str());
2477 : }
2478 :
2479 1 : void passedByValue_externC() {
2480 1 : check("struct X { int a[5]; }; void f(X v) { }");
2481 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2482 :
2483 1 : check("extern \"C\" { struct X { int a[5]; }; void f(X v) { } }");
2484 1 : ASSERT_EQUALS("", errout_str());
2485 :
2486 1 : check("struct X { int a[5]; }; extern \"C\" void f(X v) { }");
2487 1 : ASSERT_EQUALS("", errout_str());
2488 :
2489 1 : check("struct X { int a[5]; }; void f(const X v);");
2490 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'v' should be passed by const reference.\n", errout_str());
2491 :
2492 1 : check("extern \"C\" { struct X { int a[5]; }; void f(const X v); }");
2493 1 : ASSERT_EQUALS("", errout_str());
2494 :
2495 1 : check("struct X { int a[5]; }; extern \"C\" void f(const X v) { }");
2496 1 : ASSERT_EQUALS("", errout_str());
2497 : }
2498 :
2499 1 : void constVariable() {
2500 1 : check("int f(std::vector<int> x) {\n"
2501 : " int& i = x[0];\n"
2502 : " return i;\n"
2503 : "}");
2504 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n"
2505 : "[test.cpp:2]: (style) Variable 'i' can be declared as reference to const\n",
2506 : errout_str());
2507 :
2508 1 : check("int f(std::vector<int>& x) {\n"
2509 : " return x[0];\n"
2510 : "}");
2511 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2512 :
2513 1 : check("int f(std::vector<int> x) {\n"
2514 : " const int& i = x[0];\n"
2515 : " return i;\n"
2516 : "}");
2517 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n", errout_str());
2518 :
2519 1 : check("int f(std::vector<int> x) {\n"
2520 : " static int& i = x[0];\n"
2521 : " return i;\n"
2522 : "}");
2523 1 : ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n", errout_str());
2524 :
2525 1 : check("int f(std::vector<int> x) {\n"
2526 : " int& i = x[0];\n"
2527 : " i++;\n"
2528 : " return i;\n"
2529 : "}");
2530 1 : ASSERT_EQUALS("", errout_str());
2531 :
2532 1 : check("int& f(std::vector<int>& x) {\n"
2533 : " x.push_back(1);\n"
2534 : " int& i = x[0];\n"
2535 : " return i;\n"
2536 : "}");
2537 1 : ASSERT_EQUALS("", errout_str());
2538 :
2539 1 : check("int f(const std::vector<int>& x) {\n"
2540 : " return x[0];\n"
2541 : "}");
2542 1 : ASSERT_EQUALS("", errout_str());
2543 :
2544 1 : check("int& f(std::vector<int>& x) {\n"
2545 : " return x[0];\n"
2546 : "}");
2547 1 : ASSERT_EQUALS("", errout_str());
2548 :
2549 1 : check("const int& f(std::vector<int>& x) {\n"
2550 : " return x[0];\n"
2551 : "}");
2552 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2553 :
2554 1 : check("int f(std::vector<int>& x) {\n"
2555 : " x[0]++;\n"
2556 : " return x[0];\n"
2557 : "}");
2558 1 : ASSERT_EQUALS("", errout_str());
2559 :
2560 1 : check("struct A { int a; };\n"
2561 : "A f(std::vector<A>& x) {\n"
2562 : " x[0].a = 1;\n"
2563 : " return x[0];\n"
2564 : "}");
2565 1 : ASSERT_EQUALS("", errout_str());
2566 :
2567 1 : check("struct A { int a(); };\n"
2568 : "A f(std::vector<A>& x) {\n"
2569 : " x[0].a();\n"
2570 : " return x[0];\n"
2571 : "}");
2572 1 : ASSERT_EQUALS("", errout_str());
2573 :
2574 1 : check("int g(int& x);\n"
2575 : "int f(std::vector<int>& x) {\n"
2576 : " g(x[0]);\n"
2577 : " return x[0];\n"
2578 : "}");
2579 1 : ASSERT_EQUALS("", errout_str());
2580 :
2581 1 : check("template<class T>\n"
2582 : "T f(T& x) {\n"
2583 : " return x[0];\n"
2584 : "}");
2585 1 : ASSERT_EQUALS("", errout_str());
2586 :
2587 1 : check("template<class T>\n"
2588 : "T f(T&& x) {\n"
2589 : " return x[0];\n"
2590 : "}");
2591 1 : ASSERT_EQUALS("", errout_str());
2592 :
2593 1 : check("template<class T>\n"
2594 : "T f(T& x) {\n"
2595 : " return x[0];\n"
2596 : "}\n"
2597 : "void h() { std::vector<int> v; h(v); }");
2598 1 : ASSERT_EQUALS("", errout_str());
2599 :
2600 1 : check("int f(int& x) {\n"
2601 : " return std::move(x);\n"
2602 : "}");
2603 1 : ASSERT_EQUALS("", errout_str());
2604 :
2605 1 : check("void f(std::ostream& os) {\n"
2606 : " os << \"Hello\";\n"
2607 : "}");
2608 1 : ASSERT_EQUALS("", errout_str());
2609 :
2610 1 : check("void g(int*);\n"
2611 : "void f(int& x) {\n"
2612 : " g(&x);\n"
2613 : "}");
2614 1 : ASSERT_EQUALS("", errout_str());
2615 :
2616 1 : check("struct A { A(int*); };\n"
2617 : "A f(int& x) {\n"
2618 : " return A(&x);\n"
2619 : "}");
2620 1 : ASSERT_EQUALS("", errout_str());
2621 :
2622 1 : check("struct A { A(int*); };\n"
2623 : "A f(int& x) {\n"
2624 : " return A{&x};\n"
2625 : "}");
2626 1 : ASSERT_EQUALS("", errout_str());
2627 :
2628 1 : check("void f(int& x, int& y) {\n"
2629 : " y++;\n"
2630 : "}");
2631 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2632 :
2633 1 : check("struct A {\n"
2634 : " explicit A(int& y) : x(&y) {}\n"
2635 : " int * x = nullptr;\n"
2636 : "};");
2637 1 : ASSERT_EQUALS("", errout_str());
2638 :
2639 1 : check("struct A {\n"
2640 : " std::vector<int> v;\n"
2641 : " void swap(A& a) {\n"
2642 : " v.swap(a.v);\n"
2643 : " }\n"
2644 : "};");
2645 1 : ASSERT_EQUALS("", errout_str());
2646 :
2647 1 : check("struct A {\n"
2648 : " template<class T>\n"
2649 : " void f();\n"
2650 : " template<class T>\n"
2651 : " void f() const;\n"
2652 : "};\n"
2653 : "void g(A& a) {\n"
2654 : " a.f<int>();\n"
2655 : "}");
2656 1 : ASSERT_EQUALS("", errout_str());
2657 :
2658 1 : check("void f(std::vector<int>& v) {\n"
2659 : " for(auto&& x:v)\n"
2660 : " x = 1;\n"
2661 : "}");
2662 1 : ASSERT_EQUALS("", errout_str());
2663 :
2664 1 : check("void f(std::vector<int>& v) {\n"
2665 : " for(auto x:v)\n"
2666 : " x = 1;\n"
2667 : "}");
2668 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n", errout_str());
2669 :
2670 1 : check("void f(std::vector<int>& v) {\n"
2671 : " for(auto& x:v) {}\n"
2672 : "}");
2673 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' can be declared as reference to const\n",
2674 : errout_str());
2675 :
2676 1 : check("void f(std::vector<int>& v) {\n" // #10980
2677 : " for (int& i : v)\n"
2678 : " if (i == 0) {}\n"
2679 : " for (const int& i : v)\n"
2680 : " if (i == 0) {}\n"
2681 : " for (auto& i : v)\n"
2682 : " if (i == 0) {}\n"
2683 : " for (const auto& i : v)\n"
2684 : " if (i == 0) {}\n"
2685 : " v.clear();\n"
2686 : "}\n");
2687 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' can be declared as reference to const\n"
2688 : "[test.cpp:6]: (style) Variable 'i' can be declared as reference to const\n",
2689 : errout_str());
2690 :
2691 1 : check("void f(std::vector<int>& v) {\n"
2692 : " for(const auto& x:v) {}\n"
2693 : "}");
2694 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n", errout_str());
2695 :
2696 1 : check("void f(int& i) {\n"
2697 : " int& j = i;\n"
2698 : " j++;\n"
2699 : "}");
2700 1 : ASSERT_EQUALS("", errout_str());
2701 :
2702 1 : check("void f(std::vector<int>& v) {\n"
2703 : " int& i = v[0];\n"
2704 : " i++;\n"
2705 : "}");
2706 1 : ASSERT_EQUALS("", errout_str());
2707 :
2708 1 : check("void f(std::map<unsigned int, std::map<std::string, unsigned int> >& m, unsigned int i) {\n"
2709 : " std::map<std::string, unsigned int>& members = m[i];\n"
2710 : " members.clear();\n"
2711 : "}");
2712 1 : ASSERT_EQUALS("", errout_str());
2713 :
2714 1 : check("struct A {\n"
2715 : " int& x;\n"
2716 : " A(int& y) : x(y)\n"
2717 : " {}\n"
2718 : "};");
2719 1 : ASSERT_EQUALS("", errout_str());
2720 :
2721 1 : check("struct A {\n"
2722 : " A(int& x);\n"
2723 : "};\n"
2724 : "struct B : A {\n"
2725 : " B(int& x) : A(x)\n"
2726 : " {}\n"
2727 : "};");
2728 1 : ASSERT_EQUALS("", errout_str());
2729 :
2730 1 : check("void f(bool b, int& x, int& y) {\n"
2731 : " auto& z = x;\n"
2732 : " auto& w = b ? y : z;\n"
2733 : " w = 1;\n"
2734 : "}");
2735 1 : ASSERT_EQUALS("", errout_str());
2736 :
2737 1 : check("struct S {\n"
2738 : " int i;\n"
2739 : "};\n"
2740 : "int& f(S& s) {\n"
2741 : " return s.i;\n"
2742 : "}");
2743 1 : ASSERT_EQUALS("", errout_str());
2744 :
2745 1 : check("int* f(std::list<int>& x, unsigned int y) {\n"
2746 : " for (int& m : x) {\n"
2747 : " if (m == y)\n"
2748 : " return &m;\n"
2749 : " }\n"
2750 : " return nullptr;\n"
2751 : "}");
2752 1 : ASSERT_EQUALS("", errout_str());
2753 :
2754 1 : check("int& f(std::list<int>& x, int& y) {\n"
2755 : " for (int& m : x) {\n"
2756 : " if (m == y)\n"
2757 : " return m;\n"
2758 : " }\n"
2759 : " return y;\n"
2760 : "}");
2761 1 : ASSERT_EQUALS("", errout_str());
2762 :
2763 1 : check("bool from_string(int& t, const std::string& s) {\n"
2764 : " std::istringstream iss(s);\n"
2765 : " return !(iss >> t).fail();\n"
2766 : "}\n");
2767 1 : ASSERT_EQUALS("", errout_str());
2768 :
2769 : // #9710
2770 1 : check("class a {\n"
2771 : " void operator()(int& i) const {\n"
2772 : " i++;\n"
2773 : " }\n"
2774 : "};\n"
2775 : "void f(int& i) {\n"
2776 : " a()(i);\n"
2777 : "}\n");
2778 1 : ASSERT_EQUALS("", errout_str());
2779 :
2780 1 : check("class a {\n"
2781 : " void operator()(int& i) const {\n"
2782 : " i++;\n"
2783 : " }\n"
2784 : "};\n"
2785 : "void f(int& i) {\n"
2786 : " a x;\n"
2787 : " x(i);\n"
2788 : "}\n");
2789 1 : ASSERT_EQUALS("", errout_str());
2790 :
2791 1 : check("class a {\n"
2792 : " void operator()(const int& i) const;\n"
2793 : "};\n"
2794 : "void f(int& i) {\n"
2795 : " a x;\n"
2796 : " x(i);\n"
2797 : "}\n");
2798 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'i' can be declared as reference to const\n", errout_str());
2799 :
2800 : //cast or assignment to a non-const reference should prevent the warning
2801 1 : check("struct T { void dostuff() const {}};\n"
2802 : "void a(T& x) {\n"
2803 : " x.dostuff();\n"
2804 : "}");
2805 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2806 1 : check("struct T : public U { void dostuff() const {}};\n"
2807 : "void a(T& x) {\n"
2808 : " x.dostuff();\n"
2809 : " const T& z = x;\n" // Make sure we find all assignments
2810 : " T& y = x;\n"
2811 : " y.mutate();\n" // to avoid warnings that y can be const
2812 : "}");
2813 1 : ASSERT_EQUALS("", errout_str());
2814 1 : check("struct T : public U { void dostuff() const {}};\n"
2815 : "void a(T& x) {\n"
2816 : " x.dostuff();\n"
2817 : " const U& y = x\n"
2818 : "}");
2819 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2820 1 : check("struct T : public U { void dostuff() const {}};\n"
2821 : "void a(T& x) {\n"
2822 : " x.dostuff();\n"
2823 : " U& y = x;\n"
2824 : " y.mutate();\n" // to avoid warnings that y can be const
2825 : "}");
2826 1 : ASSERT_EQUALS("", errout_str());
2827 1 : check("struct T : public U { void dostuff() const {}};\n"
2828 : "void a(T& x) {\n"
2829 : " x.dostuff();\n"
2830 : " my<fancy>::type& y = x;\n" // we don't know if y is const or not
2831 : " y.mutate();\n" // to avoid warnings that y can be const
2832 : "}");
2833 1 : ASSERT_EQUALS("", errout_str());
2834 1 : check("struct T : public U { void dostuff() const {}};\n"
2835 : "void a(T& x) {\n"
2836 : " x.dostuff();\n"
2837 : " const U& y = static_cast<const U&>(x);\n"
2838 : " y.mutate();\n" // to avoid warnings that y can be const
2839 : "}");
2840 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2841 1 : check("struct T : public U { void dostuff() const {}};\n"
2842 : "void a(T& x) {\n"
2843 : " x.dostuff();\n"
2844 : " U& y = static_cast<U&>(x);\n"
2845 : " y.mutate();\n" // to avoid warnings that y can be const
2846 : "}");
2847 1 : ASSERT_EQUALS("", errout_str());
2848 1 : check("struct T : public U { void dostuff() const {}};\n"
2849 : "void a(T& x) {\n"
2850 : " x.dostuff();\n"
2851 : " const U& y = dynamic_cast<const U&>(x)\n"
2852 : "}");
2853 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2854 1 : check("struct T : public U { void dostuff() const {}};\n"
2855 : "void a(T& x) {\n"
2856 : " x.dostuff();\n"
2857 : " const U& y = dynamic_cast<U const &>(x);\n"
2858 : "}");
2859 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2860 1 : check("struct T : public U { void dostuff() const {}};\n"
2861 : "void a(T& x) {\n"
2862 : " x.dostuff();\n"
2863 : " const U& y = dynamic_cast<U & const>(x);\n"
2864 : "}");
2865 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2866 1 : check("struct T : public U { void dostuff() const {}};\n"
2867 : "void a(T& x) {\n"
2868 : " x.dostuff();\n"
2869 : " U& y = dynamic_cast<U&>(x);\n"
2870 : " y.mutate();\n" // to avoid warnings that y can be const
2871 : "}");
2872 1 : ASSERT_EQUALS("", errout_str());
2873 1 : check("struct T : public U { void dostuff() const {}};\n"
2874 : "void a(T& x) {\n"
2875 : " x.dostuff();\n"
2876 : " const U& y = dynamic_cast<typename const U&>(x);\n"
2877 : "}");
2878 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2879 1 : check("struct T : public U { void dostuff() const {}};\n"
2880 : "void a(T& x) {\n"
2881 : " x.dostuff();\n"
2882 : " U& y = dynamic_cast<typename U&>(x);\n"
2883 : " y.mutate();\n" // to avoid warnings that y can be const
2884 : "}");
2885 1 : ASSERT_EQUALS("", errout_str());
2886 1 : check("struct T : public U { void dostuff() const {}};\n"
2887 : "void a(T& x) {\n"
2888 : " x.dostuff();\n"
2889 : " U* y = dynamic_cast<U*>(&x);\n"
2890 : " y->mutate();\n" // to avoid warnings that y can be const
2891 : "}");
2892 1 : ASSERT_EQUALS("", errout_str());
2893 :
2894 1 : check("struct T : public U { void dostuff() const {}};\n"
2895 : "void a(T& x) {\n"
2896 : " x.dostuff();\n"
2897 : " const U * y = dynamic_cast<const U *>(&x);\n"
2898 : " y->mutate();\n" // to avoid warnings that y can be const
2899 : "}");
2900 1 : TODO_ASSERT_EQUALS("can be const", errout_str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
2901 1 : check("struct T : public U { void dostuff() const {}};\n"
2902 : "void a(T& x) {\n"
2903 : " x.dostuff();\n"
2904 : " U const * y = dynamic_cast<U const *>(&x);\n"
2905 : " y->mutate();\n" // to avoid warnings that y can be const
2906 : "}");
2907 1 : TODO_ASSERT_EQUALS("can be const", errout_str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
2908 1 : check("struct T : public U { void dostuff() const {}};\n"
2909 : "void a(T& x) {\n"
2910 : " x.dostuff();\n"
2911 : " const U const * const * const * const y = dynamic_cast<const U const * const * const * const>(&x);\n"
2912 : " y->mutate();\n" // to avoid warnings that y can be const
2913 : "}");
2914 1 : ASSERT_EQUALS("", errout_str());
2915 1 : check("struct T : public U { void dostuff() const {}};\n"
2916 : "void a(T& x) {\n"
2917 : " x.dostuff();\n"
2918 : " const U const * const * const * const y = dynamic_cast<const U const * const * const * const>(&x);\n"
2919 : " y->mutate();\n" // to avoid warnings that y can be const
2920 : "}");
2921 1 : TODO_ASSERT_EQUALS("can be const", errout_str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
2922 1 : check("struct T : public U { void dostuff() const {}};\n"
2923 : "void a(T& x) {\n"
2924 : " x.dostuff();\n"
2925 : " const U const * const * * const y = dynamic_cast<const U const * const * * const>(&x);\n"
2926 : " y->mutate();\n" // to avoid warnings that y can be const
2927 : "}");
2928 1 : ASSERT_EQUALS("", errout_str());
2929 1 : check("struct T : public U { void dostuff() const {}};\n"
2930 : "void a(T& x) {\n"
2931 : " x.dostuff();\n"
2932 : " my::fancy<typename type const *> const * const * const y = dynamic_cast<my::fancy<typename type const *> const * const * const>(&x);\n"
2933 : " y->mutate();\n" // to avoid warnings that y can be const
2934 : "}");
2935 1 : ASSERT_EQUALS("", errout_str());
2936 :
2937 1 : check("struct T : public U { void dostuff() const {}};\n"
2938 : "void a(T& x) {\n"
2939 : " x.dostuff();\n"
2940 : " const U& y = (const U&)(x);\n"
2941 : "}");
2942 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n"
2943 : "[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n",
2944 : errout_str());
2945 1 : check("struct T : public U { void dostuff() const {}};\n"
2946 : "void a(T& x) {\n"
2947 : " x.dostuff();\n"
2948 : " U& y = (U&)(x);\n"
2949 : " y.mutate();\n" // to avoid warnings that y can be const
2950 : "}");
2951 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n", errout_str());
2952 1 : check("struct T : public U { void dostuff() const {}};\n"
2953 : "void a(T& x) {\n"
2954 : " x.dostuff();\n"
2955 : " const U& y = (typename const U&)(x);\n"
2956 : "}");
2957 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n"
2958 : "[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n",
2959 : errout_str());
2960 1 : check("struct T : public U { void dostuff() const {}};\n"
2961 : "void a(T& x) {\n"
2962 : " x.dostuff();\n"
2963 : " U& y = (typename U&)(x);\n"
2964 : " y.mutate();\n" // to avoid warnings that y can be const
2965 : "}");
2966 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n", errout_str());
2967 1 : check("struct T : public U { void dostuff() const {}};\n"
2968 : "void a(T& x) {\n"
2969 : " x.dostuff();\n"
2970 : " U* y = (U*)(&x);\n"
2971 : " y->mutate();\n" // to avoid warnings that y can be const
2972 : "}");
2973 1 : ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout_str());
2974 :
2975 1 : check("struct C { void f() const; };\n" // #9875 - crash
2976 : "\n"
2977 : "void foo(C& x) {\n"
2978 : " x.f();\n"
2979 : " foo( static_cast<U2>(0) );\n"
2980 : "}");
2981 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'x' can be declared as reference to const\n", errout_str());
2982 :
2983 1 : check("class a {\n"
2984 : " void foo(const int& i) const;\n"
2985 : " void operator()(int& i) const;\n"
2986 : "};\n"
2987 : "void f(int& i) {\n"
2988 : " a()(i);\n"
2989 : "}\n");
2990 1 : ASSERT_EQUALS("", errout_str());
2991 :
2992 1 : check("class a {\n"
2993 : " void operator()(const int& i) const;\n"
2994 : "};\n"
2995 : "void f(int& i) {\n"
2996 : " a()(i);\n"
2997 : "}\n");
2998 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'i' can be declared as reference to const\n", errout_str());
2999 :
3000 : // #9767
3001 1 : check("void fct1(MyClass& object) {\n"
3002 : " fct2([&](void){}, object);\n"
3003 : "}\n"
3004 : "bool fct2(std::function<void()> lambdaExpression, MyClass& object) {\n"
3005 : " object.modify();\n"
3006 : "}\n");
3007 1 : ASSERT_EQUALS("", errout_str());
3008 :
3009 : // #9778
3010 1 : check("struct A {};\n"
3011 : "struct B : A {};\n"
3012 : "B& f(A& x) {\n"
3013 : " return static_cast<B&>(x);\n"
3014 : "}\n");
3015 1 : ASSERT_EQUALS("", errout_str());
3016 :
3017 : // #10002
3018 1 : check("using A = int*;\n"
3019 : "void f(const A& x) {\n"
3020 : " ++(*x);\n"
3021 : "}\n");
3022 1 : ASSERT_EQUALS("", errout_str());
3023 :
3024 : // #10086
3025 1 : check("struct V {\n"
3026 : " V& get(typename std::vector<V>::size_type i) {\n"
3027 : " std::vector<V>& arr = v;\n"
3028 : " return arr[i];\n"
3029 : " }\n"
3030 : " std::vector<V> v;\n"
3031 : "};\n");
3032 1 : ASSERT_EQUALS("", errout_str());
3033 :
3034 1 : check("void e();\n"
3035 : "void g(void);\n"
3036 : "void h(void);\n"
3037 : "void ah(void);\n"
3038 : "void ai(void);\n"
3039 : "void j(void);\n"
3040 : "void e(void);\n"
3041 : "void k(void);\n"
3042 : "void l(void);\n"
3043 : "void m(void);\n"
3044 : "void n(void);\n"
3045 : "void o(void);\n"
3046 : "void q(void);\n"
3047 : "void r(void);\n"
3048 : "void t(void);\n"
3049 : "void u(void);\n"
3050 : "void v(void);\n"
3051 : "void w(void);\n"
3052 : "void z(void);\n"
3053 : "void aj(void);\n"
3054 : "void am(void);\n"
3055 : "void g(void);\n"
3056 : "void h(void);\n"
3057 : "void ah(void);\n"
3058 : "void an(void);\n"
3059 : "void e(void);\n"
3060 : "void k(void);\n"
3061 : "void ao(wchar_t *d);\n"
3062 : "void ah(void);\n"
3063 : "void e(void);\n"
3064 : "void an(void);\n"
3065 : "void e(void);\n"
3066 : "void k(void);\n"
3067 : "void g(void);\n"
3068 : "void ah(void);\n"
3069 : "void an(void);\n"
3070 : "void e(void);\n"
3071 : "void e(void);\n"
3072 : "void e(void);\n"
3073 : "void k(void);\n"
3074 : "void g(void);\n"
3075 : "void ah(void);\n"
3076 : "void an(void);\n"
3077 : "void e(void);\n"
3078 : "void e(void);\n"
3079 : "void k(void);\n"
3080 : "void g(void);\n"
3081 : "void h(void);\n"
3082 : "void ah(void);\n"
3083 : "void an(void);\n"
3084 : "void e(void);\n"
3085 : "void k(void);\n"
3086 : "void e(void);\n"
3087 : "void g(void);\n"
3088 : "void ah(void);\n"
3089 : "void k(void);\n"
3090 : "void an(void);\n"
3091 : "void e(void);\n"
3092 : "void e(void);\n"
3093 : "void e(void);\n"
3094 : "void k(void);\n"
3095 : "void g(void);\n"
3096 : "void h(void);\n"
3097 : "void ah(void);\n"
3098 : "void k(void);\n"
3099 : "void an(void);\n"
3100 : "void k(void);\n"
3101 : "void e(void);\n"
3102 : "void g(void);\n"
3103 : "void ah(void);\n"
3104 : "void e(void);\n"
3105 : "void k(void);\n"
3106 : "void g(void);\n"
3107 : "void h(void);\n"
3108 : "void ah(void);\n"
3109 : "void an(void);\n"
3110 : "void an(void);\n"
3111 : "void k(void);\n"
3112 : "void e(void);\n"
3113 : "void e(void);\n"
3114 : "void e(void);\n"
3115 : "void g(void);\n"
3116 : "void k(void);\n"
3117 : "void g(void);\n"
3118 : "void h(void);\n"
3119 : "void ah(void);\n"
3120 : "void an(void);\n"
3121 : "void k(void);\n"
3122 : "void k(void);\n"
3123 : "void e(void);\n"
3124 : "void g(void);\n"
3125 : "void g(void);\n"
3126 : "void ah(void);\n"
3127 : "void an(void);\n"
3128 : "void e(void);\n"
3129 : "void k(void);\n"
3130 : "void e(void);\n"
3131 : "void ap(wchar_t *c, int d);\n"
3132 : "void ah(void);\n"
3133 : "void an(void);\n"
3134 : "void g(void);\n"
3135 : "void h(void);\n"
3136 : "void ah(void);\n"
3137 : "void aq(char *b, size_t d, char *c, int a);\n"
3138 : "void ar(char *b, size_t d, char *c, va_list a);\n"
3139 : "void k(void);\n"
3140 : "void g(void);\n"
3141 : "void g(void);\n"
3142 : "void h(void);\n"
3143 : "void ah(void);\n"
3144 : "void an(void);\n"
3145 : "void k(void);\n"
3146 : "void k(void);\n"
3147 : "void e(void);\n"
3148 : "void g(void);\n"
3149 : "void g(void);\n"
3150 : "void as(std::string s);\n"
3151 : "void at(std::ifstream &f);\n"
3152 : "void au(std::istream &f);\n"
3153 : "void av(std::string &aa, std::wstring &ab);\n"
3154 : "void aw(bool b, double x, double y);\n"
3155 : "void ax(int i);\n"
3156 : "void ay(std::string c, std::wstring a);\n"
3157 : "void az(const std::locale &ac);\n"
3158 : "void an();\n"
3159 : "void ba(std::ifstream &f);\n"
3160 : "void bb(std::istream &f) {\n"
3161 : "f.read(NULL, 0);\n"
3162 : "}\n"
3163 : "void h(void) {\n"
3164 : "struct tm *tm = 0;\n"
3165 : "(void)std::asctime(tm);\n"
3166 : "(void)std::asctime(0);\n"
3167 : "}\n"
3168 : "void bc(size_t ae) {\n"
3169 : "wchar_t *ad = 0, *af = 0;\n"
3170 : "struct tm *ag = 0;\n"
3171 : "(void)std::wcsftime(ad, ae, af, ag);\n"
3172 : "(void)std::wcsftime(0, ae, 0, 0);\n"
3173 : "}\n"
3174 : "void k(void) {}\n"
3175 : "void bd(void);\n"
3176 : "void be(void);\n"
3177 : "void bf(int b);\n"
3178 : "void e(void);\n"
3179 : "void e(void);\n"
3180 : "void bg(wchar_t *p);\n"
3181 : "void bh(const std::list<int> &ak, const std::list<int> &al);\n"
3182 : "void ah();\n"
3183 : "void an();\n"
3184 : "void h();");
3185 1 : ASSERT_EQUALS("[test.cpp:131]: (style) Variable 'tm' can be declared as pointer to const\n"
3186 : "[test.cpp:136]: (style) Variable 'af' can be declared as pointer to const\n"
3187 : "[test.cpp:137]: (style) Variable 'ag' can be declared as pointer to const\n",
3188 : errout_str());
3189 :
3190 1 : check("class C\n"
3191 : "{\n"
3192 : "public:\n"
3193 : " explicit C(int&);\n"
3194 : "};\n"
3195 : "\n"
3196 : "class D\n"
3197 : "{\n"
3198 : "public:\n"
3199 : " explicit D(int&);\n"
3200 : "\n"
3201 : "private:\n"
3202 : " C c;\n"
3203 : "};\n"
3204 : "\n"
3205 : "D::D(int& i)\n"
3206 : " : c(i)\n"
3207 : "{\n"
3208 : "}");
3209 1 : ASSERT_EQUALS("", errout_str());
3210 :
3211 1 : check("class C\n"
3212 : "{\n"
3213 : "public:\n"
3214 : " explicit C(int&);\n"
3215 : "};\n"
3216 : "\n"
3217 : "class D\n"
3218 : "{\n"
3219 : "public:\n"
3220 : " explicit D(int&) noexcept;\n"
3221 : "\n"
3222 : "private:\n"
3223 : " C c;\n"
3224 : "};\n"
3225 : "\n"
3226 : "D::D(int& i) noexcept\n"
3227 : " : c(i)\n"
3228 : "{}");
3229 1 : ASSERT_EQUALS("", errout_str());
3230 :
3231 1 : check("class C\n"
3232 : "{\n"
3233 : "public:\n"
3234 : " explicit C(const int&);\n"
3235 : "};\n"
3236 : "\n"
3237 : "class D\n"
3238 : "{\n"
3239 : "public:\n"
3240 : " explicit D(int&);\n"
3241 : "\n"
3242 : "private:\n"
3243 : " C c;\n"
3244 : "};\n"
3245 : "\n"
3246 : "D::D(int& i)\n"
3247 : " : c(i)\n"
3248 : "{\n"
3249 : "}");
3250 1 : TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared as reference to const\n", "", errout_str());
3251 :
3252 1 : check("class C\n"
3253 : "{\n"
3254 : "public:\n"
3255 : " explicit C(int);\n"
3256 : "};\n"
3257 : "\n"
3258 : "class D\n"
3259 : "{\n"
3260 : "public:\n"
3261 : " explicit D(int&);\n"
3262 : "\n"
3263 : "private:\n"
3264 : " C c;\n"
3265 : "};\n"
3266 : "\n"
3267 : "D::D(int& i)\n"
3268 : " : c(i)\n"
3269 : "{\n"
3270 : "}");
3271 1 : TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared as reference to const\n", "", errout_str());
3272 :
3273 1 : check("class C\n"
3274 : "{\n"
3275 : "public:\n"
3276 : " explicit C(int, int);\n"
3277 : "};\n"
3278 : "\n"
3279 : "class D\n"
3280 : "{\n"
3281 : "public:\n"
3282 : " explicit D(int&);\n"
3283 : "\n"
3284 : "private:\n"
3285 : " C c;\n"
3286 : "};\n"
3287 : "\n"
3288 : "D::D(int& i)\n"
3289 : " : c(0, i)\n"
3290 : "{\n"
3291 : "}");
3292 1 : TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared as reference to const\n", "", errout_str());
3293 :
3294 1 : check("void f(std::map<int, std::vector<int>> &map) {\n" // #10266
3295 : " for (auto &[slave, panels] : map)\n"
3296 : " panels.erase(it);\n"
3297 : "}");
3298 1 : ASSERT_EQUALS("", errout_str());
3299 :
3300 1 : check("struct S { void f(); int i; };\n"
3301 : "void call_f(S& s) { (s.*(&S::f))(); }\n");
3302 1 : ASSERT_EQUALS("", errout_str());
3303 :
3304 1 : check("struct S { int a[1]; };\n"
3305 : "void f(S& s) { int* p = s.a; *p = 0; }\n");
3306 1 : ASSERT_EQUALS("", errout_str());
3307 :
3308 1 : check("struct Foo {\n" // #9910
3309 : " int* p{};\n"
3310 : " int* get() { return p; }\n"
3311 : " const int* get() const { return p; }\n"
3312 : "};\n"
3313 : "struct Bar {\n"
3314 : " int j{};\n"
3315 : " void f(Foo& foo) const { int* q = foo.get(); *q = j; }\n"
3316 : "};\n");
3317 1 : ASSERT_EQUALS("", errout_str());
3318 :
3319 1 : check("struct S {\n" // #10679
3320 : " void g(long L, const C*& PC) const;\n"
3321 : " void g(long L, C*& PC);\n"
3322 : "};\n"
3323 : "void f(S& s) {\n"
3324 : " C* PC{};\n"
3325 : " s.g(0, PC);\n"
3326 : "};\n");
3327 1 : ASSERT_EQUALS("", errout_str());
3328 :
3329 : // #10785
3330 1 : check("template <class T, class C>\n"
3331 : "struct d {\n"
3332 : " T& g(C& c, T C::*f) { return c.*f; }\n"
3333 : "};\n");
3334 1 : ASSERT_EQUALS("", errout_str());
3335 :
3336 1 : check("void f(std::map<int, int>& m) {\n"
3337 : " std::cout << m[0] << std::endl;\n"
3338 : "};\n");
3339 1 : ASSERT_EQUALS("", errout_str());
3340 :
3341 1 : check("void f(std::vector<std::map<int, int>>& v) {\n" // #11607
3342 : " for (auto& m : v)\n"
3343 : " std::cout << m[0];\n"
3344 : "}\n");
3345 1 : ASSERT_EQUALS("", errout_str());
3346 :
3347 1 : check("struct S { int i; };\n" // #11473
3348 : "void f(std::vector<std::vector<S>>&m, int*& p) {\n"
3349 : " auto& a = m[0];\n"
3350 : " for (auto& s : a) {\n"
3351 : " p = &s.i;\n"
3352 : " return;\n"
3353 : " }\n"
3354 : "}\n");
3355 1 : ASSERT_EQUALS("", errout_str());
3356 :
3357 1 : check("int& g(int* p, int& r) {\n" // #11625
3358 : " if (p)\n"
3359 : " return *p;\n"
3360 : " return r;\n"
3361 : "}\n");
3362 1 : ASSERT_EQUALS("", errout_str());
3363 :
3364 1 : check("template <typename T> void f(std::vector<T*>& d, const std::vector<T*>& s) {\n" // #11632
3365 : " for (const auto& e : s) {\n"
3366 : " T* newE = new T(*e);\n"
3367 : " d.push_back(newE);\n"
3368 : " }\n"
3369 : "}\n");
3370 1 : ASSERT_EQUALS("", errout_str());
3371 :
3372 1 : check("void f(std::array<int, 2>& a) {\n"
3373 : " if (a[0]) {}\n"
3374 : "}\n"
3375 : "void g(std::array<int, 2>& a) {\n"
3376 : " a.fill(0);\n"
3377 : "}\n");
3378 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'a' can be declared as const array\n", errout_str());
3379 :
3380 : // #11682
3381 1 : check("struct b {\n"
3382 : " void mutate();\n"
3383 : "};\n"
3384 : "struct c {\n"
3385 : " const b& get() const;\n"
3386 : " b get();\n"
3387 : "};\n"
3388 : "struct d {\n"
3389 : " void f(c& e) const {\n"
3390 : " e.get().mutate();\n"
3391 : " }\n"
3392 : "};\n");
3393 1 : ASSERT_EQUALS("", errout_str());
3394 :
3395 1 : check("struct B { virtual void f() const {} };\n" // #11528
3396 : "struct D : B {};\n"
3397 : "void g(B* b) {\n"
3398 : " D* d = dynamic_cast<D*>(b);\n"
3399 : " if (d)\n"
3400 : " d->f();\n"
3401 : "}\n");
3402 1 : ASSERT_EQUALS(
3403 : "[test.cpp:4]: (style) Variable 'd' can be declared as pointer to const\n",
3404 : errout_str());
3405 :
3406 1 : check("void g(const int*);\n"
3407 : "void f(const std::vector<int*>&v) {\n"
3408 : " for (int* i : v)\n"
3409 : " g(i);\n"
3410 : "}\n");
3411 1 : ASSERT_EQUALS(
3412 : "[test.cpp:3]: (style) Variable 'i' can be declared as pointer to const\n",
3413 : errout_str());
3414 :
3415 1 : check("struct A {\n" // #11225
3416 : " A();\n"
3417 : " virtual ~A();\n"
3418 : "};\n"
3419 : "struct B : A {};\n"
3420 : "void f(A* a) {\n"
3421 : " const B* b = dynamic_cast<const B*>(a);\n"
3422 : "}\n"
3423 : "void g(A* a) {\n"
3424 : " const B* b = (const B*)a;\n"
3425 : "}\n");
3426 1 : ASSERT_EQUALS("[test.cpp:10]: (style) C-style pointer casting\n"
3427 : "[test.cpp:6]: (style) Parameter 'a' can be declared as pointer to const\n"
3428 : "[test.cpp:9]: (style) Parameter 'a' can be declared as pointer to const\n",
3429 : errout_str());
3430 :
3431 1 : check("void g(int*);\n"
3432 : "void f(std::vector<int>& v) {\n"
3433 : " g(v.data());\n"
3434 : "}\n");
3435 1 : ASSERT_EQUALS("", errout_str());
3436 :
3437 1 : check("void g(const int*);\n"
3438 : "void f(std::vector<int>& v) {\n"
3439 : " g(v.data());\n"
3440 : "}\n");
3441 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'v' can be declared as reference to const\n", errout_str());
3442 :
3443 1 : check("struct a {\n"
3444 : " template <class T>\n"
3445 : " void mutate();\n"
3446 : "};\n"
3447 : "struct b {};\n"
3448 : "template <class T>\n"
3449 : "void f(a& x) {\n"
3450 : " x.mutate<T>();\n"
3451 : "}\n"
3452 : "template <class T>\n"
3453 : "void f(const b&)\n"
3454 : "{}\n"
3455 : "void g(a& c) { f<int>(c); }\n");
3456 1 : ASSERT_EQUALS("", errout_str());
3457 :
3458 1 : check("struct S {\n"
3459 : " template <typename T>\n"
3460 : " T* g() {\n"
3461 : " return reinterpret_cast<T*>(m);\n"
3462 : " }\n"
3463 : " template <typename T>\n"
3464 : " const T* g() const {\n"
3465 : " return reinterpret_cast<const T*>(m);\n"
3466 : " }\n"
3467 : " char* m;\n"
3468 : "};\n"
3469 : "void f(S& s) {\n"
3470 : " const int* p = s.g<int>();\n"
3471 : "}\n");
3472 1 : ASSERT_EQUALS("", errout_str());
3473 :
3474 1 : check("struct S { int x; };\n" // #11818
3475 : "std::istream& f(std::istream& is, S& s) {\n"
3476 : " return is >> s.x;\n"
3477 : "}\n");
3478 1 : ASSERT_EQUALS("", errout_str());
3479 :
3480 1 : check("bool f(std::string& s1, std::string& s2) {\n" // #12203
3481 : " return &s1 == &s2;\n"
3482 : "}\n");
3483 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 's1' can be declared as reference to const\n"
3484 : "[test.cpp:1]: (style) Parameter 's2' can be declared as reference to const\n",
3485 : errout_str());
3486 :
3487 1 : check("void f(int& r) {\n" // #12214
3488 : " (void)(true);\n"
3489 : " if (r) {}\n"
3490 : "}\n");
3491 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'r' can be declared as reference to const\n", errout_str());
3492 :
3493 1 : check("struct S { void f(int&); };\n" // #12216
3494 : "void g(S& s, int& r, void (S::* p2m)(int&)) {\n"
3495 : " (s.*p2m)(r);\n"
3496 : "}\n");
3497 1 : ASSERT_EQUALS("", errout_str());
3498 :
3499 1 : check("struct S {\n"
3500 : " void f(int& r) { p = &r; }\n"
3501 : " int* p;\n"
3502 : "};\n"
3503 : "void g(std::vector<int>& v1, std::vector<int*>& v2) {\n"
3504 : " std::transform(v1.begin(), v1.end(), v2.begin(), [](auto& x) { return &x; });\n"
3505 : "}\n");
3506 1 : ASSERT_EQUALS("", errout_str());
3507 :
3508 1 : check("class T;\n" // #11869
3509 : "class E {\n"
3510 : "public:\n"
3511 : " class F {\n"
3512 : " public:\n"
3513 : " explicit F(const T* t);\n"
3514 : " };\n"
3515 : "};\n"
3516 : "void f(T& t) {\n"
3517 : " std::list<E::F> c(1, E::F(&t));\n"
3518 : "}\n");
3519 1 : ASSERT_EQUALS("[test.cpp:9]: (style) Parameter 't' can be declared as reference to const\n", errout_str());
3520 :
3521 1 : check("struct T;\n"
3522 : "struct U {\n"
3523 : " struct V { explicit V(const T* p); };\n"
3524 : "};\n"
3525 : "void g(U::V v);\n"
3526 : "void f(T& t) {\n"
3527 : " g(U::V(&t));\n"
3528 : "}\n");
3529 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Parameter 't' can be declared as reference to const\n", errout_str());
3530 :
3531 1 : check("void f1(std::vector<int>& v) {\n" // #11207
3532 : " auto it = v.cbegin();\n"
3533 : " while (it != v.cend()) {\n"
3534 : " if (*it > 12) {}\n"
3535 : " ++it;\n"
3536 : " }\n"
3537 : "}\n"
3538 : "void f2(std::vector<int>& v) {\n"
3539 : " auto it = v.begin();\n"
3540 : " while (it != v.end()) {\n"
3541 : " if (*it > 12) {}\n"
3542 : " ++it;\n"
3543 : " }\n"
3544 : "}\n");
3545 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n"
3546 : "[test.cpp:8]: (style) Parameter 'v' can be declared as reference to const\n",
3547 : errout_str());
3548 :
3549 1 : check("void cb(const std::string&);\n" // #12349, #12350, #12351
3550 : "void f(std::string& s) {\n"
3551 : " const std::string& str(s);\n"
3552 : " cb(str);\n"
3553 : "}\n"
3554 : "void g(std::string& s) {\n"
3555 : " const std::string& str{ s };\n"
3556 : " cb(str);\n"
3557 : "}\n"
3558 : "void h(std::string* s) {\n"
3559 : " const std::string& str(*s);\n"
3560 : " cb(str);\n"
3561 : "}\n"
3562 : "void k(std::string* s) {\n"
3563 : " const std::string& str = *s;\n"
3564 : " cb(str);\n"
3565 : "}\n"
3566 : "void m(std::string& s) {\n"
3567 : " const std::string str(s);\n"
3568 : " cb(str);\n"
3569 : "}\n"
3570 : "void n(std::string* s) {\n"
3571 : " const std::string& str(*s);\n"
3572 : " cb(str);\n"
3573 : "}\n");
3574 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as reference to const\n"
3575 : "[test.cpp:6]: (style) Parameter 's' can be declared as reference to const\n"
3576 : "[test.cpp:18]: (style) Parameter 's' can be declared as reference to const\n"
3577 : "[test.cpp:10]: (style) Parameter 's' can be declared as pointer to const\n"
3578 : "[test.cpp:14]: (style) Parameter 's' can be declared as pointer to const\n"
3579 : "[test.cpp:22]: (style) Parameter 's' can be declared as pointer to const\n",
3580 : errout_str());
3581 :
3582 1 : check("struct S {\n"
3583 : " S(std::string& r);\n"
3584 : "};\n"
3585 : "void f(std::string& str) {\n"
3586 : " const S& s(str);\n"
3587 : "}\n");
3588 1 : ASSERT_EQUALS("", errout_str());
3589 :
3590 1 : check("struct C {\n" // #10052
3591 : " int& operator()(int);\n"
3592 : "};\n"
3593 : "void f(std::vector<C>& c) {\n"
3594 : " c[0](5) = 12;\n"
3595 : "}\n");
3596 1 : ASSERT_EQUALS("", errout_str());
3597 :
3598 1 : check("int f(int& t) {\n" // #11713
3599 : " return 0;\n"
3600 : "}\n");
3601 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 't' can be declared as reference to const\n", errout_str());
3602 :
3603 1 : check("void f(std::list<std::string>& v) {\n" // #12202
3604 : " v.remove_if([](std::string& s) {\n"
3605 : " return true;\n"
3606 : " });\n"
3607 : "}\n");
3608 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as reference to const\n", errout_str());
3609 : }
3610 :
3611 1 : void constParameterCallback() {
3612 1 : check("int callback(std::vector<int>& x) { return x[0]; }\n"
3613 : "void f() { dostuff(callback); }");
3614 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1]: (style) Parameter 'x' can be declared as reference to const. However it seems that 'callback' is a callback function, if 'x' is declared with const you might also need to cast function pointer(s).\n", errout_str());
3615 :
3616 : // #9906
3617 1 : check("class EventEngine : public IEventEngine {\n"
3618 : "public:\n"
3619 : " EventEngine();\n"
3620 : "\n"
3621 : "private:\n"
3622 : " void signalEvent(ev::sig& signal, int revents);\n"
3623 : "};\n"
3624 : "\n"
3625 : "EventEngine::EventEngine() {\n"
3626 : " mSigWatcher.set<EventEngine, &EventEngine::signalEvent>(this);\n"
3627 : "}\n"
3628 : "\n"
3629 : "void EventEngine::signalEvent(ev::sig& signal, int revents) {\n"
3630 : " switch (signal.signum) {}\n"
3631 : "}");
3632 1 : ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:13]: (style) Parameter 'signal' can be declared as reference to const. However it seems that 'signalEvent' is a callback function, if 'signal' is declared with const you might also need to cast function pointer(s).\n", errout_str());
3633 : }
3634 :
3635 1 : void constPointer() {
3636 1 : check("void foo(int *p) { return *p; }");
3637 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3638 :
3639 1 : check("void foo(int *p) { x = *p; }");
3640 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3641 :
3642 1 : check("void foo(int *p) { int &ref = *p; ref = 12; }");
3643 1 : ASSERT_EQUALS("", errout_str());
3644 :
3645 1 : check("void foo(int *p) { x = *p + 10; }");
3646 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3647 :
3648 1 : check("void foo(int *p) { return p[10]; }");
3649 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3650 :
3651 1 : check("void foo(int *p) { int &ref = p[0]; ref = 12; }");
3652 1 : ASSERT_EQUALS("", errout_str());
3653 :
3654 1 : check("void foo(int *p) { x[*p] = 12; }");
3655 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3656 :
3657 1 : check("void foo(int *p) { if (p) {} }");
3658 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3659 :
3660 1 : check("void foo(int *p) { if (p || x) {} }");
3661 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3662 :
3663 1 : check("void foo(int *p) { if (p == 0) {} }");
3664 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3665 :
3666 1 : check("void foo(int *p) { if (!p) {} }");
3667 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3668 :
3669 1 : check("void foo(int *p) { if (*p > 123) {} }");
3670 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3671 :
3672 1 : check("void foo(int *p) { return *p + 1; }");
3673 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3674 :
3675 1 : check("void foo(int *p) { return *p > 1; }");
3676 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
3677 :
3678 1 : check("void foo(const int* c) { if (c == 0) {}; }");
3679 1 : ASSERT_EQUALS("", errout_str());
3680 :
3681 1 : check("struct a { void b(); };\n"
3682 : "struct c {\n"
3683 : " a* d;\n"
3684 : " a& g() { return *d; }\n"
3685 : "};\n");
3686 1 : ASSERT_EQUALS("", errout_str());
3687 :
3688 1 : check("struct a { void b(); };\n"
3689 : "struct c { a* d; };\n"
3690 : "void e(c);\n");
3691 1 : ASSERT_EQUALS("", errout_str());
3692 :
3693 1 : check("struct V {\n"
3694 : " V& get(typename std::vector<V>::size_type i, std::vector<V>* arr) {\n"
3695 : " return arr->at(i);\n"
3696 : " }\n"
3697 : "};\n");
3698 1 : ASSERT_EQUALS("", errout_str());
3699 :
3700 1 : check("struct A {};\n"
3701 : "struct B : A {};\n"
3702 : "B* f(A* x) {\n"
3703 : " return static_cast<B*>(x);\n"
3704 : "}\n");
3705 1 : ASSERT_EQUALS("", errout_str());
3706 :
3707 1 : check("int f(std::vector<int>* x) {\n"
3708 : " int& i = (*x)[0];\n"
3709 : " i++;\n"
3710 : " return i;\n"
3711 : "}");
3712 1 : ASSERT_EQUALS("", errout_str());
3713 :
3714 1 : check("struct A { int a; };\n"
3715 : "A f(std::vector<A>* x) {\n"
3716 : " x->front().a = 1;\n"
3717 : " return x->front();\n"
3718 : "}");
3719 1 : ASSERT_EQUALS("", errout_str());
3720 :
3721 1 : check("void f(std::vector<int>* v) {\n"
3722 : " for(auto&& x:*v)\n"
3723 : " x = 1;\n"
3724 : "}");
3725 1 : ASSERT_EQUALS("", errout_str());
3726 :
3727 1 : check("struct A {\n"
3728 : " int* x;\n"
3729 : " A(int* y) : x(y)\n"
3730 : " {}\n"
3731 : "};");
3732 1 : ASSERT_EQUALS("", errout_str());
3733 :
3734 1 : check("void f(bool b, int* x, int* y) {\n"
3735 : " int* z = x;\n"
3736 : " int* w = b ? y : z;\n"
3737 : " *w = 1;\n"
3738 : "}");
3739 1 : ASSERT_EQUALS("", errout_str());
3740 :
3741 1 : check("void f(bool b, int* x, int* y) {\n"
3742 : " int& z = *x;\n"
3743 : " int& w = b ? *y : z;\n"
3744 : " w = 1;\n"
3745 : "}");
3746 1 : ASSERT_EQUALS("", errout_str());
3747 :
3748 1 : check("class Base { virtual void dostuff(int *p) = 0; };\n" // #10397
3749 : "class Derived: public Base { int x; void dostuff(int *p) override { x = *p; } };");
3750 1 : ASSERT_EQUALS("", errout_str());
3751 :
3752 1 : check("struct Data { char buf[128]; };\n" // #10483
3753 : "void encrypt(Data& data) {\n"
3754 : " const char a[] = \"asfasd\";\n"
3755 : " memcpy(data.buf, &a, sizeof(a));\n"
3756 : "}");
3757 1 : ASSERT_EQUALS("", errout_str());
3758 :
3759 : // #10547
3760 1 : check("void foo(std::istream &istr) {\n"
3761 : " unsigned char x[2];\n"
3762 : " istr >> x[0];\n"
3763 : "}");
3764 1 : ASSERT_EQUALS("", errout_str());
3765 :
3766 : // #10744
3767 1 : check("S& f() {\n"
3768 : " static S* p = new S();\n"
3769 : " return *p;\n"
3770 : "}\n");
3771 1 : ASSERT_EQUALS("", errout_str());
3772 :
3773 1 : check("int f() {\n"
3774 : " static int i[1] = {};\n"
3775 : " return i[0];\n"
3776 : "}\n");
3777 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' can be declared as const array\n", errout_str());
3778 :
3779 1 : check("int f() {\n"
3780 : " static int i[] = { 0 };\n"
3781 : " int j = i[0] + 1;\n"
3782 : " return j;\n"
3783 : "}\n");
3784 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' can be declared as const array\n", errout_str());
3785 :
3786 : // #10471
3787 1 : check("void f(std::array<int, 1> const& i) {\n"
3788 : " if (i[0] == 0) {}\n"
3789 : "}\n");
3790 1 : ASSERT_EQUALS("", errout_str());
3791 :
3792 : // #10466
3793 1 : check("typedef void* HWND;\n"
3794 : "void f(const std::vector<HWND>&v) {\n"
3795 : " for (const auto* h : v)\n"
3796 : " if (h) {}\n"
3797 : " for (const auto& h : v)\n"
3798 : " if (h) {}\n"
3799 : "}\n");
3800 1 : ASSERT_EQUALS(
3801 : "[test.cpp:5]: (style) Variable 'h' can be declared as pointer to const\n",
3802 : errout_str());
3803 :
3804 1 : check("void f(const std::vector<int*>& v) {\n"
3805 : " for (const auto& p : v)\n"
3806 : " if (p == nullptr) {}\n"
3807 : " for (const auto* p : v)\n"
3808 : " if (p == nullptr) {}\n"
3809 : "}\n");
3810 1 : ASSERT_EQUALS(
3811 : "[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n",
3812 : errout_str());
3813 :
3814 1 : check("void f(std::vector<int*>& v) {\n"
3815 : " for (const auto& p : v)\n"
3816 : " if (p == nullptr) {}\n"
3817 : " for (const auto* p : v)\n"
3818 : " if (p == nullptr) {}\n"
3819 : " for (const int* const& p : v)\n"
3820 : " if (p == nullptr) {}\n"
3821 : " for (const int* p : v)\n"
3822 : " if (p == nullptr) {}\n"
3823 : "}\n");
3824 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n"
3825 : "[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n",
3826 : errout_str());
3827 :
3828 1 : check("void f(std::vector<const int*>& v) {\n"
3829 : " for (const auto& p : v)\n"
3830 : " if (p == nullptr) {}\n"
3831 : " for (const auto* p : v)\n"
3832 : " if (p == nullptr) {}\n"
3833 : "}\n");
3834 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n", errout_str());
3835 :
3836 1 : check("void f(const std::vector<const int*>& v) {\n"
3837 : " for (const auto& p : v)\n"
3838 : " if (p == nullptr) {}\n"
3839 : " for (const auto* p : v)\n"
3840 : " if (p == nullptr) {}\n"
3841 : "}\n");
3842 1 : ASSERT_EQUALS("", errout_str());
3843 :
3844 1 : check("void f(const int* const p) {\n"
3845 : " if (p == nullptr) {}\n"
3846 : "}\n");
3847 1 : ASSERT_EQUALS("", errout_str());
3848 :
3849 1 : check("void g(int*);\n"
3850 : "void f(int* const* pp) {\n"
3851 : " int* p = pp[0];\n"
3852 : " g(p);\n"
3853 : "}\n");
3854 1 : ASSERT_EQUALS("", errout_str());
3855 :
3856 1 : check("template <typename T>\n"
3857 : "struct S {\n"
3858 : " static bool f(const T& t) { return t != nullptr; }\n"
3859 : "};\n"
3860 : "S<int*> s;\n");
3861 1 : ASSERT_EQUALS("", errout_str());
3862 :
3863 1 : check("void f(int i) {\n"
3864 : " const char *tmp;\n"
3865 : " char* a[] = { \"a\", \"aa\" };\n"
3866 : " static char* b[] = { \"b\", \"bb\" };\n"
3867 : " tmp = a[i];\n"
3868 : " printf(\"%s\", tmp);\n"
3869 : " tmp = b[i];\n"
3870 : " printf(\"%s\", tmp);\n"
3871 : "}\n");
3872 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' can be declared as const array\n"
3873 : "[test.cpp:4]: (style) Variable 'b' can be declared as const array\n",
3874 : errout_str());
3875 :
3876 1 : check("typedef void* HWND;\n" // #11084
3877 : "void f(const HWND h) {\n"
3878 : " if (h == nullptr) {}\n"
3879 : "}\n");
3880 1 : ASSERT_EQUALS("", errout_str());
3881 :
3882 1 : check("using HWND = void*;\n"
3883 : "void f(const HWND h) {\n"
3884 : " if (h == nullptr) {}\n"
3885 : "}\n");
3886 1 : ASSERT_EQUALS("", errout_str());
3887 :
3888 1 : check("typedef int A;\n"
3889 : "void f(A* x) {\n"
3890 : " if (x == nullptr) {}\n"
3891 : "}\n");
3892 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
3893 :
3894 1 : check("using A = int;\n"
3895 : "void f(A* x) {\n"
3896 : " if (x == nullptr) {}\n"
3897 : "}\n");
3898 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
3899 :
3900 1 : check("struct S { void v(); };\n" // #11095
3901 : "void f(S* s) {\n"
3902 : " (s - 1)->v();\n"
3903 : "}\n");
3904 1 : ASSERT_EQUALS("", errout_str());
3905 :
3906 1 : check("void f(std::vector<int*>& v) {\n" // #11085
3907 : " for (int* p : v) {\n"
3908 : " if (p) {}\n"
3909 : " }\n"
3910 : " for (auto* p : v) {\n"
3911 : " if (p) {}\n"
3912 : " }\n"
3913 : " v.clear();\n"
3914 : "}\n");
3915 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n"
3916 : "[test.cpp:5]: (style) Variable 'p' can be declared as pointer to const\n",
3917 : errout_str());
3918 :
3919 1 : check("void f() {\n"
3920 : " char a[1][1];\n"
3921 : " char* b[1];\n"
3922 : " b[0] = a[0];\n"
3923 : " **b = 0;\n"
3924 : "}\n");
3925 1 : ASSERT_EQUALS("", errout_str());
3926 :
3927 1 : check("ptrdiff_t f(int *p0, int *p1) {\n" // #11148
3928 : " return p0 - p1;\n"
3929 : "}\n");
3930 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p0' can be declared as pointer to const\n"
3931 : "[test.cpp:1]: (style) Parameter 'p1' can be declared as pointer to const\n",
3932 : errout_str());
3933 :
3934 1 : check("void f() {\n"
3935 : " std::array<int, 1> a{}, b{};\n"
3936 : " const std::array<int, 1>& r = a;\n"
3937 : " if (r == b) {}\n"
3938 : "}\n");
3939 1 : ASSERT_EQUALS("", errout_str());
3940 :
3941 1 : check("struct S {};\n" // #11599
3942 : "void g(S);\n"
3943 : "void h(const S&);\n"
3944 : "void h(int, int, const S&);\n"
3945 : "void i(S&);\n"
3946 : "void j(const S*);\n"
3947 : "void j(int, int, const S*);\n"
3948 : "void f1(S* s) {\n"
3949 : " g(*s);\n"
3950 : "}\n"
3951 : "void f2(S* s) {\n"
3952 : " h(*s);\n"
3953 : "}\n"
3954 : "void f3(S* s) {\n"
3955 : " h(1, 2, *s);\n"
3956 : "}\n"
3957 : "void f4(S* s) {\n"
3958 : " i(*s);\n"
3959 : "}\n"
3960 : "void f5(S& s) {\n"
3961 : " j(&s);\n"
3962 : "}\n"
3963 : "void f6(S& s) {\n"
3964 : " j(1, 2, &s);\n"
3965 : "}\n");
3966 1 : ASSERT_EQUALS("[test.cpp:20]: (style) Parameter 's' can be declared as reference to const\n"
3967 : "[test.cpp:23]: (style) Parameter 's' can be declared as reference to const\n"
3968 : "[test.cpp:8]: (style) Parameter 's' can be declared as pointer to const\n"
3969 : "[test.cpp:11]: (style) Parameter 's' can be declared as pointer to const\n"
3970 : "[test.cpp:14]: (style) Parameter 's' can be declared as pointer to const\n",
3971 : errout_str());
3972 :
3973 1 : check("void g(int, const int*);\n"
3974 : "void h(const int*);\n"
3975 : "void f(int* p) {\n"
3976 : " g(1, p);\n"
3977 : " h(p);\n"
3978 : "}\n");
3979 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'p' can be declared as pointer to const\n",
3980 : errout_str());
3981 :
3982 1 : check("void f(int, const int*);\n"
3983 : "void f(int i, int* p) {\n"
3984 : " f(i, const_cast<const int*>(p));\n"
3985 : "}\n");
3986 1 : ASSERT_EQUALS("", errout_str());
3987 :
3988 1 : check("struct S { int a; };\n"
3989 : "void f(std::vector<S>& v, int b) {\n"
3990 : " size_t n = v.size();\n"
3991 : " for (size_t i = 0; i < n; i++) {\n"
3992 : " S& s = v[i];\n"
3993 : " if (!(b & s.a))\n"
3994 : " continue;\n"
3995 : " }\n"
3996 : "}\n");
3997 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Variable 's' can be declared as reference to const\n", errout_str()); // don't crash
3998 :
3999 1 : check("void f(int& i) {\n"
4000 : " new (&i) int();\n"
4001 : "}\n");
4002 1 : ASSERT_EQUALS("", errout_str()); // don't crash
4003 :
4004 1 : check("void f(int& i) {\n"
4005 : " int& r = i;\n"
4006 : " if (!&r) {}\n"
4007 : "}\n");
4008 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'r' can be declared as reference to const\n", errout_str()); // don't crash
4009 :
4010 1 : check("class C;\n" // #11646
4011 : "void g(const C* const p);\n"
4012 : "void f(C* c) {\n"
4013 : " g(c);\n"
4014 : "}\n");
4015 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'c' can be declared as pointer to const\n", errout_str());
4016 :
4017 1 : check("typedef void (*cb_t)(int*);\n" // #11674
4018 : "void cb(int* p) {\n"
4019 : " if (*p) {}\n"
4020 : "}\n"
4021 : "void g(cb_t);\n"
4022 : "void f() {\n"
4023 : " g(cb);\n"
4024 : "}\n");
4025 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:2]: (style) Parameter 'p' can be declared as pointer to const. "
4026 : "However it seems that 'cb' is a callback function, if 'p' is declared with const you might also need to cast function pointer(s).\n",
4027 : errout_str());
4028 :
4029 1 : check("typedef void (*cb_t)(int*);\n"
4030 : "void cb(int* p) {\n"
4031 : " if (*p) {}\n"
4032 : "}\n"
4033 : "void g(cb_t);\n"
4034 : "void f() {\n"
4035 : " g(::cb);\n"
4036 : "}\n");
4037 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:2]: (style) Parameter 'p' can be declared as pointer to const. "
4038 : "However it seems that 'cb' is a callback function, if 'p' is declared with const you might also need to cast function pointer(s).\n",
4039 : errout_str());
4040 :
4041 1 : check("void f1(std::vector<int>* p) {\n" // #11681
4042 : " if (p->empty()) {}\n" // warn
4043 : "}\n"
4044 : "void f2(std::vector<int>* p) {\n"
4045 : " p->resize(0);\n"
4046 : "}\n"
4047 : "struct S {\n"
4048 : " void h1() const;\n"
4049 : " void h2();\n"
4050 : " int i;\n"
4051 : "};\n"
4052 : "void k(int&);\n"
4053 : "void g1(S* s) {\n"
4054 : " s->h1();\n" // warn
4055 : "}\n"
4056 : "void g1(S* s) {\n"
4057 : " s->h2();\n"
4058 : "}\n"
4059 : "void g1(S* s) {\n"
4060 : " if (s->i) {}\n" // warn
4061 : "}\n"
4062 : "void g2(S* s) {\n"
4063 : " s->i = 0;\n"
4064 : "}\n"
4065 : "void g3(S* s) {\n"
4066 : " k(s->i);\n"
4067 : "}\n");
4068 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n"
4069 : "[test.cpp:13]: (style) Parameter 's' can be declared as pointer to const\n"
4070 : "[test.cpp:19]: (style) Parameter 's' can be declared as pointer to const\n",
4071 : errout_str());
4072 :
4073 1 : check("struct S {\n" // #11573
4074 : " const char* g() const {\n"
4075 : " return m;\n"
4076 : " }\n"
4077 : " const char* m;\n"
4078 : "};\n"
4079 : "struct T { std::vector<S*> v; };\n"
4080 : "void f(T* t, const char* n) {\n"
4081 : " for (const auto* p : t->v)\n"
4082 : " if (strcmp(p->g(), n) == 0) {}\n"
4083 : "}\n");
4084 1 : ASSERT_EQUALS("[test.cpp:8]: (style) Parameter 't' can be declared as pointer to const\n",
4085 : errout_str());
4086 :
4087 1 : check("void f(int*& p, int* q) {\n"
4088 : " p = q;\n"
4089 : "}\n");
4090 1 : ASSERT_EQUALS("", errout_str());
4091 :
4092 1 : check("struct S { int a[1]; };\n"
4093 : "void f(S* s) {\n"
4094 : " if (s->a[0]) {}\n"
4095 : "}\n");
4096 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as pointer to const\n",
4097 : errout_str());
4098 :
4099 1 : check("size_t f(char* p) {\n" // #11842
4100 : " return strlen(p);\n"
4101 : "}\n");
4102 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout_str());
4103 :
4104 1 : check("void f(int* p) {\n" // #11862
4105 : " long long j = *(p++);\n"
4106 : "}\n");
4107 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n",
4108 : errout_str());
4109 :
4110 1 : check("void f(void *p, size_t nmemb, size_t size, int (*cmp)(const void *, const void *)) {\n"
4111 : " qsort(p, nmemb, size, cmp);\n"
4112 : "}\n");
4113 1 : ASSERT_EQUALS("", errout_str());
4114 :
4115 1 : check("void g(bool *r, std::size_t *b) {\n" // #12129
4116 : " if (*r && *b >= 5) {}\n"
4117 : "}\n");
4118 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'r' can be declared as pointer to const\n"
4119 : "[test.cpp:1]: (style) Parameter 'b' can be declared as pointer to const\n",
4120 : errout_str());
4121 :
4122 1 : check("void f(int i) {\n" // #12185
4123 : " void* p = &i;\n"
4124 : " std::cout << p << '\\n';\n"
4125 : "}\n");
4126 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n",
4127 : errout_str());
4128 :
4129 1 : check("struct S { const T* t; };\n" // #12206
4130 : "void f(S* s) {\n"
4131 : " if (s->t.i) {}\n"
4132 : "}\n");
4133 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as pointer to const\n",
4134 : errout_str());
4135 :
4136 1 : check("void f(char *a1, char *a2) {\n" // #12252
4137 : " char* b = new char[strlen(a1) + strlen(a2) + 2];\n"
4138 : " sprintf(b, \"%s_%s\", a1, a2);\n"
4139 : " delete[] b;\n"
4140 : "}\n");
4141 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'a1' can be declared as pointer to const\n"
4142 : "[test.cpp:1]: (style) Parameter 'a2' can be declared as pointer to const\n",
4143 : errout_str());
4144 :
4145 1 : check("int f(int* p) {\n" // #11713
4146 : " return 0;\n"
4147 : "}\n");
4148 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n",
4149 : errout_str());
4150 :
4151 1 : check("void f(int *src, int* dst) {\n" // #12518
4152 : " *dst++ = (int)*src++;\n"
4153 : " *dst++ = static_cast<int>(*src++);\n"
4154 : " *dst = (int)*src;\n"
4155 : "}\n"
4156 : "void g(int* dst) {\n"
4157 : " (int&)*dst = 5;\n"
4158 : "}\n");
4159 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'src' can be declared as pointer to const\n",
4160 : errout_str());
4161 :
4162 1 : check("struct S {};\n"
4163 : "void f(T* t) {\n"
4164 : " S* s = (S*)t->p;\n"
4165 : "}\n");
4166 1 : ASSERT_EQUALS("[test.cpp:3]: (style) C-style pointer casting\n"
4167 : "[test.cpp:3]: (style) Variable 's' can be declared as pointer to const\n",
4168 : errout_str()); // don't crash
4169 :
4170 1 : check("struct S { int i; };\n" // #12205
4171 : "void f(S* s) {\n"
4172 : " (void)s->i;\n"
4173 : "}\n");
4174 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as pointer to const\n",
4175 : errout_str());
4176 : }
4177 :
4178 1 : void switchRedundantAssignmentTest() {
4179 1 : check("void foo()\n"
4180 : "{\n"
4181 : " int y = 1;\n"
4182 : " switch (a)\n"
4183 : " {\n"
4184 : " case 2:\n"
4185 : " y = 2;\n"
4186 : " case 3:\n"
4187 : " y = 3;\n"
4188 : " }\n"
4189 : " bar(y);\n"
4190 : "}");
4191 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4192 :
4193 1 : check("void foo()\n"
4194 : "{\n"
4195 : " int y = 1;\n"
4196 : " switch (a)\n"
4197 : " {\n"
4198 : " case 2:\n"
4199 : " {\n"
4200 : " y = 2;\n"
4201 : " }\n"
4202 : " case 3:\n"
4203 : " y = 3;\n"
4204 : " }\n"
4205 : " bar(y);\n"
4206 : "}");
4207 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4208 :
4209 1 : check("void foo()\n"
4210 : "{\n"
4211 : " int y = 1;\n"
4212 : " switch (a)\n"
4213 : " {\n"
4214 : " case 2:\n"
4215 : " y = 2;\n"
4216 : " case 3:\n"
4217 : " if (x)\n"
4218 : " {\n"
4219 : " y = 3;\n"
4220 : " }\n"
4221 : " }\n"
4222 : " bar(y);\n"
4223 : "}");
4224 1 : ASSERT_EQUALS("", errout_str());
4225 :
4226 1 : check("void foo()\n"
4227 : "{\n"
4228 : " int y = 1;\n"
4229 : " switch (a)\n"
4230 : " {\n"
4231 : " case 2:\n"
4232 : " {\n"
4233 : " y = 2;\n"
4234 : " if (z)\n"
4235 : " printf(\"%d\", y);\n"
4236 : " }\n"
4237 : " case 3:\n"
4238 : " y = 3;\n"
4239 : " }\n"
4240 : " bar(y);\n"
4241 : "}");
4242 1 : ASSERT_EQUALS("", errout_str());
4243 :
4244 1 : check("void foo()\n"
4245 : "{\n"
4246 : " int x = a;\n"
4247 : " int y = 1;\n"
4248 : " switch (x)\n"
4249 : " {\n"
4250 : " case 2:\n"
4251 : " x = 2;\n"
4252 : " case 3:\n"
4253 : " y = 3;\n"
4254 : " }\n"
4255 : " bar(y);\n"
4256 : "}");
4257 1 : ASSERT_EQUALS("", errout_str());
4258 :
4259 1 : check("void foo()\n"
4260 : "{\n"
4261 : " int y = 1;\n"
4262 : " switch (x)\n"
4263 : " {\n"
4264 : " case 2:\n"
4265 : " y = 2;\n"
4266 : " break;\n"
4267 : " case 3:\n"
4268 : " y = 3;\n"
4269 : " }\n"
4270 : " bar(y);\n"
4271 : "}");
4272 1 : ASSERT_EQUALS("", errout_str());
4273 :
4274 1 : check("void foo()\n"
4275 : "{\n"
4276 : " int y = 1;\n"
4277 : " while(xyz()) {\n"
4278 : " switch (x)\n"
4279 : " {\n"
4280 : " case 2:\n"
4281 : " y = 2;\n"
4282 : " continue;\n"
4283 : " case 3:\n"
4284 : " y = 3;\n"
4285 : " }\n"
4286 : " bar(y);\n"
4287 : " }\n"
4288 : "}");
4289 1 : ASSERT_EQUALS("", errout_str());
4290 :
4291 1 : check("void foo()\n"
4292 : "{\n"
4293 : " int y = 1;\n"
4294 : " while(xyz()) {\n"
4295 : " switch (x)\n"
4296 : " {\n"
4297 : " case 2:\n"
4298 : " y = 2;\n"
4299 : " throw e;\n"
4300 : " case 3:\n"
4301 : " y = 3;\n"
4302 : " }\n"
4303 : " bar(y);\n"
4304 : " }\n"
4305 : "}");
4306 1 : ASSERT_EQUALS("", errout_str());
4307 :
4308 1 : check("void foo()\n"
4309 : "{\n"
4310 : " int y = 1;\n"
4311 : " switch (x)\n"
4312 : " {\n"
4313 : " case 2:\n"
4314 : " y = 2;\n"
4315 : " printf(\"%d\", y);\n"
4316 : " case 3:\n"
4317 : " y = 3;\n"
4318 : " }\n"
4319 : " bar(y);\n"
4320 : "}");
4321 1 : ASSERT_EQUALS("", errout_str());
4322 :
4323 1 : check("void foo()\n"
4324 : "{\n"
4325 : " int y = 1;\n"
4326 : " switch (x)\n"
4327 : " {\n"
4328 : " case 2:\n"
4329 : " y = 2;\n"
4330 : " bar();\n"
4331 : " case 3:\n"
4332 : " y = 3;\n"
4333 : " }\n"
4334 : " bar(y);\n"
4335 : "}");
4336 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:10]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4337 :
4338 1 : check("void bar() {}\n" // bar isn't noreturn
4339 : "void foo()\n"
4340 : "{\n"
4341 : " int y = 1;\n"
4342 : " switch (x)\n"
4343 : " {\n"
4344 : " case 2:\n"
4345 : " y = 2;\n"
4346 : " bar();\n"
4347 : " case 3:\n"
4348 : " y = 3;\n"
4349 : " }\n"
4350 : " bar(y);\n"
4351 : "}");
4352 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4353 :
4354 1 : check("void foo(int a) {\n"
4355 : " char str[10];\n"
4356 : " switch (a)\n"
4357 : " {\n"
4358 : " case 2:\n"
4359 : " strcpy(str, \"a'\");\n"
4360 : " case 3:\n"
4361 : " strcpy(str, \"b'\");\n"
4362 : " }\n"
4363 : "}", true, false, false);
4364 1 : TODO_ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:8]: (style) Buffer 'str' is being written before its old content has been used. 'break;' missing?\n",
4365 : "",
4366 : errout_str());
4367 :
4368 1 : check("void foo(int a) {\n"
4369 : " char str[10];\n"
4370 : " switch (a)\n"
4371 : " {\n"
4372 : " case 2:\n"
4373 : " strncpy(str, \"a'\");\n"
4374 : " case 3:\n"
4375 : " strncpy(str, \"b'\");\n"
4376 : " }\n"
4377 : "}");
4378 1 : TODO_ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:8]: (style) Buffer 'str' is being written before its old content has been used. 'break;' missing?\n",
4379 : "",
4380 : errout_str());
4381 :
4382 1 : check("void foo(int a) {\n"
4383 : " char str[10];\n"
4384 : " int z = 0;\n"
4385 : " switch (a)\n"
4386 : " {\n"
4387 : " case 2:\n"
4388 : " strcpy(str, \"a'\");\n"
4389 : " z++;\n"
4390 : " case 3:\n"
4391 : " strcpy(str, \"b'\");\n"
4392 : " z++;\n"
4393 : " }\n"
4394 : "}", true, false, false);
4395 1 : TODO_ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:10]: (style) Buffer 'str' is being written before its old content has been used. 'break;' missing?\n",
4396 : "",
4397 : errout_str());
4398 :
4399 1 : check("void foo(int a) {\n"
4400 : " char str[10];\n"
4401 : " switch (a)\n"
4402 : " {\n"
4403 : " case 2:\n"
4404 : " strcpy(str, \"a'\");\n"
4405 : " break;\n"
4406 : " case 3:\n"
4407 : " strcpy(str, \"b'\");\n"
4408 : " break;\n"
4409 : " }\n"
4410 : "}");
4411 1 : ASSERT_EQUALS("", errout_str());
4412 :
4413 1 : check("void foo(int a) {\n"
4414 : " char str[10];\n"
4415 : " switch (a)\n"
4416 : " {\n"
4417 : " case 2:\n"
4418 : " strcpy(str, \"a'\");\n"
4419 : " printf(str);\n"
4420 : " case 3:\n"
4421 : " strcpy(str, \"b'\");\n"
4422 : " }\n"
4423 : "}", true, false, false);
4424 1 : ASSERT_EQUALS("", errout_str());
4425 :
4426 : // Ticket #5158 "segmentation fault (valid code)"
4427 1 : check("typedef struct ct_data_s {\n"
4428 : " union {\n"
4429 : " char freq;\n"
4430 : " } fc;\n"
4431 : "} ct_data;\n"
4432 : "typedef struct internal_state {\n"
4433 : " struct ct_data_s dyn_ltree[10];\n"
4434 : "} deflate_state;\n"
4435 : "void f(deflate_state *s) {\n"
4436 : " s->dyn_ltree[0].fc.freq++;\n"
4437 : "}\n", true, false, false);
4438 1 : ASSERT_EQUALS("", errout_str());
4439 :
4440 : // Ticket #6132 "crash: daca: kvirc CheckOther::checkRedundantAssignment()"
4441 1 : check("void HttpFileTransfer :: transferTerminated ( bool bSuccess ) {\n"
4442 : "if ( m_szCompletionCallback . isNull ( ) ) {\n"
4443 : "KVS_TRIGGER_EVENT ( KviEvent_OnHTTPGetTerminated , out ? out : ( g_pApp . activeConsole ( ) ) , & vParams )\n"
4444 : "} else {\n"
4445 : "KviKvsScript :: run ( m_szCompletionCallback , out ? out : ( g_pApp . activeConsole ( ) ) , & vParams ) ;\n"
4446 : "}\n"
4447 : "}\n", true, false, true);
4448 1 : ASSERT_EQUALS("", errout_str());
4449 :
4450 1 : check("void f() {\n"
4451 : " int x;\n"
4452 : " switch (state) {\n"
4453 : " case 1: x = 3; goto a;\n"
4454 : " case 1: x = 6; goto a;\n"
4455 : " }\n"
4456 : "}");
4457 1 : ASSERT_EQUALS("", errout_str());
4458 : }
4459 :
4460 1 : void switchRedundantOperationTest() {
4461 1 : check("void foo()\n"
4462 : "{\n"
4463 : " int y = 1;\n"
4464 : " switch (a)\n"
4465 : " {\n"
4466 : " case 2:\n"
4467 : " ++y;\n"
4468 : " case 3:\n"
4469 : " y = 3;\n"
4470 : " }\n"
4471 : " bar(y);\n"
4472 : "}");
4473 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4474 1 : check("void foo()\n"
4475 : "{\n"
4476 : " int y = 1;\n"
4477 : " switch (a)\n"
4478 : " {\n"
4479 : " case 2:\n"
4480 : " {\n"
4481 : " ++y;\n"
4482 : " }\n"
4483 : " case 3:\n"
4484 : " y = 3;\n"
4485 : " }\n"
4486 : " bar(y);\n"
4487 : "}");
4488 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4489 1 : check("void foo()\n"
4490 : "{\n"
4491 : " int y = 1;\n"
4492 : " switch (a)\n"
4493 : " {\n"
4494 : " case 2:\n"
4495 : " (void)y;\n"
4496 : " case 3:\n"
4497 : " ++y;\n"
4498 : " }\n"
4499 : " bar(y);\n"
4500 : "}");
4501 1 : ASSERT_EQUALS("", errout_str());
4502 1 : check("void foo()\n"
4503 : "{\n"
4504 : " int y = 1;\n"
4505 : " switch (a)\n"
4506 : " {\n"
4507 : " case 2:\n"
4508 : " ++y;\n"
4509 : " case 3:\n"
4510 : " ++y;\n"
4511 : " }\n"
4512 : " bar(y);\n"
4513 : "}");
4514 1 : ASSERT_EQUALS("", errout_str());
4515 1 : check("void foo()\n"
4516 : "{\n"
4517 : " int y = 1;\n"
4518 : " switch (a)\n"
4519 : " {\n"
4520 : " case 2:\n"
4521 : " --y;\n"
4522 : " case 3:\n"
4523 : " y = 3;\n"
4524 : " }\n"
4525 : " bar(y);\n"
4526 : "}");
4527 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4528 1 : check("void foo()\n"
4529 : "{\n"
4530 : " int y = 1;\n"
4531 : " switch (a)\n"
4532 : " {\n"
4533 : " case 2:\n"
4534 : " {\n"
4535 : " --y;\n"
4536 : " }\n"
4537 : " case 3:\n"
4538 : " y = 3;\n"
4539 : " }\n"
4540 : " bar(y);\n"
4541 : "}");
4542 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4543 1 : check("void foo()\n"
4544 : "{\n"
4545 : " int y = 1;\n"
4546 : " switch (a)\n"
4547 : " {\n"
4548 : " case 2:\n"
4549 : " (void)y;\n"
4550 : " case 3:\n"
4551 : " --y;\n"
4552 : " }\n"
4553 : " bar(y);\n"
4554 : "}");
4555 1 : ASSERT_EQUALS("", errout_str());
4556 1 : check("void foo()\n"
4557 : "{\n"
4558 : " int y = 1;\n"
4559 : " switch (a)\n"
4560 : " {\n"
4561 : " case 2:\n"
4562 : " --y;\n"
4563 : " case 3:\n"
4564 : " --y;\n"
4565 : " }\n"
4566 : " bar(y);\n"
4567 : "}");
4568 1 : ASSERT_EQUALS("", errout_str());
4569 1 : check("void foo()\n"
4570 : "{\n"
4571 : " int y = 1;\n"
4572 : " switch (a)\n"
4573 : " {\n"
4574 : " case 2:\n"
4575 : " y++;\n"
4576 : " case 3:\n"
4577 : " y = 3;\n"
4578 : " }\n"
4579 : " bar(y);\n"
4580 : "}");
4581 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4582 1 : check("void foo()\n"
4583 : "{\n"
4584 : " int y = 1;\n"
4585 : " switch (a)\n"
4586 : " {\n"
4587 : " case 2:\n"
4588 : " {\n"
4589 : " y++;\n"
4590 : " }\n"
4591 : " case 3:\n"
4592 : " y = 3;\n"
4593 : " }\n"
4594 : " bar(y);\n"
4595 : "}");
4596 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4597 1 : check("void foo()\n"
4598 : "{\n"
4599 : " int y = 1;\n"
4600 : " switch (a)\n"
4601 : " {\n"
4602 : " case 2:\n"
4603 : " y = 2;\n"
4604 : " case 3:\n"
4605 : " y++;\n"
4606 : " }\n"
4607 : " bar(y);\n"
4608 : "}", true, false, false);
4609 1 : ASSERT_EQUALS("", errout_str());
4610 1 : check("void foo()\n"
4611 : "{\n"
4612 : " int y = 1;\n"
4613 : " switch (a)\n"
4614 : " {\n"
4615 : " case 2:\n"
4616 : " y++;\n"
4617 : " case 3:\n"
4618 : " y++;\n"
4619 : " }\n"
4620 : " bar(y);\n"
4621 : "}");
4622 1 : ASSERT_EQUALS("", errout_str());
4623 1 : check("void foo()\n"
4624 : "{\n"
4625 : " int y = 1;\n"
4626 : " switch (a)\n"
4627 : " {\n"
4628 : " case 2:\n"
4629 : " y--;\n"
4630 : " case 3:\n"
4631 : " y = 3;\n"
4632 : " }\n"
4633 : " bar(y);\n"
4634 : "}");
4635 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4636 1 : check("void foo()\n"
4637 : "{\n"
4638 : " int y = 1;\n"
4639 : " switch (a)\n"
4640 : " {\n"
4641 : " case 2:\n"
4642 : " {\n"
4643 : " y--;\n"
4644 : " }\n"
4645 : " case 3:\n"
4646 : " y = 3;\n"
4647 : " }\n"
4648 : " bar(y);\n"
4649 : "}");
4650 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:11]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4651 1 : check("void foo()\n"
4652 : "{\n"
4653 : " int y = 1;\n"
4654 : " switch (a)\n"
4655 : " {\n"
4656 : " case 2:\n"
4657 : " y = 2;\n"
4658 : " case 3:\n"
4659 : " y--;\n"
4660 : " }\n"
4661 : " bar(y);\n"
4662 : "}", true, false, false);
4663 1 : ASSERT_EQUALS("", errout_str());
4664 1 : check("void foo()\n"
4665 : "{\n"
4666 : " int y = 1;\n"
4667 : " switch (a)\n"
4668 : " {\n"
4669 : " case 2:\n"
4670 : " y--;\n"
4671 : " case 3:\n"
4672 : " y--;\n"
4673 : " }\n"
4674 : " bar(y);\n"
4675 : "}");
4676 1 : ASSERT_EQUALS("", errout_str());
4677 1 : check("void foo()\n"
4678 : "{\n"
4679 : " int y = 1;\n"
4680 : " switch (a)\n"
4681 : " {\n"
4682 : " case 2:\n"
4683 : " y++;\n"
4684 : " case 3:\n"
4685 : " if (x)\n"
4686 : " {\n"
4687 : " y = 3;\n"
4688 : " }\n"
4689 : " }\n"
4690 : " bar(y);\n"
4691 : "}");
4692 1 : ASSERT_EQUALS("", errout_str());
4693 1 : check("void foo()\n"
4694 : "{\n"
4695 : " int y = 1;\n"
4696 : " switch (a)\n"
4697 : " {\n"
4698 : " case 2:\n"
4699 : " {\n"
4700 : " y++;\n"
4701 : " if (y)\n"
4702 : " printf(\"%d\", y);\n"
4703 : " }\n"
4704 : " case 3:\n"
4705 : " y = 3;\n"
4706 : " }\n"
4707 : " bar(y);\n"
4708 : "}");
4709 1 : ASSERT_EQUALS("", errout_str());
4710 1 : check("void foo()\n"
4711 : "{\n"
4712 : " int x = a;\n"
4713 : " int y = 1;\n"
4714 : " switch (x)\n"
4715 : " {\n"
4716 : " case 2:\n"
4717 : " x++;\n"
4718 : " case 3:\n"
4719 : " y++;\n"
4720 : " }\n"
4721 : " bar(y);\n"
4722 : "}");
4723 1 : ASSERT_EQUALS("", errout_str());
4724 1 : check("void foo()\n"
4725 : "{\n"
4726 : " int y = 1;\n"
4727 : " switch (x)\n"
4728 : " {\n"
4729 : " case 2:\n"
4730 : " y++;\n"
4731 : " break;\n"
4732 : " case 3:\n"
4733 : " y = 3;\n"
4734 : " }\n"
4735 : " bar(y);\n"
4736 : "}");
4737 1 : ASSERT_EQUALS("", errout_str());
4738 1 : check("void foo()\n"
4739 : "{\n"
4740 : " int y = 1;\n"
4741 : " while(xyz()) {\n"
4742 : " switch (x)\n"
4743 : " {\n"
4744 : " case 2:\n"
4745 : " y++;\n"
4746 : " continue;\n"
4747 : " case 3:\n"
4748 : " y = 3;\n"
4749 : " }\n"
4750 : " bar(y);\n"
4751 : " }\n"
4752 : "}");
4753 1 : ASSERT_EQUALS("", errout_str());
4754 1 : check("void foo()\n"
4755 : "{\n"
4756 : " int y = 1;\n"
4757 : " while(xyz()) {\n"
4758 : " switch (x)\n"
4759 : " {\n"
4760 : " case 2:\n"
4761 : " y++;\n"
4762 : " throw e;\n"
4763 : " case 3:\n"
4764 : " y = 3;\n"
4765 : " }\n"
4766 : " bar(y);\n"
4767 : " }\n"
4768 : "}");
4769 1 : ASSERT_EQUALS("", errout_str());
4770 1 : check("void foo()\n"
4771 : "{\n"
4772 : " int y = 1;\n"
4773 : " switch (x)\n"
4774 : " {\n"
4775 : " case 2:\n"
4776 : " y++;\n"
4777 : " printf(\"%d\", y);\n"
4778 : " case 3:\n"
4779 : " y = 3;\n"
4780 : " }\n"
4781 : " bar(y);\n"
4782 : "}");
4783 1 : ASSERT_EQUALS("", errout_str());
4784 1 : check("void foo()\n"
4785 : "{\n"
4786 : " int y = 1;\n"
4787 : " switch (x)\n"
4788 : " {\n"
4789 : " case 2:\n"
4790 : " y++;\n"
4791 : " bar();\n"
4792 : " case 3:\n"
4793 : " y = 3;\n"
4794 : " }\n"
4795 : " bar(y);\n"
4796 : "}");
4797 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:10]: (style) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errout_str());
4798 :
4799 1 : check("bool f() {\n"
4800 : " bool ret = false;\n"
4801 : " switch (switchCond) {\n"
4802 : " case 1:\n"
4803 : " ret = true;\n"
4804 : " break;\n"
4805 : " case 31:\n"
4806 : " ret = true;\n"
4807 : " break;\n"
4808 : " case 54:\n"
4809 : " ret = true;\n"
4810 : " break;\n"
4811 : " };\n"
4812 : " ret = true;\n"
4813 : " return ret;\n"
4814 : "}");
4815 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:14]: (style) Variable 'ret' is reassigned a value before the old one has been used.\n"
4816 : "[test.cpp:8] -> [test.cpp:14]: (style) Variable 'ret' is reassigned a value before the old one has been used.\n"
4817 : "[test.cpp:11] -> [test.cpp:14]: (style) Variable 'ret' is reassigned a value before the old one has been used.\n",
4818 : errout_str());
4819 : }
4820 :
4821 1 : void switchRedundantBitwiseOperationTest() {
4822 1 : check("void foo(int a)\n"
4823 : "{\n"
4824 : " int y = 1;\n"
4825 : " switch (a)\n"
4826 : " {\n"
4827 : " case 2:\n"
4828 : " y |= 3;\n"
4829 : " case 3:\n"
4830 : " y |= 3;\n"
4831 : " break;\n"
4832 : " }\n"
4833 : "}");
4834 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Redundant bitwise operation on 'y' in 'switch' statement. 'break;' missing?\n", errout_str());
4835 :
4836 1 : check("void foo(int a)\n"
4837 : "{\n"
4838 : " int y = 1;\n"
4839 : " switch (a)\n"
4840 : " {\n"
4841 : " case 2:\n"
4842 : " y = y | 3;\n"
4843 : " case 3:\n"
4844 : " y = y | 3;\n"
4845 : " break;\n"
4846 : " }\n"
4847 : "}");
4848 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Redundant bitwise operation on 'y' in 'switch' statement. 'break;' missing?\n", errout_str());
4849 :
4850 1 : check("void foo(int a)\n"
4851 : "{\n"
4852 : " int y = 1;\n"
4853 : " switch (a)\n"
4854 : " {\n"
4855 : " case 2:\n"
4856 : " y |= 3;\n"
4857 : " default:\n"
4858 : " y |= 3;\n"
4859 : " break;\n"
4860 : " }\n"
4861 : "}");
4862 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Redundant bitwise operation on 'y' in 'switch' statement. 'break;' missing?\n", errout_str());
4863 :
4864 1 : check("void foo(int a)\n"
4865 : "{\n"
4866 : " int y = 1;\n"
4867 : " switch (a)\n"
4868 : " {\n"
4869 : " case 2:\n"
4870 : " y |= 3;\n"
4871 : " default:\n"
4872 : " if (z)\n"
4873 : " y |= 3;\n"
4874 : " break;\n"
4875 : " }\n"
4876 : "}");
4877 1 : ASSERT_EQUALS("", errout_str());
4878 :
4879 1 : check("void foo(int a)\n"
4880 : "{\n"
4881 : " int y = 1;\n"
4882 : " switch (a)\n"
4883 : " {\n"
4884 : " case 2:\n"
4885 : " y |= z;\n"
4886 : " z++\n"
4887 : " default:\n"
4888 : " y |= z;\n"
4889 : " break;\n"
4890 : " }\n"
4891 : "}");
4892 1 : ASSERT_EQUALS("", errout_str());
4893 :
4894 1 : check("void foo(int a)\n"
4895 : "{\n"
4896 : " int y = 1;\n"
4897 : " switch (a)\n"
4898 : " {\n"
4899 : " case 2:\n"
4900 : " y |= 3;\n"
4901 : " bar(y);\n"
4902 : " case 3:\n"
4903 : " y |= 3;\n"
4904 : " break;\n"
4905 : " }\n"
4906 : "}");
4907 1 : ASSERT_EQUALS("", errout_str());
4908 :
4909 1 : check("void foo(int a)\n"
4910 : "{\n"
4911 : " int y = 1;\n"
4912 : " switch (a)\n"
4913 : " {\n"
4914 : " case 2:\n"
4915 : " y |= 3;\n"
4916 : " y = 4;\n"
4917 : " case 3:\n"
4918 : " y |= 3;\n"
4919 : " break;\n"
4920 : " }\n"
4921 : "}");
4922 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:8]: (style) Variable 'y' is reassigned a value before the old one has been used.\n", errout_str());
4923 :
4924 1 : check("void foo(int a)\n"
4925 : "{\n"
4926 : " int y = 1;\n"
4927 : " switch (a)\n"
4928 : " {\n"
4929 : " case 2:\n"
4930 : " y &= 3;\n"
4931 : " case 3:\n"
4932 : " y &= 3;\n"
4933 : " break;\n"
4934 : " }\n"
4935 : "}");
4936 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Redundant bitwise operation on 'y' in 'switch' statement. 'break;' missing?\n", errout_str());
4937 :
4938 1 : check("void foo(int a)\n"
4939 : "{\n"
4940 : " int y = 1;\n"
4941 : " switch (a)\n"
4942 : " {\n"
4943 : " case 2:\n"
4944 : " y |= 3;\n"
4945 : " break;\n"
4946 : " case 3:\n"
4947 : " y |= 3;\n"
4948 : " break;\n"
4949 : " }\n"
4950 : "}");
4951 1 : ASSERT_EQUALS("", errout_str());
4952 :
4953 1 : check("void foo(int a)\n"
4954 : "{\n"
4955 : " int y = 1;\n"
4956 : " switch (a)\n"
4957 : " {\n"
4958 : " case 2:\n"
4959 : " y ^= 3;\n"
4960 : " case 3:\n"
4961 : " y ^= 3;\n"
4962 : " break;\n"
4963 : " }\n"
4964 : "}");
4965 1 : ASSERT_EQUALS("", errout_str());
4966 :
4967 1 : check("void foo(int a)\n"
4968 : "{\n"
4969 : " int y = 1;\n"
4970 : " switch (a)\n"
4971 : " {\n"
4972 : " case 2:\n"
4973 : " y |= 2;\n"
4974 : " case 3:\n"
4975 : " y |= 3;\n"
4976 : " break;\n"
4977 : " }\n"
4978 : "}");
4979 1 : ASSERT_EQUALS("", errout_str());
4980 :
4981 1 : check("void foo(int a)\n"
4982 : "{\n"
4983 : " int y = 1;\n"
4984 : " switch (a)\n"
4985 : " {\n"
4986 : " case 2:\n"
4987 : " y &= 2;\n"
4988 : " case 3:\n"
4989 : " y &= 3;\n"
4990 : " break;\n"
4991 : " }\n"
4992 : "}");
4993 1 : ASSERT_EQUALS("", errout_str());
4994 :
4995 1 : check("void foo(int a)\n"
4996 : "{\n"
4997 : " int y = 1;\n"
4998 : " switch (a)\n"
4999 : " {\n"
5000 : " case 2:\n"
5001 : " y |= 2;\n"
5002 : " case 3:\n"
5003 : " y &= 2;\n"
5004 : " break;\n"
5005 : " }\n"
5006 : "}");
5007 1 : ASSERT_EQUALS("", errout_str());
5008 : }
5009 :
5010 1 : void unreachableCode() {
5011 1 : check("void foo(int a) {\n"
5012 : " while(1) {\n"
5013 : " if (a++ >= 100) {\n"
5014 : " break;\n"
5015 : " continue;\n"
5016 : " }\n"
5017 : " }\n"
5018 : "}", true, false, false);
5019 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5020 :
5021 1 : check("int foo(int a) {\n"
5022 : " return 0;\n"
5023 : " return(a-1);\n"
5024 : "}", true, false, false);
5025 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5026 :
5027 1 : check("int foo(int a) {\n"
5028 : " A:"
5029 : " return(0);\n"
5030 : " goto A;\n"
5031 : "}", true, false, false);
5032 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5033 :
5034 1 : constexpr char xmldata[] = "<?xml version=\"1.0\"?>\n"
5035 : "<def>\n"
5036 : " <function name=\"exit\">\n"
5037 : " <noreturn>true</noreturn>\n"
5038 : " <arg nr=\"1\"/>\n"
5039 : " </function>\n"
5040 : "</def>";
5041 1 : /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata, sizeof(xmldata)).build();
5042 :
5043 1 : check("void foo() {\n"
5044 : " exit(0);\n"
5045 : " break;\n"
5046 : "}", true, false, false, false, &settings);
5047 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5048 :
5049 1 : check("class NeonSession {\n"
5050 : " void exit();\n"
5051 : "};\n"
5052 : "void NeonSession::exit()\n"
5053 : "{\n"
5054 : " SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborted\");\n"
5055 : "}", true, false, false, false, &settings);
5056 1 : ASSERT_EQUALS("", errout_str());
5057 :
5058 1 : check("void NeonSession::exit()\n"
5059 : "{\n"
5060 : " SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborted\");\n"
5061 : "}", true, false, false, false, &settings);
5062 1 : ASSERT_EQUALS("", errout_str());
5063 :
5064 1 : check("void foo() { xResAccess->exit(); }", true, false, false, false, &settings);
5065 1 : ASSERT_EQUALS("", errout_str());
5066 :
5067 1 : check("void foo(int a)\n"
5068 : "{\n"
5069 : " switch(a) {\n"
5070 : " case 0:\n"
5071 : " printf(\"case 0\");\n"
5072 : " break;\n"
5073 : " break;\n"
5074 : " case 1:\n"
5075 : " c++;\n"
5076 : " break;\n"
5077 : " }\n"
5078 : "}", true, false, false);
5079 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5080 :
5081 1 : check("void foo(int a)\n"
5082 : "{\n"
5083 : " switch(a) {\n"
5084 : " case 0:\n"
5085 : " printf(\"case 0\");\n"
5086 : " break;\n"
5087 : " case 1:\n"
5088 : " c++;\n"
5089 : " break;\n"
5090 : " }\n"
5091 : "}");
5092 1 : ASSERT_EQUALS("", errout_str());
5093 :
5094 1 : check("void foo(int a)\n"
5095 : "{\n"
5096 : " while(true) {\n"
5097 : " if (a++ >= 100) {\n"
5098 : " break;\n"
5099 : " break;\n"
5100 : " }\n"
5101 : " }\n"
5102 : "}", true, false, false);
5103 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5104 :
5105 1 : check("void foo(int a)\n"
5106 : "{\n"
5107 : " while(true) {\n"
5108 : " if (a++ >= 100) {\n"
5109 : " continue;\n"
5110 : " continue;\n"
5111 : " }\n"
5112 : " a+=2;\n"
5113 : " }\n"
5114 : "}", true, false, false);
5115 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5116 :
5117 1 : check("void foo(int a)\n"
5118 : "{\n"
5119 : " while(true) {\n"
5120 : " if (a++ >= 100) {\n"
5121 : " continue;\n"
5122 : " }\n"
5123 : " a+=2;\n"
5124 : " }\n"
5125 : "}");
5126 1 : ASSERT_EQUALS("", errout_str());
5127 :
5128 1 : check("int foo() {\n"
5129 : " throw 0;\n"
5130 : " return 1;\n"
5131 : "}", true, false, false);
5132 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5133 :
5134 1 : check("void foo() {\n"
5135 : " throw 0;\n"
5136 : " return;\n"
5137 : "}", true, false, false);
5138 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5139 :
5140 1 : check("int foo() {\n"
5141 : " throw = 0;\n"
5142 : " return 1;\n"
5143 : "}", false, false, false);
5144 1 : ASSERT_EQUALS("", errout_str());
5145 :
5146 1 : check("int foo() {\n"
5147 : " return 0;\n"
5148 : " return 1;\n"
5149 : "}", true, false, false, false);
5150 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5151 :
5152 1 : check("int foo() {\n"
5153 : " return 0;\n"
5154 : " foo();\n"
5155 : "}", true, false, false);
5156 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Statements following 'return' will never be executed.\n", errout_str());
5157 :
5158 1 : check("int foo(int unused) {\n"
5159 : " return 0;\n"
5160 : " (void)unused;\n"
5161 : "}", true, false, false);
5162 1 : ASSERT_EQUALS("", errout_str());
5163 :
5164 1 : check("int foo(int unused1, int unused2) {\n"
5165 : " return 0;\n"
5166 : " (void)unused1;\n"
5167 : " (void)unused2;\n"
5168 : "}", true, false, false);
5169 1 : ASSERT_EQUALS("", errout_str());
5170 :
5171 1 : check("int foo(int unused1, int unused2) {\n"
5172 : " return 0;\n"
5173 : " (void)unused1;\n"
5174 : " (void)unused2;\n"
5175 : " foo();\n"
5176 : "}", true, false, false);
5177 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Statements following 'return' will never be executed.\n", errout_str());
5178 :
5179 1 : check("int foo() {\n"
5180 : " if(bar)\n"
5181 : " return 0;\n"
5182 : " return 124;\n"
5183 : "}");
5184 1 : ASSERT_EQUALS("", errout_str());
5185 :
5186 1 : check("int foo() {\n"
5187 : " while(bar) {\n"
5188 : " return 0;\n"
5189 : " return 0;\n"
5190 : " return 0;\n"
5191 : " return 0;\n"
5192 : " }\n"
5193 : " return 124;\n"
5194 : "}", true, false, false);
5195 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5196 :
5197 1 : check("void foo() {\n"
5198 : " while(bar) {\n"
5199 : " return;\n"
5200 : " break;\n"
5201 : " }\n"
5202 : "}", true, false, false);
5203 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5204 :
5205 : // #5707
5206 1 : check("extern int i,j;\n"
5207 : "int foo() {\n"
5208 : " switch(i) {\n"
5209 : " default: j=1; break;\n"
5210 : " }\n"
5211 : " return 0;\n"
5212 : " j=2;\n"
5213 : "}", true, false, false);
5214 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Statements following 'return' will never be executed.\n", errout_str());
5215 :
5216 1 : check("int foo() {\n"
5217 : " return 0;\n"
5218 : " label:\n"
5219 : " throw 0;\n"
5220 : "}", true, false, false);
5221 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Label 'label' is not used.\n", errout_str());
5222 :
5223 1 : check("struct A {\n"
5224 : " virtual void foo (P & Val) throw ();\n"
5225 : " virtual void foo1 (P & Val) throw ();\n"
5226 : "}");
5227 1 : ASSERT_EQUALS("", errout_str());
5228 :
5229 1 : check("int foo() {\n"
5230 : " goto label;\n"
5231 : " while (true) {\n"
5232 : " bar();\n"
5233 : " label:\n"
5234 : " }\n"
5235 : "}");
5236 1 : ASSERT_EQUALS("", errout_str()); // #3457
5237 :
5238 1 : check("int foo() {\n"
5239 : " goto label;\n"
5240 : " do {\n"
5241 : " bar();\n"
5242 : " label:\n"
5243 : " } while (true);\n"
5244 : "}");
5245 1 : ASSERT_EQUALS("", errout_str()); // #3457
5246 :
5247 1 : check("int foo() {\n"
5248 : " goto label;\n"
5249 : " for (;;) {\n"
5250 : " bar();\n"
5251 : " label:\n"
5252 : " }\n"
5253 : "}");
5254 1 : ASSERT_EQUALS("", errout_str()); // #3457
5255 :
5256 : // #3383. TODO: Use preprocessor
5257 1 : check("int foo() {\n"
5258 : "\n" // #ifdef A
5259 : " return 0;\n"
5260 : "\n" // #endif
5261 : " return 1;\n"
5262 : "}", true, false, false);
5263 1 : ASSERT_EQUALS("", errout_str());
5264 1 : check("int foo() {\n"
5265 : "\n" // #ifdef A
5266 : " return 0;\n"
5267 : "\n" // #endif
5268 : " return 1;\n"
5269 : "}", true, true, false);
5270 1 : ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Consecutive return, break, continue, goto or throw statements are unnecessary.\n", errout_str());
5271 :
5272 : // #4711 lambda functions
5273 1 : check("int f() {\n"
5274 : " return g([](int x){(void)x+1; return x;});\n"
5275 : "}",
5276 : true,
5277 : false,
5278 : false);
5279 1 : ASSERT_EQUALS("", errout_str());
5280 :
5281 : // #4756
5282 1 : check("template <>\n"
5283 : "inline uint16_t htobe(uint16_t value) {\n"
5284 : " return ( __extension__ ({\n"
5285 : " register unsigned short int __v, __x = (unsigned short int) (value);\n"
5286 : " if (__builtin_constant_p (__x))\n"
5287 : " __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8)));\n"
5288 : " else\n"
5289 : " __asm__ (\"rorw $8, %w0\" : \"=r\" (__v) : \"0\" (__x) : \"cc\");\n"
5290 : " (void)__v;\n"
5291 : " }));\n"
5292 : "}", true, false, false);
5293 1 : ASSERT_EQUALS("", errout_str());
5294 :
5295 : // #6008
5296 1 : check("static std::function< int ( int, int ) > GetFunctor() {\n"
5297 : " return [](int a_, int b_) -> int {\n"
5298 : " int sum = a_ + b_;\n"
5299 : " return sum;\n"
5300 : " };\n"
5301 : "}", true, false, false);
5302 1 : ASSERT_EQUALS("", errout_str());
5303 :
5304 : // #5789
5305 1 : check("struct per_state_info {\n"
5306 : " uint64_t enter, exit;\n"
5307 : " uint64_t events;\n"
5308 : " per_state_info() : enter(0), exit(0), events(0) {}\n"
5309 : "};", true, false, false);
5310 1 : ASSERT_EQUALS("", errout_str());
5311 :
5312 : // #6664
5313 1 : check("void foo() {\n"
5314 : " (beat < 100) ? (void)0 : exit(0);\n"
5315 : " bar();\n"
5316 : "}", true, false, false, false, &settings);
5317 1 : ASSERT_EQUALS("", errout_str());
5318 :
5319 1 : check("void foo() {\n"
5320 : " (beat < 100) ? exit(0) : (void)0;\n"
5321 : " bar();\n"
5322 : "}", true, false, false, false, &settings);
5323 1 : ASSERT_EQUALS("", errout_str());
5324 :
5325 : // #8261
5326 : // TODO Do not throw AST validation exception
5327 1 : TODO_ASSERT_THROW(check("void foo() {\n"
5328 : " (beat < 100) ? (void)0 : throw(0);\n"
5329 : " bar();\n"
5330 : "}", true, false, false, false, &settings), InternalError);
5331 : //ASSERT_EQUALS("", errout_str());
5332 :
5333 1 : check("int foo() {\n"
5334 : " exit(0);\n"
5335 : " return 1;\n" // <- clarify for tools that function does not continue..
5336 : "}");
5337 1 : ASSERT_EQUALS("", errout_str());
5338 :
5339 1 : check("void f() {\n"
5340 : " enum : uint8_t { A, B } var = A;\n"
5341 : "}\n");
5342 1 : ASSERT_EQUALS("", errout_str());
5343 :
5344 1 : checkP("#define INB(x) __extension__ ({ u_int tmp = (x); inb(tmp); })\n" // #4739
5345 : "static unsigned char cmos_hal_read(unsigned index) {\n"
5346 : " unsigned short port_0, port_1;\n"
5347 : " assert(!verify_cmos_byte_index(index));\n"
5348 : " if (index < 128) {\n"
5349 : " port_0 = 0x70;\n"
5350 : " port_1 = 0x71;\n"
5351 : " }\n"
5352 : " else {\n"
5353 : " port_0 = 0x72;\n"
5354 : " port_1 = 0x73;\n"
5355 : " }\n"
5356 : " OUTB(index, port_0);\n"
5357 : " return INB(port_1);\n"
5358 : "}\n", "test.c");
5359 1 : ASSERT_EQUALS("", errout_str());
5360 :
5361 1 : check("[[noreturn]] void n();\n"
5362 : "void f() {\n"
5363 : " n();\n"
5364 : " g();\n"
5365 : "}\n");
5366 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Statements following noreturn function 'n()' will never be executed.\n", errout_str());
5367 :
5368 1 : check("void f() {\n"
5369 : " exit(1);\n"
5370 : " g();\n"
5371 : "}\n");
5372 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Statements following noreturn function 'exit()' will never be executed.\n", errout_str());
5373 :
5374 1 : check("void f() {\n"
5375 : " do {\n"
5376 : " break;\n"
5377 : " g();\n"
5378 : " } while (0);\n"
5379 : "}\n");
5380 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Statements following 'break' will never be executed.\n", errout_str());
5381 : }
5382 :
5383 1 : void redundantContinue() {
5384 1 : check("void f() {\n" // #11195
5385 : " for (int i = 0; i < 10; ++i) {\n"
5386 : " printf(\"i = %d\\n\", i);\n"
5387 : " continue;\n"
5388 : " }\n"
5389 : "}\n");
5390 1 : ASSERT_EQUALS("[test.cpp:4]: (style) 'continue' is redundant since it is the last statement in a loop.\n", errout_str());
5391 :
5392 1 : check("void f() {\n"
5393 : " int i = 0;"
5394 : " do {\n"
5395 : " ++i;\n"
5396 : " printf(\"i = %d\\n\", i);\n"
5397 : " continue;\n"
5398 : " } while (i < 10);\n"
5399 : "}\n");
5400 1 : ASSERT_EQUALS("[test.cpp:5]: (style) 'continue' is redundant since it is the last statement in a loop.\n", errout_str());
5401 : }
5402 :
5403 :
5404 1 : void suspiciousCase() {
5405 1 : check("void foo() {\n"
5406 : " switch(a) {\n"
5407 : " case A&&B:\n"
5408 : " foo();\n"
5409 : " case (A||B):\n"
5410 : " foo();\n"
5411 : " case A||B:\n"
5412 : " foo();\n"
5413 : " }\n"
5414 : "}");
5415 1 : ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Found suspicious case label in switch(). Operator '&&' probably doesn't work as intended.\n"
5416 : "[test.cpp:5]: (warning, inconclusive) Found suspicious case label in switch(). Operator '||' probably doesn't work as intended.\n"
5417 : "[test.cpp:7]: (warning, inconclusive) Found suspicious case label in switch(). Operator '||' probably doesn't work as intended.\n", errout_str());
5418 :
5419 1 : check("void foo() {\n"
5420 : " switch(a) {\n"
5421 : " case 1:\n"
5422 : " a=A&&B;\n"
5423 : " }\n"
5424 : "}");
5425 1 : ASSERT_EQUALS("", errout_str());
5426 :
5427 : // TODO Do not throw AST validation exception
5428 1 : TODO_ASSERT_THROW(check("void foo() {\n"
5429 : " switch(a) {\n"
5430 : " case A&&B?B:A:\n"
5431 : " foo();\n"
5432 : " }\n"
5433 : "}"), InternalError);
5434 : //ASSERT_EQUALS("", errout_str());
5435 : }
5436 :
5437 1 : void suspiciousEqualityComparison() {
5438 1 : check("void foo(int c) {\n"
5439 : " if (x) c == 0;\n"
5440 : "}");
5441 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5442 :
5443 1 : check("void foo(const int* c) {\n"
5444 : " if (x) *c == 0;\n"
5445 : "}");
5446 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5447 :
5448 :
5449 1 : check("void foo(int c) {\n"
5450 : " if (c == 1) {\n"
5451 : " c = 0;\n"
5452 : " }\n"
5453 : "}");
5454 1 : ASSERT_EQUALS("", errout_str());
5455 :
5456 1 : check("void foo(int c) {\n"
5457 : " c == 1;\n"
5458 : "}");
5459 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5460 :
5461 1 : check("void foo(int c) {\n"
5462 : " for (int i = 0; i == 10; i ++) {\n"
5463 : " a ++;\n"
5464 : " }\n"
5465 : "}");
5466 1 : ASSERT_EQUALS("", errout_str());
5467 :
5468 1 : check("void foo(int c) {\n"
5469 : " for (i == 0; i < 10; i ++) {\n"
5470 : " c ++;\n"
5471 : " }\n"
5472 : "}");
5473 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5474 :
5475 1 : check("void foo(int c) {\n"
5476 : " for (i == 1; i < 10; i ++) {\n"
5477 : " c ++;\n"
5478 : " }\n"
5479 : "}");
5480 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5481 :
5482 1 : check("void foo(int c) {\n"
5483 : " for (i == 2; i < 10; i ++) {\n"
5484 : " c ++;\n"
5485 : " }\n"
5486 : "}");
5487 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5488 :
5489 1 : check("void foo(int c) {\n"
5490 : " for (int i = 0; i < 10; i == c) {\n"
5491 : " c ++;\n"
5492 : " }\n"
5493 : "}");
5494 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5495 :
5496 1 : check("void foo(int c) {\n"
5497 : " for (; running == 1;) {\n"
5498 : " c ++;\n"
5499 : " }\n"
5500 : "}");
5501 1 : ASSERT_EQUALS("", errout_str());
5502 :
5503 1 : check("void foo(int c) {\n"
5504 : " printf(\"%i\", ({x==0;}));\n"
5505 : "}");
5506 1 : ASSERT_EQUALS("", errout_str());
5507 :
5508 1 : check("void foo(int arg) {\n"
5509 : " printf(\"%i\", ({int x = do_something(); x == 0;}));\n"
5510 : "}");
5511 1 : ASSERT_EQUALS("", errout_str());
5512 :
5513 1 : check("void foo(int x) {\n"
5514 : " printf(\"%i\", ({x == 0; x > 0 ? 10 : 20}));\n"
5515 : "}");
5516 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious equality comparison. Did you intend to assign a value instead?\n", errout_str());
5517 :
5518 1 : check("void foo(int x) {\n"
5519 : " for (const Token* end = tok->link(); tok != end; tok = (tok == end) ? end : tok->next()) {\n"
5520 : " x++;\n"
5521 : " }\n"
5522 : "}");
5523 1 : ASSERT_EQUALS("", errout_str());
5524 :
5525 1 : check("void foo(int x) {\n"
5526 : " for (int i = (x == 0) ? 0 : 5; i < 10; i ++) {\n"
5527 : " x++;\n"
5528 : " }\n"
5529 : "}");
5530 1 : ASSERT_EQUALS("", errout_str());
5531 :
5532 1 : check("void foo(int x) {\n"
5533 : " for (int i = 0; i < 10; i += (x == 5) ? 1 : 2) {\n"
5534 : " x++;\n"
5535 : " }\n"
5536 : "}");
5537 1 : ASSERT_EQUALS("", errout_str());
5538 : }
5539 :
5540 1 : void suspiciousUnaryPlusMinus() { // #8004
5541 1 : check("int g() { return 1; }\n"
5542 : "void f() {\n"
5543 : " +g();\n"
5544 : " -g();\n"
5545 : "}\n");
5546 1 : ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Found suspicious operator '+', result is not used.\n"
5547 : "[test.cpp:4]: (warning, inconclusive) Found suspicious operator '-', result is not used.\n",
5548 : errout_str());
5549 :
5550 1 : check("void f(int i) {\n"
5551 : " +i;\n"
5552 : " -i;\n"
5553 : "}\n");
5554 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious operator '+', result is not used.\n"
5555 : "[test.cpp:3]: (warning, inconclusive) Found suspicious operator '-', result is not used.\n",
5556 : errout_str());
5557 : }
5558 :
5559 1 : void selfAssignment() {
5560 1 : check("void foo()\n"
5561 : "{\n"
5562 : " int x = 1;\n"
5563 : " x = x;\n"
5564 : " return 0;\n"
5565 : "}");
5566 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Redundant assignment of 'x' to itself.\n", errout_str());
5567 :
5568 1 : check("void foo()\n"
5569 : "{\n"
5570 : " int x = x;\n"
5571 : "}");
5572 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant assignment of 'x' to itself.\n", errout_str());
5573 :
5574 1 : check("struct A { int b; };\n"
5575 : "void foo(A* a1, A* a2) {\n"
5576 : " a1->b = a1->b;\n"
5577 : "}");
5578 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant assignment of 'a1->b' to itself.\n", errout_str());
5579 :
5580 1 : check("int x;\n"
5581 : "void f()\n"
5582 : "{\n"
5583 : " x = x = 3;\n"
5584 : "}");
5585 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Redundant assignment of 'x' to itself.\n", errout_str());
5586 :
5587 : // #4073 (segmentation fault)
5588 1 : check("void Foo::myFunc( int a )\n"
5589 : "{\n"
5590 : " if (a == 42)\n"
5591 : " a = a;\n"
5592 : "}");
5593 :
5594 1 : check("void foo()\n"
5595 : "{\n"
5596 : " int x = 1;\n"
5597 : " x = x + 1;\n"
5598 : " return 0;\n"
5599 : "}");
5600 1 : ASSERT_EQUALS("", errout_str());
5601 :
5602 1 : check("void foo()\n"
5603 : "{\n"
5604 : " int *x = getx();\n"
5605 : " *x = x;\n"
5606 : "}");
5607 1 : ASSERT_EQUALS("", errout_str());
5608 :
5609 1 : check("void foo() {\n"
5610 : " BAR *x = getx();\n"
5611 : " x = x;\n"
5612 : "}");
5613 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant assignment of 'x' to itself.\n", errout_str());
5614 :
5615 : // #2502 - non-primitive type -> there might be some side effects
5616 1 : check("void foo()\n"
5617 : "{\n"
5618 : " Fred fred; fred = fred;\n"
5619 : "}");
5620 1 : ASSERT_EQUALS("", errout_str());
5621 :
5622 1 : check("void f(int x) {\n"
5623 : " x = (x == 0);"
5624 : " func(x);\n"
5625 : "}");
5626 1 : ASSERT_EQUALS("", errout_str());
5627 :
5628 1 : check("void f(int x) {\n"
5629 : " x = (x != 0);"
5630 : " func(x);\n"
5631 : "}");
5632 1 : ASSERT_EQUALS("", errout_str());
5633 :
5634 : // ticket #3001 - false positive
5635 1 : check("void foo(int x) {\n"
5636 : " x = x ? x : 0;\n"
5637 : "}");
5638 1 : ASSERT_EQUALS("", errout_str());
5639 :
5640 : // #3800 - false negative when variable is extern
5641 1 : check("extern int i;\n"
5642 : "void f() {\n"
5643 : " i = i;\n"
5644 : "}");
5645 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant assignment of 'i' to itself.\n", errout_str());
5646 :
5647 : // #4291 - id for variables accessed through 'this'
5648 1 : check("class Foo {\n"
5649 : " int var;\n"
5650 : " void func();\n"
5651 : "};\n"
5652 : "void Foo::func() {\n"
5653 : " this->var = var;\n"
5654 : "}");
5655 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Redundant assignment of 'this->var' to itself.\n", errout_str());
5656 :
5657 1 : check("class Foo {\n"
5658 : " int var;\n"
5659 : " void func(int var);\n"
5660 : "};\n"
5661 : "void Foo::func(int var) {\n"
5662 : " this->var = var;\n"
5663 : "}");
5664 1 : ASSERT_EQUALS("", errout_str());
5665 :
5666 : // #6406 - designated initializer doing bogus self assignment
5667 1 : check("struct callbacks {\n"
5668 : " void (*s)(void);\n"
5669 : "};\n"
5670 : "void something(void) {}\n"
5671 : "void f() {\n"
5672 : " struct callbacks ops = { .s = ops.s };\n"
5673 : "}");
5674 1 : TODO_ASSERT_EQUALS("[test.cpp:6]: (style) Redundant assignment of 'something' to itself.\n", "", errout_str());
5675 :
5676 1 : check("class V\n"
5677 : "{\n"
5678 : "public:\n"
5679 : " V()\n"
5680 : " {\n"
5681 : " x = y = z = 0.0;\n"
5682 : " }\n"
5683 : " V( double x, const double y_, const double &z_)\n"
5684 : " {\n"
5685 : " x = x; y = y; z = z;\n"
5686 : " }\n"
5687 : " double x, y, z;\n"
5688 : "};");
5689 1 : ASSERT_EQUALS("[test.cpp:10]: (style) Redundant assignment of 'x' to itself.\n"
5690 : "[test.cpp:10]: (style) Redundant assignment of 'y' to itself.\n"
5691 : "[test.cpp:10]: (style) Redundant assignment of 'z' to itself.\n", errout_str());
5692 :
5693 1 : check("void f(int i) { i = !!i; }");
5694 1 : ASSERT_EQUALS("", errout_str());
5695 :
5696 1 : check("void foo() {\n"
5697 : " int x = 1;\n"
5698 : " int &ref = x;\n"
5699 : " ref = x;\n"
5700 : "}\n");
5701 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Redundant assignment of 'ref' to itself.\n", errout_str());
5702 :
5703 1 : check("class Foo {\n" // #9850
5704 : " int i{};\n"
5705 : " void modify();\n"
5706 : " void method() {\n"
5707 : " Foo copy = *this;\n"
5708 : " modify();\n"
5709 : " *this = copy;\n"
5710 : " }\n"
5711 : "};\n");
5712 1 : ASSERT_EQUALS("", errout_str());
5713 :
5714 1 : check("struct S {\n" // #11383
5715 : " void f() {\n"
5716 : " int x = 42;"
5717 : " auto l2 = [i = i, x, y = 0]() { return i + x + y; };\n"
5718 : " }\n"
5719 : " int i;\n"
5720 : "};\n");
5721 1 : ASSERT_EQUALS("", errout_str());
5722 :
5723 1 : check("void f() {\n" // #10337
5724 : " int b[2] = { 1, 2 };\n"
5725 : " int idx = 0;\n"
5726 : " int& i = b[idx];\n"
5727 : " idx++;\n"
5728 : " i = b[idx];\n"
5729 : "};\n");
5730 1 : ASSERT_EQUALS("", errout_str());
5731 :
5732 1 : check("void g(int*);\n" // #12390
5733 : "void f() {\n"
5734 : " int o = s.i;\n"
5735 : " g(&s.i);\n"
5736 : " s.i = o;\n"
5737 : "}\n");
5738 1 : ASSERT_EQUALS("", errout_str());
5739 : }
5740 :
5741 1 : void trac1132() {
5742 1 : check("class Lock\n"
5743 : "{\n"
5744 : "public:\n"
5745 : " Lock(int i)\n"
5746 : " {\n"
5747 : " std::cout << \"Lock \" << i << std::endl;\n"
5748 : " }\n"
5749 : " ~Lock()\n"
5750 : " {\n"
5751 : " std::cout << \"~Lock\" << std::endl;\n"
5752 : " }\n"
5753 : "};\n"
5754 : "int main()\n"
5755 : "{\n"
5756 : " Lock(123);\n"
5757 : " std::cout << \"hello\" << std::endl;\n"
5758 : " return 0;\n"
5759 : "}");
5760 1 : ASSERT_EQUALS("[test.cpp:15]: (style) Instance of 'Lock' object is destroyed immediately.\n", errout_str());
5761 : }
5762 :
5763 1 : void trac3693() {
5764 1 : check("struct A{\n"
5765 : " enum {\n"
5766 : " b = 300\n"
5767 : " };\n"
5768 : "};\n"
5769 : "const int DFLT_TIMEOUT = A::b % 1000000 ;\n", true, false, false);
5770 1 : ASSERT_EQUALS("", errout_str());
5771 : }
5772 :
5773 1 : void testMisusedScopeObjectDoesNotPickFunction1() {
5774 1 : check("int main ( )\n"
5775 : "{\n"
5776 : " CouldBeFunction ( 123 ) ;\n"
5777 : " return 0 ;\n"
5778 : "}");
5779 1 : ASSERT_EQUALS("", errout_str());
5780 : }
5781 :
5782 1 : void testMisusedScopeObjectDoesNotPickFunction2() {
5783 1 : check("struct error {\n"
5784 : " error() {}\n"
5785 : "};\n"
5786 : "\n"
5787 : "class parser {\n"
5788 : "public:\n"
5789 : " void error() const {}\n"
5790 : "\n"
5791 : " void foo() const {\n"
5792 : " error();\n"
5793 : " do_something();\n"
5794 : " }\n"
5795 : "};");
5796 1 : ASSERT_EQUALS("", errout_str());
5797 : }
5798 :
5799 1 : void testMisusedScopeObjectPicksClass() {
5800 1 : check("class NotAFunction ;\n"
5801 : "int function ( )\n"
5802 : "{\n"
5803 : " NotAFunction ( 123 );\n"
5804 : " return 0 ;\n"
5805 : "}");
5806 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Instance of 'NotAFunction' object is destroyed immediately.\n", errout_str());
5807 : }
5808 :
5809 1 : void testMisusedScopeObjectPicksStruct() {
5810 1 : check("struct NotAClass;\n"
5811 : "bool func ( )\n"
5812 : "{\n"
5813 : " NotAClass ( 123 ) ;\n"
5814 : " return true ;\n"
5815 : "}");
5816 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Instance of 'NotAClass' object is destroyed immediately.\n", errout_str());
5817 : }
5818 :
5819 1 : void testMisusedScopeObjectDoesNotPickIf() {
5820 1 : check("bool func( int a , int b , int c )\n"
5821 : "{\n"
5822 : " if ( a > b ) return c == a ;\n"
5823 : " return b == a ;\n"
5824 : "}");
5825 1 : ASSERT_EQUALS("", errout_str());
5826 : }
5827 :
5828 1 : void testMisusedScopeObjectDoesNotPickConstructorDeclaration() {
5829 1 : check("class Something : public SomethingElse\n"
5830 : "{\n"
5831 : "public:\n"
5832 : "~Something ( ) ;\n"
5833 : "Something ( ) ;\n"
5834 : "}");
5835 1 : ASSERT_EQUALS("", errout_str());
5836 : }
5837 :
5838 1 : void testMisusedScopeObjectDoesNotPickFunctor() {
5839 1 : check("class IncrementFunctor\n"
5840 : "{\n"
5841 : "public:\n"
5842 : " void operator()(int &i)\n"
5843 : " {\n"
5844 : " ++i;\n"
5845 : " }\n"
5846 : "};\n"
5847 : "\n"
5848 : "int main()\n"
5849 : "{\n"
5850 : " int a = 1;\n"
5851 : " IncrementFunctor()(a);\n"
5852 : " return a;\n"
5853 : "}");
5854 1 : ASSERT_EQUALS("", errout_str());
5855 : }
5856 :
5857 1 : void testMisusedScopeObjectDoesNotPickLocalClassConstructors() {
5858 1 : check("void f() {\n"
5859 : " class Foo {\n"
5860 : " Foo() { }\n"
5861 : " Foo(int a) { }\n"
5862 : " Foo(int a, int b) { }\n"
5863 : " };\n"
5864 : " Foo();\n"
5865 : " do_something();\n"
5866 : "}");
5867 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Instance of 'Foo' object is destroyed immediately.\n", errout_str());
5868 : }
5869 :
5870 1 : void testMisusedScopeObjectDoesNotPickUsedObject() {
5871 1 : check("struct Foo {\n"
5872 : " void bar() {\n"
5873 : " }\n"
5874 : "};\n"
5875 : "\n"
5876 : "void fn() {\n"
5877 : " Foo().bar();\n"
5878 : "}");
5879 1 : ASSERT_EQUALS("", errout_str());
5880 : }
5881 :
5882 1 : void testMisusedScopeObjectDoesNotPickPureC() {
5883 : // Ticket #2352
5884 1 : const char code[] = "struct cb_watch_bool {\n"
5885 : " int a;\n"
5886 : "};\n"
5887 : "\n"
5888 : "void f()\n"
5889 : "{\n"
5890 : " cb_watch_bool();\n"
5891 : " do_something();\n"
5892 : "}\n";
5893 :
5894 1 : check(code, true);
5895 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Instance of 'cb_watch_bool' object is destroyed immediately.\n", errout_str());
5896 :
5897 1 : check(code, false);
5898 1 : ASSERT_EQUALS("", errout_str());
5899 :
5900 : // Ticket #2639
5901 1 : check("struct stat { int a; int b; };\n"
5902 : "void stat(const char *fn, struct stat *);\n"
5903 : "\n"
5904 : "void foo() {\n"
5905 : " stat(\"file.txt\", &st);\n"
5906 : " do_something();\n"
5907 : "}");
5908 1 : ASSERT_EQUALS("",errout_str());
5909 :
5910 1 : check("struct AMethodObject {\n" // #4336
5911 : " AMethodObject(double, double, double);\n"
5912 : "};\n"
5913 : "struct S {\n"
5914 : " static void A(double, double, double);\n"
5915 : "};\n"
5916 : "void S::A(double const a1, double const a2, double const a3) {\n"
5917 : " AMethodObject(a1, a2, a3);\n"
5918 : "}\n");
5919 1 : ASSERT_EQUALS("",errout_str());
5920 : }
5921 :
5922 1 : void testMisusedScopeObjectDoesNotPickNestedClass() {
5923 1 : const char code[] = "class ios_base {\n"
5924 : "public:\n"
5925 : " class Init {\n"
5926 : " public:\n"
5927 : " };\n"
5928 : "};\n"
5929 : "class foo {\n"
5930 : "public:\n"
5931 : " foo();\n"
5932 : " void Init(int);\n"
5933 : "};\n"
5934 : "foo::foo() {\n"
5935 : " Init(0);\n"
5936 : " do_something();\n"
5937 : "}\n";
5938 :
5939 1 : check(code, true);
5940 1 : ASSERT_EQUALS("", errout_str());
5941 : }
5942 :
5943 1 : void testMisusedScopeObjectInConstructor() {
5944 1 : const char code[] = "class Foo {\n"
5945 : "public:\n"
5946 : " Foo(char x) {\n"
5947 : " Foo(x, 0);\n"
5948 : " do_something();\n"
5949 : " }\n"
5950 : " Foo(char x, int y) { }\n"
5951 : "};\n";
5952 1 : check(code, true);
5953 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Instance of 'Foo' object is destroyed immediately.\n", errout_str());
5954 : }
5955 :
5956 1 : void testMisusedScopeObjectStandardType() {
5957 1 : check("int g();\n"
5958 : "void f(int i) {\n"
5959 : " int();\n"
5960 : " int(0);\n"
5961 : " int( g() );\n" // don't warn
5962 : " int{};\n"
5963 : " int{ 0 };\n"
5964 : " int{ i };\n"
5965 : " int{ g() };\n" // don't warn
5966 : " g();\n"
5967 : "}\n", true);
5968 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Instance of 'int' object is destroyed immediately.\n"
5969 : "[test.cpp:4]: (style) Instance of 'int' object is destroyed immediately.\n"
5970 : "[test.cpp:6]: (style) Instance of 'int' object is destroyed immediately.\n"
5971 : "[test.cpp:7]: (style) Instance of 'int' object is destroyed immediately.\n"
5972 : "[test.cpp:8]: (style) Instance of 'int' object is destroyed immediately.\n",
5973 : errout_str());
5974 :
5975 1 : check("void f(int j) {\n"
5976 : " for (; bool(j); ) {}\n"
5977 : "}\n", true);
5978 1 : ASSERT_EQUALS("", errout_str());
5979 :
5980 1 : check("void g() {\n"
5981 : " float (f);\n"
5982 : " float (*p);\n"
5983 : "}\n", true);
5984 1 : ASSERT_EQUALS("", errout_str());
5985 :
5986 1 : check("int f(int i) {\n"
5987 : " void();\n"
5988 : " return i;\n"
5989 : "}\n", true);
5990 1 : ASSERT_EQUALS("", errout_str());
5991 : }
5992 :
5993 1 : void testMisusedScopeObjectNamespace() {
5994 1 : check("namespace M {\n" // #4779
5995 : " namespace N {\n"
5996 : " struct S {};\n"
5997 : " }\n"
5998 : "}\n"
5999 : "int f() {\n"
6000 : " M::N::S();\n"
6001 : " return 0;\n"
6002 : "}\n", true);
6003 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Instance of 'M::N::S' object is destroyed immediately.\n", errout_str());
6004 :
6005 1 : check("void f() {\n" // #10057
6006 : " std::string(\"abc\");\n"
6007 : " std::string{ \"abc\" };\n"
6008 : " std::pair<int, int>(1, 2);\n"
6009 : " (void)0;\n"
6010 : "}\n", true);
6011 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Instance of 'std::string' object is destroyed immediately.\n"
6012 : "[test.cpp:3]: (style) Instance of 'std::string' object is destroyed immediately.\n"
6013 : "[test.cpp:4]: (style) Instance of 'std::pair' object is destroyed immediately.\n",
6014 : errout_str());
6015 :
6016 1 : check("struct S {\n" // #10083
6017 : " void f() {\n"
6018 : " std::lock_guard<std::mutex>(m);\n"
6019 : " }\n"
6020 : " void g() {\n"
6021 : " std::scoped_lock<std::mutex>(m);\n"
6022 : " }\n"
6023 : " void h() {\n"
6024 : " std::scoped_lock(m);\n"
6025 : " }\n"
6026 : " std::mutex m;\n"
6027 : "}\n", true);
6028 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Instance of 'std::lock_guard' object is destroyed immediately.\n"
6029 : "[test.cpp:6]: (style) Instance of 'std::scoped_lock' object is destroyed immediately.\n"
6030 : "[test.cpp:9]: (style) Instance of 'std::scoped_lock' object is destroyed immediately.\n",
6031 : errout_str());
6032 :
6033 1 : check("struct S { int i; };\n"
6034 : "namespace {\n"
6035 : " S s() { return ::S{42}; }\n"
6036 : "}\n", true);
6037 1 : ASSERT_EQUALS("", errout_str());
6038 : }
6039 :
6040 1 : void testMisusedScopeObjectAssignment() { // #11371
6041 1 : check("struct S;\n"
6042 : "S f();\n"
6043 : "S& g();\n"
6044 : "S&& h();\n"
6045 : "S* i();\n"
6046 : "void t0() { f() = {}; }\n"
6047 : "void t1() { g() = {}; }\n"
6048 : "void t2() { h() = {}; }\n"
6049 : "void t3() { *i() = {}; }\n", true);
6050 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Instance of 'S' object is destroyed immediately, assignment has no effect.\n", errout_str());
6051 : }
6052 :
6053 1 : void trac2084() {
6054 1 : check("void f()\n"
6055 : "{\n"
6056 : " struct sigaction sa;\n"
6057 : "\n"
6058 : " { sigaction(SIGHUP, &sa, 0); };\n"
6059 : " { sigaction(SIGINT, &sa, 0); };\n"
6060 : "}");
6061 1 : ASSERT_EQUALS("", errout_str());
6062 : }
6063 :
6064 1 : void trac2071() {
6065 1 : check("void f() {\n"
6066 : " struct AB {\n"
6067 : " AB(int a) { }\n"
6068 : " };\n"
6069 : "\n"
6070 : " const AB ab[3] = { AB(0), AB(1), AB(2) };\n"
6071 : "}");
6072 1 : ASSERT_EQUALS("", errout_str());
6073 : }
6074 :
6075 1 : void clarifyCalculation() {
6076 1 : check("int f(char c) {\n"
6077 : " return 10 * (c == 0) ? 1 : 2;\n"
6078 : "}");
6079 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '*' and '?'.\n", errout_str());
6080 :
6081 1 : check("void f(char c) {\n"
6082 : " printf(\"%i\", 10 * (c == 0) ? 1 : 2);\n"
6083 : "}");
6084 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '*' and '?'.\n", errout_str());
6085 :
6086 1 : check("void f() {\n"
6087 : " return (2*a)?b:c;\n"
6088 : "}");
6089 1 : ASSERT_EQUALS("", errout_str());
6090 :
6091 1 : check("void f(char c) {\n"
6092 : " printf(\"%i\", a + b ? 1 : 2);\n"
6093 : "}",true,false,false);
6094 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '+' and '?'.\n", errout_str());
6095 :
6096 1 : check("void f() {\n"
6097 : " std::cout << x << y ? 2 : 3;\n"
6098 : "}");
6099 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '<<' and '?'.\n", errout_str());
6100 :
6101 1 : check("void f() {\n"
6102 : " int ab = a - b ? 2 : 3;\n"
6103 : "}");
6104 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '-' and '?'.\n", errout_str());
6105 :
6106 1 : check("void f() {\n"
6107 : " int ab = a | b ? 2 : 3;\n"
6108 : "}");
6109 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '|' and '?'.\n", errout_str());
6110 :
6111 : // ticket #195
6112 1 : check("int f(int x, int y) {\n"
6113 : " return x >> ! y ? 8 : 2;\n"
6114 : "}");
6115 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Clarify calculation precedence for '>>' and '?'.\n", errout_str());
6116 :
6117 1 : check("int f() {\n"
6118 : " return shift < sizeof(int64_t)*8 ? 1 : 2;\n"
6119 : "}");
6120 1 : ASSERT_EQUALS("", errout_str());
6121 :
6122 1 : check("void f() { a = *p ? 1 : 2; }");
6123 1 : ASSERT_EQUALS("", errout_str());
6124 :
6125 1 : check("void f(int x) { const char *p = x & 1 ? \"1\" : \"0\"; }");
6126 1 : ASSERT_EQUALS("", errout_str());
6127 :
6128 1 : check("void foo() { x = a % b ? \"1\" : \"0\"; }");
6129 1 : ASSERT_EQUALS("", errout_str());
6130 :
6131 1 : check("void f(int x) { return x & 1 ? '1' : '0'; }");
6132 1 : ASSERT_EQUALS("", errout_str());
6133 :
6134 1 : check("void f(int x) { return x & 16 ? 1 : 0; }");
6135 1 : ASSERT_EQUALS("", errout_str());
6136 :
6137 1 : check("void f(int x) { return x % 16 ? 1 : 0; }");
6138 1 : ASSERT_EQUALS("", errout_str());
6139 :
6140 1 : check("enum {X,Y}; void f(int x) { return x & Y ? 1 : 0; }");
6141 1 : ASSERT_EQUALS("", errout_str());
6142 : }
6143 :
6144 1 : void clarifyStatement() {
6145 1 : check("char* f(char* c) {\n"
6146 : " *c++;\n"
6147 : " return c;\n"
6148 : "}");
6149 1 : ASSERT_EQUALS(
6150 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6151 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6152 : errout_str());
6153 :
6154 1 : check("char* f(char** c) {\n"
6155 : " *c[5]--;\n"
6156 : " return *c;\n"
6157 : "}");
6158 1 : ASSERT_EQUALS(
6159 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6160 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6161 : errout_str());
6162 :
6163 1 : check("void f(Foo f) {\n"
6164 : " *f.a++;\n"
6165 : "}");
6166 1 : ASSERT_EQUALS(
6167 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6168 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6169 : errout_str());
6170 :
6171 1 : check("void f(Foo f) {\n"
6172 : " *f.a[5].v[3]++;\n"
6173 : "}");
6174 1 : ASSERT_EQUALS(
6175 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6176 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6177 : errout_str());
6178 :
6179 1 : check("void f(Foo f) {\n"
6180 : " *f.a(1, 5).v[x + y]++;\n"
6181 : "}");
6182 1 : ASSERT_EQUALS(
6183 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6184 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6185 : errout_str());
6186 :
6187 1 : check("char* f(char* c) {\n"
6188 : " (*c)++;\n"
6189 : " return c;\n"
6190 : "}");
6191 1 : ASSERT_EQUALS("", errout_str());
6192 :
6193 1 : check("void f(char* c) {\n"
6194 : " bar(*c++);\n"
6195 : "}");
6196 1 : ASSERT_EQUALS("", errout_str());
6197 :
6198 1 : check("char*** f(char*** c) {\n"
6199 : " ***c++;\n"
6200 : " return c;\n"
6201 : "}");
6202 1 : ASSERT_EQUALS(
6203 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6204 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6205 : errout_str());
6206 :
6207 1 : check("char** f(char*** c) {\n"
6208 : " **c[5]--;\n"
6209 : " return **c;\n"
6210 : "}");
6211 1 : ASSERT_EQUALS(
6212 : "[test.cpp:2]: (warning, inconclusive) Found suspicious operator '*', result is not used.\n"
6213 : "[test.cpp:2]: (warning) In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n",
6214 : errout_str());
6215 :
6216 1 : check("char*** f(char*** c) {\n"
6217 : " (***c)++;\n"
6218 : " return c;\n"
6219 : "}");
6220 1 : ASSERT_EQUALS("", errout_str());
6221 :
6222 1 : check("void f(const int*** p) {\n" // #10923
6223 : " delete[] **p;\n"
6224 : "}\n");
6225 1 : ASSERT_EQUALS("", errout_str());
6226 :
6227 1 : check("void *f(char** c) {\n"
6228 : " bar(**c++);\n"
6229 : "}");
6230 1 : ASSERT_EQUALS("", errout_str());
6231 :
6232 1 : check("void *f(char* p) {\n"
6233 : " for (p = path; *p++;) ;\n"
6234 : "}");
6235 1 : ASSERT_EQUALS("", errout_str());
6236 :
6237 1 : check("void f() {\n"
6238 : " std::array<std::array<double,3>,3> array;\n"
6239 : "}\n");
6240 1 : ASSERT_EQUALS("", errout_str());
6241 :
6242 1 : check("void f(const std::vector<int*>& v) {\n" // #12088
6243 : " for (auto it = v.begin(); it != v.end(); delete *it++);\n"
6244 : "}\n");
6245 1 : ASSERT_EQUALS("", errout_str());
6246 : }
6247 :
6248 1 : void duplicateBranch() {
6249 1 : check("void f(int a, int &b) {\n"
6250 : " if (a)\n"
6251 : " b = 1;\n"
6252 : " else\n"
6253 : " b = 1;\n"
6254 : "}");
6255 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6256 :
6257 1 : check("void f(int a, int &b) {\n"
6258 : " if (a) {\n"
6259 : " if (a == 1)\n"
6260 : " b = 2;\n"
6261 : " else\n"
6262 : " b = 2;\n"
6263 : " } else\n"
6264 : " b = 1;\n"
6265 : "}");
6266 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6267 :
6268 1 : check("void f(int a, int &b) {\n"
6269 : " if (a == 1)\n"
6270 : " b = 1;\n"
6271 : " else {\n"
6272 : " if (a)\n"
6273 : " b = 2;\n"
6274 : " else\n"
6275 : " b = 2;\n"
6276 : " }\n"
6277 : "}");
6278 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6279 :
6280 1 : check("int f(int signed, unsigned char value) {\n"
6281 : " int ret;\n"
6282 : " if (signed)\n"
6283 : " ret = (signed char)value;\n" // cast must be kept so the simplifications and verification is skipped
6284 : " else\n"
6285 : " ret = (unsigned char)value;\n"
6286 : " return ret;\n"
6287 : "}", true, false, false);
6288 1 : ASSERT_EQUALS("", errout_str());
6289 :
6290 1 : check("void f() {\n"
6291 : " if (b)\n"
6292 : " __asm__(\"mov ax, bx\");\n"
6293 : " else\n"
6294 : " __asm__(\"mov bx, bx\");\n"
6295 : "}");
6296 1 : ASSERT_EQUALS("", errout_str()); // #3407
6297 :
6298 1 : check("void f() {\n"
6299 : " if (b)\n"
6300 : " __asm__(\"mov ax, bx\");\n"
6301 : " else\n"
6302 : " __asm__(\"mov ax, bx\");\n"
6303 : "}");
6304 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6305 : }
6306 :
6307 1 : void duplicateBranch1() {
6308 :
6309 : // tests inspired by http://www.viva64.com/en/b/0149/ ( Comparison between PVS-Studio and cppcheck )
6310 : // Errors detected in Quake 3: Arena by PVS-Studio: Fragment 2
6311 1 : check("void f()\n"
6312 : "{\n"
6313 : " if (front < 0)\n"
6314 : " frac = front/(front-back);\n"
6315 : " else\n"
6316 : " frac = front/(front-back);\n"
6317 : "}");
6318 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6319 :
6320 1 : check("void f()\n"
6321 : "{\n"
6322 : " if (front < 0)\n"
6323 : " { frac = front/(front-back);}\n"
6324 : " else\n"
6325 : " frac = front/((front-back));\n"
6326 : "}");
6327 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6328 :
6329 : // No message about empty branches (#5354)
6330 1 : check("void f()\n"
6331 : "{\n"
6332 : " if (front < 0)\n"
6333 : " {}\n"
6334 : " else\n"
6335 : " {}\n"
6336 : "}");
6337 1 : ASSERT_EQUALS("", errout_str());
6338 : }
6339 :
6340 1 : void duplicateBranch2() {
6341 1 : checkP("#define DOSTUFF1 ;\n"
6342 : "#define DOSTUFF2 ;\n"
6343 : "void f(int x) {\n" // #4329
6344 : " if (x)\n"
6345 : " DOSTUFF1\n"
6346 : " else\n"
6347 : " DOSTUFF2\n"
6348 : "}");
6349 1 : ASSERT_EQUALS("", errout_str());
6350 : }
6351 :
6352 1 : void duplicateBranch3() {
6353 1 : check("void f(bool b, int i) {\n"
6354 : " int j = i;\n"
6355 : " if (b) {\n"
6356 : " x = i;\n"
6357 : " } else {\n"
6358 : " x = j;\n"
6359 : " }\n"
6360 : "}");
6361 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n"
6362 : "[test.cpp:2]: (style) The scope of the variable 'j' can be reduced.\n",
6363 : errout_str());
6364 :
6365 1 : check("void f(bool b, int i) {\n"
6366 : " int j = i;\n"
6367 : " i++;\n"
6368 : " if (b) {\n"
6369 : " x = i;\n"
6370 : " } else {\n"
6371 : " x = j;\n"
6372 : " }\n"
6373 : "}");
6374 1 : ASSERT_EQUALS("", errout_str());
6375 : }
6376 :
6377 1 : void duplicateBranch4() {
6378 1 : check("void* f(bool b) {\n"
6379 : " if (b) {\n"
6380 : " return new A::Y(true);\n"
6381 : " } else {\n"
6382 : " return new A::Z(true);\n"
6383 : " }\n"
6384 : "}");
6385 1 : ASSERT_EQUALS("", errout_str());
6386 : }
6387 :
6388 1 : void duplicateBranch5() {
6389 1 : check("void f(bool b) {\n"
6390 : " int j;\n"
6391 : " if (b) {\n"
6392 : " unsigned int i = 0;\n"
6393 : " j = i;\n"
6394 : " } else {\n"
6395 : " unsigned int i = 0;\n"
6396 : " j = i;\n"
6397 : " }\n"
6398 : "}");
6399 1 : ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:3]: (style, inconclusive) Found duplicate branches for 'if' and 'else'.\n", errout_str());
6400 :
6401 1 : check("void f(bool b) {\n"
6402 : " int j;\n"
6403 : " if (b) {\n"
6404 : " unsigned int i = 0;\n"
6405 : " j = i;\n"
6406 : " } else {\n"
6407 : " unsigned int i = 0;\n"
6408 : " j = 1;\n"
6409 : " }\n"
6410 : "}");
6411 1 : ASSERT_EQUALS("", errout_str());
6412 :
6413 1 : check("void f(bool b) {\n"
6414 : " int j;\n"
6415 : " if (b) {\n"
6416 : " unsigned int i = 0;\n"
6417 : " } else {\n"
6418 : " int i = 0;\n"
6419 : " }\n"
6420 : "}");
6421 1 : ASSERT_EQUALS("", errout_str());
6422 :
6423 1 : check("void f(bool b) {\n"
6424 : " int j;\n"
6425 : " if (b) {\n"
6426 : " unsigned int i = 0;\n"
6427 : " j = i;\n"
6428 : " } else {\n"
6429 : " int i = 0;\n"
6430 : " j = i;\n"
6431 : " }\n"
6432 : "}");
6433 1 : ASSERT_EQUALS("", errout_str());
6434 : }
6435 :
6436 1 : void duplicateBranch6() {
6437 1 : check("void f(bool b) {\n"
6438 : " if (b) {\n"
6439 : " } else {\n"
6440 : " int i = 0;\n"
6441 : " }\n"
6442 : "}");
6443 1 : ASSERT_EQUALS("", errout_str());
6444 :
6445 1 : check("void f(bool b) {\n"
6446 : " if (b) {\n"
6447 : " int i = 0;\n"
6448 : " } else {\n"
6449 : " }\n"
6450 : "}");
6451 1 : ASSERT_EQUALS("", errout_str());
6452 : }
6453 :
6454 1 : void duplicateExpression1() {
6455 1 : check("void foo(int a) {\n"
6456 : " if (a == a) { }\n"
6457 : "}");
6458 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6459 :
6460 1 : check("void fun(int b) {\n"
6461 : " return a && a ||\n"
6462 : " b == b &&\n"
6463 : " d > d &&\n"
6464 : " e < e &&\n"
6465 : " f ;\n"
6466 : "}");
6467 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&'.\n"
6468 : "[test.cpp:3]: (style) Same expression on both sides of '=='.\n"
6469 : "[test.cpp:4]: (style) Same expression on both sides of '>'.\n"
6470 : "[test.cpp:5]: (style) Same expression on both sides of '<'.\n", errout_str());
6471 :
6472 1 : check("void foo() {\n"
6473 : " return a && a;\n"
6474 : "}");
6475 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&'.\n", errout_str());
6476 :
6477 1 : check("void foo() {\n"
6478 : " a = b && b;\n"
6479 : "}");
6480 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&'.\n", errout_str());
6481 :
6482 1 : check("void foo(int b) {\n"
6483 : " f(a,b == b);\n"
6484 : "}");
6485 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6486 :
6487 1 : check("void foo(int b) {\n"
6488 : " f(b == b, a);\n"
6489 : "}");
6490 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6491 :
6492 1 : check("void foo() {\n"
6493 : " if (x!=2 || x!=2) {}\n"
6494 : "}");
6495 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6496 :
6497 1 : check("void foo(int a, int b) {\n"
6498 : " if ((a < b) && (b > a)) { }\n"
6499 : "}");
6500 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&' because 'a<b' and 'b>a' represent the same value.\n", errout_str());
6501 :
6502 1 : check("void foo(int a, int b) {\n"
6503 : " if ((a <= b) && (b >= a)) { }\n"
6504 : "}");
6505 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&' because 'a<=b' and 'b>=a' represent the same value.\n", errout_str());
6506 :
6507 1 : check("void foo() {\n"
6508 : " if (x!=2 || y!=3 || x!=2) {}\n"
6509 : "}");
6510 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression 'x!=2' found multiple times in chain of '||' operators.\n", errout_str());
6511 :
6512 1 : check("void foo() {\n"
6513 : " if (x!=2 && (x=y) && x!=2) {}\n"
6514 : "}");
6515 1 : ASSERT_EQUALS("", errout_str());
6516 :
6517 1 : check("void foo() {\n"
6518 : " if (a && b || a && b) {}\n"
6519 : "}");
6520 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6521 :
6522 1 : check("void foo() {\n"
6523 : " if (a && b || b && c) {}\n"
6524 : "}");
6525 1 : ASSERT_EQUALS("", errout_str());
6526 :
6527 1 : check("void foo() {\n"
6528 : " if (a && b | b && c) {}\n"
6529 : "}");
6530 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '|'.\n", errout_str());
6531 :
6532 1 : check("void foo() {\n"
6533 : " if ((a + b) | (a + b)) {}\n"
6534 : "}");
6535 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '|'.\n", errout_str());
6536 :
6537 1 : check("void foo() {\n"
6538 : " if ((a | b) & (a | b)) {}\n"
6539 : "}");
6540 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&'.\n", errout_str());
6541 :
6542 1 : check("void foo(int a, int b) {\n"
6543 : " if ((a | b) == (a | b)) {}\n"
6544 : "}");
6545 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6546 :
6547 1 : check("void foo() {\n"
6548 : " if (a1[a2[c & 0xff] & 0xff]) {}\n"
6549 : "}");
6550 1 : ASSERT_EQUALS("", errout_str());
6551 :
6552 1 : check("void d(const char f, int o, int v)\n"
6553 : "{\n"
6554 : " if (((f=='R') && (o == 1) && ((v < 2) || (v > 99))) ||\n"
6555 : " ((f=='R') && (o == 2) && ((v < 2) || (v > 99))) ||\n"
6556 : " ((f=='T') && (o == 2) && ((v < 200) || (v > 9999)))) {}\n"
6557 : "}");
6558 1 : ASSERT_EQUALS("", errout_str());
6559 :
6560 1 : check("int f(int x) { return x+x; }");
6561 1 : ASSERT_EQUALS("", errout_str());
6562 :
6563 1 : check("void f(int x) { while (x+=x) ; }");
6564 1 : ASSERT_EQUALS("", errout_str());
6565 :
6566 1 : check("void foo() {\n"
6567 : " if (a && b && b) {}\n"
6568 : "}");
6569 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&'.\n", errout_str());
6570 :
6571 1 : check("void foo() {\n"
6572 : " if (a || b || b) {}\n"
6573 : "}");
6574 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6575 :
6576 1 : check("void foo() {\n"
6577 : " if (a / 1000 / 1000) {}\n"
6578 : "}");
6579 1 : ASSERT_EQUALS("", errout_str());
6580 :
6581 1 : check("int foo(int i) {\n"
6582 : " return i/i;\n"
6583 : "}");
6584 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '/'.\n", errout_str());
6585 :
6586 1 : check("void foo() {\n"
6587 : " if (a << 1 << 1) {}\n"
6588 : "}");
6589 1 : ASSERT_EQUALS("", errout_str());
6590 :
6591 1 : check("int f() { return !!y; }"); // No FP
6592 1 : ASSERT_EQUALS("", errout_str());
6593 :
6594 : // make sure there are not "same expression" fp when there are different casts
6595 1 : check("void f(long x) { if ((int32_t)x == (int64_t)x) {} }",
6596 : true, // filename
6597 : false, // inconclusive
6598 : false, // runSimpleChecks
6599 : false, // verbose
6600 : nullptr // settings
6601 : );
6602 1 : ASSERT_EQUALS("", errout_str());
6603 :
6604 : // make sure there are not "same expression" fp when there are different ({}) expressions
6605 1 : check("void f(long x) { if (({ 1+2; }) == ({3+4;})) {} }");
6606 1 : ASSERT_EQUALS("", errout_str());
6607 :
6608 : // #5535: Reference named like its type
6609 1 : check("void foo() { UMSConfig& UMSConfig = GetUMSConfiguration(); }");
6610 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Variable 'UMSConfig' can be declared as reference to const\n", errout_str());
6611 :
6612 : // #3868 - false positive (same expression on both sides of |)
6613 1 : check("void f(int x) {\n"
6614 : " a = x ? A | B | C\n"
6615 : " : A | B;\n"
6616 : "}");
6617 1 : ASSERT_EQUALS("", errout_str());
6618 :
6619 1 : check("void f(const Bar &bar) {\n"
6620 : " bool a = bar.isSet() && bar->isSet();\n"
6621 : " bool b = bar.isSet() && bar.isSet();\n"
6622 : "}");
6623 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Same expression on both sides of '&&'.\n", errout_str());
6624 :
6625 :
6626 1 : check("void foo(int a, int b) {\n"
6627 : " if ((b + a) | (a + b)) {}\n"
6628 : "}");
6629 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '|' because 'b+a' and 'a+b' represent the same value.\n", errout_str());
6630 :
6631 1 : check("void foo(const std::string& a, const std::string& b) {\n"
6632 : " return a.find(b+\"&\") || a.find(\"&\"+b);\n"
6633 : "}");
6634 1 : ASSERT_EQUALS("", errout_str());
6635 :
6636 1 : check("void foo(int a, int b) {\n"
6637 : " if ((b > a) | (a > b)) {}\n" // > is not commutative
6638 : "}");
6639 1 : ASSERT_EQUALS("", errout_str());
6640 :
6641 1 : check("void foo(double a, double b) {\n"
6642 : " if ((b + a) > (a + b)) {}\n"
6643 : "}");
6644 1 : ASSERT_EQUALS("[test.cpp:2]: (style) The comparison 'b+a > a+b' is always false because 'b+a' and 'a+b' represent the same value.\n", errout_str());
6645 :
6646 1 : check("void f(int x) {\n"
6647 : " if ((x == 1) && (x == 0x00000001))\n"
6648 : " a++;\n"
6649 : "}");
6650 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '&&' because 'x==1' and 'x==0x00000001' represent the same value.\n", errout_str());
6651 :
6652 1 : check("void f() {\n"
6653 : " enum { Four = 4 };\n"
6654 : " if (Four == 4) {}"
6655 : "}", true, true, false);
6656 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The comparison 'Four == 4' is always true.\n",
6657 : errout_str());
6658 :
6659 1 : check("void f() {\n"
6660 : " enum { Four = 4 };\n"
6661 : " static_assert(Four == 4, \"\");\n"
6662 : "}");
6663 1 : ASSERT_EQUALS("", errout_str());
6664 :
6665 1 : check("void f() {\n"
6666 : " enum { Four = 4 };\n"
6667 : " static_assert(4 == Four, \"\");\n"
6668 : "}");
6669 1 : ASSERT_EQUALS("", errout_str());
6670 :
6671 1 : check("void f() {\n"
6672 : " enum { FourInEnumOne = 4 };\n"
6673 : " enum { FourInEnumTwo = 4 };\n"
6674 : " if (FourInEnumOne == FourInEnumTwo) {}\n"
6675 : "}", true, true, false);
6676 1 : ASSERT_EQUALS("[test.cpp:4]: (style) The comparison 'FourInEnumOne == FourInEnumTwo' is always true because 'FourInEnumOne' and 'FourInEnumTwo' represent the same value.\n",
6677 : errout_str());
6678 :
6679 1 : check("void f() {\n"
6680 : " enum { FourInEnumOne = 4 };\n"
6681 : " enum { FourInEnumTwo = 4 };\n"
6682 : " static_assert(FourInEnumOne == FourInEnumTwo, \"\");\n"
6683 : "}");
6684 1 : ASSERT_EQUALS("", errout_str());
6685 :
6686 1 : check("void foo(int a, int b) {\n"
6687 : " if (sizeof(a) == sizeof(a)) { }\n"
6688 : " if (sizeof(a) == sizeof(b)) { }\n"
6689 : "}");
6690 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6691 :
6692 1 : check("float bar(int) __attribute__((pure));\n"
6693 : "char foo(int) __attribute__((pure));\n"
6694 : "int test(int a, int b) {\n"
6695 : " if (bar(a) == bar(a)) { }\n"
6696 : " if (unknown(a) == unknown(a)) { }\n"
6697 : " if (foo(a) == foo(a)) { }\n"
6698 : "}");
6699 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Same expression on both sides of '=='.\n", errout_str());
6700 : }
6701 :
6702 1 : void duplicateExpression2() { // check if float is NaN or Inf
6703 1 : check("int f(long double ldbl, double dbl, float flt) {\n" // ticket #2730
6704 : " if (ldbl != ldbl) have_nan = 1;\n"
6705 : " if (!(dbl == dbl)) have_nan = 1;\n"
6706 : " if (flt != flt) have_nan = 1;\n"
6707 : " return have_nan;\n"
6708 : "}");
6709 1 : ASSERT_EQUALS("", errout_str());
6710 :
6711 1 : check("float f(float x) { return x-x; }"); // ticket #4485 (Inf)
6712 1 : ASSERT_EQUALS("", errout_str());
6713 :
6714 1 : check("float f(float x) { return (X double)x == (X double)x; }", true, false, false);
6715 1 : ASSERT_EQUALS("", errout_str());
6716 :
6717 1 : check("struct X { float f; };\n"
6718 : "float f(struct X x) { return x.f == x.f; }");
6719 1 : ASSERT_EQUALS("", errout_str());
6720 :
6721 1 : check("struct X { int i; };\n"
6722 : "int f(struct X x) { return x.i == x.i; }");
6723 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout_str());
6724 :
6725 : // #5284 - when type is unknown, assume it's float
6726 1 : check("int f() { return x==x; }");
6727 1 : ASSERT_EQUALS("", errout_str());
6728 : }
6729 :
6730 1 : void duplicateExpression3() {
6731 1 : constexpr char xmldata[] = "<?xml version=\"1.0\"?>\n"
6732 : "<def>\n"
6733 : " <function name=\"mystrcmp\">\n"
6734 : " <pure/>\n"
6735 : " <arg nr=\"1\"/>\n"
6736 : " <arg nr=\"2\"/>\n"
6737 : " </function>\n"
6738 : "</def>";
6739 1 : /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata, sizeof(xmldata)).build();
6740 :
6741 1 : check("void foo() {\n"
6742 : " if (x() || x()) {}\n"
6743 : "}");
6744 1 : ASSERT_EQUALS("", errout_str());
6745 :
6746 1 : check("struct A {\n"
6747 : " void foo() const;\n"
6748 : " bool bar() const;\n"
6749 : "};\n"
6750 : "void A::foo() const {\n"
6751 : " if (bar() && bar()) {}\n"
6752 : "}");
6753 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Same expression on both sides of '&&'.\n", errout_str());
6754 :
6755 1 : check("struct A {\n"
6756 : " void foo();\n"
6757 : " bool bar();\n"
6758 : " bool bar() const;\n"
6759 : "};\n"
6760 : "void A::foo() {\n"
6761 : " if (bar() && bar()) {}\n"
6762 : "}");
6763 1 : ASSERT_EQUALS("", errout_str());
6764 :
6765 1 : check("class B {\n"
6766 : " void bar(int i);\n"
6767 : "};\n"
6768 : "class A {\n"
6769 : " void bar(int i) const;\n"
6770 : "};\n"
6771 : "void foo() {\n"
6772 : " B b;\n"
6773 : " A a;\n"
6774 : " if (b.bar(1) && b.bar(1)) {}\n"
6775 : " if (a.bar(1) && a.bar(1)) {}\n"
6776 : "}");
6777 1 : ASSERT_EQUALS("[test.cpp:11]: (style) Same expression on both sides of '&&'.\n", errout_str());
6778 :
6779 1 : check("class D { void strcmp(); };\n"
6780 : "void foo() {\n"
6781 : " D d;\n"
6782 : " if (d.strcmp() && d.strcmp()) {}\n"
6783 : "}");
6784 1 : ASSERT_EQUALS("", errout_str());
6785 :
6786 1 : check("void foo() {\n"
6787 : " if ((mystrcmp(a, b) == 0) || (mystrcmp(a, b) == 0)) {}\n"
6788 : "}", true, false, true, false, &settings);
6789 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6790 :
6791 1 : check("void GetValue() { return rand(); }\n"
6792 : "void foo() {\n"
6793 : " if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n"
6794 : "}");
6795 1 : ASSERT_EQUALS("", errout_str());
6796 :
6797 1 : check("void __attribute__((const)) GetValue() { return X; }\n"
6798 : "void foo() {\n"
6799 : " if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n"
6800 : "}");
6801 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Same expression on both sides of '||'.\n", errout_str());
6802 :
6803 1 : check("void GetValue() __attribute__((const));\n"
6804 : "void GetValue() { return X; }\n"
6805 : "void foo() {\n"
6806 : " if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n"
6807 : "}");
6808 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Same expression on both sides of '||'.\n", errout_str());
6809 :
6810 1 : check("void foo() {\n"
6811 : " if (str == \"(\" || str == \"(\") {}\n"
6812 : "}");
6813 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6814 :
6815 1 : check("void foo() {\n"
6816 : " if (bar(a) && !strcmp(a, b) && bar(a) && !strcmp(a, b)) {}\n"
6817 : "}");
6818 1 : ASSERT_EQUALS("", errout_str());
6819 :
6820 : // #5334
6821 1 : check("void f(C *src) {\n"
6822 : " if (x<A*>(src) || x<B*>(src))\n"
6823 : " a++;\n"
6824 : "}");
6825 1 : ASSERT_EQUALS("", errout_str());
6826 :
6827 1 : check("void f(A *src) {\n"
6828 : " if (dynamic_cast<B*>(src) || dynamic_cast<B*>(src)) {}\n"
6829 : "}\n", true, false, false); // don't run simplifications
6830 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout_str());
6831 :
6832 : // #5819
6833 1 : check("Vector func(Vector vec1) {\n"
6834 : " return fabs(vec1 & vec1 & vec1);\n"
6835 : "}");
6836 1 : ASSERT_EQUALS("", errout_str());
6837 :
6838 1 : check("Vector func(int vec1) {\n"
6839 : " return fabs(vec1 & vec1 & vec1);\n"
6840 : "}");
6841 1 : ASSERT_EQUALS(
6842 : "[test.cpp:2]: (style) Same expression on both sides of '&'.\n"
6843 : "[test.cpp:2]: (style) Same expression on both sides of '&'.\n", // duplicate
6844 : errout_str());
6845 :
6846 : }
6847 :
6848 1 : void duplicateExpression4() {
6849 1 : check("void foo() {\n"
6850 : " if (*a++ != b || *a++ != b) {}\n"
6851 : "}");
6852 1 : ASSERT_EQUALS("", errout_str());
6853 :
6854 1 : check("void foo() {\n"
6855 : " if (*a-- != b || *a-- != b) {}\n"
6856 : "}");
6857 1 : ASSERT_EQUALS("", errout_str());
6858 :
6859 : // assignment
6860 1 : check("void f() {\n"
6861 : " while (*(a+=2)==*(b+=2) && *(a+=2)==*(b+=2)) {}\n"
6862 : "}");
6863 1 : ASSERT_EQUALS("", errout_str());
6864 : }
6865 :
6866 1 : void duplicateExpression5() { // #3749 - macros with same values
6867 1 : check("void f() {\n"
6868 : " if ($a == $a) { }\n"
6869 : "}");
6870 1 : ASSERT_EQUALS("", errout_str());
6871 : }
6872 :
6873 1 : void duplicateExpression6() { // #4639
6874 1 : check("float IsNan(float value) { return !(value == value); }\n"
6875 : "double IsNan(double value) { return !(value == value); }\n"
6876 : "long double IsNan(long double value) { return !(value == value); }");
6877 1 : ASSERT_EQUALS("", errout_str());
6878 : }
6879 :
6880 1 : void duplicateExpression7() {
6881 1 : check("void f() {\n"
6882 : " const int i = sizeof(int);\n"
6883 : " if ( i != sizeof (int)){}\n"
6884 : "}");
6885 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'i != sizeof(int)' is always false because 'i' and 'sizeof(int)' represent the same value.\n", errout_str());
6886 :
6887 1 : check("void f() {\n"
6888 : " const int i = sizeof(int);\n"
6889 : " if ( sizeof (int) != i){}\n"
6890 : "}");
6891 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'sizeof(int) != i' is always false because 'sizeof(int)' and 'i' represent the same value.\n", errout_str());
6892 :
6893 1 : check("void f(int a = 1) { if ( a != 1){}}");
6894 1 : ASSERT_EQUALS("", errout_str());
6895 :
6896 1 : check("void f() {\n"
6897 : " int a = 1;\n"
6898 : " if ( a != 1){}\n"
6899 : "}");
6900 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'a != 1' is always false.\n", errout_str());
6901 :
6902 1 : check("void f() {\n"
6903 : " int a = 1;\n"
6904 : " int b = 1;\n"
6905 : " if ( a != b){}\n"
6906 : "}");
6907 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:4]: (style) The comparison 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout_str());
6908 :
6909 1 : check("void f() {\n"
6910 : " int a = 1;\n"
6911 : " int b = a;\n"
6912 : " if ( a != b){}\n"
6913 : "}");
6914 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The comparison 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout_str());
6915 :
6916 1 : check("void use(int);\n"
6917 : "void f() {\n"
6918 : " int a = 1;\n"
6919 : " int b = 1;\n"
6920 : " use(b);\n"
6921 : " if ( a != 1){}\n"
6922 : "}");
6923 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) The comparison 'a != 1' is always false.\n", errout_str());
6924 :
6925 1 : check("void use(int);\n"
6926 : "void f() {\n"
6927 : " int a = 1;\n"
6928 : " use(a);\n"
6929 : " a = 2;\n"
6930 : " if ( a != 1){}\n"
6931 : "}");
6932 1 : ASSERT_EQUALS("", errout_str());
6933 :
6934 1 : check("void use(int);\n"
6935 : "void f() {\n"
6936 : " int a = 2;\n"
6937 : " use(a);\n"
6938 : " a = 1;\n"
6939 : " if ( a != 1){}\n"
6940 : "}");
6941 1 : ASSERT_EQUALS("", errout_str());
6942 :
6943 1 : check("const int a = 1;\n"
6944 : "void f() {\n"
6945 : " if ( a != 1){}\n"
6946 : "}");
6947 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:3]: (style) The comparison 'a != 1' is always false.\n", errout_str());
6948 :
6949 1 : check("int a = 1;\n"
6950 : " void f() {\n"
6951 : " if ( a != 1){}\n"
6952 : "}");
6953 1 : ASSERT_EQUALS("", errout_str());
6954 :
6955 1 : check("void f() {\n"
6956 : " static const int a = 1;\n"
6957 : " if ( a != 1){}\n"
6958 : "}");
6959 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'a != 1' is always false.\n", errout_str());
6960 :
6961 1 : check("void f() {\n"
6962 : " static int a = 1;\n"
6963 : " if ( a != 1){}\n"
6964 : "}");
6965 1 : ASSERT_EQUALS("", errout_str());
6966 :
6967 1 : check("void f() {\n"
6968 : " int a = 1;\n"
6969 : " if ( a != 1){\n"
6970 : " a++;\n"
6971 : " }}");
6972 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'a != 1' is always false.\n", errout_str());
6973 :
6974 1 : check("void f(int b) {\n"
6975 : " int a = 1;\n"
6976 : " while (b) {\n"
6977 : " if ( a != 1){}\n"
6978 : " a++;\n"
6979 : " }\n"
6980 : "}");
6981 1 : ASSERT_EQUALS("", errout_str());
6982 :
6983 1 : check("bool f(bool a, bool b) {\n"
6984 : " const bool c = a;\n"
6985 : " return a && b && c;\n"
6986 : "}");
6987 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression 'a' found multiple times in chain of '&&' operators because 'a' and 'c' represent the same value.\n",
6988 : errout_str());
6989 :
6990 : // 6906
6991 1 : check("void f(const bool b) {\n"
6992 : " const bool b1 = !b;\n"
6993 : " if(!b && b1){}\n"
6994 : "}");
6995 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression on both sides of '&&' because '!b' and 'b1' represent the same value.\n", errout_str());
6996 :
6997 : // 7284
6998 1 : check("void f(void) {\n"
6999 : " if (a || !!a) {}\n"
7000 : "}");
7001 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because 'a' and '!!a' represent the same value.\n", errout_str());
7002 :
7003 : // 8205
7004 1 : check("void f(int x) {\n"
7005 : " int Diag = 0;\n"
7006 : " switch (x) {\n"
7007 : " case 12:\n"
7008 : " if (Diag==0) {}\n"
7009 : " break;\n"
7010 : " }\n"
7011 : "}");
7012 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (style) The comparison 'Diag == 0' is always true.\n", errout_str());
7013 :
7014 : // #9744
7015 1 : check("void f(const std::vector<int>& ints) {\n"
7016 : " int i = 0;\n"
7017 : " for (int p = 0; i < ints.size(); ++i) {\n"
7018 : " if (p == 0) {}\n"
7019 : " }\n"
7020 : "}\n");
7021 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The comparison 'p == 0' is always true.\n", errout_str());
7022 :
7023 : // #11820
7024 1 : check("unsigned f(unsigned x) {\n"
7025 : " return x - !!x;\n"
7026 : "}\n"
7027 : "unsigned g(unsigned x) {\n"
7028 : " return !!x - x;\n"
7029 : "}\n");
7030 1 : ASSERT_EQUALS("", errout_str());
7031 : }
7032 :
7033 1 : void duplicateExpression8() {
7034 1 : check("void f() {\n"
7035 : " int a = 1;\n"
7036 : " int b = a;\n"
7037 : " a = 2;\n"
7038 : " if ( b != a){}\n"
7039 : "}");
7040 1 : ASSERT_EQUALS("", errout_str());
7041 :
7042 1 : check("void f(int * a, int i) { int b = a[i]; a[i] = 2; if ( b != a[i]){}}");
7043 1 : ASSERT_EQUALS("", errout_str());
7044 :
7045 1 : check("void f(int * a, int i) { int b = *a; *a = 2; if ( b != *a){}}");
7046 1 : ASSERT_EQUALS("", errout_str());
7047 :
7048 1 : check("struct A { int f() const; };\n"
7049 : "A g();\n"
7050 : "void foo() {\n"
7051 : " for (A x = A();;) {\n"
7052 : " const int a = x.f();\n"
7053 : " x = g();\n"
7054 : " if (x.f() == a) break;\n"
7055 : " }\n"
7056 : "}");
7057 1 : ASSERT_EQUALS("", errout_str());
7058 :
7059 1 : check("int f(int i);\n"
7060 : "struct A {\n"
7061 : " enum E { B, C };\n"
7062 : " bool f(E);\n"
7063 : "};\n"
7064 : "void foo() {\n"
7065 : " A a;\n"
7066 : " const bool x = a.f(A::B);\n"
7067 : " const bool y = a.f(A::C);\n"
7068 : " if(!x && !y) return;\n"
7069 : "}");
7070 1 : ASSERT_EQUALS("", errout_str());
7071 :
7072 1 : check("void foo() {\n"
7073 : " const bool x = a.f(A::B);\n"
7074 : " const bool y = a.f(A::C);\n"
7075 : " if (!x && !y) return;\n"
7076 : "}");
7077 1 : ASSERT_EQUALS("", errout_str());
7078 :
7079 1 : check("void f(bool * const b);\n"
7080 : "void foo() {\n"
7081 : " bool x = true;\n"
7082 : " bool y = true;\n"
7083 : " f(&x);\n"
7084 : " if (!x && !y) return;\n"
7085 : "}");
7086 1 : ASSERT_EQUALS("", errout_str());
7087 :
7088 1 : check("void f() {\n"
7089 : " const int a = {};\n"
7090 : " if(a == 1) {}\n"
7091 : "}");
7092 1 : ASSERT_EQUALS("", errout_str());
7093 :
7094 1 : check("volatile const int var = 42;\n"
7095 : "void f() { if(var == 42) {} }");
7096 1 : ASSERT_EQUALS("", errout_str());
7097 :
7098 1 : check("void f() {\n"
7099 : " int a = 0;\n"
7100 : " struct b c;\n"
7101 : " c.a = &a;\n"
7102 : " g(&c);\n"
7103 : " if (a == 0) {}\n"
7104 : "}");
7105 1 : ASSERT_EQUALS("", errout_str());
7106 : }
7107 :
7108 1 : void duplicateExpression9() {
7109 : // #9320
7110 1 : check("void f() {\n"
7111 : " uint16_t x = 1000;\n"
7112 : " uint8_t y = x;\n"
7113 : " if (x != y) {}\n"
7114 : "}");
7115 1 : ASSERT_EQUALS("", errout_str());
7116 : }
7117 :
7118 1 : void duplicateExpression10() {
7119 : // #9485
7120 1 : check("int f() {\n"
7121 : " const int a = 1;\n"
7122 : " const int b = a-1;\n"
7123 : " const int c = a+1;\n"
7124 : " return c;\n"
7125 : "}");
7126 1 : ASSERT_EQUALS("", errout_str());
7127 : }
7128 :
7129 1 : void duplicateExpression11() {
7130 1 : check("class Fred {\n"
7131 : "public:\n"
7132 : " double getScale() const { return m_range * m_zoom; }\n"
7133 : " void setZoom(double z) { m_zoom = z; }\n"
7134 : " void dostuff(int);\n"
7135 : "private:\n"
7136 : " double m_zoom;\n"
7137 : " double m_range;\n"
7138 : "};\n"
7139 : "\n"
7140 : "void Fred::dostuff(int x) {\n"
7141 : " if (x == 43) {\n"
7142 : " double old_scale = getScale();\n"
7143 : " setZoom(m_zoom + 1);\n"
7144 : " double scale_ratio = getScale() / old_scale;\n" // <- FP
7145 : " }\n"
7146 : "}");
7147 1 : ASSERT_EQUALS("", errout_str());
7148 : }
7149 :
7150 1 : void duplicateExpression12() { //#10026
7151 1 : check("int f(const std::vector<int> &buffer, const uint8_t index)\n"
7152 : "{\n"
7153 : " int var = buffer[index - 1];\n"
7154 : " return buffer[index - 1] - var;\n" // <<
7155 : "}");
7156 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Same expression on both sides of '-' because 'buffer[index-1]' and 'var' represent the same value.\n", errout_str());
7157 : }
7158 :
7159 1 : void duplicateExpression13() { //#7899
7160 1 : check("void f() {\n"
7161 : " if (sizeof(long) == sizeof(long long)) {}\n"
7162 : "}");
7163 1 : ASSERT_EQUALS("", errout_str());
7164 : }
7165 :
7166 1 : void duplicateExpression14() { //#9871
7167 1 : check("int f() {\n"
7168 : " int k = 7;\n"
7169 : " int* f = &k;\n"
7170 : " int* g = &k;\n"
7171 : " return (f + 4 != g + 4);\n"
7172 : "}\n");
7173 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4] -> [test.cpp:5]: (style) The comparison 'f+4 != g+4' is always false because 'f+4' and 'g+4' represent the same value.\n", errout_str());
7174 : }
7175 :
7176 1 : void duplicateExpression15() { //#10650
7177 1 : check("bool f() {\n"
7178 : " const int i = int(0);\n"
7179 : " return i == 0;\n"
7180 : "}\n"
7181 : "bool g() {\n"
7182 : " const int i = int{ 0 };\n"
7183 : " return i == 0;\n"
7184 : "}\n");
7185 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'i == 0' is always true.\n"
7186 : "[test.cpp:6] -> [test.cpp:7]: (style) The comparison 'i == 0' is always true.\n",
7187 : errout_str());
7188 : }
7189 :
7190 1 : void duplicateExpression16() {
7191 1 : check("void f(const std::string& a) {\n" //#10569
7192 : " if ((a == \"x\") ||\n"
7193 : " (a == \"42\") ||\n"
7194 : " (a == \"y\") ||\n"
7195 : " (a == \"42\")) {}\n"
7196 : "}\n"
7197 : "void g(const std::string& a) {\n"
7198 : " if ((a == \"42\") ||\n"
7199 : " (a == \"x\") ||\n"
7200 : " (a == \"42\") ||\n"
7201 : " (a == \"y\")) {}\n"
7202 : "}\n"
7203 : "void h(const std::string& a) {\n"
7204 : " if ((a == \"42\") ||\n"
7205 : " (a == \"x\") ||\n"
7206 : " (a == \"y\") ||\n"
7207 : " (a == \"42\")) {}\n"
7208 : "}\n");
7209 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:4]: (style) Same expression 'a==\"42\"' found multiple times in chain of '||' operators.\n"
7210 : "[test.cpp:7] -> [test.cpp:9]: (style) Same expression 'a==\"42\"' found multiple times in chain of '||' operators.\n"
7211 : "[test.cpp:13] -> [test.cpp:16]: (style) Same expression 'a==\"42\"' found multiple times in chain of '||' operators.\n",
7212 : errout_str());
7213 :
7214 1 : check("void f(const char* s) {\n" // #6371
7215 : " if (*s == '\x0F') {\n"
7216 : " if (!s[1] || !s[2] || !s[1])\n"
7217 : " break;\n"
7218 : " }\n"
7219 : "}\n");
7220 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Same expression '!s[1]' found multiple times in chain of '||' operators.\n", errout_str());
7221 : }
7222 :
7223 1 : void duplicateExpression17() {
7224 1 : check("enum { E0 };\n" // #12036
7225 : "void f() {\n"
7226 : " if (0 > E0) {}\n"
7227 : " if (E0 > 0) {}\n"
7228 : " if (E0 == 0) {}\n"
7229 : "}\n");
7230 1 : ASSERT_EQUALS("[test.cpp:3]: (style) The comparison '0 > E0' is always false.\n"
7231 : "[test.cpp:4]: (style) The comparison 'E0 > 0' is always false.\n"
7232 : "[test.cpp:5]: (style) The comparison 'E0 == 0' is always true.\n",
7233 : errout_str());
7234 :
7235 1 : check("struct S {\n" // #12040, #12044
7236 : " static const int I = 0;\n"
7237 : " enum { E0 };\n"
7238 : " enum F { F0 };\n"
7239 : " void f() {\n"
7240 : " if (0 > I) {}\n"
7241 : " if (0 > S::I) {}\n"
7242 : " if (0 > E0) {}\n"
7243 : " if (0 > S::E0) {}\n"
7244 : " }\n"
7245 : "};\n"
7246 : "void g() {\n"
7247 : " if (0 > S::I) {}\n"
7248 : " if (0 > S::E0) {}\n"
7249 : " if (0 > S::F::F0) {}\n"
7250 : "}\n");
7251 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:6]: (style) The comparison '0 > I' is always false.\n"
7252 : "[test.cpp:2] -> [test.cpp:7]: (style) The comparison '0 > S::I' is always false.\n"
7253 : "[test.cpp:8]: (style) The comparison '0 > E0' is always false.\n"
7254 : "[test.cpp:9]: (style) The comparison '0 > S::E0' is always false.\n"
7255 : "[test.cpp:2] -> [test.cpp:13]: (style) The comparison '0 > S::I' is always false.\n"
7256 : "[test.cpp:14]: (style) The comparison '0 > S::E0' is always false.\n"
7257 : "[test.cpp:15]: (style) The comparison '0 > S::F::F0' is always false.\n",
7258 : errout_str());
7259 :
7260 1 : check("template<typename T, typename U>\n" // #12122
7261 : "void f() {\n"
7262 : " static_assert(std::is_same<T, U>::value || std::is_integral<T>::value);\n"
7263 : "}\n");
7264 1 : ASSERT_EQUALS("", errout_str());
7265 : }
7266 :
7267 1 : void duplicateExpressionLoop() {
7268 1 : check("void f() {\n"
7269 : " int a = 1;\n"
7270 : " while ( a != 1){}\n"
7271 : "}");
7272 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'a != 1' is always false.\n", errout_str());
7273 :
7274 1 : check("void f() { int a = 1; while ( a != 1){ a++; }}");
7275 1 : ASSERT_EQUALS("", errout_str());
7276 :
7277 1 : check("void f() { int a = 1; for ( int i=0; i < 3 && a != 1; i++){ a++; }}");
7278 1 : ASSERT_EQUALS("", errout_str());
7279 :
7280 1 : check("void f(int b) { int a = 1; while (b) { if ( a != 1){} b++; } a++; }");
7281 1 : ASSERT_EQUALS("", errout_str());
7282 :
7283 1 : check("void f() {\n"
7284 : " for(int i = 0; i < 10;) {\n"
7285 : " if( i != 0 ) {}\n"
7286 : " }\n"
7287 : "}");
7288 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'i != 0' is always false.\n", errout_str());
7289 :
7290 1 : check("void f() {\n"
7291 : " for(int i = 0; i < 10;) {\n"
7292 : " if( i != 0 ) {}\n"
7293 : " i++;\n"
7294 : " }\n"
7295 : "}");
7296 1 : ASSERT_EQUALS("", errout_str());
7297 :
7298 1 : check("void f() {\n"
7299 : " for(int i = 0; i < 10;) {\n"
7300 : " if( i != 0 ) { i++; }\n"
7301 : " i++;\n"
7302 : " }\n"
7303 : "}");
7304 1 : ASSERT_EQUALS("", errout_str());
7305 :
7306 1 : check("void f() {\n"
7307 : " for(int i = 0; i < 10;) {\n"
7308 : " if( i != 0 ) { i++; }\n"
7309 : " }\n"
7310 : "}");
7311 1 : ASSERT_EQUALS("", errout_str());
7312 :
7313 1 : check("void f() {\n"
7314 : " int i = 0;\n"
7315 : " while(i < 10) {\n"
7316 : " if( i != 0 ) {}\n"
7317 : " i++;\n"
7318 : " }\n"
7319 : "}");
7320 1 : ASSERT_EQUALS("", errout_str());
7321 :
7322 1 : check("void f(int b) {\n"
7323 : " while (b) {\n"
7324 : " int a = 1;\n"
7325 : " if ( a != 1){}\n"
7326 : " b++;\n"
7327 : " }\n"
7328 : "}");
7329 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The comparison 'a != 1' is always false.\n", errout_str());
7330 :
7331 1 : check("struct T {\n" // #11083
7332 : " std::string m;\n"
7333 : " const std::string & str() const { return m; }\n"
7334 : " T* next();\n"
7335 : "};\n"
7336 : "void f(T* t) {\n"
7337 : " const std::string& s = t->str();\n"
7338 : " while (t && t->str() == s)\n"
7339 : " t = t->next();\n"
7340 : " do {\n"
7341 : " t = t->next();\n"
7342 : " } while (t && t->str() == s);\n"
7343 : " for (; t && t->str() == s; t = t->next());\n"
7344 : "}\n");
7345 1 : ASSERT_EQUALS("", errout_str());
7346 : }
7347 :
7348 1 : void duplicateExpressionTernary() { // #6391
7349 1 : check("void f() {\n"
7350 : " return A ? x : x;\n"
7351 : "}");
7352 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression in both branches of ternary operator.\n", errout_str());
7353 :
7354 1 : check("int f(bool b, int a) {\n"
7355 : " const int c = a;\n"
7356 : " return b ? a : c;\n"
7357 : "}");
7358 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression in both branches of ternary operator.\n", errout_str());
7359 :
7360 1 : check("void f() {\n"
7361 : " return A ? x : z;\n"
7362 : "}");
7363 1 : ASSERT_EQUALS("", errout_str());
7364 :
7365 1 : check("void f(unsigned char c) {\n"
7366 : " x = y ? (signed char)c : (unsigned char)c;\n"
7367 : "}");
7368 1 : ASSERT_EQUALS("", errout_str());
7369 :
7370 1 : check("std::string stringMerge(std::string const& x, std::string const& y) {\n" // #7938
7371 : " return ((x > y) ? (y + x) : (x + y));\n"
7372 : "}");
7373 1 : ASSERT_EQUALS("", errout_str());
7374 :
7375 : // #6426
7376 : {
7377 1 : const char code[] = "void foo(bool flag) {\n"
7378 : " bar( (flag) ? ~0u : ~0ul);\n"
7379 : "}";
7380 1 : /*const*/ Settings settings = _settings;
7381 1 : settings.platform.sizeof_int = 4;
7382 1 : settings.platform.int_bit = 32;
7383 :
7384 1 : settings.platform.sizeof_long = 4;
7385 1 : settings.platform.long_bit = 32;
7386 1 : check(code, &settings);
7387 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same value in both branches of ternary operator.\n", errout_str());
7388 :
7389 1 : settings.platform.sizeof_long = 8;
7390 1 : settings.platform.long_bit = 64;
7391 1 : check(code, &settings);
7392 1 : ASSERT_EQUALS("", errout_str());
7393 : }
7394 : }
7395 :
7396 1 : void duplicateValueTernary() {
7397 1 : check("void f() {\n"
7398 : " if( a ? (b ? false:false): false ) ;\n"
7399 : "}");
7400 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same value in both branches of ternary operator.\n", errout_str());
7401 :
7402 1 : check("int f1(int a) {return (a == 1) ? (int)1 : 1; }");
7403 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7404 :
7405 1 : check("int f2(int a) {return (a == 1) ? (int)1 : (int)1; }");
7406 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7407 :
7408 1 : check("int f3(int a) {return (a == 1) ? 1 : (int)1; }");
7409 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7410 :
7411 1 : check("int f4(int a) {return (a == 1) ? 1 : 1; }");
7412 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7413 :
7414 1 : check("int f5(int a) {return (a == (int)1) ? (int)1 : 1; }");
7415 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7416 :
7417 1 : check("int f6(int a) {return (a == (int)1) ? (int)1 : (int)1; }");
7418 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7419 :
7420 1 : check("int f7(int a) {return (a == (int)1) ? 1 : (int)1; }");
7421 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7422 :
7423 1 : check("int f8(int a) {return (a == (int)1) ? 1 : 1; }");
7424 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout_str());
7425 :
7426 1 : check("struct Foo {\n"
7427 : " std::vector<int> bar{1,2,3};\n"
7428 : " std::vector<int> baz{4,5,6};\n"
7429 : "};\n"
7430 : "void f() {\n"
7431 : " Foo foo;\n"
7432 : " it = true ? foo.bar.begin() : foo.baz.begin();\n"
7433 : "}\n");
7434 1 : ASSERT_EQUALS("", errout_str());
7435 :
7436 1 : check("void f(bool b) {\n"
7437 : " std::vector<int> bar{1,2,3};\n"
7438 : " std::vector<int> baz{4,5,6};\n"
7439 : " std::vector<int> v = b ? bar : baz;\n"
7440 : "}\n");
7441 1 : ASSERT_EQUALS("", errout_str());
7442 :
7443 1 : check("void f(bool q) {\n" // #9570
7444 : " static int a = 0;\n"
7445 : " static int b = 0;\n"
7446 : " int& x = q ? a : b;\n"
7447 : " ++x;\n"
7448 : "}\n");
7449 1 : ASSERT_EQUALS("", errout_str());
7450 :
7451 1 : check("struct S { int a, b; };\n" // #10107
7452 : "S f(bool x, S s) {\n"
7453 : " (x) ? f.a = 42 : f.b = 42;\n"
7454 : " return f;\n"
7455 : "}\n");
7456 1 : ASSERT_EQUALS("", errout_str());
7457 :
7458 1 : check("float f(float x) {\n" // # 11368
7459 : " return (x >= 0.0) ? 0.0 : -0.0;\n"
7460 : "}\n");
7461 1 : ASSERT_EQUALS("", errout_str());
7462 : }
7463 :
7464 1 : void duplicateExpressionTemplate() {
7465 1 : check("template <int I> void f() {\n" // #6930
7466 : " if (I >= 0 && I < 3) {}\n"
7467 : "}\n"
7468 : "\n"
7469 : "static auto a = f<0>();");
7470 1 : ASSERT_EQUALS("", errout_str());
7471 :
7472 1 : check("template<typename T>\n" // #7754
7473 : "void f() {\n"
7474 : " if (std::is_same_v<T, char> || std::is_same_v<T, unsigned char>) {}\n"
7475 : "}\n");
7476 1 : ASSERT_EQUALS("", errout_str());
7477 :
7478 1 : check("typedef long long int64_t;"
7479 : "template<typename T>\n"
7480 : "void f() {\n"
7481 : " if (std::is_same_v<T, long> || std::is_same_v<T, int64_t>) {}\n"
7482 : "}\n");
7483 1 : ASSERT_EQUALS("", errout_str());
7484 :
7485 1 : checkP("#define int32_t int"
7486 : "template<typename T>\n"
7487 : "void f() {\n"
7488 : " if (std::is_same_v<T, int> || std::is_same_v<T, int32_t>) {}\n"
7489 : "}\n");
7490 1 : ASSERT_EQUALS("", errout_str());
7491 :
7492 1 : checkP("#define F(v) (v) != 0\n" // #12392
7493 : "template<class T>\n"
7494 : "void f() {\n"
7495 : " if (F(0)) {}\n"
7496 : "}\n"
7497 : "void g() {\n"
7498 : " f<int>();\n"
7499 : "}\n");
7500 1 : ASSERT_EQUALS("", errout_str());
7501 : }
7502 :
7503 1 : void duplicateExpressionCompareWithZero() {
7504 1 : check("void f(const int* x, bool b) {\n"
7505 : " if ((x && b) || (x != 0 && b)) {}\n"
7506 : "}\n");
7507 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because 'x&&b' and 'x!=0&&b' represent the same value.\n", errout_str());
7508 :
7509 1 : check("void f(const int* x, bool b) {\n"
7510 : " if ((x != 0 && b) || (x && b)) {}\n"
7511 : "}\n");
7512 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because 'x!=0&&b' and 'x&&b' represent the same value.\n", errout_str());
7513 :
7514 1 : check("void f(const int* x, bool b) {\n"
7515 : " if ((x && b) || (b && x != 0)) {}\n"
7516 : "}\n");
7517 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because 'x&&b' and 'b&&x!=0' represent the same value.\n", errout_str());
7518 :
7519 1 : check("void f(const int* x, bool b) {\n"
7520 : " if ((!x && b) || (x == 0 && b)) {}\n"
7521 : "}\n");
7522 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because '!x&&b' and 'x==0&&b' represent the same value.\n", errout_str());
7523 :
7524 1 : check("void f(const int* x, bool b) {\n"
7525 : " if ((x == 0 && b) || (!x && b)) {}\n"
7526 : "}\n");
7527 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because 'x==0&&b' and '!x&&b' represent the same value.\n", errout_str());
7528 :
7529 1 : check("void f(const int* x, bool b) {\n"
7530 : " if ((!x && b) || (b && x == 0)) {}\n"
7531 : "}\n");
7532 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '||' because '!x&&b' and 'b&&x==0' represent the same value.\n", errout_str());
7533 :
7534 1 : check("struct A {\n"
7535 : " int* getX() const;\n"
7536 : " bool getB() const;\n"
7537 : " void f() {\n"
7538 : " if ((getX() && getB()) || (getX() != 0 && getB())) {}\n"
7539 : " }\n"
7540 : "};\n");
7541 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Same expression on both sides of '||' because 'getX()&&getB()' and 'getX()!=0&&getB()' represent the same value.\n", errout_str());
7542 :
7543 1 : check("void f(const int* x, bool b) {\n"
7544 : " if ((x && b) || (x == 0 && b)) {}\n"
7545 : "}\n");
7546 1 : ASSERT_EQUALS("", errout_str());
7547 :
7548 1 : check("void f(const int* x, bool b) {\n"
7549 : " if ((!x && b) || (x != 0 && b)) {}\n"
7550 : "}\n");
7551 1 : ASSERT_EQUALS("", errout_str());
7552 : }
7553 :
7554 1 : void oppositeExpression() {
7555 1 : check("void f(bool a) { if(a && !a) {} }");
7556 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '&&'.\n", errout_str());
7557 :
7558 1 : check("void f(bool a) { if(a != !a) {} }");
7559 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '!='.\n", errout_str());
7560 :
7561 1 : check("void f(bool a) { if( a == !(a) ) {}}");
7562 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7563 :
7564 1 : check("void f(bool a) { if( a != !(a) ) {}}");
7565 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '!='.\n", errout_str());
7566 :
7567 1 : check("void f(bool a) { if( !(a) == a ) {}}");
7568 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7569 :
7570 1 : check("void f(bool a) { if( !(a) != a ) {}}");
7571 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '!='.\n", errout_str());
7572 :
7573 1 : check("void f(bool a) { if( !(!a) == !(a) ) {}}");
7574 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7575 :
7576 1 : check("void f(bool a) { if( !(!a) != !(a) ) {}}");
7577 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '!='.\n", errout_str());
7578 :
7579 1 : check("void f1(bool a) {\n"
7580 : " const bool b = a;\n"
7581 : " if( a == !(b) ) {}\n"
7582 : " if( b == !(a) ) {}\n"
7583 : "}");
7584 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n"
7585 : "[test.cpp:2] -> [test.cpp:4]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7586 :
7587 1 : check("void f2(const bool *a) {\n"
7588 : " const bool b = *a;\n"
7589 : " if( *a == !(b) ) {}\n"
7590 : " if( b == !(*a) ) {}\n"
7591 : "}");
7592 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n"
7593 : "[test.cpp:2] -> [test.cpp:4]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7594 :
7595 1 : check("void f(bool a) { a = !a; }");
7596 1 : ASSERT_EQUALS("", errout_str());
7597 :
7598 1 : check("void f(int a) { if( a < -a ) {}}");
7599 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Opposite expression on both sides of '<'.\n", errout_str());
7600 :
7601 1 : check("void f(int a) { a -= -a; }");
7602 1 : ASSERT_EQUALS("", errout_str());
7603 :
7604 1 : check("void f(int a) { a = a / (-a); }");
7605 1 : ASSERT_EQUALS("", errout_str());
7606 :
7607 1 : check("bool f(int i){ return !((i - 1) & i); }");
7608 1 : ASSERT_EQUALS("", errout_str());
7609 :
7610 1 : check("bool f(unsigned i){ return (x > 0) && (x & (x-1)) == 0; }");
7611 1 : ASSERT_EQUALS("", errout_str());
7612 :
7613 1 : check("void A::f(bool a, bool c)\n"
7614 : "{\n"
7615 : " const bool b = a;\n"
7616 : " if(c) { a = false; }\n"
7617 : " if(b && !a) { }\n"
7618 : "}");
7619 1 : ASSERT_EQUALS("", errout_str());
7620 :
7621 1 : check("void f(bool c) {\n"
7622 : " const bool b = a;\n"
7623 : " if(c) { a = false; }\n"
7624 : " if(b && !a) { }\n"
7625 : "}");
7626 1 : ASSERT_EQUALS("", errout_str());
7627 :
7628 1 : check("void f() {\n"
7629 : " bool x = a;\n"
7630 : " dostuff();\n"
7631 : " if (x && a) {}\n"
7632 : "}");
7633 1 : ASSERT_EQUALS("", errout_str());
7634 :
7635 1 : check("void f() {\n"
7636 : " const bool b = g();\n"
7637 : " if (!b && g()) {}\n"
7638 : "}");
7639 1 : ASSERT_EQUALS("", errout_str());
7640 :
7641 1 : check("void f(const bool *a) {\n"
7642 : " const bool b = a[42];\n"
7643 : " if( b == !(a[42]) ) {}\n"
7644 : "}\n");
7645 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7646 :
7647 1 : check("void f(const bool *a) {\n"
7648 : " const bool b = a[42];\n"
7649 : " if( a[42] == !(b) ) {}\n"
7650 : "}\n");
7651 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7652 :
7653 1 : check("void f(const bool *a) {\n"
7654 : " const bool b = *a;\n"
7655 : " if( b == !(*a) ) {}\n"
7656 : "}\n");
7657 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7658 :
7659 1 : check("void f(const bool *a) {\n"
7660 : " const bool b = *a;\n"
7661 : " if( *a == !(b) ) {}\n"
7662 : "}\n");
7663 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Opposite expression on both sides of '=='.\n", errout_str());
7664 :
7665 1 : check("void f(uint16_t u) {\n" // #9342
7666 : " if (u != (u & -u))\n"
7667 : " return false;\n"
7668 : " if (u != (-u & u))\n"
7669 : " return false;\n"
7670 : " return true;\n"
7671 : "}\n");
7672 1 : ASSERT_EQUALS("", errout_str());
7673 : }
7674 :
7675 1 : void duplicateVarExpression() {
7676 1 : check("int f() __attribute__((pure));\n"
7677 : "int g() __attribute__((pure));\n"
7678 : "void test() {\n"
7679 : " int i = f();\n"
7680 : " int j = f();\n"
7681 : "}");
7682 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7683 :
7684 1 : check("struct Foo { int f() const; int g() const; };\n"
7685 : "void test() {\n"
7686 : " Foo f = Foo{};\n"
7687 : " int i = f.f();\n"
7688 : " int j = f.f();\n"
7689 : "}");
7690 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7691 :
7692 1 : check("struct Foo { int f() const; int g() const; };\n"
7693 : "void test() {\n"
7694 : " Foo f = Foo{};\n"
7695 : " Foo f2 = Foo{};\n"
7696 : " int i = f.f();\n"
7697 : " int j = f.f();\n"
7698 : "}");
7699 1 : ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:5]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7700 :
7701 1 : check("int f() __attribute__((pure));\n"
7702 : "int g() __attribute__((pure));\n"
7703 : "void test() {\n"
7704 : " int i = 1 + f();\n"
7705 : " int j = 1 + f();\n"
7706 : "}");
7707 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7708 :
7709 1 : check("int f() __attribute__((pure));\n"
7710 : "int g() __attribute__((pure));\n"
7711 : "void test() {\n"
7712 : " int i = f() + 1;\n"
7713 : " int j = 1 + f();\n"
7714 : "}");
7715 1 : ASSERT_EQUALS("", errout_str());
7716 :
7717 1 : check("int f() __attribute__((pure));\n"
7718 : "int g() __attribute__((pure));\n"
7719 : "void test() {\n"
7720 : " int x = f();\n"
7721 : " int i = x + 1;\n"
7722 : " int j = f() + 1;\n"
7723 : "}");
7724 1 : ASSERT_EQUALS("", errout_str());
7725 :
7726 1 : check("int f() __attribute__((pure));\n"
7727 : "int g() __attribute__((pure));\n"
7728 : "void test() {\n"
7729 : " int i = f() + f();\n"
7730 : " int j = f() + f();\n"
7731 : "}");
7732 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7733 :
7734 1 : check("int f(int) __attribute__((pure));\n"
7735 : "int g(int) __attribute__((pure));\n"
7736 : "void test() {\n"
7737 : " int i = f(0);\n"
7738 : " int j = f(0);\n"
7739 : "}");
7740 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7741 :
7742 1 : check("int f(int) __attribute__((pure));\n"
7743 : "int g(int) __attribute__((pure));\n"
7744 : "void test() {\n"
7745 : " const int x = 0;\n"
7746 : " int i = f(0);\n"
7747 : " int j = f(x);\n"
7748 : "}");
7749 1 : ASSERT_EQUALS("", errout_str());
7750 :
7751 1 : check("void test(const int * p, const int * q) {\n"
7752 : " int i = *p;\n"
7753 : " int j = *p;\n"
7754 : "}");
7755 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7756 :
7757 1 : check("struct A { int x; int y; };"
7758 : "void test(A a) {\n"
7759 : " int i = a.x;\n"
7760 : " int j = a.x;\n"
7761 : "}");
7762 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (style) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7763 :
7764 1 : check("void test() {\n"
7765 : " int i = 0;\n"
7766 : " int j = 0;\n"
7767 : "}");
7768 1 : ASSERT_EQUALS("", errout_str());
7769 :
7770 1 : check("void test() {\n"
7771 : " int i = -1;\n"
7772 : " int j = -1;\n"
7773 : "}");
7774 1 : ASSERT_EQUALS("", errout_str());
7775 :
7776 1 : check("int f(int);\n"
7777 : "void test() {\n"
7778 : " int i = f(0);\n"
7779 : " int j = f(1);\n"
7780 : "}");
7781 1 : ASSERT_EQUALS("", errout_str());
7782 :
7783 1 : check("int f();\n"
7784 : "int g();\n"
7785 : "void test() {\n"
7786 : " int i = f() || f();\n"
7787 : " int j = f() && f();\n"
7788 : "}");
7789 1 : ASSERT_EQUALS("", errout_str());
7790 :
7791 1 : check("struct Foo {};\n"
7792 : "void test() {\n"
7793 : " Foo i = Foo();\n"
7794 : " Foo j = Foo();\n"
7795 : "}");
7796 1 : ASSERT_EQUALS("", errout_str());
7797 :
7798 1 : check("struct Foo {};\n"
7799 : "void test() {\n"
7800 : " Foo i = Foo{};\n"
7801 : " Foo j = Foo{};\n"
7802 : "}");
7803 1 : ASSERT_EQUALS("", errout_str());
7804 :
7805 1 : check("struct Foo { int f() const; float g() const; };\n"
7806 : "void test() {\n"
7807 : " Foo f = Foo{};\n"
7808 : " int i = f.f();\n"
7809 : " int j = f.f();\n"
7810 : "}");
7811 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7812 :
7813 1 : check("struct Foo { int f(); int g(); };\n"
7814 : "void test() {\n"
7815 : " Foo f = Foo{};\n"
7816 : " int i = f.f();\n"
7817 : " int j = f.f();\n"
7818 : "}");
7819 1 : ASSERT_EQUALS("", errout_str());
7820 :
7821 1 : check("void test() {\n"
7822 : " int i = f();\n"
7823 : " int j = f();\n"
7824 : "}");
7825 1 : ASSERT_EQUALS("", errout_str());
7826 :
7827 1 : check("void test(int x) {\n"
7828 : " int i = ++x;\n"
7829 : " int j = ++x;\n"
7830 : "}");
7831 1 : ASSERT_EQUALS("", errout_str());
7832 :
7833 1 : check("void test(int x) {\n"
7834 : " int i = x++;\n"
7835 : " int j = x++;\n"
7836 : "}");
7837 1 : ASSERT_EQUALS("", errout_str());
7838 :
7839 1 : check("void test(int x) {\n"
7840 : " int i = --x;\n"
7841 : " int j = --x;\n"
7842 : "}");
7843 1 : ASSERT_EQUALS("", errout_str());
7844 :
7845 1 : check("void test(int x) {\n"
7846 : " int i = x--;\n"
7847 : " int j = x--;\n"
7848 : "}");
7849 1 : ASSERT_EQUALS("", errout_str());
7850 :
7851 1 : check("void test(int x) {\n"
7852 : " int i = x + 1;\n"
7853 : " int j = 1 + x;\n"
7854 : "}");
7855 1 : ASSERT_EQUALS("", errout_str());
7856 : }
7857 :
7858 1 : void duplicateVarExpressionUnique() {
7859 1 : check("struct SW { int first; };\n"
7860 : "void foo(SW* x) {\n"
7861 : " int start = x->first;\n"
7862 : " int end = x->first;\n"
7863 : "}");
7864 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n"
7865 : "[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n",
7866 : errout_str());
7867 :
7868 1 : check("struct SW { int first; };\n"
7869 : "void foo(SW* x, int i, int j) {\n"
7870 : " int start = x->first;\n"
7871 : " int end = x->first;\n"
7872 : "}");
7873 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n"
7874 : "[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n",
7875 : errout_str());
7876 :
7877 1 : check("struct Foo { int f() const; };\n"
7878 : "void test() {\n"
7879 : " Foo f = Foo{};\n"
7880 : " int i = f.f();\n"
7881 : " int j = f.f();\n"
7882 : "}");
7883 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7884 :
7885 1 : check("void test(const int * p) {\n"
7886 : " int i = *p;\n"
7887 : " int j = *p;\n"
7888 : "}");
7889 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7890 :
7891 1 : check("struct Foo { int f() const; int g(int) const; };\n"
7892 : "void test() {\n"
7893 : " Foo f = Foo{};\n"
7894 : " int i = f.f();\n"
7895 : " int j = f.f();\n"
7896 : "}");
7897 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7898 :
7899 1 : check("struct Foo { int f() const; };\n"
7900 : "void test() {\n"
7901 : " Foo f = Foo{};\n"
7902 : " int i = f.f();\n"
7903 : " int j = f.f();\n"
7904 : "}");
7905 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7906 : }
7907 :
7908 1 : void duplicateVarExpressionAssign() {
7909 1 : check("struct A { int x; int y; };"
7910 : "void use(int);\n"
7911 : "void test(A a) {\n"
7912 : " int i = a.x;\n"
7913 : " int j = a.x;\n"
7914 : " use(i);\n"
7915 : " i = j;\n"
7916 : "}");
7917 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7918 :
7919 1 : check("struct A { int x; int y; };"
7920 : "void use(int);\n"
7921 : "void test(A a) {\n"
7922 : " int i = a.x;\n"
7923 : " int j = a.x;\n"
7924 : " use(j);\n"
7925 : " j = i;\n"
7926 : "}");
7927 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n", errout_str());
7928 :
7929 1 : check("struct A { int x; int y; };"
7930 : "void use(int);\n"
7931 : "void test(A a) {\n"
7932 : " int i = a.x;\n"
7933 : " int j = a.x;\n"
7934 : " use(j);\n"
7935 : " if (i == j) {}\n"
7936 : "}");
7937 1 : ASSERT_EQUALS(
7938 : "[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n"
7939 : "[test.cpp:3] -> [test.cpp:4] -> [test.cpp:6]: (style) The comparison 'i == j' is always true because 'i' and 'j' represent the same value.\n",
7940 : errout_str());
7941 :
7942 1 : check("struct A { int x; int y; };"
7943 : "void use(int);\n"
7944 : "void test(A a) {\n"
7945 : " int i = a.x;\n"
7946 : " int j = a.x;\n"
7947 : " use(j);\n"
7948 : " if (i == a.x) {}\n"
7949 : "}");
7950 1 : ASSERT_EQUALS(
7951 : "[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n"
7952 : "[test.cpp:3] -> [test.cpp:6]: (style) The comparison 'i == a.x' is always true because 'i' and 'a.x' represent the same value.\n",
7953 : errout_str());
7954 :
7955 1 : check("struct A { int x; int y; };"
7956 : "void use(int);\n"
7957 : "void test(A a) {\n"
7958 : " int i = a.x;\n"
7959 : " int j = a.x;\n"
7960 : " use(i);\n"
7961 : " if (j == a.x) {}\n"
7962 : "}");
7963 1 : ASSERT_EQUALS(
7964 : "[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'.\n"
7965 : "[test.cpp:4] -> [test.cpp:6]: (style) The comparison 'j == a.x' is always true because 'j' and 'a.x' represent the same value.\n",
7966 : errout_str());
7967 :
7968 : // Issue #8612
7969 1 : check("struct P\n"
7970 : "{\n"
7971 : " void func();\n"
7972 : " bool operator==(const P&) const;\n"
7973 : "};\n"
7974 : "struct X\n"
7975 : "{\n"
7976 : " P first;\n"
7977 : " P second;\n"
7978 : "};\n"
7979 : "bool bar();\n"
7980 : "void baz(const P&);\n"
7981 : "void foo(const X& x)\n"
7982 : "{\n"
7983 : " P current = x.first;\n"
7984 : " P previous = x.first;\n"
7985 : " while (true)\n"
7986 : " {\n"
7987 : " baz(current);\n"
7988 : " if (bar() && previous == current)\n"
7989 : " {\n"
7990 : " current.func();\n"
7991 : " }\n"
7992 : " previous = current;\n"
7993 : " }\n"
7994 : "}");
7995 1 : ASSERT_EQUALS("[test.cpp:16] -> [test.cpp:15]: (style, inconclusive) Same expression used in consecutive assignments of 'current' and 'previous'.\n", errout_str());
7996 : }
7997 :
7998 1 : void duplicateVarExpressionCrash() {
7999 : // Issue #8624
8000 1 : check("struct X {\n"
8001 : " X();\n"
8002 : " int f() const;\n"
8003 : "};\n"
8004 : "void run() {\n"
8005 : " X x;\n"
8006 : " int a = x.f();\n"
8007 : " int b = x.f();\n"
8008 : " (void)a;\n"
8009 : " (void)b;\n"
8010 : "}");
8011 1 : ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:7]: (style, inconclusive) Same expression used in consecutive assignments of 'a' and 'b'.\n", errout_str());
8012 :
8013 : // Issue #8712
8014 1 : check("void f() {\n"
8015 : " unsigned char d;\n"
8016 : " d = d % 5;\n"
8017 : "}");
8018 1 : ASSERT_EQUALS("", errout_str());
8019 :
8020 1 : check("template <typename T>\n"
8021 : "T f() {\n"
8022 : " T x = T();\n"
8023 : "}\n"
8024 : "int &a = f<int&>();");
8025 1 : ASSERT_EQUALS("", errout_str());
8026 :
8027 : // Issue #8713
8028 1 : check("class A {\n"
8029 : " int64_t B = 32768;\n"
8030 : " P<uint8_t> m = MakeP<uint8_t>(B);\n"
8031 : "};\n"
8032 : "void f() {\n"
8033 : " uint32_t a = 42;\n"
8034 : " uint32_t b = uint32_t(A ::B / 1024);\n"
8035 : " int32_t c = int32_t(a / b);\n"
8036 : "}");
8037 1 : ASSERT_EQUALS("", errout_str());
8038 :
8039 : // Issue #8709
8040 1 : check("a b;\n"
8041 : "void c() {\n"
8042 : " switch (d) { case b:; }\n"
8043 : " double e(b);\n"
8044 : " if(e <= 0) {}\n"
8045 : "}");
8046 1 : ASSERT_EQUALS("", errout_str());
8047 :
8048 : // #10718
8049 : // Should probably not be inconclusive
8050 1 : check("struct a {\n"
8051 : " int b() const;\n"
8052 : " auto c() -> decltype(0) {\n"
8053 : " a d;\n"
8054 : " int e = d.b(), f = d.b();\n"
8055 : " return e + f;\n"
8056 : " }\n"
8057 : "};\n");
8058 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:5]: (style, inconclusive) Same expression used in consecutive assignments of 'e' and 'f'.\n", errout_str());
8059 : }
8060 :
8061 1 : void multiConditionSameExpression() {
8062 1 : check("void f() {\n"
8063 : " int val = 0;\n"
8064 : " if (val < 0) continue;\n"
8065 : " if ((val > 0)) {}\n"
8066 : "}");
8067 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'val < 0' is always false.\n"
8068 : "[test.cpp:2] -> [test.cpp:4]: (style) The comparison 'val > 0' is always false.\n", errout_str());
8069 :
8070 1 : check("void f() {\n"
8071 : " int val = 0;\n"
8072 : " int *p = &val;n"
8073 : " val = 1;\n"
8074 : " if (*p < 0) continue;\n"
8075 : " if ((*p > 0)) {}\n"
8076 : "}\n");
8077 1 : ASSERT_EQUALS(
8078 : "[test.cpp:3]: (style) Variable 'p' can be declared as pointer to const\n",
8079 : errout_str());
8080 :
8081 1 : check("void f() {\n"
8082 : " int val = 0;\n"
8083 : " int *p = &val;\n"
8084 : " if (*p < 0) continue;\n"
8085 : " if ((*p > 0)) {}\n"
8086 : "}\n");
8087 1 : TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison '*p < 0' is always false.\n"
8088 : "[test.cpp:2] -> [test.cpp:4]: (style) The comparison '*p > 0' is always false.\n",
8089 : "[test.cpp:3]: (style) Variable 'p' can be declared as pointer to const\n",
8090 : errout_str());
8091 :
8092 1 : check("void f() {\n"
8093 : " int val = 0;\n"
8094 : " if (val < 0) {\n"
8095 : " if ((val > 0)) {}\n"
8096 : " }\n"
8097 : "}");
8098 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'val < 0' is always false.\n"
8099 : "[test.cpp:2] -> [test.cpp:4]: (style) The comparison 'val > 0' is always false.\n", errout_str());
8100 :
8101 1 : check("void f() {\n"
8102 : " int val = 0;\n"
8103 : " if (val < 0) {\n"
8104 : " if ((val < 0)) {}\n"
8105 : " }\n"
8106 : "}");
8107 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'val < 0' is always false.\n"
8108 : "[test.cpp:2] -> [test.cpp:4]: (style) The comparison 'val < 0' is always false.\n", errout_str());
8109 :
8110 1 : check("void f() {\n"
8111 : " int activate = 0;\n"
8112 : " int foo = 0;\n"
8113 : " if (activate) {}\n"
8114 : " else if (foo) {}\n"
8115 : "}");
8116 1 : ASSERT_EQUALS("", errout_str());
8117 : }
8118 :
8119 1 : void checkSignOfUnsignedVariable() {
8120 1 : check("void foo() {\n"
8121 : " for(unsigned char i = 10; i >= 0; i--) {}\n"
8122 : "}");
8123 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'i' can't be negative so it is unnecessary to test it.\n", errout_str());
8124 :
8125 1 : check("void foo(bool b) {\n"
8126 : " for(unsigned int i = 10; b || i >= 0; i--) {}\n"
8127 : "}");
8128 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'i' can't be negative so it is unnecessary to test it.\n", errout_str());
8129 :
8130 : {
8131 1 : const char code[] = "void foo(unsigned int x) {\n"
8132 : " if (x < 0) {}\n"
8133 : "}";
8134 1 : check(code, true, false, true, false);
8135 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8136 1 : check(code, true, false, true, true);
8137 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8138 : }
8139 :
8140 1 : check("void foo(unsigned int x) {\n"
8141 : " if (x < 0u) {}\n"
8142 : "}");
8143 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8144 :
8145 1 : check("void foo(int x) {\n"
8146 : " if (x < 0) {}\n"
8147 : "}");
8148 1 : ASSERT_EQUALS("", errout_str());
8149 :
8150 : {
8151 1 : const char code[] = "void foo(unsigned x) {\n"
8152 : " int y = 0;\n"
8153 : " if (x < y) {}\n"
8154 : "}";
8155 1 : check(code, true, false, true, false);
8156 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8157 1 : check(code, true, false, true, true);
8158 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8159 : }
8160 1 : check("void foo(unsigned x) {\n"
8161 : " int y = 0;\n"
8162 : " if (b)\n"
8163 : " y = 1;\n"
8164 : " if (x < y) {}\n"
8165 : "}");
8166 1 : ASSERT_EQUALS("", errout_str());
8167 :
8168 1 : check("void foo(unsigned int x) {\n"
8169 : " if (0 > x) {}\n"
8170 : "}");
8171 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8172 :
8173 1 : check("void foo(unsigned int x) {\n"
8174 : " if (0UL > x) {}\n"
8175 : "}");
8176 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8177 :
8178 1 : check("void foo(int x) {\n"
8179 : " if (0 > x) {}\n"
8180 : "}");
8181 1 : ASSERT_EQUALS("", errout_str());
8182 :
8183 1 : check("void foo(unsigned int x) {\n"
8184 : " if (x >= 0) {}\n"
8185 : "}");
8186 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8187 :
8188 1 : check("void foo(unsigned int x, unsigned y) {\n"
8189 : " if (x - y >= 0) {}\n"
8190 : "}");
8191 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x-y' can't be negative so it is unnecessary to test it.\n", errout_str());
8192 :
8193 1 : check("void foo(unsigned int x) {\n"
8194 : " if (x >= 0ull) {}\n"
8195 : "}");
8196 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8197 :
8198 1 : check("void foo(int x) {\n"
8199 : " if (x >= 0) {}\n"
8200 : "}");
8201 1 : ASSERT_EQUALS("", errout_str());
8202 :
8203 1 : check("void foo(unsigned int x) {\n"
8204 : " if (0 <= x) {}\n"
8205 : "}");
8206 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8207 :
8208 1 : check("void foo(unsigned int x) {\n"
8209 : " if (0ll <= x) {}\n"
8210 : "}");
8211 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8212 :
8213 1 : check("void foo(int x) {\n"
8214 : " if (0 <= x) {}\n"
8215 : "}");
8216 1 : ASSERT_EQUALS("", errout_str());
8217 :
8218 1 : check("void foo(unsigned int x, bool y) {\n"
8219 : " if (x < 0 && y) {}\n"
8220 : "}");
8221 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8222 :
8223 1 : check("void foo(int x, bool y) {\n"
8224 : " if (x < 0 && y) {}\n"
8225 : "}");
8226 1 : ASSERT_EQUALS("", errout_str());
8227 :
8228 1 : check("void foo(unsigned int x, bool y) {\n"
8229 : " if (0 > x && y) {}\n"
8230 : "}");
8231 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8232 :
8233 1 : check("void foo(int x, bool y) {\n"
8234 : " if (0 > x && y) {}\n"
8235 : "}");
8236 1 : ASSERT_EQUALS("", errout_str());
8237 :
8238 1 : check("void foo(unsigned int x, bool y) {\n"
8239 : " if (x >= 0 && y) {}\n"
8240 : "}");
8241 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8242 :
8243 1 : check("void foo(int x, bool y) {\n"
8244 : " if (x >= 0 && y) {}\n"
8245 : "}");
8246 1 : ASSERT_EQUALS("", errout_str());
8247 :
8248 :
8249 1 : check("void foo(unsigned int x, bool y) {\n"
8250 : " if (y && x < 0) {}\n"
8251 : "}");
8252 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8253 :
8254 1 : check("void foo(int x, bool y) {\n"
8255 : " if (y && x < 0) {}\n"
8256 : "}");
8257 1 : ASSERT_EQUALS("", errout_str());
8258 :
8259 1 : check("void foo(unsigned int x, bool y) {\n"
8260 : " if (y && 0 > x) {}\n"
8261 : "}");
8262 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8263 :
8264 1 : check("void foo(int x, bool y) {\n"
8265 : " if (y && 0 > x) {}\n"
8266 : "}");
8267 1 : ASSERT_EQUALS("", errout_str());
8268 :
8269 1 : check("void foo(unsigned int x, bool y) {\n"
8270 : " if (y && x >= 0) {}\n"
8271 : "}");
8272 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8273 :
8274 1 : check("void foo(int x, bool y) {\n"
8275 : " if (y && x >= 0) {}\n"
8276 : "}");
8277 1 : ASSERT_EQUALS("", errout_str());
8278 :
8279 :
8280 1 : check("void foo(unsigned int x, bool y) {\n"
8281 : " if (x < 0 || y) {}\n"
8282 : "}");
8283 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8284 :
8285 1 : check("void foo(int x, bool y) {\n"
8286 : " if (x < 0 || y) {}\n"
8287 : "}");
8288 1 : ASSERT_EQUALS("", errout_str());
8289 :
8290 1 : check("void foo(unsigned int x, bool y) {\n"
8291 : " if (0 > x || y) {}\n"
8292 : "}");
8293 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8294 :
8295 1 : check("void foo(int x, bool y) {\n"
8296 : " if (0 > x || y) {}\n"
8297 : "}");
8298 1 : ASSERT_EQUALS("", errout_str());
8299 :
8300 1 : check("void foo(unsigned int x, bool y) {\n"
8301 : " if (x >= 0 || y) {}\n"
8302 : "}");
8303 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be negative so it is unnecessary to test it.\n", errout_str());
8304 :
8305 1 : check("void foo(int x, bool y) {\n"
8306 : " if (x >= 0 || y) {}\n"
8307 : "}");
8308 1 : ASSERT_EQUALS("", errout_str());
8309 :
8310 : // #3233 - FP when template is used (template parameter is numeric constant)
8311 : {
8312 1 : const char code[] = "template<int n> void foo(unsigned int x) {\n"
8313 : " if (x <= n);\n"
8314 : "}\n"
8315 : "foo<0>();";
8316 1 : check(code, true, false);
8317 1 : ASSERT_EQUALS("", errout_str());
8318 1 : check(code, true, true);
8319 1 : ASSERT_EQUALS("", errout_str());
8320 : }
8321 :
8322 : {
8323 1 : check("template<int n> void foo(unsigned int x) {\n"
8324 : "if (x <= 0);\n"
8325 : "}");
8326 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout_str());
8327 : }
8328 :
8329 : // #8836
8330 1 : check("uint32_t value = 0xFUL;\n"
8331 : "void f() {\n"
8332 : " if (value < 0u)\n"
8333 : " {\n"
8334 : " value = 0u;\n"
8335 : " }\n"
8336 : "}");
8337 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Checking if unsigned expression 'value' is less than zero.\n", errout_str());
8338 :
8339 : // #9040
8340 1 : /*const*/ Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build();
8341 1 : check("using BOOL = unsigned;\n"
8342 : "int i;\n"
8343 : "bool f() {\n"
8344 : " return i >= 0;\n"
8345 : "}\n", &settings1);
8346 1 : ASSERT_EQUALS("", errout_str());
8347 :
8348 : // #10612
8349 1 : check("void f(void) {\n"
8350 : " const uint32_t x = 0;\n"
8351 : " constexpr const auto y = 0xFFFFU;\n"
8352 : " if (y < x) {}\n"
8353 : "}");
8354 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Checking if unsigned expression 'y' is less than zero.\n", errout_str());
8355 :
8356 : // #12387
8357 1 : check("template<typename T>\n"
8358 : "void f(T t) {\n"
8359 : " if constexpr (std::numeric_limits<T>::is_signed) {\n"
8360 : " if (t < 0) {}\n"
8361 : " }\n"
8362 : "}\n"
8363 : "void g() {\n"
8364 : " f<uint32_t>(0);\n"
8365 : "}");
8366 1 : ASSERT_EQUALS("", errout_str());
8367 : }
8368 :
8369 1 : void checkSignOfPointer() {
8370 1 : check("void foo(const int* x) {\n"
8371 : " if (x >= 0) {}\n"
8372 : "}");
8373 1 : ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout_str());
8374 :
8375 : {
8376 1 : const char code[] = "void foo(const int* x) {\n"
8377 : " int y = 0;\n"
8378 : " if (x >= y) {}\n"
8379 : "}";
8380 1 : check(code, true, false, true, false);
8381 1 : ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout_str());
8382 1 : check(code, true, false, true, true);
8383 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout_str());
8384 : }
8385 1 : check("void foo(const int* x) {\n"
8386 : " if (*x >= 0) {}\n"
8387 : "}");
8388 1 : ASSERT_EQUALS("", errout_str());
8389 :
8390 1 : check("void foo(const int* x) {\n"
8391 : " if (x < 0) {}\n"
8392 : "}");
8393 1 : ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout_str());
8394 :
8395 : {
8396 1 : const char code[] = "void foo(const int* x) {\n"
8397 : " unsigned y = 0u;\n"
8398 : " if (x < y) {}\n"
8399 : "}";
8400 :
8401 1 : check(code, true, false, true, false);
8402 1 : ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout_str());
8403 1 : check(code, true, false, true, true);
8404 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout_str());
8405 : }
8406 :
8407 1 : check("void foo(const int* x) {\n"
8408 : " if (*x < 0) {}\n"
8409 : "}");
8410 1 : ASSERT_EQUALS("", errout_str());
8411 :
8412 1 : check("void foo(const int* x, const int* y) {\n"
8413 : " if (x - y < 0) {}\n"
8414 : "}");
8415 1 : ASSERT_EQUALS("", errout_str());
8416 :
8417 1 : check("void foo(const int* x, const int* y) {\n"
8418 : " if (x - y <= 0) {}\n"
8419 : "}");
8420 1 : ASSERT_EQUALS("", errout_str());
8421 :
8422 1 : check("void foo(const int* x, const int* y) {\n"
8423 : " if (x - y > 0) {}\n"
8424 : "}");
8425 1 : ASSERT_EQUALS("", errout_str());
8426 :
8427 1 : check("void foo(const int* x, const int* y) {\n"
8428 : " if (x - y >= 0) {}\n"
8429 : "}");
8430 1 : ASSERT_EQUALS("", errout_str());
8431 :
8432 1 : check("void foo(const Bar* x) {\n"
8433 : " if (0 <= x) {}\n"
8434 : "}");
8435 1 : ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout_str());
8436 :
8437 1 : check("struct S {\n"
8438 : " int* ptr;\n"
8439 : "};\n"
8440 : "void foo(S* first) {\n"
8441 : " if (first.ptr >= 0) {}\n"
8442 : "}");
8443 1 : ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n"
8444 : "[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n",
8445 : errout_str());
8446 :
8447 1 : check("struct S {\n"
8448 : " int* ptr;\n"
8449 : "};\n"
8450 : "void foo(S* first, S* second) {\n"
8451 : " if((first.ptr - second.ptr) >= 0) {}\n"
8452 : "}");
8453 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8454 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8455 : errout_str());
8456 :
8457 1 : check("struct S {\n"
8458 : " int* ptr;\n"
8459 : "};\n"
8460 : "void foo(S* first) {\n"
8461 : " if((first.ptr) >= 0) {}\n"
8462 : "}");
8463 1 : ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n"
8464 : "[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n",
8465 : errout_str());
8466 :
8467 1 : check("struct S {\n"
8468 : " int* ptr;\n"
8469 : "};\n"
8470 : "void foo(S* first, S* second) {\n"
8471 : " if(0 <= first.ptr - second.ptr) {}\n"
8472 : "}");
8473 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8474 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8475 : errout_str());
8476 :
8477 1 : check("struct S {\n"
8478 : " int* ptr;\n"
8479 : "};\n"
8480 : "void foo(S* first, S* second) {\n"
8481 : " if(0 <= (first.ptr - second.ptr)) {}\n"
8482 : "}");
8483 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8484 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8485 : errout_str());
8486 :
8487 1 : check("struct S {\n"
8488 : " int* ptr;\n"
8489 : "};\n"
8490 : "void foo(S* first, S* second) {\n"
8491 : " if(first.ptr - second.ptr < 0) {}\n"
8492 : "}");
8493 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8494 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8495 : errout_str());
8496 :
8497 1 : check("struct S {\n"
8498 : " int* ptr;\n"
8499 : "};\n"
8500 : "void foo(S* first, S* second) {\n"
8501 : " if((first.ptr - second.ptr) < 0) {}\n"
8502 : "}");
8503 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8504 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8505 : errout_str());
8506 :
8507 1 : check("struct S {\n"
8508 : " int* ptr;\n"
8509 : "};\n"
8510 : "void foo(S* first, S* second) {\n"
8511 : " if(0 > first.ptr - second.ptr) {}\n"
8512 : "}");
8513 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8514 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8515 : errout_str());
8516 :
8517 1 : check("struct S {\n"
8518 : " int* ptr;\n"
8519 : "};\n"
8520 : "void foo(S* first, S* second) {\n"
8521 : " if(0 > (first.ptr - second.ptr)) {}\n"
8522 : "}");
8523 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
8524 : "[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
8525 : errout_str());
8526 :
8527 1 : check("void foo(const int* x) {\n"
8528 : " if (0 <= x[0]) {}\n"
8529 : "}");
8530 1 : ASSERT_EQUALS("", errout_str());
8531 :
8532 1 : check("void foo(Bar* x) {\n"
8533 : " if (0 <= x.y) {}\n"
8534 : "}");
8535 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
8536 :
8537 1 : check("void foo(Bar* x) {\n"
8538 : " if (0 <= x->y) {}\n"
8539 : "}");
8540 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
8541 :
8542 1 : check("void foo(Bar* x, Bar* y) {\n"
8543 : " if (0 <= x->y - y->y ) {}\n"
8544 : "}");
8545 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n"
8546 : "[test.cpp:1]: (style) Parameter 'y' can be declared as pointer to const\n",
8547 : errout_str());
8548 :
8549 1 : check("void foo(const Bar* x) {\n"
8550 : " if (0 > x) {}\n"
8551 : "}");
8552 1 : ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout_str());
8553 :
8554 1 : check("void foo(const int* x) {\n"
8555 : " if (0 > x[0]) {}\n"
8556 : "}");
8557 1 : ASSERT_EQUALS("", errout_str());
8558 :
8559 1 : check("void foo(Bar* x) {\n"
8560 : " if (0 > x.y) {}\n"
8561 : "}");
8562 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
8563 :
8564 1 : check("void foo(Bar* x) {\n"
8565 : " if (0 > x->y) {}\n"
8566 : "}");
8567 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout_str());
8568 :
8569 1 : check("void foo() {\n"
8570 : " int (*t)(void *a, void *b);\n"
8571 : " if (t(a, b) < 0) {}\n"
8572 : "}");
8573 1 : ASSERT_EQUALS("", errout_str());
8574 :
8575 1 : check("void foo() {\n"
8576 : " int (*t)(void *a, void *b);\n"
8577 : " if (0 > t(a, b)) {}\n"
8578 : "}");
8579 1 : ASSERT_EQUALS("", errout_str());
8580 :
8581 1 : check("struct object_info { int *typep; };\n"
8582 : "void packed_object_info(struct object_info *oi) {\n"
8583 : " if (oi->typep < 0);\n"
8584 : "}");
8585 1 : ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n"
8586 : "[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n",
8587 : errout_str());
8588 :
8589 1 : check("struct object_info { int typep[10]; };\n"
8590 : "void packed_object_info(struct object_info *oi) {\n"
8591 : " if (oi->typep < 0);\n"
8592 : "}");
8593 1 : ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n"
8594 : "[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n",
8595 : errout_str());
8596 :
8597 1 : check("struct object_info { int *typep; };\n"
8598 : "void packed_object_info(struct object_info *oi) {\n"
8599 : " if (*oi->typep < 0);\n"
8600 : "}");
8601 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n", errout_str());
8602 : }
8603 :
8604 1 : void checkSuspiciousSemicolon1() {
8605 1 : check("void foo() {\n"
8606 : " for(int i = 0; i < 10; ++i);\n"
8607 : "}");
8608 1 : ASSERT_EQUALS("", errout_str());
8609 :
8610 : // Empty block
8611 1 : check("void foo() {\n"
8612 : " for(int i = 0; i < 10; ++i); {\n"
8613 : " }\n"
8614 : "}");
8615 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious use of ; at the end of 'for' statement.\n", errout_str());
8616 :
8617 1 : check("void foo() {\n"
8618 : " while (!quit); {\n"
8619 : " do_something();\n"
8620 : " }\n"
8621 : "}");
8622 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious use of ; at the end of 'while' statement.\n", errout_str());
8623 : }
8624 :
8625 1 : void checkSuspiciousSemicolon2() {
8626 1 : check("void foo() {\n"
8627 : " if (i == 1); {\n"
8628 : " do_something();\n"
8629 : " }\n"
8630 : "}");
8631 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious use of ; at the end of 'if' statement.\n", errout_str());
8632 :
8633 : // Seen this in the wild
8634 1 : check("void foo() {\n"
8635 : " if (Match());\n"
8636 : " do_something();\n"
8637 : "}");
8638 1 : ASSERT_EQUALS("", errout_str());
8639 :
8640 1 : check("void foo() {\n"
8641 : " if (Match());\n"
8642 : " else\n"
8643 : " do_something();\n"
8644 : "}");
8645 1 : ASSERT_EQUALS("", errout_str());
8646 :
8647 1 : check("void foo() {\n"
8648 : " if (i == 1)\n"
8649 : " ;\n"
8650 : " {\n"
8651 : " do_something();\n"
8652 : " }\n"
8653 : "}");
8654 1 : ASSERT_EQUALS("", errout_str());
8655 :
8656 1 : check("void foo() {\n"
8657 : " if (i == 1);\n"
8658 : "\n"
8659 : " {\n"
8660 : " do_something();\n"
8661 : " }\n"
8662 : "}");
8663 1 : ASSERT_EQUALS("", errout_str());
8664 : }
8665 :
8666 1 : void checkSuspiciousSemicolon3() {
8667 1 : checkP("#define REQUIRE(code) {code}\n"
8668 : "void foo() {\n"
8669 : " if (x == 123);\n"
8670 : " REQUIRE(y=z);\n"
8671 : "}");
8672 1 : ASSERT_EQUALS("", errout_str());
8673 : }
8674 :
8675 1 : void checkSuspiciousComparison() {
8676 1 : checkP("void f(int a, int b) {\n"
8677 : " a > b;\n"
8678 : "}");
8679 1 : ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Found suspicious operator '>', result is not used.\n", errout_str());
8680 :
8681 1 : checkP("void f() {\n" // #10607
8682 : " for (auto p : m)\n"
8683 : " std::vector<std::pair<std::string, std::string>> k;\n"
8684 : "}");
8685 1 : ASSERT_EQUALS("", errout_str());
8686 : }
8687 :
8688 1 : void checkInvalidFree() {
8689 1 : check("void foo(char *p) {\n"
8690 : " char *a; a = malloc(1024);\n"
8691 : " free(a + 10);\n"
8692 : "}");
8693 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching address is freed. The address you get from malloc() must be freed without offset.\n", errout_str());
8694 :
8695 1 : check("void foo(char *p) {\n"
8696 : " char *a; a = malloc(1024);\n"
8697 : " free(a - 10);\n"
8698 : "}");
8699 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching address is freed. The address you get from malloc() must be freed without offset.\n", errout_str());
8700 :
8701 1 : check("void foo(char *p) {\n"
8702 : " char *a; a = malloc(1024);\n"
8703 : " free(10 + a);\n"
8704 : "}");
8705 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching address is freed. The address you get from malloc() must be freed without offset.\n", errout_str());
8706 :
8707 1 : check("void foo(char *p) {\n"
8708 : " char *a; a = new char[1024];\n"
8709 : " delete[] (a + 10);\n"
8710 : "}");
8711 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n"
8712 : "[test.cpp:3]: (error) Mismatching address is deleted. The address you get from new must be deleted without offset.\n",
8713 : errout_str());
8714 :
8715 1 : check("void foo(char *p) {\n"
8716 : " char *a; a = new char;\n"
8717 : " delete a + 10;\n"
8718 : "}");
8719 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n"
8720 : "[test.cpp:3]: (error) Mismatching address is deleted. The address you get from new must be deleted without offset.\n",
8721 : errout_str());
8722 :
8723 1 : check("void foo(char *p) {\n"
8724 : " char *a; a = new char;\n"
8725 : " bar(a);\n"
8726 : " delete a + 10;\n"
8727 : "}");
8728 1 : ASSERT_EQUALS("", errout_str());
8729 :
8730 1 : check("void foo(char *p) {\n"
8731 : " char *a; a = new char;\n"
8732 : " char *b; b = new char;\n"
8733 : " bar(a);\n"
8734 : " delete a + 10;\n"
8735 : " delete b + 10;\n"
8736 : "}");
8737 1 : ASSERT_EQUALS("[test.cpp:6]: (error) Mismatching address is deleted. The address you get from new must be deleted without offset.\n", errout_str());
8738 :
8739 1 : check("void foo(char *p) {\n"
8740 : " char *a; a = new char;\n"
8741 : " char *b; b = new char;\n"
8742 : " bar(a, b);\n"
8743 : " delete a + 10;\n"
8744 : " delete b + 10;\n"
8745 : "}");
8746 1 : ASSERT_EQUALS("", errout_str());
8747 :
8748 1 : check("void foo(char *p) {\n"
8749 : " char *a; a = new char;\n"
8750 : " bar()\n"
8751 : " delete a + 10;\n"
8752 : "}");
8753 1 : ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n"
8754 : "[test.cpp:4]: (error) Mismatching address is deleted. The address you get from new must be deleted without offset.\n",
8755 : errout_str());
8756 :
8757 1 : check("void foo(size_t xx) {\n"
8758 : " char *ptr; ptr = malloc(42);\n"
8759 : " ptr += xx;\n"
8760 : " free(ptr + 1 - xx);\n"
8761 : "}");
8762 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Mismatching address is freed. The address you get from malloc() must be freed without offset.\n", errout_str());
8763 :
8764 1 : check("void foo(size_t xx) {\n"
8765 : " char *ptr; ptr = malloc(42);\n"
8766 : " std::cout << ptr;\n"
8767 : " ptr = otherPtr;\n"
8768 : " free(otherPtr - xx - 1);\n"
8769 : "}");
8770 1 : ASSERT_EQUALS(
8771 : "[test.cpp:2]: (style) Variable 'ptr' can be declared as pointer to const\n",
8772 : errout_str());
8773 : }
8774 :
8775 1 : void checkRedundantCopy() {
8776 1 : check("const std::string& getA(){static std::string a;return a;}\n"
8777 : "void foo() {\n"
8778 : " const std::string a = getA();\n"
8779 : "}");
8780 1 : ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Use const reference for 'a' to avoid unnecessary data copying.\n", errout_str());
8781 :
8782 1 : check("class A { public: A() {} char x[100]; };\n"
8783 : "const A& getA(){static A a;return a;}\n"
8784 : "int main()\n"
8785 : "{\n"
8786 : " const A a = getA();\n"
8787 : " return 0;\n"
8788 : "}");
8789 1 : ASSERT_EQUALS("[test.cpp:5]: (performance, inconclusive) Use const reference for 'a' to avoid unnecessary data copying.\n", errout_str());
8790 :
8791 1 : check("const int& getA(){static int a;return a;}\n"
8792 : "int main()\n"
8793 : "{\n"
8794 : " const int a = getA();\n"
8795 : " return 0;\n"
8796 : "}");
8797 1 : ASSERT_EQUALS("", errout_str());
8798 :
8799 1 : check("const int& getA(){static int a;return a;}\n"
8800 : "int main()\n"
8801 : "{\n"
8802 : " int getA = 0;\n"
8803 : " const int a = getA + 3;\n"
8804 : " return 0;\n"
8805 : "}");
8806 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:4]: (style) Local variable \'getA\' shadows outer function\n", errout_str());
8807 :
8808 1 : check("class A { public: A() {} char x[100]; };\n"
8809 : "const A& getA(){static A a;return a;}\n"
8810 : "int main()\n"
8811 : "{\n"
8812 : " const A a(getA());\n"
8813 : " return 0;\n"
8814 : "}");
8815 1 : ASSERT_EQUALS("[test.cpp:5]: (performance, inconclusive) Use const reference for 'a' to avoid unnecessary data copying.\n", errout_str());
8816 :
8817 1 : check("const int& getA(){static int a;return a;}\n"
8818 : "int main()\n"
8819 : "{\n"
8820 : " const int a(getA());\n"
8821 : " return 0;\n"
8822 : "}");
8823 1 : ASSERT_EQUALS("", errout_str());
8824 :
8825 1 : check("class A{\n"
8826 : "public:A(int a=0){_a = a;}\n"
8827 : "A operator+(const A & a){return A(_a+a._a);}\n"
8828 : "private:int _a;};\n"
8829 : "const A& getA(){static A a;return a;}\n"
8830 : "int main()\n"
8831 : "{\n"
8832 : " const A a = getA() + 1;\n"
8833 : " return 0;\n"
8834 : "}");
8835 1 : ASSERT_EQUALS("", errout_str());
8836 :
8837 1 : check("class A{\n"
8838 : "public:A(int a=0){_a = a;}\n"
8839 : "A operator+(const A & a){return A(_a+a._a);}\n"
8840 : "private:int _a;};\n"
8841 : "const A& getA(){static A a;return a;}\n"
8842 : "int main()\n"
8843 : "{\n"
8844 : " const A a(getA()+1);\n"
8845 : " return 0;\n"
8846 : "}");
8847 1 : ASSERT_EQUALS("", errout_str());
8848 :
8849 : // #5190 - FP when creating object with constructor that takes a reference
8850 1 : check("class A {};\n"
8851 : "class B { B(const A &a); };\n"
8852 : "const A &getA();\n"
8853 : "void f() {\n"
8854 : " const B b(getA());\n"
8855 : "}");
8856 1 : ASSERT_EQUALS("", errout_str());
8857 :
8858 1 : check("class A {};\n"
8859 : "class B { B(const A& a); };\n"
8860 : "const A& getA();\n"
8861 : "void f() {\n"
8862 : " const B b{ getA() };\n"
8863 : "}");
8864 1 : ASSERT_EQUALS("", errout_str());
8865 :
8866 : // #5618
8867 1 : const char* code5618 = "class Token {\n"
8868 : "public:\n"
8869 : " const std::string& str();\n"
8870 : "};\n"
8871 : "void simplifyArrayAccessSyntax() {\n"
8872 : " for (Token *tok = list.front(); tok; tok = tok->next()) {\n"
8873 : " const std::string temp = tok->str();\n"
8874 : " tok->str(tok->strAt(2));\n"
8875 : " }\n"
8876 : "}";
8877 1 : check(code5618, true, true);
8878 1 : ASSERT_EQUALS("", errout_str());
8879 1 : check(code5618, true, false);
8880 1 : ASSERT_EQUALS("", errout_str());
8881 :
8882 : // #5890 - crash: wesnoth desktop_util.cpp / unicode.hpp
8883 1 : check("typedef std::vector<char> X;\n"
8884 : "X f<X>(const X &in) {\n"
8885 : " const X s = f<X>(in);\n"
8886 : " return f<X>(s);\n"
8887 : "}");
8888 1 : ASSERT_EQUALS("", errout_str());
8889 :
8890 : // #7981 - False positive redundantCopyLocalConst - const ref argument to ctor
8891 1 : check("class CD {\n"
8892 : " public:\n"
8893 : " CD(const CD&);\n"
8894 : " static const CD& getOne();\n"
8895 : "};\n"
8896 : " \n"
8897 : "void foo() {\n"
8898 : " const CD cd(CD::getOne());\n"
8899 : "}", true, true);
8900 1 : ASSERT_EQUALS("", errout_str());
8901 :
8902 1 : check("struct S {\n" // #10545
8903 : " int modify();\n"
8904 : " const std::string& get() const;\n"
8905 : "};\n"
8906 : "std::string f(S& s) {\n"
8907 : " const std::string old = s.get();\n"
8908 : " int i = s.modify();\n"
8909 : " if (i != 0)\n"
8910 : " return old;\n"
8911 : " return {};\n"
8912 : "}", true, /*inconclusive*/ true);
8913 1 : ASSERT_EQUALS("", errout_str());
8914 :
8915 1 : check("struct X { int x; };\n" // #10191
8916 : "struct S {\n"
8917 : " X _x;\n"
8918 : " X& get() { return _x; }\n"
8919 : " void modify() { _x.x += 42; }\n"
8920 : " int copy() {\n"
8921 : " const X x = get();\n"
8922 : " modify();\n"
8923 : " return x.x;\n"
8924 : " }\n"
8925 : " int constref() {\n"
8926 : " const X& x = get();\n"
8927 : " modify();\n"
8928 : " return x.x;\n"
8929 : " }\n"
8930 : "};\n", true, /*inconclusive*/ true);
8931 1 : ASSERT_EQUALS("", errout_str());
8932 :
8933 : // #10704
8934 1 : check("struct C {\n"
8935 : " std::string str;\n"
8936 : " const std::string& get() const { return str; }\n"
8937 : "};\n"
8938 : "struct D {\n"
8939 : " C c;\n"
8940 : " bool f() const {\n"
8941 : " std::string s = c.get();\n"
8942 : " return s.empty();\n"
8943 : " }\n"
8944 : "};\n");
8945 1 : ASSERT_EQUALS("[test.cpp:8]: (performance, inconclusive) Use const reference for 's' to avoid unnecessary data copying.\n", errout_str());
8946 :
8947 1 : check("struct C {\n"
8948 : " const std::string & get() const { return m; }\n"
8949 : " std::string m;\n"
8950 : "};\n"
8951 : "C getC();\n"
8952 : "void f() {\n"
8953 : " const std::string s = getC().get();\n"
8954 : "}\n"
8955 : "void g() {\n"
8956 : " std::string s = getC().get();\n"
8957 : "}\n");
8958 1 : ASSERT_EQUALS("", errout_str());
8959 :
8960 1 : check("struct S {\n" // #12139
8961 : " int x, y;\n"
8962 : "};\n"
8963 : "struct T {\n"
8964 : " S s;\n"
8965 : " const S& get() const { return s; }\n"
8966 : "};\n"
8967 : "void f(const T& t) {\n"
8968 : " const S a = t.get();\n"
8969 : " if (a.x > a.y) {}\n"
8970 : "}\n");
8971 1 : ASSERT_EQUALS("", errout_str());
8972 : }
8973 :
8974 1 : void checkNegativeShift() {
8975 1 : check("void foo()\n"
8976 : "{\n"
8977 : " int a; a = 123;\n"
8978 : " (void)(a << -1);\n"
8979 : "}");
8980 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Shifting by a negative value is undefined behaviour\n", errout_str());
8981 1 : check("void foo()\n"
8982 : "{\n"
8983 : " int a; a = 123;\n"
8984 : " (void)(a >> -1);\n"
8985 : "}");
8986 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Shifting by a negative value is undefined behaviour\n", errout_str());
8987 1 : check("void foo()\n"
8988 : "{\n"
8989 : " int a; a = 123;\n"
8990 : " a <<= -1;\n"
8991 : "}");
8992 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Shifting by a negative value is undefined behaviour\n", errout_str());
8993 1 : check("void foo()\n"
8994 : "{\n"
8995 : " int a; a = 123;\n"
8996 : " a >>= -1;\n"
8997 : "}");
8998 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Shifting by a negative value is undefined behaviour\n", errout_str());
8999 1 : check("void foo()\n"
9000 : "{\n"
9001 : " std::cout << -1;\n"
9002 : "}");
9003 1 : ASSERT_EQUALS("", errout_str());
9004 1 : check("void foo()\n"
9005 : "{\n"
9006 : " std::cout << a << -1 ;\n"
9007 : "}");
9008 1 : ASSERT_EQUALS("", errout_str());
9009 1 : check("void foo()\n"
9010 : "{\n"
9011 : " std::cout << 3 << -1 ;\n"
9012 : "}");
9013 1 : ASSERT_EQUALS("", errout_str());
9014 1 : check("void foo() {\n"
9015 : " x = (-10+2) << 3;\n"
9016 : "}");
9017 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Shifting a negative value is technically undefined behaviour\n", errout_str());
9018 :
9019 1 : check("x = y ? z << $-1 : 0;");
9020 1 : ASSERT_EQUALS("", errout_str());
9021 :
9022 : // Negative LHS
9023 1 : check("const int x = -1 >> 2;");
9024 1 : ASSERT_EQUALS("[test.cpp:1]: (portability) Shifting a negative value is technically undefined behaviour\n", errout_str());
9025 :
9026 : // #6383 - unsigned type
9027 1 : check("const int x = (unsigned int)(-1) >> 2;");
9028 1 : ASSERT_EQUALS("", errout_str());
9029 :
9030 : // #7814 - UB happening in valueflowcode when it tried to compute shifts.
9031 1 : check("int shift1() { return 1 >> -1 ;}\n"
9032 : "int shift2() { return 1 << -1 ;}\n"
9033 : "int shift3() { return -1 >> 1 ;}\n"
9034 : "int shift4() { return -1 << 1 ;}");
9035 1 : ASSERT_EQUALS("[test.cpp:1]: (error) Shifting by a negative value is undefined behaviour\n"
9036 : "[test.cpp:2]: (error) Shifting by a negative value is undefined behaviour\n"
9037 : "[test.cpp:3]: (portability) Shifting a negative value is technically undefined behaviour\n"
9038 : "[test.cpp:4]: (portability) Shifting a negative value is technically undefined behaviour\n", errout_str());
9039 : }
9040 :
9041 1 : void incompleteArrayFill() {
9042 1 : check("void f() {\n"
9043 : " int a[5];\n"
9044 : " memset(a, 123, 5);\n"
9045 : " memcpy(a, b, 5);\n"
9046 : " memmove(a, b, 5);\n"
9047 : "}");
9048 1 : ASSERT_EQUALS(// TODO "[test.cpp:4] -> [test.cpp:5]: (performance) Buffer 'a' is being written before its old content has been used.\n"
9049 : "[test.cpp:3]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n"
9050 : "[test.cpp:4]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memcpy()' with 'sizeof(*a)'?\n"
9051 : "[test.cpp:5]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memmove()' with 'sizeof(*a)'?\n", errout_str());
9052 :
9053 1 : check("int a[5];\n"
9054 : "namespace Z { struct B { int a[5]; } b; }\n"
9055 : "void f() {\n"
9056 : " memset(::a, 123, 5);\n"
9057 : " memset(Z::b.a, 123, 5);\n"
9058 : "}");
9059 1 : TODO_ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Array '::a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*::a)'?\n"
9060 : "[test.cpp:5]: (warning, inconclusive) Array 'Z::b.a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*Z::b.a)'?\n",
9061 : "[test.cpp:4]: (warning, inconclusive) Array '::a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*::a)'?\n", errout_str());
9062 :
9063 1 : check("void f() {\n"
9064 : " Foo* a[5];\n"
9065 : " memset(a, 'a', 5);\n"
9066 : "}");
9067 1 : ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n", errout_str());
9068 :
9069 1 : check("class Foo {int a; int b;};\n"
9070 : "void f() {\n"
9071 : " Foo a[5];\n"
9072 : " memset(a, 'a', 5);\n"
9073 : "}");
9074 1 : ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n", errout_str());
9075 :
9076 1 : check("void f() {\n"
9077 : " Foo a[5];\n" // Size of foo is unknown
9078 : " memset(a, 'a', 5);\n"
9079 : "}");
9080 1 : ASSERT_EQUALS("", errout_str());
9081 :
9082 1 : check("void f() {\n"
9083 : " char a[5];\n"
9084 : " memset(a, 'a', 5);\n"
9085 : "}");
9086 1 : ASSERT_EQUALS("", errout_str());
9087 :
9088 1 : check("void f() {\n"
9089 : " int a[5];\n"
9090 : " memset(a+15, 'a', 5);\n"
9091 : "}");
9092 1 : ASSERT_EQUALS("", errout_str());
9093 :
9094 1 : check("void f() {\n"
9095 : " bool a[5];\n"
9096 : " memset(a, false, 5);\n"
9097 : "}");
9098 1 : ASSERT_EQUALS("[test.cpp:3]: (portability, inconclusive) Array 'a' might be filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n", errout_str());
9099 : }
9100 :
9101 1 : void redundantVarAssignment() {
9102 1 : setMultiline();
9103 :
9104 : // Simple tests
9105 1 : check("void f(int i) {\n"
9106 : " i = 1;\n"
9107 : " i = 1;\n"
9108 : "}");
9109 1 : ASSERT_EQUALS("test.cpp:3:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9110 : "test.cpp:2:note:i is assigned\n"
9111 : "test.cpp:3:note:i is overwritten\n", errout_str());
9112 :
9113 : // non-local variable => only show warning when inconclusive is used
9114 1 : check("int i;\n"
9115 : "void f() {\n"
9116 : " i = 1;\n"
9117 : " i = 1;\n"
9118 : "}");
9119 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9120 : "test.cpp:3:note:i is assigned\n"
9121 : "test.cpp:4:note:i is overwritten\n", errout_str());
9122 :
9123 1 : check("void f() {\n"
9124 : " int i;\n"
9125 : " i = 1;\n"
9126 : " i = 1;\n"
9127 : "}");
9128 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9129 : "test.cpp:3:note:i is assigned\n"
9130 : "test.cpp:4:note:i is overwritten\n", errout_str());
9131 :
9132 1 : check("void f() {\n"
9133 : " static int i;\n"
9134 : " i = 1;\n"
9135 : " i = 1;\n"
9136 : "}");
9137 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
9138 :
9139 1 : check("void f() {\n"
9140 : " int i[10];\n"
9141 : " i[2] = 1;\n"
9142 : " i[2] = 1;\n"
9143 : "}");
9144 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'i[2]' is reassigned a value before the old one has been used.\n"
9145 : "test.cpp:3:note:i[2] is assigned\n"
9146 : "test.cpp:4:note:i[2] is overwritten\n", errout_str());
9147 :
9148 1 : check("void f(int x) {\n"
9149 : " int i[10];\n"
9150 : " i[x] = 1;\n"
9151 : " x=1;\n"
9152 : " i[x] = 1;\n"
9153 : "}");
9154 1 : ASSERT_EQUALS("", errout_str());
9155 :
9156 1 : check("void f(const int x) {\n"
9157 : " int i[10];\n"
9158 : " i[x] = 1;\n"
9159 : " i[x] = 1;\n"
9160 : "}");
9161 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'i[x]' is reassigned a value before the old one has been used.\n"
9162 : "test.cpp:3:note:i[x] is assigned\n"
9163 : "test.cpp:4:note:i[x] is overwritten\n", errout_str());
9164 :
9165 : // Testing different types
9166 1 : check("void f() {\n"
9167 : " Foo& bar = foo();\n"
9168 : " bar = x;\n"
9169 : "}");
9170 1 : ASSERT_EQUALS("", errout_str());
9171 :
9172 1 : check("void f() {\n"
9173 : " Foo& bar = foo();\n"
9174 : " bar = x;\n"
9175 : " bar = y;\n"
9176 : "}");
9177 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
9178 :
9179 1 : check("void f() {\n"
9180 : " Foo& bar = foo();\n" // #4425. bar might refer to something global, etc.
9181 : " bar = y();\n"
9182 : " foo();\n"
9183 : " bar = y();\n"
9184 : "}");
9185 1 : ASSERT_EQUALS("", errout_str());
9186 :
9187 : // Tests with function call between assignment
9188 1 : check("void f(int i) {\n"
9189 : " i = 1;\n"
9190 : " bar();\n"
9191 : " i = 1;\n"
9192 : "}");
9193 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9194 : "test.cpp:2:note:i is assigned\n"
9195 : "test.cpp:4:note:i is overwritten\n", errout_str());
9196 :
9197 1 : check("int i;\n"
9198 : "void f() {\n"
9199 : " i = 1;\n"
9200 : " bar();\n" // Global variable might be accessed in bar()
9201 : " i = 1;\n"
9202 : "}");
9203 1 : ASSERT_EQUALS("", errout_str());
9204 :
9205 1 : check("void f() {\n"
9206 : " static int i;\n"
9207 : " i = 1;\n"
9208 : " bar();\n" // bar() might call f() recursively. This could be a false positive in more complex examples (when value of i is used somewhere. See #4229)
9209 : " i = 2;\n"
9210 : "}");
9211 1 : ASSERT_EQUALS("", errout_str());
9212 :
9213 1 : check("void f() {\n"
9214 : " int i;\n"
9215 : " i = 1;\n"
9216 : " bar();\n"
9217 : " i = 1;\n"
9218 : "}");
9219 1 : ASSERT_EQUALS("test.cpp:5:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9220 : "test.cpp:3:note:i is assigned\n"
9221 : "test.cpp:5:note:i is overwritten\n", errout_str());
9222 :
9223 1 : check("void bar(int i) {}\n"
9224 : "void f(int i) {\n"
9225 : " i = 1;\n"
9226 : " bar(i);\n" // Passed as argument
9227 : " i = 1;\n"
9228 : "}");
9229 1 : ASSERT_EQUALS("", errout_str());
9230 :
9231 1 : check("void f() {\n"
9232 : " Foo bar = foo();\n"
9233 : " bar();\n" // #5568. operator() called
9234 : " bar = y();\n"
9235 : "}");
9236 1 : ASSERT_EQUALS("", errout_str());
9237 :
9238 : // Branch tests
9239 1 : check("void f(int i) {\n"
9240 : " i = 1;\n"
9241 : " if(x)\n"
9242 : " i = 0;\n"
9243 : "}");
9244 1 : ASSERT_EQUALS("", errout_str());
9245 :
9246 1 : check("void f(int i) {\n"
9247 : " if(x)\n"
9248 : " i = 0;\n"
9249 : " i = 1;\n"
9250 : " i = 2;\n"
9251 : "}");
9252 1 : ASSERT_EQUALS("test.cpp:5:style:Variable 'i' is reassigned a value before the old one has been used.\n"
9253 : "test.cpp:4:note:i is assigned\n"
9254 : "test.cpp:5:note:i is overwritten\n", errout_str());
9255 :
9256 : // #4513
9257 1 : check("int x;\n"
9258 : "int g() {\n"
9259 : " return x*x;\n"
9260 : "}\n"
9261 : "void f() {\n"
9262 : " x = 2;\n"
9263 : " x = g();\n"
9264 : "}");
9265 1 : ASSERT_EQUALS("", errout_str());
9266 :
9267 1 : check("int g() {\n"
9268 : " return x*x;\n"
9269 : "}\n"
9270 : "void f(int x) {\n"
9271 : " x = 2;\n"
9272 : " x = g();\n"
9273 : "}");
9274 1 : ASSERT_EQUALS("test.cpp:6:style:Variable 'x' is reassigned a value before the old one has been used.\n"
9275 : "test.cpp:5:note:x is assigned\n"
9276 : "test.cpp:6:note:x is overwritten\n", errout_str());
9277 :
9278 1 : check("void f() {\n"
9279 : " Foo& bar = foo();\n"
9280 : " bar = x;\n"
9281 : " bar = y();\n"
9282 : "}");
9283 1 : ASSERT_EQUALS("", errout_str());
9284 :
9285 1 : check("class C {\n"
9286 : " int x;\n"
9287 : " void g() { return x * x; }\n"
9288 : " void f();\n"
9289 : "};\n"
9290 : "\n"
9291 : "void C::f() {\n"
9292 : " x = 2;\n"
9293 : " x = g();\n"
9294 : "}");
9295 1 : ASSERT_EQUALS("", errout_str());
9296 :
9297 1 : check("class C {\n"
9298 : " int x;\n"
9299 : " void g() { return x*x; }\n"
9300 : " void f(Foo z);\n"
9301 : "};\n"
9302 : "\n"
9303 : "void C::f(Foo z) {\n"
9304 : " x = 2;\n"
9305 : " x = z.g();\n"
9306 : "}");
9307 1 : ASSERT_EQUALS("", errout_str());
9308 :
9309 : // ({ })
9310 1 : check("void f() {\n"
9311 : " int x;\n"
9312 : " x = 321;\n"
9313 : " x = ({ asm(123); })\n"
9314 : "}");
9315 1 : ASSERT_EQUALS("", errout_str());
9316 :
9317 : // from #3103 (avoid a false negative)
9318 1 : check("int foo(){\n"
9319 : " int x;\n"
9320 : " x = 1;\n"
9321 : " x = 1;\n"
9322 : " return x + 1;\n"
9323 : "}");
9324 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'x' is reassigned a value before the old one has been used.\n"
9325 : "test.cpp:3:note:x is assigned\n"
9326 : "test.cpp:4:note:x is overwritten\n", errout_str());
9327 :
9328 : // from #3103 (avoid a false positive)
9329 1 : check("int foo(){\n"
9330 : " int x;\n"
9331 : " x = 1;\n"
9332 : " if (y)\n" // <-- cppcheck does not know anything about 'y'
9333 : " x = 2;\n"
9334 : " return x + 1;\n"
9335 : "}");
9336 1 : ASSERT_EQUALS("", errout_str());
9337 :
9338 : // initialization, assignment with 0
9339 1 : check("void f() {\n" // Ticket #4356
9340 : " int x = 0;\n" // <- ignore initialization with 0
9341 : " x = 3;\n"
9342 : "}");
9343 1 : ASSERT_EQUALS("", errout_str());
9344 :
9345 1 : check("void f() {\n"
9346 : " state_t *x = NULL;\n"
9347 : " x = dostuff();\n"
9348 : "}");
9349 1 : ASSERT_EQUALS(
9350 : "test.cpp:2:style:Variable 'x' can be declared as pointer to const\n",
9351 : errout_str());
9352 :
9353 1 : check("void f() {\n"
9354 : " state_t *x;\n"
9355 : " x = NULL;\n"
9356 : " x = dostuff();\n"
9357 : "}");
9358 1 : ASSERT_EQUALS(
9359 : "test.cpp:2:style:Variable 'x' can be declared as pointer to const\n",
9360 : errout_str());
9361 :
9362 1 : check("int foo() {\n" // #4420
9363 : " int x;\n"
9364 : " bar(++x);\n"
9365 : " x = 5;\n"
9366 : " return bar(x);\n"
9367 : "}");
9368 1 : ASSERT_EQUALS("", errout_str());
9369 :
9370 : // struct member..
9371 1 : check("struct AB { int a; int b; };\n"
9372 : "\n"
9373 : "int f() {\n"
9374 : " struct AB ab;\n"
9375 : " ab.a = 1;\n"
9376 : " ab.a = 2;\n"
9377 : " return ab.a;\n"
9378 : "}");
9379 1 : ASSERT_EQUALS("test.cpp:6:style:Variable 'ab.a' is reassigned a value before the old one has been used.\n"
9380 : "test.cpp:5:note:ab.a is assigned\n"
9381 : "test.cpp:6:note:ab.a is overwritten\n", errout_str());
9382 :
9383 1 : check("struct AB { int a; int b; };\n"
9384 : "\n"
9385 : "int f() {\n"
9386 : " struct AB ab;\n"
9387 : " ab.a = 1;\n"
9388 : " ab = do_something();\n"
9389 : " return ab.a;\n"
9390 : "}");
9391 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
9392 :
9393 1 : check("struct AB { int a; int b; };\n"
9394 : "\n"
9395 : "int f() {\n"
9396 : " struct AB ab;\n"
9397 : " ab.a = 1;\n"
9398 : " do_something(&ab);\n"
9399 : " ab.a = 2;\n"
9400 : " return ab.a;\n"
9401 : "}");
9402 1 : ASSERT_EQUALS("", errout_str());
9403 :
9404 1 : check("struct AB { int a; int b; };\n"
9405 : "\n"
9406 : "int f(DO_SOMETHING do_something) {\n"
9407 : " struct AB ab;\n"
9408 : " ab.a = 1;\n"
9409 : " do_something(&ab);\n"
9410 : " ab.a = 2;\n"
9411 : " return ab.a;\n"
9412 : "}");
9413 1 : ASSERT_EQUALS("", errout_str());
9414 :
9415 1 : check("struct AB { int a; int b; };\n"
9416 : "\n"
9417 : "int f(struct AB *ab) {\n"
9418 : " ab->a = 1;\n"
9419 : " ab->b = 2;\n"
9420 : " ab++;\n"
9421 : " ab->a = 1;\n"
9422 : " ab->b = 2;\n"
9423 : "}");
9424 1 : ASSERT_EQUALS("", errout_str());
9425 :
9426 1 : check("struct AB { int a; int b; };\n"
9427 : "\n"
9428 : "int f(struct AB *ab) {\n"
9429 : " ab->a = 1;\n"
9430 : " ab->b = 2;\n"
9431 : " ab = x;\n"
9432 : " ab->a = 1;\n"
9433 : " ab->b = 2;\n"
9434 : "}");
9435 1 : ASSERT_EQUALS("", errout_str());
9436 :
9437 1 : check("void f(struct AB *ab) {\n" // #
9438 : " ab->data->x = 1;\n"
9439 : " ab = &ab1;\n"
9440 : " ab->data->x = 2;\n"
9441 : "}");
9442 1 : ASSERT_EQUALS("", errout_str());
9443 :
9444 : // #5964
9445 1 : check("void func(char *buffer, const char *format, int precision, unsigned value) {\n"
9446 : " (precision < 0) ? sprintf(buffer, format, value) : sprintf(buffer, format, precision, value);\n"
9447 : "}");
9448 1 : ASSERT_EQUALS("", errout_str());
9449 :
9450 : // don't crash
9451 1 : check("struct data {\n"
9452 : " struct { int i; } fc;\n"
9453 : "};\n"
9454 : "struct state {\n"
9455 : " struct data d[123];\n"
9456 : "};\n"
9457 : "void func(struct state *s) {\n"
9458 : " s->foo[s->x++] = 2;\n"
9459 : " s->d[1].fc.i++;\n"
9460 : "}");
9461 :
9462 : // #6525 - inline assembly
9463 1 : check("void f(int i) {\n"
9464 : " i = 1;\n"
9465 : " asm(\"foo\");\n"
9466 : " i = 1;\n"
9467 : "}");
9468 1 : ASSERT_EQUALS("", errout_str());
9469 :
9470 : // #6555
9471 1 : check("void foo() {\n"
9472 : " char *p = 0;\n"
9473 : " try {\n"
9474 : " p = fred();\n"
9475 : " p = wilma();\n"
9476 : " }\n"
9477 : " catch (...) {\n"
9478 : " barney(p);\n"
9479 : " }\n"
9480 : "}");
9481 1 : ASSERT_EQUALS("", errout_str());
9482 :
9483 1 : check("void foo() {\n"
9484 : " char *p = 0;\n"
9485 : " try {\n"
9486 : " p = fred();\n"
9487 : " p = wilma();\n"
9488 : " }\n"
9489 : " catch (...) {\n"
9490 : " barney(x);\n"
9491 : " }\n"
9492 : "}");
9493 1 : ASSERT_EQUALS("test.cpp:2:style:The scope of the variable 'p' can be reduced.\n"
9494 : "test.cpp:2:style:Variable 'p' can be declared as pointer to const\n",
9495 : errout_str());
9496 :
9497 1 : check("void foo() {\n"
9498 : " char *p = 0;\n"
9499 : " try {\n"
9500 : " if(z) {\n"
9501 : " p = fred();\n"
9502 : " p = wilma();\n"
9503 : " }\n"
9504 : " }\n"
9505 : " catch (...) {\n"
9506 : " barney(p);\n"
9507 : " }\n"
9508 : "}");
9509 1 : ASSERT_EQUALS("", errout_str());
9510 :
9511 : // Member variable pointers
9512 1 : check("void podMemPtrs() {\n"
9513 : " int POD::*memptr;\n"
9514 : " memptr = &POD::a;\n"
9515 : " memptr = &POD::b;\n"
9516 : " if (memptr)\n"
9517 : " memptr = 0;\n"
9518 : "}");
9519 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'memptr' is reassigned a value before the old one has been used.\n"
9520 : "test.cpp:3:note:memptr is assigned\n"
9521 : "test.cpp:4:note:memptr is overwritten\n", errout_str());
9522 :
9523 : // Pointer function argument (#3857)
9524 1 : check("void f(float * var)\n"
9525 : "{\n"
9526 : " var[0] = 0.2f;\n"
9527 : " var[0] = 0.2f;\n" // <-- is initialized twice
9528 : "}");
9529 1 : ASSERT_EQUALS("test.cpp:4:style:Variable 'var[0]' is reassigned a value before the old one has been used.\n"
9530 : "test.cpp:3:note:var[0] is assigned\n"
9531 : "test.cpp:4:note:var[0] is overwritten\n", errout_str());
9532 :
9533 1 : check("void f(float * var)\n"
9534 : "{\n"
9535 : " *var = 0.2f;\n"
9536 : " *var = 0.2f;\n" // <-- is initialized twice
9537 : "}");
9538 1 : ASSERT_EQUALS("test.cpp:4:style:Variable '*var' is reassigned a value before the old one has been used.\n"
9539 : "test.cpp:3:note:*var is assigned\n"
9540 : "test.cpp:4:note:*var is overwritten\n", errout_str());
9541 :
9542 : // Volatile variables
9543 1 : check("void f() {\n"
9544 : " volatile char *reg = (volatile char *)0x12345;\n"
9545 : " *reg = 12;\n"
9546 : " *reg = 34;\n"
9547 : "}");
9548 1 : ASSERT_EQUALS("test.cpp:2:style:C-style pointer casting\n", errout_str());
9549 :
9550 1 : check("void f(std::map<int, int>& m, int key, int value) {\n" // #6379
9551 : " m[key] = value;\n"
9552 : " m[key] = value;\n"
9553 : "}\n");
9554 1 : ASSERT_EQUALS("test.cpp:3:style:Variable 'm[key]' is reassigned a value before the old one has been used.\n"
9555 : "test.cpp:2:note:m[key] is assigned\n"
9556 : "test.cpp:3:note:m[key] is overwritten\n",
9557 : errout_str());
9558 : }
9559 :
9560 1 : void redundantVarAssignment_trivial() {
9561 1 : check("void f() {\n"
9562 : " int a = 0;\n"
9563 : " a = 4;\n"
9564 : "}");
9565 1 : ASSERT_EQUALS("", errout_str());
9566 :
9567 1 : check("void f() {\n"
9568 : " int a;\n"
9569 : " a = 0;\n"
9570 : " a = 4;\n"
9571 : "}");
9572 1 : ASSERT_EQUALS("", errout_str());
9573 :
9574 1 : check("void f() {\n"
9575 : " unsigned a;\n"
9576 : " a = 0u;\n"
9577 : " a = 2u;\n"
9578 : "}");
9579 1 : ASSERT_EQUALS("", errout_str());
9580 :
9581 1 : check("void f() {\n"
9582 : " void* a;\n"
9583 : " a = (void*)0;\n"
9584 : " a = p;\n"
9585 : "}");
9586 1 : ASSERT_EQUALS(
9587 : "[test.cpp:2]: (style) Variable 'a' can be declared as pointer to const\n",
9588 : errout_str());
9589 :
9590 1 : check("void f() {\n"
9591 : " void* a;\n"
9592 : " a = (void*)0U;\n"
9593 : " a = p;\n"
9594 : "}");
9595 1 : ASSERT_EQUALS(
9596 : "[test.cpp:2]: (style) Variable 'a' can be declared as pointer to const\n",
9597 : errout_str());
9598 : }
9599 :
9600 1 : void redundantVarAssignment_struct() {
9601 1 : check("struct foo {\n"
9602 : " int a,b;\n"
9603 : "};\n"
9604 : "\n"
9605 : "int main() {\n"
9606 : " struct foo x;\n"
9607 : " x.a = _mm_set1_ps(1.0);\n"
9608 : " x.a = _mm_set1_ps(2.0);\n"
9609 : "}");
9610 1 : ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:8]: (style) Variable 'x.a' is reassigned a value before the old one has been used.\n", errout_str());
9611 :
9612 1 : check("void f() {\n"
9613 : " struct AB ab;\n"
9614 : " ab.x = 23;\n"
9615 : " ab.y = 41;\n"
9616 : " ab.x = 1;\n"
9617 : "}");
9618 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Variable 'ab.x' is reassigned a value before the old one has been used.\n", errout_str());
9619 :
9620 1 : check("void f() {\n"
9621 : " struct AB ab = {0};\n"
9622 : " ab = foo();\n"
9623 : "}");
9624 1 : ASSERT_EQUALS("", errout_str());
9625 : }
9626 :
9627 1 : void redundantVarAssignment_7133() {
9628 : // #7133
9629 1 : check("sal_Int32 impl_Export() {\n"
9630 : " try {\n"
9631 : " try {\n"
9632 : " uno::Sequence< uno::Any > aArgs(2);\n"
9633 : " beans::NamedValue aValue;\n"
9634 : " aValue.Name = \"DocumentHandler\";\n"
9635 : " aValue.Value <<= xDocHandler;\n"
9636 : " aArgs[0] <<= aValue;\n"
9637 : " aValue.Name = \"Model\";\n"
9638 : " aValue.Value <<= xDocumentComp;\n"
9639 : " aArgs[1] <<= aValue;\n"
9640 : " }\n"
9641 : " catch (const uno::Exception&) {\n"
9642 : " }\n"
9643 : " }\n"
9644 : " catch (const uno::Exception&) {\n"
9645 : " }\n"
9646 : "}", true, true);
9647 1 : ASSERT_EQUALS("", errout_str());
9648 :
9649 1 : check("void ConvertBitmapData(sal_uInt16 nDestBits) {\n"
9650 : " BitmapBuffer aSrcBuf;\n"
9651 : " aSrcBuf.mnBitCount = nSrcBits;\n"
9652 : " BitmapBuffer aDstBuf;\n"
9653 : " aSrcBuf.mnBitCount = nDestBits;\n"
9654 : " bConverted = ::ImplFastBitmapConversion( aDstBuf, aSrcBuf, aTwoRects );\n"
9655 : "}", false);
9656 1 : ASSERT_EQUALS("[test.c:3] -> [test.c:5]: (style) Variable 'aSrcBuf.mnBitCount' is reassigned a value before the old one has been used.\n", errout_str());
9657 1 : check("void ConvertBitmapData(sal_uInt16 nDestBits) {\n"
9658 : " BitmapBuffer aSrcBuf;\n"
9659 : " aSrcBuf.mnBitCount = nSrcBits;\n"
9660 : " BitmapBuffer aDstBuf;\n"
9661 : " aSrcBuf.mnBitCount = nDestBits;\n"
9662 : " bConverted = ::ImplFastBitmapConversion( aDstBuf, aSrcBuf, aTwoRects );\n"
9663 : "}");
9664 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Variable 'aSrcBuf.mnBitCount' is reassigned a value before the old one has been used.\n",
9665 : errout_str());
9666 :
9667 1 : check("class C { void operator=(int x); };\n" // #8368 - assignment operator might have side effects => inconclusive
9668 : "void f() {\n"
9669 : " C c;\n"
9670 : " c = x;\n"
9671 : " c = x;\n"
9672 : "}");
9673 1 : ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style, inconclusive) Variable 'c' is reassigned a value before the old one has been used if variable is no semaphore variable.\n", errout_str());
9674 : }
9675 :
9676 1 : void redundantVarAssignment_stackoverflow() {
9677 1 : check("typedef struct message_node {\n"
9678 : " char code;\n"
9679 : " size_t size;\n"
9680 : " struct message_node *next, *prev;\n"
9681 : "} *message_list;\n"
9682 : "static message_list remove_message_from_list(message_list m) {\n"
9683 : " m->prev->next = m->next;\n"
9684 : " m->next->prev = m->prev;\n"
9685 : " return m->next;\n"
9686 : "}");
9687 1 : ASSERT_EQUALS("", errout_str());
9688 : }
9689 :
9690 1 : void redundantVarAssignment_lambda() {
9691 : // #7152
9692 1 : check("int foo() {\n"
9693 : " int x = 0, y = 0;\n"
9694 : " auto f = [&]() { if (x < 5) ++y; };\n"
9695 : " x = 2;\n"
9696 : " f();\n"
9697 : " x = 6;\n"
9698 : " f();\n"
9699 : " return y;\n"
9700 : "}");
9701 1 : ASSERT_EQUALS("", errout_str());
9702 :
9703 : // #10228
9704 1 : check("std::tuple<int, int> g();\n"
9705 : "void h(int);\n"
9706 : "void f() {\n"
9707 : " auto [a, b] = g();\n"
9708 : " auto l = [a = a]() { h(i); };\n"
9709 : "}\n");
9710 1 : ASSERT_EQUALS("", errout_str());
9711 : }
9712 :
9713 1 : void redundantVarAssignment_loop() {
9714 1 : check("void f() {\n"
9715 : " char buf[10];\n"
9716 : " int i;\n"
9717 : " for (i = 0; i < 4; i++)\n"
9718 : " buf[i] = 131;\n"
9719 : " buf[i] = 0;\n"
9720 : "}");
9721 1 : ASSERT_EQUALS("", errout_str());
9722 :
9723 1 : check("void bar() {\n" // #9262 do-while with break
9724 : " int x = 0;\n"
9725 : " x = 432;\n"
9726 : " do {\n"
9727 : " if (foo()) break;\n"
9728 : " x = 1;\n"
9729 : " } while (false);\n"
9730 : "}");
9731 1 : ASSERT_EQUALS("", errout_str());
9732 :
9733 1 : check("void foo(int num) {\n" // #9420 FP
9734 : " int a = num;\n"
9735 : " for (int b = 0; b < num; a = b++)\n"
9736 : " dostuff(a);\n"
9737 : "}");
9738 1 : ASSERT_EQUALS("", errout_str());
9739 :
9740 1 : check("void foo(int num) {\n" // #9420 FN
9741 : " int a = num;\n"
9742 : " for (int b = 0; b < num; a = b++);\n"
9743 : "}");
9744 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
9745 : }
9746 :
9747 1 : void redundantVarAssignment_after_switch() {
9748 1 : check("void f(int x) {\n" // #7907
9749 : " int ret;\n"
9750 : " switch (x) {\n"
9751 : " case 123:\n"
9752 : " ret = 1;\n" // redundant assignment
9753 : " break;\n"
9754 : " }\n"
9755 : " ret = 3;\n"
9756 : "}");
9757 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:8]: (style) Variable 'ret' is reassigned a value before the old one has been used.\n", errout_str());
9758 : }
9759 :
9760 1 : void redundantVarAssignment_pointer() {
9761 1 : check("void f(int *ptr) {\n"
9762 : " int *x = ptr + 1;\n"
9763 : " *x = 23;\n"
9764 : " foo(ptr);\n"
9765 : " *x = 32;\n"
9766 : "}");
9767 1 : ASSERT_EQUALS("", errout_str());
9768 :
9769 : // #8997
9770 1 : check("void f() {\n"
9771 : " char x[2];\n"
9772 : " char* p = x;\n"
9773 : " *p = 1;\n"
9774 : " p += 1;\n"
9775 : " *p = 1;\n"
9776 : "}");
9777 1 : ASSERT_EQUALS("", errout_str());
9778 : }
9779 :
9780 1 : void redundantVarAssignment_pointer_parameter() {
9781 1 : check("void f(int *p) {\n"
9782 : " *p = 1;\n"
9783 : " if (condition) return;\n"
9784 : " *p = 2;\n"
9785 : "}");
9786 1 : ASSERT_EQUALS("", errout_str());
9787 : }
9788 :
9789 1 : void redundantVarAssignment_array() {
9790 1 : check("void f() {\n"
9791 : " int arr[10];\n"
9792 : " int i = 0;\n"
9793 : " arr[i] = 1;\n"
9794 : " i += 2;\n"
9795 : " arr[i] = 3;\n"
9796 : " dostuff(arr);\n"
9797 : "}");
9798 1 : ASSERT_EQUALS("", errout_str());
9799 : }
9800 :
9801 1 : void redundantVarAssignment_switch_break() {
9802 : // #10058
9803 1 : check("void f(int a, int b) {\n"
9804 : " int ret = 0;\n"
9805 : " switch (a) {\n"
9806 : " case 1:\n"
9807 : " ret = 543;\n"
9808 : " if (b) break;\n"
9809 : " ret = 1;\n"
9810 : " break;\n"
9811 : " }"
9812 : " return ret;\n"
9813 : "}");
9814 1 : ASSERT_EQUALS("", errout_str());
9815 :
9816 1 : check("void f(int a, int b) {\n"
9817 : " int ret = 0;\n"
9818 : " switch (a) {\n"
9819 : " case 1:\n"
9820 : " ret = 543;\n"
9821 : " if (b) break;\n"
9822 : " ret = 1;\n"
9823 : " break;\n"
9824 : " }"
9825 : "}");
9826 1 : ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:7]: (style) Variable 'ret' is reassigned a value before the old one has been used.\n", errout_str());
9827 : }
9828 :
9829 1 : void redundantInitialization() {
9830 1 : setMultiline();
9831 :
9832 1 : check("void f() {\n"
9833 : " int err = -ENOMEM;\n"
9834 : " err = dostuff();\n"
9835 : "}");
9836 1 : ASSERT_EQUALS("test.cpp:3:style:Redundant initialization for 'err'. The initialized value is overwritten before it is read.\n"
9837 : "test.cpp:2:note:err is initialized\n"
9838 : "test.cpp:3:note:err is overwritten\n",
9839 : errout_str());
9840 :
9841 1 : check("void f() {\n"
9842 : " struct S s = {1,2,3};\n"
9843 : " s = dostuff();\n"
9844 : "}");
9845 1 : ASSERT_EQUALS("test.cpp:3:style:Redundant initialization for 's'. The initialized value is overwritten before it is read.\n"
9846 : "test.cpp:2:note:s is initialized\n"
9847 : "test.cpp:3:note:s is overwritten\n",
9848 : errout_str());
9849 :
9850 1 : check("void f() {\n"
9851 : " int *p = NULL;\n"
9852 : " p = dostuff();\n"
9853 : "}");
9854 1 : ASSERT_EQUALS(
9855 : "test.cpp:2:style:Variable 'p' can be declared as pointer to const\n",
9856 : errout_str());
9857 :
9858 : // "trivial" initialization => do not warn
9859 1 : check("void f() {\n"
9860 : " struct S s = {0};\n"
9861 : " s = dostuff();\n"
9862 : "}");
9863 1 : ASSERT_EQUALS("", errout_str());
9864 :
9865 1 : check("namespace N { enum E {e0,e1}; }\n"
9866 : "void f() {\n"
9867 : " N::E e = N::e0;\n" // #9261
9868 : " e = dostuff();\n"
9869 : "}");
9870 1 : ASSERT_EQUALS("", errout_str());
9871 :
9872 1 : check("void f() {\n" // #10143
9873 : " std::shared_ptr<int> i = g();\n"
9874 : " h();\n"
9875 : " i = nullptr;\n"
9876 : "}\n");
9877 1 : ASSERT_EQUALS("", errout_str());
9878 :
9879 1 : check("int f(const std::vector<int>& v) {\n" // #9815
9880 : " int i = g();\n"
9881 : " i = std::distance(v.begin(), std::find_if(v.begin(), v.end(), [=](int j) { return i == j; }));\n"
9882 : " return i;\n"
9883 : "}\n");
9884 1 : ASSERT_EQUALS("", errout_str());
9885 : }
9886 :
9887 1 : void redundantMemWrite() {
9888 1 : return; // FIXME: temporary hack
9889 :
9890 : // Simple tests
9891 : // cppcheck-suppress unreachableCode - remove when code is enabled again
9892 : check("void f() {\n"
9893 : " char a[10];\n"
9894 : " memcpy(a, foo, bar);\n"
9895 : " memset(a, 0, bar);\n"
9896 : "}");
9897 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (performance) Buffer 'a' is being written before its old content has been used.\n", errout_str());
9898 :
9899 : check("void f() {\n"
9900 : " char a[10];\n"
9901 : " strcpy(a, foo);\n"
9902 : " strncpy(a, 0, bar);\n"
9903 : "}");
9904 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (performance) Buffer 'a' is being written before its old content has been used.\n", errout_str());
9905 :
9906 : check("void f() {\n"
9907 : " char a[10];\n"
9908 : " sprintf(a, \"foo\");\n"
9909 : " memmove(a, 0, bar);\n"
9910 : "}");
9911 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (performance) Buffer 'a' is being written before its old content has been used.\n", errout_str());
9912 :
9913 : check("void f(char *filename) {\n"
9914 : " char *p = strrchr(filename,'.');\n"
9915 : " strcpy(p, \"foo\");\n"
9916 : " dostuff(filename);\n"
9917 : " strcpy(p, \"foo\");\n"
9918 : "}");
9919 : ASSERT_EQUALS("", errout_str());
9920 :
9921 : // Writing to different parts of a buffer
9922 : check("void f(void* a) {\n"
9923 : " memcpy(a, foo, bar);\n"
9924 : " memset(a+5, 0, bar);\n"
9925 : "}");
9926 : ASSERT_EQUALS("", errout_str());
9927 :
9928 : // Use variable as second argument
9929 : check("void f(void* a, void* b) {\n"
9930 : " memset(a, 0, 5);\n"
9931 : " memcpy(b, a, 5);\n"
9932 : " memset(a, 1, 5);\n"
9933 : "}");
9934 : ASSERT_EQUALS("", errout_str());
9935 :
9936 : // strcat is special
9937 : check("void f() {\n"
9938 : " char a[10];\n"
9939 : " strcpy(a, foo);\n"
9940 : " strcat(a, bar);\n" // Not redundant
9941 : " strcpy(a, x);\n" // Redundant
9942 : "}");
9943 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (performance) Buffer 'a' is being written before its old content has been used.\n", errout_str());
9944 :
9945 : // Tests with function call between copy
9946 : check("void f() {\n"
9947 : " char a[10];\n"
9948 : " snprintf(a, foo, bar);\n"
9949 : " bar();\n"
9950 : " memset(a, 0, size);\n"
9951 : "}");
9952 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (performance) Buffer 'a' is being written before its old content has been used.\n", errout_str());
9953 :
9954 : check("void* a;\n"
9955 : "void f() {\n"
9956 : " memset(a, 0, size);\n"
9957 : " bar();\n" // Global variable might be accessed in bar()
9958 : " memset(a, 0, size);\n"
9959 : "}");
9960 : ASSERT_EQUALS("", errout_str());
9961 :
9962 : check("void f() {\n"
9963 : " char a[10];\n"
9964 : " memset(a, 0, size);\n"
9965 : " bar();\n"
9966 : " memset(a, 0, size);\n"
9967 : "}");
9968 : TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (performance) Buffer 'a' is being written before its old content has been used.\n", "", errout_str());
9969 :
9970 : check("void bar(void* a) {}\n"
9971 : "void f(void* a) {\n"
9972 : " memset(a, 0, size);\n"
9973 : " bar(a);\n" // Passed as argument
9974 : " memset(a, 0, size);\n"
9975 : "}");
9976 : ASSERT_EQUALS("", errout_str());
9977 :
9978 : // Branch tests
9979 : check("void f(void* a) {\n"
9980 : " memset(a, 0, size);\n"
9981 : " if(x)\n"
9982 : " memset(a, 0, size);\n"
9983 : "}");
9984 : ASSERT_EQUALS("", errout_str());
9985 :
9986 : // #4455 - initialization of local buffer
9987 : check("void f(void) {"
9988 : " char buf[10];\n"
9989 : " memset(buf, 0, 10);\n"
9990 : " strcpy(buf, string);\n"
9991 : "}");
9992 : ASSERT_EQUALS("", errout_str());
9993 :
9994 : check("void f(void) {\n"
9995 : " char buf[10] = {0};\n"
9996 : " memset(buf, 0, 10);\n"
9997 : " strcpy(buf, string);\n"
9998 : "}");
9999 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (performance) Buffer 'buf' is being written before its old content has been used.\n", errout_str());
10000 :
10001 : // #5689 - use return value of strcpy
10002 : check("int f(void* a) {\n"
10003 : " int i = atoi(strcpy(a, foo));\n"
10004 : " strncpy(a, 0, bar);\n"
10005 : " return i;\n"
10006 : "}");
10007 : ASSERT_EQUALS("", errout_str());
10008 :
10009 : // #7175 - read+write
10010 : check("void f() {\n"
10011 : " char buf[100];\n"
10012 : " strcpy(buf, x);\n"
10013 : " strcpy(buf, dostuff(buf));\n" // <- read + write
10014 : " strcpy(buf, x);\n"
10015 : "}");
10016 : ASSERT_EQUALS("", errout_str());
10017 :
10018 : check("void f() {\n"
10019 : " char buf[100];\n"
10020 : " strcpy(buf, x);\n"
10021 : " strcpy(buf, dostuff(buf));\n"
10022 : " strcpy(buf, x);\n"
10023 : "}");
10024 : TODO_ASSERT_EQUALS("error", "", errout_str());
10025 : }
10026 :
10027 1 : void varFuncNullUB() { // #4482
10028 1 : check("void a(...);\n"
10029 : "void b() { a(NULL); }");
10030 1 : ASSERT_EQUALS("[test.cpp:2]: (portability) Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n", errout_str());
10031 :
10032 1 : check("void a(char *p, ...);\n"
10033 : "void b() { a(NULL, 2); }");
10034 1 : ASSERT_EQUALS("", errout_str());
10035 : }
10036 :
10037 1 : void checkCastIntToCharAndBack() { // #160
10038 :
10039 : // check getchar
10040 1 : check("void f() {\n"
10041 : "unsigned char c; c = getchar();\n"
10042 : " while( c != EOF)\n"
10043 : " {\n"
10044 : " bar(c);\n"
10045 : " c = getchar();\n"
10046 : " } ;\n"
10047 : "}");
10048 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing getchar() return value in char variable and then comparing with EOF.\n", errout_str());
10049 :
10050 1 : check("void f() {\n"
10051 : "unsigned char c = getchar();\n"
10052 : " while( EOF != c)\n"
10053 : " {\n"
10054 : " bar(c);\n"
10055 : " } ;\n"
10056 : "}");
10057 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing getchar() return value in char variable and then comparing with EOF.\n", errout_str());
10058 :
10059 1 : check("void f() {\n"
10060 : " unsigned char c; c = getchar();\n"
10061 : " while( EOF != c )\n"
10062 : " {\n"
10063 : " bar(c);\n"
10064 : " c = getchar();\n"
10065 : " } ;\n"
10066 : "}");
10067 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing getchar() return value in char variable and then comparing with EOF.\n", errout_str());
10068 :
10069 1 : check("void f() {\n"
10070 : " unsigned char c;\n"
10071 : " while( EOF != ( c = getchar() ) )\n"
10072 : " {\n"
10073 : " }\n"
10074 : "}");
10075 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing getchar() return value in char variable and then comparing with EOF.\n", errout_str());
10076 :
10077 1 : check("void f() {\n"
10078 : " int i; i = getchar();\n"
10079 : " while( i != EOF)\n"
10080 : " {\n"
10081 : " bar(i);\n"
10082 : " i = getchar();\n"
10083 : " } ;\n"
10084 : "}");
10085 1 : ASSERT_EQUALS("", errout_str());
10086 :
10087 1 : check("void f() {\n"
10088 : " int i; i = getchar();\n"
10089 : " while( EOF != i )\n"
10090 : " {\n"
10091 : " bar(i);\n"
10092 : " i = getchar();\n"
10093 : " } ;\n"
10094 : "}");
10095 1 : ASSERT_EQUALS("", errout_str());
10096 :
10097 :
10098 : // check getc
10099 1 : check("void f (FILE * pFile){\n"
10100 : "unsigned char c;\n"
10101 : "do {\n"
10102 : " c = getc (pFile);\n"
10103 : "} while (c != EOF)"
10104 : "}");
10105 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Storing getc() return value in char variable and then comparing with EOF.\n", errout_str());
10106 :
10107 1 : check("void f (FILE * pFile){\n"
10108 : "unsigned char c;\n"
10109 : "do {\n"
10110 : " c = getc (pFile);\n"
10111 : "} while (EOF != c)"
10112 : "}");
10113 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Storing getc() return value in char variable and then comparing with EOF.\n", errout_str());
10114 :
10115 1 : check("void f (FILE * pFile){\n"
10116 : "int i;\n"
10117 : "do {\n"
10118 : " i = getc (pFile);\n"
10119 : "} while (i != EOF)"
10120 : "}");
10121 1 : ASSERT_EQUALS("", errout_str());
10122 :
10123 1 : check("void f (FILE * pFile){\n"
10124 : "int i;\n"
10125 : "do {\n"
10126 : " i = getc (pFile);\n"
10127 : "} while (EOF != i)"
10128 : "}");
10129 1 : ASSERT_EQUALS("", errout_str());
10130 :
10131 :
10132 : // check fgetc
10133 1 : check("void f (FILE * pFile){\n"
10134 : "unsigned char c;\n"
10135 : "do {\n"
10136 : " c = fgetc (pFile);\n"
10137 : "} while (c != EOF)"
10138 : "}");
10139 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Storing fgetc() return value in char variable and then comparing with EOF.\n", errout_str());
10140 :
10141 1 : check("void f (FILE * pFile){\n"
10142 : "char c;\n"
10143 : "do {\n"
10144 : " c = fgetc (pFile);\n"
10145 : "} while (EOF != c)"
10146 : "}");
10147 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Storing fgetc() return value in char variable and then comparing with EOF.\n", errout_str());
10148 :
10149 1 : check("void f (FILE * pFile){\n"
10150 : "signed char c;\n"
10151 : "do {\n"
10152 : " c = fgetc (pFile);\n"
10153 : "} while (EOF != c)"
10154 : "}");
10155 1 : ASSERT_EQUALS("", errout_str());
10156 :
10157 1 : check("void f (FILE * pFile){\n"
10158 : "int i;\n"
10159 : "do {\n"
10160 : " i = fgetc (pFile);\n"
10161 : "} while (i != EOF)"
10162 : "}");
10163 1 : ASSERT_EQUALS("", errout_str());
10164 :
10165 1 : check("void f (FILE * pFile){\n"
10166 : "int i;\n"
10167 : "do {\n"
10168 : " i = fgetc (pFile);\n"
10169 : "} while (EOF != i)"
10170 : "}");
10171 1 : ASSERT_EQUALS("", errout_str());
10172 :
10173 : // cin.get()
10174 1 : check("void f(){\n"
10175 : " char ch; ch = std::cin.get();\n"
10176 : " while (EOF != ch) {\n"
10177 : " std::cout << ch;\n"
10178 : " ch = std::cin.get();\n"
10179 : " }\n"
10180 : "}");
10181 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing cin.get() return value in char variable and then comparing with EOF.\n", errout_str());
10182 :
10183 1 : check("void f(){\n"
10184 : " char ch; ch = std::cin.get();\n"
10185 : " while (ch != EOF) {\n"
10186 : " std::cout << ch;\n"
10187 : " ch = std::cin.get();\n"
10188 : " }\n"
10189 : "}");
10190 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Storing cin.get() return value in char variable and then comparing with EOF.\n", errout_str());
10191 :
10192 1 : check("void f(){\n"
10193 : " int i; i = std::cin.get();\n"
10194 : " while ( EOF != i ) {\n"
10195 : " std::cout << i;\n"
10196 : " i = std::cin.get();\n"
10197 : " }\n"
10198 : "}");
10199 1 : ASSERT_EQUALS("", errout_str());
10200 :
10201 1 : check("void f(){\n"
10202 : " int i; i = std::cin.get();\n"
10203 : " while ( i != EOF ) {\n"
10204 : " std::cout << i;\n"
10205 : " i = std::cin.get();\n"
10206 : " }\n"
10207 : "}");
10208 1 : ASSERT_EQUALS("", errout_str());
10209 : }
10210 :
10211 1 : void checkCommaSeparatedReturn() {
10212 1 : check("int fun(int a) {\n"
10213 : " if (a < 0)\n"
10214 : " return a++,\n"
10215 : " do_something();\n"
10216 : "}", true, false, false);
10217 1 : TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Comma is used in return statement. The comma can easily be misread as a ';'.\n", "", errout_str());
10218 :
10219 1 : check("int fun(int a) {\n"
10220 : " if (a < 0)\n"
10221 : " return a++, do_something();\n"
10222 : "}", true, false, false);
10223 1 : ASSERT_EQUALS("", errout_str());
10224 :
10225 1 : check("int fun(int a) {\n"
10226 : " if (a < 0)\n"
10227 : " return a+5,\n"
10228 : " do_something();\n"
10229 : "}", true, false, false);
10230 1 : TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Comma is used in return statement. The comma can easily be misread as a ';'.\n", "", errout_str());
10231 :
10232 1 : check("int fun(int a) {\n"
10233 : " if (a < 0)\n"
10234 : " return a+5, do_something();\n"
10235 : "}", true, false, false);
10236 1 : ASSERT_EQUALS("", errout_str());
10237 :
10238 1 : check("int fun(int a) {\n"
10239 : " if (a < 0)\n"
10240 : " return c<int,\nint>::b;\n"
10241 : "}", true, false, false);
10242 1 : ASSERT_EQUALS("", errout_str());
10243 :
10244 : // #4943 take care of C++11 initializer lists
10245 1 : check("std::vector<Foo> Bar() {\n"
10246 : " return\n"
10247 : " {\n"
10248 : " { \"1\" },\n"
10249 : " { \"2\" },\n"
10250 : " { \"3\" }\n"
10251 : " };\n"
10252 : "}", true, false, false);
10253 1 : ASSERT_EQUALS("", errout_str());
10254 : }
10255 :
10256 1 : void checkPassByReference() {
10257 : // #8570 passByValue when std::move is used
10258 1 : check("struct A\n"
10259 : "{\n"
10260 : " std::vector<int> x;\n"
10261 : "};\n"
10262 : "\n"
10263 : "struct B\n"
10264 : "{\n"
10265 : " explicit B(A a) : a(std::move(a)) {}\n"
10266 : " void Init(A _a) { a = std::move(_a); }\n"
10267 : " A a;"
10268 : "};", true, false, true);
10269 1 : ASSERT_EQUALS("", errout_str());
10270 :
10271 1 : check("struct A\n"
10272 : "{\n"
10273 : " std::vector<int> x;\n"
10274 : "};\n"
10275 : "\n"
10276 : "struct B\n"
10277 : "{\n"
10278 : " explicit B(A a) : a{std::move(a)} {}\n"
10279 : " void Init(A _a) { a = std::move(_a); }\n"
10280 : " A a;"
10281 : "};", true, false, true);
10282 1 : ASSERT_EQUALS("", errout_str());
10283 :
10284 1 : check("struct A\n"
10285 : "{\n"
10286 : " std::vector<int> x;\n"
10287 : "};\n"
10288 : "\n"
10289 : "struct B\n"
10290 : "{\n"
10291 : " B(A a, A a2) : a{std::move(a)}, a2{std::move(a2)} {}\n"
10292 : " void Init(A _a) { a = std::move(_a); }\n"
10293 : " A a;"
10294 : " A a2;"
10295 : "};", true, false, true);
10296 1 : ASSERT_EQUALS("", errout_str());
10297 :
10298 1 : check("struct A\n"
10299 : "{\n"
10300 : " std::vector<int> x;\n"
10301 : "};\n"
10302 : "\n"
10303 : "struct B\n"
10304 : "{\n"
10305 : " B(A a, A a2) : a{std::move(a)}, a2{a2} {}\n"
10306 : " void Init(A _a) { a = std::move(_a); }\n"
10307 : " A a;"
10308 : " A a2;"
10309 : "};", true, false, true);
10310 1 : ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout_str());
10311 :
10312 1 : check("struct A\n"
10313 : "{\n"
10314 : " std::vector<int> x;\n"
10315 : "};\n"
10316 : "\n"
10317 : "struct B\n"
10318 : "{\n"
10319 : " B(A a, A a2) : a{std::move(a)}, a2(a2) {}\n"
10320 : " void Init(A _a) { a = std::move(_a); }\n"
10321 : " A a;"
10322 : " A a2;"
10323 : "};", true, false, true);
10324 1 : ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout_str());
10325 :
10326 1 : check("std::map<int, int> m;\n" // #10817
10327 : "void f(const decltype(m)::const_iterator i) {}");
10328 1 : ASSERT_EQUALS("", errout_str());
10329 :
10330 1 : check("int (*pf) (std::vector<int>) = nullptr;\n" // #12118
10331 : "int f(std::vector<int> v) {\n"
10332 : " return v.size();\n"
10333 : "}\n"
10334 : "void g() {\n"
10335 : " pf = f;\n"
10336 : "}\n");
10337 1 : ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (performance) Function parameter 'v' should be passed by const reference. However it seems that 'f' is a callback function.\n",
10338 : errout_str());
10339 :
10340 1 : check("template<typename T> struct A;\n" // #12621
10341 : "template<typename T>\n"
10342 : "struct B { A<T> a; };\n"
10343 : "template<typename T>\n"
10344 : "struct A { B<T> b; };\n"
10345 : "template<typename T>\n"
10346 : "struct C : public virtual A<T>, public virtual B<T> {\n"
10347 : " A<T> x;\n"
10348 : " B<T> y;\n"
10349 : " C(A<T> x_, B<T> y_) : x(x_), y(y_) {}\n"
10350 : "};\n");
10351 1 : ASSERT_EQUALS("", errout_str()); // don't crash
10352 : }
10353 :
10354 1 : void checkComparisonFunctionIsAlwaysTrueOrFalse() {
10355 : // positive test
10356 1 : check("bool f(int x){\n"
10357 : " return isless(x,x);\n"
10358 : "}");
10359 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of two identical variables with isless(x,x) always evaluates to false.\n", errout_str());
10360 :
10361 1 : check("bool f(int x){\n"
10362 : " return isgreater(x,x);\n"
10363 : "}");
10364 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of two identical variables with isgreater(x,x) always evaluates to false.\n", errout_str());
10365 :
10366 1 : check("bool f(int x){\n"
10367 : " return islessgreater(x,x);\n"
10368 : "}");
10369 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of two identical variables with islessgreater(x,x) always evaluates to false.\n", errout_str());
10370 :
10371 1 : check("bool f(int x){\n"
10372 : " return islessequal(x,x);\n"
10373 : "}");
10374 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of two identical variables with islessequal(x,x) always evaluates to true.\n", errout_str());
10375 :
10376 1 : check("bool f(int x){\n"
10377 : " return isgreaterequal(x,x);\n"
10378 : "}");
10379 1 : ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of two identical variables with isgreaterequal(x,x) always evaluates to true.\n", errout_str());
10380 :
10381 : // no warning should be reported for
10382 1 : check("bool f(int x, int y){\n"
10383 : " return isgreaterequal(x,y) && islessequal(x,y) && islessgreater(x,y) && isgreater(x,y) && isless(x,y);\n"
10384 : "}");
10385 1 : ASSERT_EQUALS("", errout_str());
10386 : }
10387 :
10388 1 : void integerOverflow() { // 5895
10389 : // no signed integer overflow should happen
10390 1 : check("void f(unsigned long long ull) {\n"
10391 : " if (ull == 0x89504e470d0a1a0a || ull == 0x8a4d4e470d0a1a0a) ;\n"
10392 : "}");
10393 1 : ASSERT_EQUALS("", errout_str());
10394 : }
10395 :
10396 1 : void redundantPointerOp() {
10397 1 : check("int *f(int *x) {\n"
10398 : " return &*x;\n"
10399 : "}\n", true, true);
10400 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant pointer operation on 'x' - it's already a pointer.\n", errout_str());
10401 :
10402 1 : check("int *f(int *y) {\n"
10403 : " return &(*y);\n"
10404 : "}\n", true, true);
10405 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant pointer operation on 'y' - it's already a pointer.\n", errout_str());
10406 :
10407 1 : check("int f() {\n" // #10991
10408 : " int value = 4;\n"
10409 : " int result1 = *(&value);\n"
10410 : " int result2 = *&value;\n"
10411 : " return result1 + result2;\n"
10412 : "}\n", true, true);
10413 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Redundant pointer operation on 'value' - it's already a variable.\n"
10414 : "[test.cpp:4]: (style) Redundant pointer operation on 'value' - it's already a variable.\n",
10415 : errout_str());
10416 :
10417 1 : check("void f(int& a, int b) {\n"
10418 : " *(&a) = b;\n"
10419 : "}\n", true, true);
10420 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant pointer operation on 'a' - it's already a variable.\n",
10421 : errout_str());
10422 :
10423 1 : check("void f(int**& p) {}\n", true, true);
10424 1 : ASSERT_EQUALS("", errout_str());
10425 :
10426 1 : checkP("#define RESTORE(ORIG, COPY) { *ORIG = *COPY; }\n"
10427 : "void f(int* p, int i) {\n"
10428 : " RESTORE(p, &i);\n"
10429 : "}\n");
10430 1 : ASSERT_EQUALS("", errout_str());
10431 :
10432 : // no warning for bitwise AND
10433 1 : check("void f(const int *b) {\n"
10434 : " int x = 0x20 & *b;\n"
10435 : "}\n", true, true);
10436 1 : ASSERT_EQUALS("", errout_str());
10437 :
10438 : // No message for double pointers to structs
10439 1 : check("void f(struct foo **my_struct) {\n"
10440 : " char **pass_to_func = &(*my_struct)->buf;\n"
10441 : "}\n", true, true);
10442 1 : ASSERT_EQUALS("", errout_str());
10443 :
10444 : // another double pointer to struct - with an array
10445 1 : check("void f(struct foo **my_struct) {\n"
10446 : " char **pass_to_func = &(*my_struct)->buf[10];\n"
10447 : "}\n", true, true);
10448 1 : ASSERT_EQUALS("", errout_str());
10449 :
10450 : // double pointer to array
10451 1 : check("void f(char **ptr) {\n"
10452 : " int *x = &(*ptr)[10];\n"
10453 : "}\n", true, true);
10454 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' can be declared as pointer to const\n", errout_str());
10455 :
10456 : // function calls
10457 1 : check("void f(Mutex *mut) {\n"
10458 : " pthread_mutex_lock(&*mut);\n"
10459 : "}\n", true, false);
10460 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant pointer operation on 'mut' - it's already a pointer.\n", errout_str());
10461 :
10462 : // make sure we got the AST match for "(" right
10463 1 : check("void f(char *ptr) {\n"
10464 : " if (&*ptr == NULL)\n"
10465 : " return;\n"
10466 : "}\n", true, true);
10467 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Redundant pointer operation on 'ptr' - it's already a pointer.\n", errout_str());
10468 :
10469 : // no warning for macros
10470 1 : checkP("#define MUTEX_LOCK(m) pthread_mutex_lock(&(m))\n"
10471 : "void f(struct mutex *mut) {\n"
10472 : " MUTEX_LOCK(*mut);\n"
10473 : "}\n");
10474 1 : ASSERT_EQUALS("", errout_str());
10475 :
10476 1 : checkP("#define B(op) bar(op)\n"
10477 : "#define C(orf) B(&orf)\n"
10478 : "void foo(const int * pkey) {\n"
10479 : " C(*pkey);\n"
10480 : "}\n");
10481 1 : ASSERT_EQUALS("", errout_str());
10482 : }
10483 :
10484 1 : void test_isSameExpression() { // see #5738
10485 1 : check("bool isInUnoIncludeFile(StringRef name) {"
10486 : " return name.startswith(SRCDIR \"/com/\") || name.startswith(SRCDIR \"/uno/\");\n"
10487 : "};", true, false);
10488 1 : ASSERT_EQUALS("", errout_str());
10489 : }
10490 :
10491 1 : void raceAfterInterlockedDecrement() {
10492 1 : checkInterlockedDecrement("void f() {\n"
10493 : " int counter = 0;\n"
10494 : " InterlockedDecrement(&counter);\n"
10495 : " whatever();\n"
10496 : "}");
10497 1 : ASSERT_EQUALS("", errout_str());
10498 :
10499 1 : checkInterlockedDecrement("void f() {\n"
10500 : " int counter = 0;\n"
10501 : " InterlockedDecrement(&counter);\n"
10502 : " if (counter)\n"
10503 : " return;\n"
10504 : " destroy();\n"
10505 : "}");
10506 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10507 :
10508 1 : checkInterlockedDecrement("void f() {\n"
10509 : " int counter = 0;\n"
10510 : " InterlockedDecrement(&counter);\n"
10511 : " if (!counter)\n"
10512 : " destroy();\n"
10513 : "}");
10514 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10515 :
10516 1 : checkInterlockedDecrement("void f() {\n"
10517 : " int counter = 0;\n"
10518 : " InterlockedDecrement(&counter);\n"
10519 : " if (counter > 0)\n"
10520 : " return;\n"
10521 : " destroy();\n"
10522 : "}");
10523 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10524 :
10525 1 : checkInterlockedDecrement("void f() {\n"
10526 : " int counter = 0;\n"
10527 : " InterlockedDecrement(&counter);\n"
10528 : " if (0 < counter)\n"
10529 : " return;\n"
10530 : " destroy();\n"
10531 : "}");
10532 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10533 :
10534 1 : checkInterlockedDecrement("void f() {\n"
10535 : " int counter = 0;\n"
10536 : " InterlockedDecrement(&counter);\n"
10537 : " if (counter == 0)\n"
10538 : " destroy();\n"
10539 : "}");
10540 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10541 :
10542 1 : checkInterlockedDecrement("void f() {\n"
10543 : " int counter = 0;\n"
10544 : " InterlockedDecrement(&counter);\n"
10545 : " if (0 == counter)\n"
10546 : " destroy();\n"
10547 : "}");
10548 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10549 :
10550 1 : checkInterlockedDecrement("void f() {\n"
10551 : " int counter = 0;\n"
10552 : " InterlockedDecrement(&counter);\n"
10553 : " if (0 != counter)\n"
10554 : " return;\n"
10555 : " destroy()\n"
10556 : "}");
10557 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10558 :
10559 1 : checkInterlockedDecrement("void f() {\n"
10560 : " int counter = 0;\n"
10561 : " InterlockedDecrement(&counter);\n"
10562 : " if (counter != 0)\n"
10563 : " return;\n"
10564 : " destroy()\n"
10565 : "}");
10566 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10567 :
10568 1 : checkInterlockedDecrement("void f() {\n"
10569 : " int counter = 0;\n"
10570 : " InterlockedDecrement(&counter);\n"
10571 : " if (counter <= 0)\n"
10572 : " destroy();\n"
10573 : "}");
10574 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10575 :
10576 1 : checkInterlockedDecrement("void f() {\n"
10577 : " int counter = 0;\n"
10578 : " InterlockedDecrement(&counter);\n"
10579 : " if (0 >= counter)\n"
10580 : " destroy();\n"
10581 : "}");
10582 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10583 :
10584 1 : checkInterlockedDecrement("void f() {\n"
10585 : " int counter = 0;\n"
10586 : " int newCount = InterlockedDecrement(&counter);\n"
10587 : " if (newCount)\n"
10588 : " return;\n"
10589 : " destroy();\n"
10590 : "}");
10591 1 : ASSERT_EQUALS("", errout_str());
10592 :
10593 1 : checkInterlockedDecrement("void f() {\n"
10594 : " int counter = 0;\n"
10595 : " int newCount = InterlockedDecrement(&counter);\n"
10596 : " if (!newCount)\n"
10597 : " destroy();\n"
10598 : "}");
10599 1 : ASSERT_EQUALS("", errout_str());
10600 :
10601 1 : checkInterlockedDecrement("void f() {\n"
10602 : " int counter = 0;\n"
10603 : " int newCount = InterlockedDecrement(&counter);\n"
10604 : " if (newCount > 0)\n"
10605 : " return;\n"
10606 : " destroy();\n"
10607 : "}");
10608 1 : ASSERT_EQUALS("", errout_str());
10609 :
10610 1 : checkInterlockedDecrement("void f() {\n"
10611 : " int counter = 0;\n"
10612 : " int newCount = InterlockedDecrement(&counter);\n"
10613 : " if (0 < newCount)\n"
10614 : " return;\n"
10615 : " destroy();\n"
10616 : "}");
10617 1 : ASSERT_EQUALS("", errout_str());
10618 :
10619 1 : checkInterlockedDecrement("void f() {\n"
10620 : " int counter = 0;\n"
10621 : " int newCount = InterlockedDecrement(&counter);\n"
10622 : " if (newCount == 0)\n"
10623 : " destroy();\n"
10624 : "}");
10625 1 : ASSERT_EQUALS("", errout_str());
10626 :
10627 1 : checkInterlockedDecrement("void f() {\n"
10628 : " int counter = 0;\n"
10629 : " int newCount = InterlockedDecrement(&counter);\n"
10630 : " if (0 == newCount)\n"
10631 : " destroy();\n"
10632 : "}");
10633 1 : ASSERT_EQUALS("", errout_str());
10634 :
10635 1 : checkInterlockedDecrement("void f() {\n"
10636 : " int counter = 0;\n"
10637 : " int newCount = InterlockedDecrement(&counter);\n"
10638 : " if (0 != newCount)\n"
10639 : " return;\n"
10640 : " destroy()\n"
10641 : "}");
10642 1 : ASSERT_EQUALS("", errout_str());
10643 :
10644 1 : checkInterlockedDecrement("void f() {\n"
10645 : " int counter = 0;\n"
10646 : " int newCount = InterlockedDecrement(&counter);\n"
10647 : " if (newCount != 0)\n"
10648 : " return;\n"
10649 : " destroy()\n"
10650 : "}");
10651 1 : ASSERT_EQUALS("", errout_str());
10652 :
10653 1 : checkInterlockedDecrement("void f() {\n"
10654 : " int counter = 0;\n"
10655 : " int newCount = InterlockedDecrement(&counter);\n"
10656 : " if (newCount <= 0)\n"
10657 : " destroy();\n"
10658 : "}");
10659 1 : ASSERT_EQUALS("", errout_str());
10660 :
10661 1 : checkInterlockedDecrement("void f() {\n"
10662 : " int counter = 0;\n"
10663 : " int newCount = InterlockedDecrement(&counter);\n"
10664 : " if (0 >= newCount)\n"
10665 : " destroy;\n"
10666 : "}");
10667 1 : ASSERT_EQUALS("", errout_str());
10668 :
10669 1 : checkInterlockedDecrement("int f() {\n"
10670 : " int counter = 0;\n"
10671 : " if (InterlockedDecrement(&counter) == 0) {\n"
10672 : " destroy();\n"
10673 : " return 0;\n"
10674 : " } else {\n"
10675 : " return counter;\n"
10676 : " }\n"
10677 : "}");
10678 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10679 :
10680 1 : checkInterlockedDecrement("int f() {\n"
10681 : " int counter = 0;\n"
10682 : " if (::InterlockedDecrement(&counter) == 0) {\n"
10683 : " destroy();\n"
10684 : " return 0;\n"
10685 : " } else {\n"
10686 : " return counter;\n"
10687 : " }\n"
10688 : "}");
10689 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10690 :
10691 :
10692 1 : checkInterlockedDecrement("int f() {\n"
10693 : " int counter = 0;\n"
10694 : " if (InterlockedDecrement(&counter) == 0) {\n"
10695 : " destroy();\n"
10696 : " return 0;\n"
10697 : " }\n"
10698 : " return counter;\n"
10699 : "}");
10700 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10701 :
10702 1 : checkInterlockedDecrement("int f() {\n"
10703 : " int counter = 0;\n"
10704 : " if (::InterlockedDecrement(&counter) == 0) {\n"
10705 : " destroy();\n"
10706 : " return 0;\n"
10707 : " }\n"
10708 : " return counter;\n"
10709 : "}");
10710 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10711 :
10712 1 : checkInterlockedDecrement("int f() {\n"
10713 : " int counter = 0;\n"
10714 : " if (InterlockedDecrement(&counter) == 0) {\n"
10715 : " destroy();\n"
10716 : " return 0;\n"
10717 : " } else\n"
10718 : " return counter;\n"
10719 : " \n"
10720 : "}");
10721 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10722 :
10723 1 : checkInterlockedDecrement("int f() {\n"
10724 : " int counter = 0;\n"
10725 : " if (::InterlockedDecrement(&counter) == 0) {\n"
10726 : " destroy();\n"
10727 : " return 0;\n"
10728 : " } else\n"
10729 : " return counter;\n"
10730 : " \n"
10731 : "}");
10732 1 : ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout_str());
10733 : }
10734 :
10735 1 : void testUnusedLabel() {
10736 1 : check("void f() {\n"
10737 : " label:\n"
10738 : "}");
10739 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Label 'label' is not used.\n", errout_str());
10740 :
10741 1 : check("void f() {\n"
10742 : " label:\n"
10743 : " foo();\n"
10744 : " goto label;\n"
10745 : "}");
10746 1 : ASSERT_EQUALS("", errout_str());
10747 :
10748 1 : check("void f() {\n"
10749 : " label:\n"
10750 : " foo();\n"
10751 : " goto label;\n"
10752 : "}\n"
10753 : "void g() {\n"
10754 : " label:\n"
10755 : "}");
10756 1 : ASSERT_EQUALS("[test.cpp:7]: (style) Label 'label' is not used.\n", errout_str());
10757 :
10758 1 : check("void f() {\n"
10759 : " switch(a) {\n"
10760 : " default:\n"
10761 : " }\n"
10762 : "}");
10763 1 : ASSERT_EQUALS("", errout_str());
10764 :
10765 1 : check("void f() {\n"
10766 : " class X {\n"
10767 : " protected:\n"
10768 : " };\n"
10769 : "}");
10770 1 : ASSERT_EQUALS("", errout_str());
10771 :
10772 1 : check("void f() {\n"
10773 : " class X {\n"
10774 : " my_protected:\n"
10775 : " };\n"
10776 : "}");
10777 1 : ASSERT_EQUALS("", errout_str());
10778 :
10779 1 : check("int test(char art) {\n"
10780 : " switch (art) {\n"
10781 : " caseZERO:\n"
10782 : " return 0;\n"
10783 : " case1:\n"
10784 : " return 1;\n"
10785 : " case 2:\n"
10786 : " return 2;\n"
10787 : " }\n"
10788 : "}");
10789 1 : ASSERT_EQUALS("[test.cpp:3]: (warning) Label 'caseZERO' is not used. Should this be a 'case' of the enclosing switch()?\n"
10790 : "[test.cpp:5]: (warning) Label 'case1' is not used. Should this be a 'case' of the enclosing switch()?\n", errout_str());
10791 :
10792 1 : check("int test(char art) {\n"
10793 : " switch (art) {\n"
10794 : " case 2:\n"
10795 : " return 2;\n"
10796 : " }\n"
10797 : " label:\n"
10798 : "}");
10799 1 : ASSERT_EQUALS("[test.cpp:6]: (style) Label 'label' is not used.\n", errout_str());
10800 : }
10801 :
10802 1 : void testEvaluationOrder() {
10803 1 : check("void f() {\n"
10804 : " int x = dostuff();\n"
10805 : " return x + x++;\n"
10806 : "}", false);
10807 1 : ASSERT_EQUALS("[test.c:3]: (error) Expression 'x+x++' depends on order of evaluation of side effects\n", errout_str());
10808 :
10809 : // #7226
10810 1 : check("long int f1(const char *exp) {\n"
10811 : " return strtol(++exp, (char **)&exp, 10);\n"
10812 : "}", false);
10813 1 : ASSERT_EQUALS("", errout_str());
10814 :
10815 1 : check("long int f1(const char *exp) {\n"
10816 : " return dostuff(++exp, exp, 10);\n"
10817 : "}", false);
10818 1 : ASSERT_EQUALS("[test.c:2]: (error) Expression '++exp,exp' depends on order of evaluation of side effects\n", errout_str());
10819 :
10820 1 : check("void f() {\n"
10821 : " int a;\n"
10822 : " while (a=x(), a==123) {}\n"
10823 : "}", false);
10824 1 : ASSERT_EQUALS("", errout_str());
10825 :
10826 : // # 8717
10827 1 : check("void f(int argc, char *const argv[]) {\n"
10828 : " char **local_argv = safe_malloc(sizeof (*local_argv));\n"
10829 : " int local_argc = 0;\n"
10830 : " local_argv[local_argc++] = argv[0];\n"
10831 : "}\n", false);
10832 1 : ASSERT_EQUALS("", errout_str());
10833 :
10834 1 : check("void f() {\n"
10835 : " int x = 0;\n"
10836 : " return 0 + x++;\n"
10837 : "}\n", false);
10838 1 : ASSERT_EQUALS("", errout_str());
10839 :
10840 1 : check("void f(int x, int y) {\n"
10841 : " int a[10];\n"
10842 : " a[x+y] = a[y+x]++;;\n"
10843 : "}\n", false);
10844 1 : ASSERT_EQUALS("[test.c:3]: (error) Expression 'a[x+y]=a[y+x]++' depends on order of evaluation of side effects\n", errout_str());
10845 : }
10846 :
10847 1 : void testEvaluationOrderSelfAssignment() {
10848 : // self assignment
10849 1 : check("void f() {\n"
10850 : " int x = x = y + 1;\n"
10851 : "}", false);
10852 1 : ASSERT_EQUALS(
10853 : "[test.c:2]: (style) Redundant assignment of 'x' to itself.\n"
10854 : "[test.c:2]: (style) Redundant assignment of 'x' to itself.\n", // duplicate
10855 : errout_str());
10856 : }
10857 :
10858 1 : void testEvaluationOrderMacro() {
10859 : // macro, don't bailout (#7233)
10860 1 : checkP("#define X x\n"
10861 : "void f(int x) {\n"
10862 : " return x + X++;\n"
10863 : "}", "test.c");
10864 1 : ASSERT_EQUALS("[test.c:3]: (error) Expression 'x+x++' depends on order of evaluation of side effects\n", errout_str());
10865 : }
10866 :
10867 1 : void testEvaluationOrderSequencePointsFunctionCall() {
10868 : // FP
10869 1 : check("void f(int id) {\n"
10870 : " id = dostuff(id += 42);\n"
10871 : "}", false);
10872 1 : ASSERT_EQUALS("", errout_str());
10873 :
10874 : // FN
10875 1 : check("void f(int id) {\n"
10876 : " id = id + dostuff(id += 42);\n"
10877 : "}", false);
10878 1 : TODO_ASSERT_EQUALS("error", "", errout_str());
10879 : }
10880 :
10881 1 : void testEvaluationOrderSequencePointsComma() {
10882 1 : check("int f(void) {\n"
10883 : " int t;\n"
10884 : " return (unsigned char)(t=1,t^c);\n"
10885 : "}", false);
10886 1 : ASSERT_EQUALS("", errout_str());
10887 :
10888 1 : check("void f(void) {\n"
10889 : " int t;\n"
10890 : " dostuff(t=1,t^c);\n"
10891 : "}", false);
10892 1 : ASSERT_EQUALS("[test.c:3]: (error) Expression 't=1,t^c' depends on order of evaluation of side effects\n", errout_str());
10893 :
10894 1 : check("void f(void) {\n"
10895 : " int t;\n"
10896 : " dostuff((t=1,t),2);\n"
10897 : "}", false);
10898 1 : ASSERT_EQUALS("", errout_str());
10899 :
10900 : // #8230
10901 1 : check("void hprf(const char* fp) {\n"
10902 : " do\n"
10903 : " ;\n"
10904 : " while (++fp, (*fp) <= 0177);\n"
10905 : "}\n", false);
10906 1 : ASSERT_EQUALS("", errout_str());
10907 :
10908 1 : check("void hprf(const char* fp) {\n"
10909 : " do\n"
10910 : " ;\n"
10911 : " while (i++, ++fp, (*fp) <= 0177);\n"
10912 : "}\n", false);
10913 1 : ASSERT_EQUALS("", errout_str());
10914 :
10915 1 : check("void f(const char* fp) {\n"
10916 : " do\n"
10917 : " ;\n"
10918 : " while (f(++fp, (*fp) <= 7));\n"
10919 : "}\n", false);
10920 1 : ASSERT_EQUALS("[test.c:4]: (error) Expression '++fp,(*fp)<=7' depends on order of evaluation of side effects\n", errout_str());
10921 : }
10922 :
10923 1 : void testEvaluationOrderSizeof() {
10924 1 : check("void f(char *buf) {\n"
10925 : " dostuff(buf++, sizeof(*buf));"
10926 : "}", false);
10927 1 : ASSERT_EQUALS("", errout_str());
10928 : }
10929 :
10930 1 : void testUnsignedLessThanZero() {
10931 1 : check("struct d {\n"
10932 : " unsigned n;\n"
10933 : "};\n"
10934 : "void f(void) {\n"
10935 : " struct d d;\n"
10936 : " d.n = 3;\n"
10937 : "\n"
10938 : " if (d.n < 0) {\n"
10939 : " return;\n"
10940 : " }\n"
10941 : "\n"
10942 : " if (0 > d.n) {\n"
10943 : " return;\n"
10944 : " }\n"
10945 : "}", false);
10946 1 : ASSERT_EQUALS("[test.c:8]: (style) Checking if unsigned expression 'd.n' is less than zero.\n"
10947 : "[test.c:12]: (style) Checking if unsigned expression 'd.n' is less than zero.\n",
10948 : errout_str());
10949 : }
10950 :
10951 1 : void doubleMove1() {
10952 1 : check("void g(A a);\n"
10953 : "void f() {\n"
10954 : " A a;\n"
10955 : " g(std::move(a));\n"
10956 : " g(std::move(a));\n"
10957 : "}");
10958 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'a'.\n", errout_str());
10959 : }
10960 :
10961 1 : void doubleMoveMemberInitialization1() {
10962 1 : check("class A\n"
10963 : "{\n"
10964 : " A(B && b)\n"
10965 : " :b1(std::move(b))\n"
10966 : " {\n"
10967 : " b2 = std::move(b);\n"
10968 : " }\n"
10969 : " B b1;\n"
10970 : " B b2;\n"
10971 : "};");
10972 1 : ASSERT_EQUALS("[test.cpp:6]: (warning) Access of moved variable 'b'.\n", errout_str());
10973 : }
10974 :
10975 1 : void doubleMoveMemberInitialization2() {
10976 1 : check("class A\n"
10977 : "{\n"
10978 : " A(B && b)\n"
10979 : " :b1(std::move(b)),\n"
10980 : " b2(std::move(b))\n"
10981 : " {}\n"
10982 : " B b1;\n"
10983 : " B b2;\n"
10984 : "};");
10985 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'b'.\n", errout_str());
10986 : }
10987 :
10988 1 : void doubleMoveMemberInitialization3() { // #9974
10989 1 : check("struct A { int i; };\n"
10990 : "struct B { A a1; A a2; };\n"
10991 : "B f() {\n"
10992 : " A a1 = { 1 };\n"
10993 : " A a2 = { 2 };\n"
10994 : " return { .a1 = std::move(a1), .a2 = std::move(a2) };\n"
10995 : "}\n");
10996 1 : ASSERT_EQUALS("", errout_str());
10997 : }
10998 :
10999 1 : void doubleMoveMemberInitialization4() { // #11440
11000 1 : check("struct S { void f(int); };\n"
11001 : "struct T {\n"
11002 : " T(int c, S&& d) : c{ c }, d{ std::move(d) } { d.f(c); }\n"
11003 : " int c;\n"
11004 : " S d;\n"
11005 : "};\n");
11006 1 : ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Access of moved variable 'd'.\n", errout_str());
11007 : }
11008 :
11009 1 : void moveAndAssign1() {
11010 1 : check("A g(A a);\n"
11011 : "void f() {\n"
11012 : " A a;\n"
11013 : " a = g(std::move(a));\n"
11014 : " a = g(std::move(a));\n"
11015 : "}");
11016 1 : ASSERT_EQUALS("", errout_str());
11017 : }
11018 :
11019 1 : void moveAndAssign2() {
11020 1 : check("A g(A a);\n"
11021 : "void f() {\n"
11022 : " A a;\n"
11023 : " B b = g(std::move(a));\n"
11024 : " C c = g(std::move(a));\n"
11025 : "}");
11026 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'a'.\n", errout_str());
11027 : }
11028 :
11029 1 : void moveAssignMoveAssign() {
11030 1 : check("void h(A a);\n"
11031 : "void f() {"
11032 : " A a;\n"
11033 : " g(std::move(a));\n"
11034 : " h(a);\n"
11035 : " a = b;\n"
11036 : " h(a);\n"
11037 : " g(std::move(a));\n"
11038 : " h(a);\n"
11039 : " a = b;\n"
11040 : " h(a);\n"
11041 : "}");
11042 1 : ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable 'a'.\n"
11043 : "[test.cpp:8]: (warning) Access of moved variable 'a'.\n", errout_str());
11044 : }
11045 :
11046 1 : void moveAndReset1() {
11047 1 : check("A g(A a);\n"
11048 : "void f() {\n"
11049 : " A a;\n"
11050 : " a.reset(g(std::move(a)));\n"
11051 : " a.reset(g(std::move(a)));\n"
11052 : "}");
11053 1 : ASSERT_EQUALS("", errout_str());
11054 : }
11055 :
11056 1 : void moveAndReset2() {
11057 1 : check("A g(A a);\n"
11058 : "void f() {\n"
11059 : " A a;\n"
11060 : " A b;\n"
11061 : " A c;\n"
11062 : " b.reset(g(std::move(a)));\n"
11063 : " c.reset(g(std::move(a)));\n"
11064 : "}");
11065 1 : ASSERT_EQUALS("[test.cpp:7]: (warning) Access of moved variable 'a'.\n", errout_str());
11066 : }
11067 :
11068 1 : void moveResetMoveReset() {
11069 1 : check("void h(A a);\n"
11070 : "void f() {"
11071 : " A a;\n"
11072 : " g(std::move(a));\n"
11073 : " h(a);\n"
11074 : " a.reset(b);\n"
11075 : " h(a);\n"
11076 : " g(std::move(a));\n"
11077 : " h(a);\n"
11078 : " a.reset(b);\n"
11079 : " h(a);\n"
11080 : "}");
11081 1 : ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable 'a'.\n"
11082 : "[test.cpp:8]: (warning) Access of moved variable 'a'.\n", errout_str());
11083 : }
11084 :
11085 1 : void moveAndFunctionParameter() {
11086 1 : check("void g(A a);\n"
11087 : "void f() {\n"
11088 : " A a;\n"
11089 : " A b = std::move(a);\n"
11090 : " g(a);\n"
11091 : " A c = a;\n"
11092 : "}");
11093 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'a'.\n"
11094 : "[test.cpp:6]: (warning) Access of moved variable 'a'.\n", errout_str());
11095 : }
11096 :
11097 1 : void moveAndFunctionParameterReference() {
11098 1 : check("void g(A & a);\n"
11099 : "void f() {\n"
11100 : " A a;\n"
11101 : " A b = std::move(a);\n"
11102 : " g(a);\n"
11103 : " A c = a;\n"
11104 : "}");
11105 1 : ASSERT_EQUALS("", errout_str());
11106 : }
11107 :
11108 1 : void moveAndFunctionParameterConstReference() {
11109 1 : check("void g(A const & a);\n"
11110 : "void f() {\n"
11111 : " A a;\n"
11112 : " A b = std::move(a);\n"
11113 : " g(a);\n"
11114 : " A c = a;\n"
11115 : "}");
11116 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'a'.\n"
11117 : "[test.cpp:6]: (warning) Access of moved variable 'a'.\n", errout_str());
11118 : }
11119 :
11120 1 : void moveAndFunctionParameterUnknown() {
11121 1 : check("void f() {\n"
11122 : " A a;\n"
11123 : " A b = std::move(a);\n"
11124 : " g(a);\n"
11125 : " A c = a;\n"
11126 : "}");
11127 1 : ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Access of moved variable 'a'.\n"
11128 : "[test.cpp:5]: (warning, inconclusive) Access of moved variable 'a'.\n", errout_str());
11129 : }
11130 :
11131 1 : void moveAndReturn() {
11132 1 : check("int f(int i) {\n"
11133 : " A a;\n"
11134 : " A b;\n"
11135 : " g(std::move(a));\n"
11136 : " if (i)\n"
11137 : " return g(std::move(b));\n"
11138 : " return h(std::move(a),std::move(b));\n"
11139 : "}");
11140 1 : ASSERT_EQUALS("[test.cpp:7]: (warning) Access of moved variable 'a'.\n", errout_str());
11141 : }
11142 :
11143 1 : void moveAndClear() {
11144 1 : check("void f() {\n"
11145 : " V v;\n"
11146 : " g(std::move(v));\n"
11147 : " v.clear();\n"
11148 : " if (v.empty()) {}\n"
11149 : "}");
11150 1 : ASSERT_EQUALS("", errout_str());
11151 : }
11152 :
11153 1 : void movedPointer() {
11154 1 : check("void f() {\n"
11155 : " P p;\n"
11156 : " g(std::move(p));\n"
11157 : " x = p->x;\n"
11158 : " y = p->y;\n"
11159 : "}");
11160 1 : ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable 'p'.\n"
11161 : "[test.cpp:5]: (warning) Access of moved variable 'p'.\n", errout_str());
11162 : }
11163 :
11164 1 : void moveAndAddressOf() {
11165 1 : check("void f() {\n"
11166 : " std::string s1 = x;\n"
11167 : " std::string s2 = std::move(s1);\n"
11168 : " p = &s1;\n"
11169 : "}");
11170 1 : ASSERT_EQUALS("", errout_str());
11171 : }
11172 :
11173 1 : void partiallyMoved() {
11174 1 : check("void f() {\n"
11175 : " A a;\n"
11176 : " gx(std::move(a).x());\n"
11177 : " gy(std::move(a).y());\n"
11178 : "}");
11179 1 : ASSERT_EQUALS("", errout_str());
11180 : }
11181 :
11182 1 : void moveAndLambda() {
11183 1 : check("void f() {\n"
11184 : " A a;\n"
11185 : " auto h = [a=std::move(a)](){return g(std::move(a));};"
11186 : " b = a;\n"
11187 : "}");
11188 1 : ASSERT_EQUALS("", errout_str());
11189 : }
11190 :
11191 1 : void moveInLoop()
11192 : {
11193 1 : check("void g(std::string&& s);\n"
11194 : "void f() {\n"
11195 : " std::string p;\n"
11196 : " while(true)\n"
11197 : " g(std::move(p));\n"
11198 : "}\n");
11199 1 : ASSERT_EQUALS("[test.cpp:5]: (warning) Access of moved variable 'p'.\n", errout_str());
11200 :
11201 1 : check("std::list<int> g(std::list<int>&&);\n"
11202 : "void f(std::list<int>l) {\n"
11203 : " for(int i = 0; i < 10; ++i) {\n"
11204 : " for (auto &j : g(std::move(l))) { (void)j; }\n"
11205 : " }\n"
11206 : "}\n");
11207 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' can be declared as reference to const\n"
11208 : "[test.cpp:4]: (warning) Access of moved variable 'l'.\n",
11209 : errout_str());
11210 : }
11211 :
11212 1 : void moveCallback()
11213 : {
11214 1 : check("bool f(std::function<void()>&& callback);\n"
11215 : "void func(std::function<void()> callback) {\n"
11216 : " if(!f(std::move(callback)))\n"
11217 : " callback();\n"
11218 : "}\n");
11219 1 : ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable 'callback'.\n", errout_str());
11220 : }
11221 :
11222 1 : void moveClassVariable()
11223 : {
11224 1 : check("struct B {\n"
11225 : " virtual void f();\n"
11226 : "};\n"
11227 : "struct D : B {\n"
11228 : " void f() override {\n"
11229 : " auto p = std::unique_ptr<D>(new D(std::move(m)));\n"
11230 : " }\n"
11231 : " D(std::unique_ptr<int> c) : m(std::move(c)) {}\n"
11232 : " std::unique_ptr<int> m;\n"
11233 : "};\n");
11234 1 : ASSERT_EQUALS("", errout_str());
11235 : }
11236 :
11237 1 : void forwardAndUsed() {
11238 1 : check("template<typename T>\n"
11239 : "void f(T && t) {\n"
11240 : " g(std::forward<T>(t));\n"
11241 : " T s = t;\n"
11242 : "}");
11243 1 : ASSERT_EQUALS("[test.cpp:4]: (warning) Access of forwarded variable 't'.\n", errout_str());
11244 : }
11245 :
11246 1 : void moveAndReference() { // #9791
11247 1 : check("void g(std::string&&);\n"
11248 : "void h(const std::string&);\n"
11249 : "void f() {\n"
11250 : " std::string s;\n"
11251 : " const std::string& r = s;\n"
11252 : " g(std::move(s));\n"
11253 : " h(r);\n"
11254 : "}\n");
11255 1 : ASSERT_EQUALS("[test.cpp:7]: (warning) Access of moved variable 'r'.\n", errout_str());
11256 : }
11257 :
11258 1 : void moveForRange()
11259 : {
11260 1 : check("struct C {\n"
11261 : " void f() {\n"
11262 : " for (auto r : mCategory.find(std::move(mWhere))) {}\n"
11263 : " }\n"
11264 : " cif::category mCategory;\n"
11265 : " cif::condition mWhere;\n"
11266 : "};\n");
11267 1 : ASSERT_EQUALS("", errout_str());
11268 : }
11269 :
11270 1 : void moveTernary()
11271 : {
11272 1 : check("void gA(std::string);\n" // #12174
11273 : "void gB(std::string);\n"
11274 : "void f(bool b) {\n"
11275 : " std::string s = \"abc\";\n"
11276 : " b ? gA(std::move(s)) : gB(std::move(s));\n"
11277 : "}\n");
11278 1 : ASSERT_EQUALS("", errout_str());
11279 :
11280 1 : check("int gA(std::string);\n"
11281 : "int gB(std::string);\n"
11282 : "void h(int);\n"
11283 : "void f(bool b) {\n"
11284 : " std::string s = \"abc\";\n"
11285 : " h(b ? gA(std::move(s)) : gB(std::move(s)));\n"
11286 : "}\n");
11287 1 : ASSERT_EQUALS("", errout_str());
11288 :
11289 1 : check("int gA(int, std::string);\n"
11290 : "int gB(int, std::string);\n"
11291 : "int h(int);\n"
11292 : "void f(bool b) {\n"
11293 : " std::string s = \"abc\";\n"
11294 : " h(b ? h(gA(5, std::move(s))) : h(gB(7, std::move(s))));\n"
11295 : "}\n");
11296 1 : ASSERT_EQUALS("", errout_str());
11297 : }
11298 :
11299 1 : void funcArgNamesDifferent() {
11300 1 : check("void func1(int a, int b, int c);\n"
11301 : "void func1(int a, int b, int c) { }\n"
11302 : "void func2(int a, int b, int c);\n"
11303 : "void func2(int A, int B, int C) { }\n"
11304 : "class Fred {\n"
11305 : " void func1(int a, int b, int c);\n"
11306 : " void func2(int a, int b, int c);\n"
11307 : " void func3(int a = 0, int b = 0, int c = 0);\n"
11308 : " void func4(int a = 0, int b = 0, int c = 0);\n"
11309 : "};\n"
11310 : "void Fred::func1(int a, int b, int c) { }\n"
11311 : "void Fred::func2(int A, int B, int C) { }\n"
11312 : "void Fred::func3(int a, int b, int c) { }\n"
11313 : "void Fred::func4(int A, int B, int C) { }");
11314 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style, inconclusive) Function 'func2' argument 1 names different: declaration 'a' definition 'A'.\n"
11315 : "[test.cpp:3] -> [test.cpp:4]: (style, inconclusive) Function 'func2' argument 2 names different: declaration 'b' definition 'B'.\n"
11316 : "[test.cpp:3] -> [test.cpp:4]: (style, inconclusive) Function 'func2' argument 3 names different: declaration 'c' definition 'C'.\n"
11317 : "[test.cpp:7] -> [test.cpp:12]: (style, inconclusive) Function 'func2' argument 1 names different: declaration 'a' definition 'A'.\n"
11318 : "[test.cpp:7] -> [test.cpp:12]: (style, inconclusive) Function 'func2' argument 2 names different: declaration 'b' definition 'B'.\n"
11319 : "[test.cpp:7] -> [test.cpp:12]: (style, inconclusive) Function 'func2' argument 3 names different: declaration 'c' definition 'C'.\n"
11320 : "[test.cpp:9] -> [test.cpp:14]: (style, inconclusive) Function 'func4' argument 1 names different: declaration 'a' definition 'A'.\n"
11321 : "[test.cpp:9] -> [test.cpp:14]: (style, inconclusive) Function 'func4' argument 2 names different: declaration 'b' definition 'B'.\n"
11322 : "[test.cpp:9] -> [test.cpp:14]: (style, inconclusive) Function 'func4' argument 3 names different: declaration 'c' definition 'C'.\n", errout_str());
11323 : }
11324 :
11325 1 : void funcArgOrderDifferent() {
11326 1 : check("void func1(int a, int b, int c);\n"
11327 : "void func1(int a, int b, int c) { }\n"
11328 : "void func2(int a, int b, int c);\n"
11329 : "void func2(int c, int b, int a) { }\n"
11330 : "void func3(int, int b, int c);\n"
11331 : "void func3(int c, int b, int a) { }\n"
11332 : "class Fred {\n"
11333 : " void func1(int a, int b, int c);\n"
11334 : " void func2(int a, int b, int c);\n"
11335 : " void func3(int a = 0, int b = 0, int c = 0);\n"
11336 : " void func4(int, int b = 0, int c = 0);\n"
11337 : "};\n"
11338 : "void Fred::func1(int a, int b, int c) { }\n"
11339 : "void Fred::func2(int c, int b, int a) { }\n"
11340 : "void Fred::func3(int c, int b, int a) { }\n"
11341 : "void Fred::func4(int c, int b, int a) { }\n",
11342 : true, false);
11343 1 : ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
11344 : "[test.cpp:5] -> [test.cpp:6]: (warning) Function 'func3' argument order different: declaration ', b, c' definition 'c, b, a'\n"
11345 : "[test.cpp:9] -> [test.cpp:14]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
11346 : "[test.cpp:10] -> [test.cpp:15]: (warning) Function 'func3' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
11347 : "[test.cpp:11] -> [test.cpp:16]: (warning) Function 'func4' argument order different: declaration ', b, c' definition 'c, b, a'\n", errout_str());
11348 : }
11349 :
11350 : // #7846 - Syntax error when using C++11 braced-initializer in default argument
11351 1 : void cpp11FunctionArgInit() {
11352 : // syntax error is not expected
11353 1 : ASSERT_NO_THROW(check("\n void foo(int declaration = {}) {"
11354 : "\n for (int i = 0; i < 10; i++) {}\n"
11355 : "\n }"
11356 : "\n "));
11357 1 : ASSERT_EQUALS("", errout_str());
11358 : }
11359 :
11360 1 : void shadowVariables() {
11361 1 : check("int x;\n"
11362 : "void f() { int x; }");
11363 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable \'x\' shadows outer variable\n", errout_str());
11364 :
11365 1 : check("int x();\n"
11366 : "void f() { int x; }");
11367 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable \'x\' shadows outer function\n", errout_str());
11368 :
11369 1 : check("struct C {\n"
11370 : " C(int x) : x(x) {}\n" // <- we do not want a FP here
11371 : " int x;\n"
11372 : "};");
11373 1 : ASSERT_EQUALS("", errout_str());
11374 :
11375 1 : check("void f() {\n"
11376 : " if (cond) {int x;}\n" // <- not a shadow variable
11377 : " int x;\n"
11378 : "}");
11379 1 : ASSERT_EQUALS("", errout_str());
11380 :
11381 1 : check("int size() {\n"
11382 : " int size;\n" // <- not a shadow variable
11383 : "}");
11384 1 : ASSERT_EQUALS("", errout_str());
11385 :
11386 1 : check("void f() {\n" // #8954 - lambda
11387 : " int x;\n"
11388 : " auto f = [](){ int x; }"
11389 : "}");
11390 1 : ASSERT_EQUALS("", errout_str());
11391 :
11392 1 : check("void f(int x) { int x; }");
11393 1 : ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Local variable 'x' shadows outer argument\n", errout_str());
11394 :
11395 1 : check("class C { C(); void foo() { static int C = 0; } }"); // #9195 - shadow constructor
11396 1 : ASSERT_EQUALS("", errout_str());
11397 :
11398 1 : check("struct C {\n" // #10091 - shadow destructor
11399 : " ~C();\n"
11400 : " void f() {\n"
11401 : " bool C{};\n"
11402 : " }\n"
11403 : "};\n"
11404 : "C::~C() = default;");
11405 1 : ASSERT_EQUALS("", errout_str());
11406 :
11407 : // 10752 - no
11408 1 : check("struct S {\n"
11409 : " int i;\n"
11410 : "\n"
11411 : " static int foo() {\n"
11412 : " int i = 0;\n"
11413 : " return i;\n"
11414 : " }\n"
11415 : "};");
11416 1 : ASSERT_EQUALS("", errout_str());
11417 :
11418 1 : check("struct S {\n"
11419 : " int i{};\n"
11420 : " void f() { int i; }\n"
11421 : "};\n");
11422 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Local variable 'i' shadows outer variable\n", errout_str());
11423 :
11424 1 : check("struct S {\n"
11425 : " int i{};\n"
11426 : " std::vector<int> v;\n"
11427 : " void f() const { for (const int& i : v) {} }\n"
11428 : "};\n");
11429 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (style) Local variable 'i' shadows outer variable\n", errout_str());
11430 :
11431 1 : check("struct S {\n" // #10405
11432 : " F* f{};\n"
11433 : " std::list<F> fl;\n"
11434 : " void S::f() const;\n"
11435 : "};\n"
11436 : "void S::f() const {\n"
11437 : " for (const F& f : fl) {}\n"
11438 : "};\n");
11439 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:7]: (style) Local variable 'f' shadows outer variable\n", errout_str());
11440 :
11441 1 : check("extern int a;\n"
11442 : "int a;\n"
11443 : "static int f(void) {\n"
11444 : " int a;\n"
11445 : " return 0;\n"
11446 : "}\n", false);
11447 1 : ASSERT_EQUALS("[test.c:1] -> [test.c:4]: (style) Local variable 'a' shadows outer variable\n", errout_str());
11448 :
11449 1 : check("int f() {\n" // #12591
11450 : " int g = 0;\n"
11451 : " return g;\n"
11452 : "}\n"
11453 : "int g() { return 1; }\n");
11454 1 : ASSERT_EQUALS("", errout_str());
11455 : }
11456 :
11457 1 : void knownArgument() {
11458 1 : check("void g(int);\n"
11459 : "void f(int x) {\n"
11460 : " g((x & 0x01) >> 7);\n"
11461 : "}");
11462 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Argument '(x&0x01)>>7' to function g is always 0. It does not matter what value 'x' has.\n", errout_str());
11463 :
11464 1 : check("void g(int);\n"
11465 : "void f(int x) {\n"
11466 : " g((int)((x & 0x01) >> 7));\n"
11467 : "}");
11468 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Argument '(int)((x&0x01)>>7)' to function g is always 0. It does not matter what value 'x' has.\n", errout_str());
11469 :
11470 1 : check("void g(int, int);\n"
11471 : "void f(int x) {\n"
11472 : " g(x, (x & 0x01) >> 7);\n"
11473 : "}");
11474 1 : ASSERT_EQUALS(
11475 : "[test.cpp:3]: (style) Argument '(x&0x01)>>7' to function g is always 0. It does not matter what value 'x' has.\n",
11476 : errout_str());
11477 :
11478 1 : check("void g(int);\n"
11479 : "void f(int x) {\n"
11480 : " g(0);\n"
11481 : "}");
11482 1 : ASSERT_EQUALS("", errout_str());
11483 :
11484 1 : check("void g(int);\n"
11485 : "void h() { return 1; }\n"
11486 : "void f(int x) {\n"
11487 : " g(h());\n"
11488 : "}");
11489 1 : ASSERT_EQUALS("", errout_str());
11490 :
11491 1 : check("void g(int);\n"
11492 : "void f(int x) {\n"
11493 : " g(std::strlen(\"a\"));\n"
11494 : "}");
11495 1 : ASSERT_EQUALS("", errout_str());
11496 :
11497 1 : check("void g(int);\n"
11498 : "void f(int x) {\n"
11499 : " g((int)0);\n"
11500 : "}");
11501 1 : ASSERT_EQUALS("", errout_str());
11502 :
11503 1 : check("void g(Foo *);\n"
11504 : "void f() {\n"
11505 : " g(reinterpret_cast<Foo*>(0));\n"
11506 : "}");
11507 1 : ASSERT_EQUALS("", errout_str());
11508 :
11509 1 : check("void g(int);\n"
11510 : "void f(int x) {\n"
11511 : " x = 0;\n"
11512 : " g(x);\n"
11513 : "}");
11514 1 : ASSERT_EQUALS("", errout_str());
11515 :
11516 1 : check("void g(int);\n"
11517 : "void f() {\n"
11518 : " const int x = 0;\n"
11519 : " g(x + 1);\n"
11520 : "}");
11521 1 : ASSERT_EQUALS("", errout_str());
11522 :
11523 1 : check("void g(int);\n"
11524 : "void f() {\n"
11525 : " char i = 1;\n"
11526 : " g(static_cast<int>(i));\n"
11527 : "}");
11528 1 : ASSERT_EQUALS("", errout_str());
11529 :
11530 1 : check("char *yytext;\n"
11531 : "void re_init_scanner() {\n"
11532 : " int size = 256;\n"
11533 : " yytext = xmalloc(size * sizeof *yytext);\n"
11534 : "}");
11535 1 : ASSERT_EQUALS("", errout_str());
11536 :
11537 1 : check("void foo(const char *c) {\n"
11538 : " if (*c == '+' && (operand || !isalnum(*c))) {}\n"
11539 : "}");
11540 1 : ASSERT_EQUALS("", errout_str());
11541 :
11542 : // #8986
11543 1 : check("void f(int);\n"
11544 : "void g() {\n"
11545 : " const int x[] = { 10, 10 };\n"
11546 : " f(x[0]);\n"
11547 : "}");
11548 1 : ASSERT_EQUALS("", errout_str());
11549 :
11550 1 : check("void f(int);\n"
11551 : "void g() {\n"
11552 : " int x[] = { 10, 10 };\n"
11553 : " f(x[0]);\n"
11554 : "}");
11555 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'x' can be declared as const array\n", errout_str());
11556 :
11557 1 : check("struct A { int x; };"
11558 : "void g(int);\n"
11559 : "void f(int x) {\n"
11560 : " A y;\n"
11561 : " y.x = 1;\n"
11562 : " g(y.x);\n"
11563 : "}");
11564 1 : ASSERT_EQUALS("", errout_str());
11565 :
11566 : // allow known argument value in assert call
11567 1 : check("void g(int);\n"
11568 : "void f(int x) {\n"
11569 : " ASSERT((int)((x & 0x01) >> 7));\n"
11570 : "}");
11571 1 : ASSERT_EQUALS("", errout_str());
11572 :
11573 : // #9905 - expression that does not use integer calculation at all
11574 1 : check("void foo() {\n"
11575 : " const std::string heading = \"Interval\";\n"
11576 : " std::cout << std::setw(heading.length());\n"
11577 : "}");
11578 1 : ASSERT_EQUALS("", errout_str());
11579 :
11580 : // #9909 - struct member with known value
11581 1 : check("struct LongStack {\n"
11582 : " int maxsize;\n"
11583 : "};\n"
11584 : "\n"
11585 : "void growLongStack(LongStack* self) {\n"
11586 : " self->maxsize = 32;\n"
11587 : " dostuff(self->maxsize * sizeof(intptr_t));\n"
11588 : "}");
11589 1 : ASSERT_EQUALS("", errout_str());
11590 :
11591 : // #11894
11592 1 : check("struct S {\n"
11593 : " int *p, n;\n"
11594 : "};\n"
11595 : "S* g() {\n"
11596 : " S* s = static_cast<S*>(calloc(1, sizeof(S)));\n"
11597 : " s->n = 100;\n"
11598 : " s->p = static_cast<int*>(malloc(s->n * sizeof(int)));\n"
11599 : " return s;\n"
11600 : "}\n");
11601 1 : ASSERT_EQUALS("", errout_str());
11602 :
11603 : // #11679
11604 1 : check("bool g(int);\n"
11605 : "void h(int);\n"
11606 : "int k(int a) { h(a); return 0; }\n"
11607 : "void f(int i) {\n"
11608 : " if (g(k(i))) {}\n"
11609 : "}\n");
11610 1 : ASSERT_EQUALS("", errout_str());
11611 :
11612 : // #11889
11613 1 : check("struct S {\n"
11614 : " int a[5];\n"
11615 : " void f(int i);\n"
11616 : "}\n"
11617 : "void g(int);\n"
11618 : "void S::f(int i) {\n"
11619 : " if (a[i] == 1) {\n"
11620 : " a[i] = 0;\n"
11621 : " g(a[i]);\n"
11622 : " }\n"
11623 : "}\n");
11624 1 : ASSERT_EQUALS("", errout_str());
11625 :
11626 : // #11927
11627 1 : check("void f(func_t func, int i) {\n"
11628 : " (func)(i, 0);\n"
11629 : "}\n");
11630 1 : ASSERT_EQUALS("", errout_str());
11631 :
11632 1 : check("struct S { void operator()(int, int); };\n"
11633 : "void f(int i) {\n"
11634 : " S()(i, 1);\n"
11635 : "}\n");
11636 1 : ASSERT_EQUALS("", errout_str());
11637 :
11638 1 : check("void f(int& r) {\n"
11639 : " g(static_cast<char>(r = 42));\n"
11640 : "}\n");
11641 1 : ASSERT_EQUALS("", errout_str());
11642 :
11643 1 : check("struct S { int i; };\n"
11644 : "void f(int i) {\n"
11645 : " const int a[] = { i - 1 * i, 0 };\n"
11646 : " auto s = S{ i - 1 * i };\n"
11647 : "}\n");
11648 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Argument 'i-1*i' to init list { is always 0. It does not matter what value 'i' has.\n"
11649 : "[test.cpp:4]: (style) Argument 'i-1*i' to constructor S is always 0. It does not matter what value 'i' has.\n",
11650 : errout_str());
11651 : }
11652 :
11653 1 : void knownArgumentHiddenVariableExpression() {
11654 : // #9914 - variable expression is explicitly hidden
11655 1 : check("void f(int x) {\n"
11656 : " dostuff(x && false);\n"
11657 : " dostuff(false && x);\n"
11658 : " dostuff(x || true);\n"
11659 : " dostuff(true || x);\n"
11660 : " dostuff(x * 0);\n"
11661 : " dostuff(0 * x);\n"
11662 : "}\n");
11663 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Argument 'false&&x' to function dostuff is always 0. Constant literal calculation disable/hide variable expression 'x'.\n"
11664 : "[test.cpp:5]: (style) Argument 'true||x' to function dostuff is always 1. Constant literal calculation disable/hide variable expression 'x'.\n"
11665 : "[test.cpp:6]: (style) Argument 'x*0' to function dostuff is always 0. Constant literal calculation disable/hide variable expression 'x'.\n"
11666 : "[test.cpp:7]: (style) Argument '0*x' to function dostuff is always 0. Constant literal calculation disable/hide variable expression 'x'.\n", errout_str());
11667 : }
11668 :
11669 1 : void knownArgumentTernaryOperator() { // #10374
11670 1 : check("void f(bool a, bool b) {\n"
11671 : " const T* P = nullptr; \n"
11672 : " long N = 0; \n"
11673 : " const bool c = foo(); \n"
11674 : " bar(P, N); \n"
11675 : " if (c ? a : b)\n"
11676 : " baz(P, N); \n"
11677 : "}");
11678 1 : ASSERT_EQUALS("", errout_str());
11679 : }
11680 :
11681 1 : void checkComparePointers() {
11682 1 : check("int f() {\n"
11683 : " const int foo[1] = {0};\n"
11684 : " const int bar[1] = {0};\n"
11685 : " int diff = 0;\n"
11686 : " if(foo > bar) {\n"
11687 : " diff = 1;\n"
11688 : " }\n"
11689 : " return diff;\n"
11690 : "}");
11691 1 : ASSERT_EQUALS(
11692 : "[test.cpp:2] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:5] -> [test.cpp:5]: (error) Comparing pointers that point to different objects\n",
11693 : errout_str());
11694 :
11695 1 : check("bool f() {\n"
11696 : " int x = 0;\n"
11697 : " int y = 0;\n"
11698 : " int* xp = &x;\n"
11699 : " int* yp = &y;\n"
11700 : " return xp > yp;\n"
11701 : "}");
11702 1 : ASSERT_EQUALS(
11703 : "[test.cpp:2] -> [test.cpp:4] -> [test.cpp:3] -> [test.cpp:5] -> [test.cpp:6]: (error) Comparing pointers that point to different objects\n"
11704 : "[test.cpp:4]: (style) Variable 'xp' can be declared as pointer to const\n"
11705 : "[test.cpp:5]: (style) Variable 'yp' can be declared as pointer to const\n",
11706 : errout_str());
11707 :
11708 1 : check("bool f() {\n"
11709 : " int x = 0;\n"
11710 : " int y = 1;\n"
11711 : " return &x > &y;\n"
11712 : "}");
11713 1 : ASSERT_EQUALS(
11714 : "[test.cpp:2] -> [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:4]: (error) Comparing pointers that point to different objects\n",
11715 : errout_str());
11716 :
11717 1 : check("struct A {int data;};\n"
11718 : "bool f() {\n"
11719 : " A x;\n"
11720 : " A y;\n"
11721 : " int* xp = &x.data;\n"
11722 : " int* yp = &y.data;\n"
11723 : " return xp > yp;\n"
11724 : "}");
11725 1 : ASSERT_EQUALS(
11726 : "[test.cpp:3] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:6] -> [test.cpp:7]: (error) Comparing pointers that point to different objects\n"
11727 : "[test.cpp:5]: (style) Variable 'xp' can be declared as pointer to const\n"
11728 : "[test.cpp:6]: (style) Variable 'yp' can be declared as pointer to const\n",
11729 : errout_str());
11730 :
11731 1 : check("struct A {int data;};\n"
11732 : "bool f(A ix, A iy) {\n"
11733 : " A* x = &ix;\n"
11734 : " A* y = &iy;\n"
11735 : " int* xp = &x->data;\n"
11736 : " int* yp = &y->data;\n"
11737 : " return xp > yp;\n"
11738 : "}");
11739 1 : ASSERT_EQUALS(
11740 : "[test.cpp:2] -> [test.cpp:3] -> [test.cpp:5] -> [test.cpp:2] -> [test.cpp:4] -> [test.cpp:6] -> [test.cpp:7]: (error) Comparing pointers that point to different objects\n"
11741 : "[test.cpp:5]: (style) Variable 'xp' can be declared as pointer to const\n"
11742 : "[test.cpp:6]: (style) Variable 'yp' can be declared as pointer to const\n",
11743 : errout_str());
11744 :
11745 1 : check("bool f(int * xp, int* yp) {\n"
11746 : " return &xp > &yp;\n"
11747 : "}");
11748 1 : ASSERT_EQUALS(
11749 : "[test.cpp:1] -> [test.cpp:2] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:2]: (error) Comparing pointers that point to different objects\n",
11750 : errout_str());
11751 :
11752 1 : check("int f() {\n"
11753 : " int x = 0;\n"
11754 : " int y = 1;\n"
11755 : " return &x - &y;\n"
11756 : "}");
11757 1 : ASSERT_EQUALS(
11758 : "[test.cpp:2] -> [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:4]: (error) Subtracting pointers that point to different objects\n",
11759 : errout_str());
11760 :
11761 1 : check("bool f() {\n"
11762 : " int x[2] = {1, 2}m;\n"
11763 : " int* xp = &x[0];\n"
11764 : " int* yp = &x[1];\n"
11765 : " return xp > yp;\n"
11766 : "}");
11767 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'xp' can be declared as pointer to const\n"
11768 : "[test.cpp:4]: (style) Variable 'yp' can be declared as pointer to const\n",
11769 : errout_str());
11770 :
11771 1 : check("bool f(const int * xp, const int* yp) {\n"
11772 : " return xp > yp;\n"
11773 : "}");
11774 1 : ASSERT_EQUALS("", errout_str());
11775 :
11776 1 : check("bool f(const int & x, const int& y) {\n"
11777 : " return &x > &y;\n"
11778 : "}");
11779 1 : ASSERT_EQUALS("", errout_str());
11780 :
11781 1 : check("int& g();\n"
11782 : "bool f() {\n"
11783 : " const int& x = g();\n"
11784 : " const int& y = g();\n"
11785 : " const int* xp = &x;\n"
11786 : " const int* yp = &y;\n"
11787 : " return xp > yp;\n"
11788 : "}");
11789 1 : ASSERT_EQUALS("", errout_str());
11790 :
11791 1 : check("struct A {int data;};\n"
11792 : "bool f(A ix) {\n"
11793 : " A* x = &ix;\n"
11794 : " A* y = x;\n"
11795 : " int* xp = &x->data;\n"
11796 : " int* yp = &y->data;\n"
11797 : " return xp > yp;\n"
11798 : "}");
11799 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'xp' can be declared as pointer to const\n"
11800 : "[test.cpp:6]: (style) Variable 'yp' can be declared as pointer to const\n",
11801 : errout_str());
11802 :
11803 1 : check("struct S { int i; };\n" // #11576
11804 : "int f(S s) {\n"
11805 : " return &s.i - (int*)&s;\n"
11806 : "}\n");
11807 1 : ASSERT_EQUALS("[test.cpp:3]: (style) C-style pointer casting\n", errout_str());
11808 :
11809 1 : check("struct S { int i; };\n"
11810 : "int f(S s1, S s2) {\n"
11811 : " return &s1.i - reinterpret_cast<int*>(&s2);\n"
11812 : "}\n");
11813 1 : ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:3]: (error) Subtracting pointers that point to different objects\n",
11814 : errout_str());
11815 :
11816 1 : check("struct S { int a; int b; };\n" // #12422
11817 : "int f() {\n"
11818 : " S s;\n"
11819 : " return &s.b - &s.a;\n"
11820 : "}\n");
11821 1 : ASSERT_EQUALS("", errout_str());
11822 : }
11823 :
11824 1 : void unusedVariableValueTemplate() {
11825 1 : check("#include <functional>\n"
11826 : "class A\n"
11827 : "{\n"
11828 : "public:\n"
11829 : " class Hash\n"
11830 : " {\n"
11831 : " public:\n"
11832 : " std::size_t operator()(const A& a) const\n"
11833 : " {\n"
11834 : " (void)a;\n"
11835 : " return 0;\n"
11836 : " }\n"
11837 : " };\n"
11838 : "};\n"
11839 : "namespace std\n"
11840 : "{\n"
11841 : " template <>\n"
11842 : " struct hash<A>\n"
11843 : " {\n"
11844 : " std::size_t operator()(const A& a) const noexcept\n"
11845 : " {\n"
11846 : " return A::Hash{}(a);\n"
11847 : " }\n"
11848 : " };\n"
11849 : "}");
11850 1 : ASSERT_EQUALS("", errout_str());
11851 : }
11852 :
11853 1 : void moduloOfOne() {
11854 1 : check("void f(unsigned int x) {\n"
11855 : " int y = x % 1;\n"
11856 : "}");
11857 1 : ASSERT_EQUALS("[test.cpp:2]: (style) Modulo of one is always equal to zero\n", errout_str());
11858 :
11859 1 : check("void f() {\n"
11860 : " for (int x = 1; x < 10; x++) {\n"
11861 : " int y = 100 % x;\n"
11862 : " }\n"
11863 : "}");
11864 1 : ASSERT_EQUALS("", errout_str());
11865 :
11866 1 : check("void f(int i, int j) {\n" // #11191
11867 : " const int c = pow(2, i);\n"
11868 : " if (j % c) {}\n"
11869 : "}\n");
11870 1 : ASSERT_EQUALS("", errout_str());
11871 : }
11872 :
11873 1 : void sameExpressionPointers() {
11874 1 : check("int f(int *i);\n"
11875 : "void g(int *a, const int *b) {\n"
11876 : " int c = *a;\n"
11877 : " f(a);\n"
11878 : " if (b && c != *a) {}\n"
11879 : "}\n");
11880 1 : ASSERT_EQUALS("", errout_str());
11881 : }
11882 :
11883 1 : void checkOverlappingWrite() {
11884 : // union
11885 1 : check("void foo() {\n"
11886 : " union { int i; float f; } u;\n"
11887 : " u.i = 0;\n"
11888 : " u.i = u.f;\n" // <- error
11889 : "}");
11890 1 : ASSERT_EQUALS("[test.cpp:4]: (error) Overlapping read/write of union is undefined behavior\n", errout_str());
11891 :
11892 1 : check("void foo() {\n" // #11013
11893 : " union { struct { uint8_t a; uint8_t b; }; uint16_t c; } u;\n"
11894 : " u.a = u.b = 0;\n"
11895 : "}");
11896 1 : ASSERT_EQUALS("", errout_str());
11897 :
11898 : // memcpy
11899 1 : check("void foo() {\n"
11900 : " char a[10];\n"
11901 : " memcpy(&a[5], &a[4], 2u);\n"
11902 : "}");
11903 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in memcpy() is undefined behavior\n", errout_str());
11904 :
11905 1 : check("void foo() {\n"
11906 : " char a[10];\n"
11907 : " memcpy(a+5, a+4, 2u);\n"
11908 : "}");
11909 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in memcpy() is undefined behavior\n", errout_str());
11910 :
11911 1 : check("void foo() {\n"
11912 : " char a[10];\n"
11913 : " memcpy(a, a+1, 2u);\n"
11914 : "}");
11915 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in memcpy() is undefined behavior\n", errout_str());
11916 :
11917 1 : check("void foo() {\n"
11918 : " char a[8];\n"
11919 : " memcpy(&a[0], &a[4], 4u);\n"
11920 : "}");
11921 1 : ASSERT_EQUALS("", errout_str());
11922 :
11923 1 : check("_Bool a[10];\n" // #10350
11924 : "void foo() {\n"
11925 : " memcpy(&a[5], &a[4], 2u * sizeof(a[0]));\n"
11926 : "}");
11927 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in memcpy() is undefined behavior\n", errout_str());
11928 :
11929 1 : check("int K[2];\n" // #12638
11930 : "void f(int* p) {\n"
11931 : " memcpy(&K[0], &K[1], sizeof(K[0]));\n"
11932 : " memcpy(&K[1], &K[0], sizeof(K[0]));\n"
11933 : " memcpy(p, p + 1, sizeof(*p));\n"
11934 : " memcpy(p + 1, p, sizeof(*p));\n"
11935 : "}");
11936 1 : ASSERT_EQUALS("", errout_str());
11937 :
11938 1 : check("int K[2];\n"
11939 : "void f(int* p) {\n"
11940 : " memcpy(&K[0], &K[1], 2 * sizeof(K[0]));\n"
11941 : " memcpy(&K[1], &K[0], 2 *sizeof(K[0]));\n"
11942 : " memcpy(p, p + 1, 2 * sizeof(*p));\n"
11943 : " memcpy(p + 1, p, 2 * sizeof(*p));\n"
11944 : "}");
11945 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in memcpy() is undefined behavior\n"
11946 : "[test.cpp:4]: (error) Overlapping read/write in memcpy() is undefined behavior\n"
11947 : "[test.cpp:5]: (error) Overlapping read/write in memcpy() is undefined behavior\n"
11948 : "[test.cpp:6]: (error) Overlapping read/write in memcpy() is undefined behavior\n",
11949 : errout_str());
11950 :
11951 : // wmemcpy
11952 1 : check("void foo() {\n"
11953 : " wchar_t a[10];\n"
11954 : " wmemcpy(&a[5], &a[4], 2u);\n"
11955 : "}");
11956 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in wmemcpy() is undefined behavior\n", errout_str());
11957 :
11958 1 : check("void foo() {\n"
11959 : " wchar_t a[10];\n"
11960 : " wmemcpy(a+5, a+4, 2u);\n"
11961 : "}");
11962 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in wmemcpy() is undefined behavior\n", errout_str());
11963 :
11964 1 : check("void foo() {\n"
11965 : " wchar_t a[10];\n"
11966 : " wmemcpy(a, a+1, 2u);\n"
11967 : "}");
11968 1 : ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in wmemcpy() is undefined behavior\n", errout_str());
11969 :
11970 : // strcpy
11971 1 : check("void foo(char *ptr) {\n"
11972 : " strcpy(ptr, ptr);\n"
11973 : "}");
11974 1 : ASSERT_EQUALS("[test.cpp:2]: (error) Overlapping read/write in strcpy() is undefined behavior\n", errout_str());
11975 : }
11976 :
11977 1 : void constVariableArrayMember() { // #10371
11978 1 : check("class Foo {\n"
11979 : "public:\n"
11980 : " Foo();\n"
11981 : " int GetVal() const { return m_Arr[0]; }\n"
11982 : " int m_Arr[1];\n"
11983 : "};\n");
11984 1 : ASSERT_EQUALS("", errout_str());
11985 : }
11986 :
11987 1 : void knownPointerToBool()
11988 : {
11989 1 : check("void g(bool);\n"
11990 : "void f() {\n"
11991 : " int i = 5;\n"
11992 : " int* p = &i;\n"
11993 : " g(p);\n"
11994 : " g(&i);\n"
11995 : "}\n");
11996 1 : ASSERT_EQUALS("[test.cpp:5]: (style) Pointer expression 'p' converted to bool is always true.\n"
11997 : "[test.cpp:6]: (style) Pointer expression '&i' converted to bool is always true.\n",
11998 : errout_str());
11999 :
12000 1 : check("void f() {\n"
12001 : " const int* x = nullptr;\n"
12002 : " std::empty(x);\n"
12003 : "}\n");
12004 1 : ASSERT_EQUALS("", errout_str());
12005 :
12006 1 : check("void f() {\n"
12007 : " const int* x = nullptr;\n"
12008 : " std::empty(const_cast<int*>(x));\n"
12009 : "}\n");
12010 1 : ASSERT_EQUALS("", errout_str());
12011 :
12012 1 : check("struct A { bool x; };\n"
12013 : "bool f(A* a) {\n"
12014 : " if (a) {\n"
12015 : " return a->x;\n"
12016 : " }\n"
12017 : " return false;\n"
12018 : "}\n");
12019 1 : ASSERT_EQUALS("", errout_str());
12020 :
12021 1 : check("struct A { int* x; };\n"
12022 : "bool f(A a) {\n"
12023 : " if (a.x) {\n"
12024 : " return a.x;\n"
12025 : " }\n"
12026 : " return false;\n"
12027 : "}\n");
12028 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Pointer expression 'a.x' converted to bool is always true.\n", errout_str());
12029 :
12030 1 : check("void f(bool* b) { if (b) *b = true; }");
12031 1 : ASSERT_EQUALS("", errout_str());
12032 :
12033 1 : check("bool f() {\n"
12034 : " int* x = nullptr;\n"
12035 : " return bool(x);\n"
12036 : "}\n");
12037 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Pointer expression 'x' converted to bool is always false.\n", errout_str());
12038 :
12039 1 : check("bool f() {\n"
12040 : " int* x = nullptr;\n"
12041 : " return bool{x};\n"
12042 : "}\n");
12043 1 : ASSERT_EQUALS("[test.cpp:3]: (style) Pointer expression 'x' converted to bool is always false.\n", errout_str());
12044 :
12045 1 : check("struct A { A(bool); };\n"
12046 : "A f() {\n"
12047 : " int* x = nullptr;\n"
12048 : " return A(x);\n"
12049 : "}\n");
12050 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Pointer expression 'x' converted to bool is always false.\n", errout_str());
12051 :
12052 1 : check("struct A { A(bool); };\n"
12053 : "A f() {\n"
12054 : " int* x = nullptr;\n"
12055 : " return A{x};\n"
12056 : "}\n");
12057 1 : ASSERT_EQUALS("[test.cpp:4]: (style) Pointer expression 'x' converted to bool is always false.\n", errout_str());
12058 :
12059 1 : check("struct B { virtual void f() {} };\n" // #11929
12060 : "struct D : B {};\n"
12061 : "void g(B* b) {\n"
12062 : " if (!b)\n"
12063 : " return;\n"
12064 : " if (dynamic_cast<D*>(b)) {}\n"
12065 : "}\n");
12066 1 : ASSERT_EQUALS("", errout_str());
12067 :
12068 1 : check("bool (*ptr)();\n" // #12170
12069 : "void f() {\n"
12070 : " if (!ptr || !ptr()) {}\n"
12071 : "}\n");
12072 1 : ASSERT_EQUALS("", errout_str());
12073 : }
12074 :
12075 1 : void iterateByValue() {
12076 1 : check("void f() {\n" // #9684
12077 : " const std::set<std::string> ss = { \"a\", \"b\", \"c\" };\n"
12078 : " for (auto s : ss)\n"
12079 : " (void)s.size();\n"
12080 : "}\n");
12081 1 : ASSERT_EQUALS("[test.cpp:3]: (performance) Range variable 's' should be declared as const reference.\n",
12082 : errout_str());
12083 : }
12084 : };
12085 :
12086 : REGISTER_TEST(TestOther)
|