[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/CoderGears/cppcheck/master/test/testother.cpp [Back]  [Original]

/*
 * Cppcheck - A tool for static C/C++ code analysis
 * Copyright (C) 2007-2014 Daniel Marjamki and Cppcheck team.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

#include "preprocessor.h"
#include "tokenize.h"
#include "symboldatabase.h"
#include "checkother.h"
#include "testsuite.h"
#include "testutils.h"
#include 
#include 

extern std::ostringstream errout;

class TestOther : public TestFixture {
public:
    TestOther() : TestFixture("TestOther") {
    }

private:
    Settings settings_std;

    void run() {
        LOAD_LIB_2(settings_std.library, "std.cfg");

        TEST_CASE(emptyBrackets);

        TEST_CASE(zeroDiv1);
        TEST_CASE(zeroDiv2);
        TEST_CASE(zeroDiv3);
        TEST_CASE(zeroDiv4);
        TEST_CASE(zeroDiv5);
        TEST_CASE(zeroDiv6);
        TEST_CASE(zeroDiv7);  // #4930
        TEST_CASE(zeroDiv8);

        TEST_CASE(zeroDivCond); // division by zero / useless condition

        TEST_CASE(nanInArithmeticExpression);

        TEST_CASE(invalidFunctionUsage1);

        TEST_CASE(varScope1);
        TEST_CASE(varScope2);
        TEST_CASE(varScope3);
        TEST_CASE(varScope4);
        TEST_CASE(varScope5);
        TEST_CASE(varScope6);
        TEST_CASE(varScope7);
        TEST_CASE(varScope8);
        TEST_CASE(varScope9);       // classes may have extra side-effects
        TEST_CASE(varScope10);      // Undefined macro FOR
        TEST_CASE(varScope11);      // #2475 - struct initialization is not inner scope
        TEST_CASE(varScope12);
        TEST_CASE(varScope13);      // variable usage in inner loop
        TEST_CASE(varScope14);
        TEST_CASE(varScope15);      // #4573 if-else-if
        TEST_CASE(varScope16);
        TEST_CASE(varScope17);
        TEST_CASE(varScope18);
        TEST_CASE(varScope19);      // Ticket #4994
        TEST_CASE(varScope20);      // Ticket #5103
        TEST_CASE(varScope21);      // Ticket #5382
        TEST_CASE(varScope22);      // Ticket #5684
        TEST_CASE(varScope23);      // Ticket #6154

        TEST_CASE(oldStylePointerCast);
        TEST_CASE(invalidPointerCast);

        TEST_CASE(passedByValue);

        TEST_CASE(mathfunctionCall_fmod);
        TEST_CASE(mathfunctionCall_sqrt);
        TEST_CASE(mathfunctionCall_log);
        TEST_CASE(mathfunctionCall_acos);
        TEST_CASE(mathfunctionCall_asin);
        TEST_CASE(mathfunctionCall_pow);
        TEST_CASE(mathfunctionCall_atan2);
        TEST_CASE(mathfunctionCall_precision);

        TEST_CASE(switchRedundantAssignmentTest);
        TEST_CASE(switchRedundantOperationTest);
        TEST_CASE(switchRedundantBitwiseOperationTest);
        TEST_CASE(switchFallThroughCase);
        TEST_CASE(unreachableCode);

        TEST_CASE(suspiciousCase);
        TEST_CASE(suspiciousEqualityComparison);

        TEST_CASE(selfAssignment);
        TEST_CASE(trac1132);
        TEST_CASE(testMisusedScopeObjectDoesNotPickFunction1);
        TEST_CASE(testMisusedScopeObjectDoesNotPickFunction2);
        TEST_CASE(testMisusedScopeObjectPicksClass);
        TEST_CASE(testMisusedScopeObjectPicksStruct);
        TEST_CASE(testMisusedScopeObjectDoesNotPickIf);
        TEST_CASE(testMisusedScopeObjectDoesNotPickConstructorDeclaration);
        TEST_CASE(testMisusedScopeObjectDoesNotPickFunctor);
        TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors);
        TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject);
        TEST_CASE(testMisusedScopeObjectDoesNotPickPureC);
        TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass);
        TEST_CASE(testMisusedScopeObjectInConstructor);
        TEST_CASE(testMisusedScopeObjectNoCodeAfter);
        TEST_CASE(trac2071);
        TEST_CASE(trac2084);
        TEST_CASE(trac3693);

        TEST_CASE(memsetZeroBytes);
        TEST_CASE(memsetInvalid2ndParam);

        TEST_CASE(redundantGetAndSetUserId);

        TEST_CASE(clarifyCalculation);
        TEST_CASE(clarifyStatement);

        TEST_CASE(duplicateBranch);
        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: Fragement 2
        TEST_CASE(duplicateBranch2); // empty macro
        TEST_CASE(duplicateExpression1);
        TEST_CASE(duplicateExpression2); // ticket #2730
        TEST_CASE(duplicateExpression3); // ticket #3317
        TEST_CASE(duplicateExpression4); // ticket #3354 (++)
        TEST_CASE(duplicateExpression5); // ticket #3749 (macros with same values)
        TEST_CASE(duplicateExpression6); // ticket #4639

        TEST_CASE(checkSignOfUnsignedVariable);
        TEST_CASE(checkSignOfPointer);

        TEST_CASE(checkForSuspiciousSemicolon1);
        TEST_CASE(checkForSuspiciousSemicolon2);

        TEST_CASE(checkDoubleFree);
        TEST_CASE(checkInvalidFree);

        TEST_CASE(checkRedundantCopy);

        TEST_CASE(checkNegativeShift);

        TEST_CASE(incompleteArrayFill);

        TEST_CASE(redundantVarAssignment);
        TEST_CASE(redundantMemWrite);

        TEST_CASE(varFuncNullUB);

        TEST_CASE(checkPipeParameterSize); // ticket #3521

        TEST_CASE(checkCastIntToCharAndBack); // ticket #160

        TEST_CASE(checkSleepTimeIntervall)

        TEST_CASE(checkCommaSeparatedReturn);

        TEST_CASE(checkComparisonFunctionIsAlwaysTrueOrFalse);

        TEST_CASE(integerOverflow); // #5895

        TEST_CASE(testReturnIgnoredReturnValue);
    }

    void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool posix = false, bool runSimpleChecks=true, Settings* settings = 0) {
        // Clear the error buffer..
        errout.str("");

        if (!settings) {
            static Settings _settings;
            settings = &_settings;
        }
        settings->addEnabled("style");
        settings->addEnabled("warning");
        settings->addEnabled("portability");
        settings->addEnabled("performance");
        settings->inconclusive = inconclusive;
        settings->experimental = experimental;
        settings->standards.posix = posix;

        if (posix) {
            const char cfg[] = "\n"
                               "\n"
                               "   0:999999 \n"
                               "";
            tinyxml2::XMLDocument xmldoc;
            xmldoc.Parse(cfg, sizeof(cfg));
            settings->library.load(xmldoc);
        }

        // Tokenize..
        Tokenizer tokenizer(settings, this);
        std::istringstream istr(code);
        tokenizer.tokenize(istr, filename ? filename : "test.cpp");

        // Check..
        CheckOther checkOther(&tokenizer, settings, this);
        checkOther.runChecks(&tokenizer, settings, this);

        if (runSimpleChecks) {
            const std::string str1(tokenizer.tokens()->stringifyList(0,true));
            tokenizer.simplifyTokenList2();
            const std::string str2(tokenizer.tokens()->stringifyList(0,true));
            if (str1 != str2)
                warnUnsimplified(str1, str2);
            checkOther.runSimplifiedChecks(&tokenizer, settings, this);
        }
    }

    void check_preprocess_suppress(const char precode[], const char *filename = nullptr) {
        // Clear the error buffer..
        errout.str("");

        if (filename == nullptr)
            filename = "test.cpp";

        Settings settings;
        settings.addEnabled("warning");
        settings.addEnabled("style");
        settings.addEnabled("performance");
        settings.experimental = true;

        // Preprocess file..
        SimpleSuppressor logger(settings, this);
        Preprocessor preprocessor(&settings, &logger);
        std::list configurations;
        std::string filedata = "";
        std::istringstream fin(precode);
        preprocessor.preprocess(fin, filedata, configurations, filename, settings._includePaths);
        const std::string code = preprocessor.getcode(filedata, "", filename);

        // Tokenize..
        Tokenizer tokenizer(&settings, &logger);
        std::istringstream istr(code);
        tokenizer.tokenize(istr, filename);

        // Check..
        CheckOther checkOther(&tokenizer, &settings, &logger);
        checkOther.checkSwitchCaseFallThrough();

        logger.reportUnmatchedSuppressions(settings.nomsg.getUnmatchedLocalSuppressions(filename, false));
    }


    void emptyBrackets() {
        check("{\n"
              "}");
        ASSERT_EQUALS("", errout.str());
    }


    void zeroDiv1() {
        check("void foo() {\n"
              "    cout = 1) {}\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x>=1' is useless or there is division by zero at line 2.\n", errout.str());

        check("void f(int x) {\n"
              "  int y = 17 / x;\n"
              "  if (x == 0) {}\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x==0' is useless or there is division by zero at line 2.\n", errout.str());

        check("void f(unsigned int x) {\n"
              "  int y = 17 / x;\n"
              "  if (x != 0) {}\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x!=0' is useless or there is division by zero at line 2.\n", errout.str());

        // function call
        check("void f1(int x, int y) { c=x/y; }\n"
              "void f2(unsigned int y) {\n"
              "    f1(123,y);\n"
              "    if (y>0){}\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Either the condition 'y>0' is useless or there is division by zero at line 1.\n", errout.str());

        // avoid false positives when variable is changed after division
        check("void f() {\n"
              "  unsigned int x = do_something();\n"
              "  int y = 17 / x;\n"
              "  x = some+calculation;\n"
              "  if (x != 0) {}\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        {
            // function is called that might modify global variable
            check("void do_something();\n"
                  "int x;\n"
                  "void f() {\n"
                  "  int y = 17 / x;\n"
                  "  do_something();\n"
                  "  if (x != 0) {}\n"
                  "}");
            ASSERT_EQUALS("", errout.str());

            // function is called. but don't care, variable is local
            check("void do_something();\n"
                  "void f() {\n"
                  "  int x = some + calculation;\n"
                  "  int y = 17 / x;\n"
                  "  do_something();\n"
                  "  if (x != 0) {}\n"
                  "}");
            ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'x!=0' is useless or there is division by zero at line 4.\n", errout.str());
        }

        check("void do_something(int value);\n"
              "void f(int x) {\n"
              "  int y = 17 / x;\n"
              "  do_something(x);\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        check("int x;\n"
              "void f() {\n"
              "  int y = 17 / x;\n"
              "  while (y || x == 0) { x--; }\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        // ticket 5033 segmentation fault (valid code) in CheckOther::checkZeroDivisionOrUselessCondition
        check("void f() {\n"
              "double* p1= new double[1];\n"
              "double* p2= new double[1];\n"
              "double* p3= new double[1];\n"
              "double* pp[3] = {p1,p2,p3};\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        // #5105 - FP
        check("int f(int a, int b) {\n"
              "  int r = a / b;\n"
              "  if (func(b)) {}\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        // ?:
        check("int f(int d) {\n"
              "  int r = (a?b:c) / d;\n"
              "  if (d == 0) {}\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'd==0' is useless or there is division by zero at line 2.\n", errout.str());

        check("int f(int a) {\n"
              "  int r = a ? 1 / a : 0;\n"
              "  if (a == 0) {}\n"
              "}");
        ASSERT_EQUALS("", errout.str());

        check("int f(int a) {\n"
              "  int r = (a == 0) ? 0 : 1 / a;\n"
              "  if (a == 0) {}\n"
              "}");
        ASSERT_EQUALS("", errout.str());
    }

    void nanInArithmeticExpression() {
        check("void f()\n"
              "{\n"
              "   double x = 3.0 / 0.0 + 1.0\n"
              "   printf(\"%f\n\", x);\n"
              "}");
        ASSERT_EQUALS(
            "[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());

        check("void f()\n"
              "{\n"
              "   double x = 3.0 / 0.0 - 1.0\n"
              "   printf(\"%f\n\", x);\n"
              "}");
        ASSERT_EQUALS(
            "[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());

        check("void f()\n"
              "{\n"
              "   double x = 1.0 + 3.0 / 0.0\n"
              "   printf(\"%f\n\", x);\n"
              "}");
        ASSERT_EQUALS(
            "[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());

        check("void f()\n"
              "{\n"
              "   double x = 1.0 - 3.0 / 0.0\n"
              "   printf(\"%f\n\", x);\n"
              "}");
        ASSERT_EQUALS(
            "[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());

        check("void f()\n"
              "{\n"
              "   double x = 3.0 / 0.0\n"
              "   printf(\"%f\n\", x);\n"
              "}");
        ASSERT_EQUALS("", errout.str());

    }

    void invalidFunctionUsage(const char code[]) {
        // Clear the error buffer..
        errout.str("");

        const char cfg[] = "\n"
                           "\n"
                           "    \n"
                           "   0,2:36 \n"
                           "";
        tinyxml2::XMLDocument xmldoc;
        xmldoc.Parse(cfg, sizeof(cfg));

        Settings settings;
        settings.library.load(xmldoc);

        // Tokenize..
        Tokenizer tokenizer(&settings, this);
        std::istringstream istr(code);
        tokenizer.tokenize(istr, "test.cpp");

        // Check for redundant code..
        CheckOther checkOther(&tokenizer, &settings, this);
        checkOther.invalidFunctionUsage();
    }

    void invalidFunctionUsage1() {
        invalidFunctionUsage("int f() { memset(a,b,sizeof(a)!=12); }");
        ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());

        invalidFunctionUsage("int f() { memset(a,b,sizeof(a)!=0); }");
        TODO_ASSERT_EQUALS("error", "", errout.str());

        invalidFunctionUsage("int f() { strtol(a,b,sizeof(a)!=12); }");
        ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 0 or 1 (comparison result) but the valid values are '0,2:36'.\n", errout.str());

        invalidFunctionUsage("int f() { strtol(a,b,1); }");
        ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 1 but the valid values are '0,2:36'.\n", errout.str());

        invalidFunctionUsage("int f() { strtol(a,b,10); }");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope(const char code[]) {
        // Clear the error buffer..
        errout.str("");

        Settings settings;
        settings.addEnabled("style");

        // Tokenize..
        Tokenizer tokenizer(&settings, this);
        std::istringstream istr(code);
        tokenizer.tokenize(istr, "test.cpp");

        // Check for redundant code..
        CheckOther checkOther(&tokenizer, &settings, this);
        checkOther.checkVariableScope();
    }

    void varScope1() {
        varScope("unsigned short foo()\n"
                 "{\n"
                 "    test_client CClient;\n"
                 "    try\n"
                 "    {\n"
                 "        if (CClient.Open())\n"
                 "        {\n"
                 "            return 0;\n"
                 "        }\n"
                 "    }\n"
                 "    catch (...)\n"
                 "    {\n"
                 "        return 2;\n"
                 "    }\n"
                 "\n"
                 "    try\n"
                 "    {\n"
                 "        CClient.Close();\n"
                 "    }\n"
                 "    catch (...)\n"
                 "    {\n"
                 "        return 2;\n"
                 "    }\n"
                 "\n"
                 "    return 1;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope2() {
        varScope("int foo()\n"
                 "{\n"
                 "    Error e;\n"
                 "    e.SetValue(12);\n"
                 "    throw e;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope3() {
        varScope("void foo()\n"
                 "{\n"
                 "    int i;\n"
                 "    int *p = 0;\n"
                 "    if (abc)\n"
                 "    {\n"
                 "        p = &i;\n"
                 "    }\n"
                 "    *p = 1;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope4() {
        varScope("void foo()\n"
                 "{\n"
                 "    int i;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope5() {
        varScope("void f(int x)\n"
                 "{\n"
                 "    int i = 0;\n"
                 "    if (x) {\n"
                 "        for ( ; i < 10; ++i) ;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());

        varScope("void f(int x) {\n"
                 "    const unsigned char i = 0;\n"
                 "    if (x) {\n"
                 "        for ( ; i < 10; ++i) ;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f(int x)\n"
                 "{\n"
                 "    int i = 0;\n"
                 "    if (x) {b()}\n"
                 "    else {\n"
                 "        for ( ; i < 10; ++i) ;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());
    }

    void varScope6() {
        varScope("void f(int x)\n"
                 "{\n"
                 "    int i = x;\n"
                 "    if (a) {\n"
                 "        x++;\n"
                 "    }\n"
                 "    if (b) {\n"
                 "        c(i);\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f()\n"
                 "{\n"
                 "int foo = 0;\n"
                 "std::vector vec(10);\n"
                 "BOOST_FOREACH(int& i, vec)\n"
                 "{\n"
                 " foo += 1;\n"
                 " if(foo == 10)\n"
                 " {\n"
                 "  return 0;\n"
                 " }\n"
                 "}\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f(int &x)\n"
                 "{\n"
                 "  int n = 1;\n"
                 "  do\n"
                 "  {\n"
                 "    ++n;\n"
                 "    ++x;\n"
                 "  } while (x);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope7() {
        varScope("void f(int x)\n"
                 "{\n"
                 "    int y = 0;\n"
                 "    b(y);\n"
                 "    if (x) {\n"
                 "        y++;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope8() {
        varScope("void test() {\n"
                 "    float edgeResistance=1;\n"
                 "    std::vector edges;\n"
                 "    BOOST_FOREACH(int edge, edges) {\n"
                 "        edgeResistance = (edge+1) / 2.0;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'edgeResistance' can be reduced.\n", errout.str());
    }

    void varScope9() {
        // classes may have extra side effects
        varScope("class fred {\n"
                 "public:\n"
                 "    void x();\n"
                 "};\n"
                 "void test(int a) {\n"
                 "    fred f;\n"
                 "    if (a == 2) {\n"
                 "        f.x();\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope10() {
        varScope("int f()\n"
                 "{\n"
                 "    int x = 0;\n"
                 "    FOR {\n"
                 "        foo(x++);\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope11() {
        varScope("int f() {\n"
                 "    int x = 0;\n"
                 "    AB ab = { x, 0 };\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("int f() {\n"
                 "    int x = 0;\n"
                 "    if (a == 0) { ++x; }\n"
                 "    AB ab = { x, 0 };\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("int f() {\n"
                 "    int x = 0;\n"
                 "    if (a == 0) { ++x; }\n"
                 "    if (a == 1) { AB ab = { x, 0 }; }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope12() {
        varScope("void f(int x) {\n"
                 "    int i[5];\n"
                 "    int* j = y;\n"
                 "    if (x)\n"
                 "        foo(i);\n"
                 "    foo(j);\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());

        varScope("void f(int x) {\n"
                 "    int i[5];\n"
                 "    int* j;\n"
                 "    if (x)\n"
                 "        j = i;\n"
                 "    foo(j);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f(int x) {\n"
                 "    const bool b = true;\n"
                 "    x++;\n"
                 "    if (x == 5)\n"
                 "        foo(b);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f(int x) {\n"
                 "    const bool b = x;\n"
                 "    x++;\n"
                 "    if (x == 5)\n"
                 "        foo(b);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope13() {
        // #2770
        varScope("void f() {\n"
                 "    int i = 0;\n"
                 "    forever {\n"
                 "        if (i++ == 42) { break; }\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope14() {
        // #3941
        varScope("void f() {\n"
                 "    const int i( foo());\n"
                 "    if(a) {\n"
                 "        for ( ; i < 10; ++i) ;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope15() {
        // #4573
        varScope("void f() {\n"
                 "    int a,b,c;\n"
                 "    if (a);\n"
                 "    else if(b);\n"
                 "    else if(c);\n"
                 "    else;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope16() {
        varScope("void f() {\n"
                 "    int a = 0;\n"
                 "    while((++a) < 56) {\n"
                 "        foo();\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f() {\n"
                 "    int a = 0;\n"
                 "    do {\n"
                 "        foo();\n"
                 "    } while((++a) < 56);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f() {\n"
                 "    int a = 0;\n"
                 "    do {\n"
                 "        a = 64;\n"
                 "        foo(a);\n"
                 "    } while((++a) < 56);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f() {\n"
                 "    int a = 0;\n"
                 "    do {\n"
                 "        a = 64;\n"
                 "        foo(a);\n"
                 "    } while(z());\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'a' can be reduced.\n", errout.str());
    }

    void varScope17() {
        varScope("void f() {\n"
                 "    int x;\n"
                 "    if (a) {\n"
                 "        x = stuff(x);\n"
                 "        morestuff(x);\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());

        varScope("void f() {\n"
                 "    int x;\n"
                 "    if (a) {\n"
                 "        x = stuff(x);\n"
                 "        morestuff(x);\n"
                 "    }\n"
                 "    if (b) {}\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
    }

    void varScope18() {
        varScope("void f() {\n"
                 "    short x;\n"
                 "\n"
                 "    switch (ab) {\n"
                 "        case A:\n"
                 "            break;\n"
                 "        case B:\n"
                 "        default:\n"
                 "            break;\n"
                 "    }\n"
                 "\n"
                 "    if (c) {\n"
                 "        x = foo();\n"
                 "        do_something(x);\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());

        varScope("void f() {\n"
                 "    short x;\n"
                 "\n"
                 "    switch (ab) {\n"
                 "        case A:\n"
                 "            x = 10;\n"
                 "            break;\n"
                 "        case B:\n"
                 "        default:\n"
                 "            break;\n"
                 "    }\n"
                 "\n"
                 "    if (c) {\n"
                 "        x = foo();\n"
                 "        do_something(x);\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());

        varScope("void f() {\n"
                 "    short x;\n"
                 "\n"
                 "    switch (ab) {\n"
                 "        case A:\n"
                 "            if(c)\n"
                 "                do_something(x);\n"
                 "            break;\n"
                 "        case B:\n"
                 "        default:\n"
                 "            break;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());

        varScope("void f() {\n"
                 "    short x;\n"
                 "\n"
                 "    switch (ab) {\n"
                 "        case A:\n"
                 "            if(c)\n"
                 "                do_something(x);\n"
                 "            break;\n"
                 "        case B:\n"
                 "        default:\n"
                 "            if(d)\n"
                 "                do_something(x);\n"
                 "            break;\n"
                 "    }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope19() { // Ticket #4994
        varScope("long f () {\n"
                 "  return a >> extern\n"
                 "}\n"
                 "long a = 1 ;\n"
                 "long b = 2 ;");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope20() { // Ticket #5103 - constant variable only used in inner scope
        varScope("int f(int a) {\n"
                 "  const int x = 234;\n"
                 "  int b = a;\n"
                 "  if (b > 32) b = x;\n"
                 "  return b;\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope21() { // Ticket #5382 - initializing two-dimensional array
        varScope("int test() {\n"
                 "    int test_value = 3;\n"
                 "    int test_array[1][1] = { { test_value } };\n"
                 "    return sizeof(test_array);\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
    }

    void varScope22() { // Ticket #5684 - "The scope of the variable 'p' can be reduced" - But it can not.
        varScope("void foo() {\n"
                 "   int* p( 42 );\n"
                 "   int i = 0;\n"
                 "   while ( i != 100 ) {\n"
                 "      *p = i;\n"
                 "      ++p;\n"
                 "      ++i;\n"
                 "   }\n"
                 "}");
        ASSERT_EQUALS("", errout.str());
        // try to avoid an obvious false negative after applying the fix for the example above:
        varScope("void foo() {\n"
                 "   int* p( 42 );\n"
                 "   int i = 0;\n"
                 "   int dummy = 0;\n"
                 "   while ( i != 100 ) {\n"
                 "      p = & dummy;\n"
                 "      *p = i;\n"
                 "      ++p;\n"
                 "      ++i;\n"
                 "   }\n"
                 "}");
        ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'p' can be reduced.\n", errout.str());
    }

    void varScope23() { // #6154: Don't suggest to reduce scope if inner scope is a lambda
        varScope("int main() {\n"
                 "   size_t myCounter = 0;\n"
                 "   Test myTest([&](size_t aX){\n"
                 "       std::cout 

Web Proxy Viewer  |  New URL  |  Original Page