LCOV - code coverage report
Current view: top level - test - testother.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 3217 3217 100.0 %
Date: 2024-04-28 12:00:40 Functions: 226 226 100.0 %
Legend: Lines: hit not hit

          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)

Generated by: LCOV version 1.14